DF-4280 / trigger.c
/* DF-4280 trigger โ ccd.c:1434 dev_drefs() guard can never be satisfied. * * disk_create() (subr_disk.c:699) creates the raw device with * make_only_dev(), which takes a PERMANENT reference (kern_conf.c:294 * reference_dev(); destroy_only_dev releases twice). cs->sc_dev IS * that raw device, so dev_drefs(cs->sc_dev) >= 2 even with zero open * descriptors, and the CCDIOCCLR guard * * if (dev_drefs(cs->sc_dev) > 1) (ccd.c:1434) * return (EBUSY); * * is ALWAYS true. Once a unit is configured it can never be * unconfigured: CCDF_INITED stays set forever, every component vnode * stays exclusively open (ccdlookup's v_opencount>1 check), the * interleave tables stay allocated, and `kldunload ccd' fails with * "In use, cannot detach" forever. * * Demonstration: configure ccdN (any ileave), then attempt * CCDIOCCLR through the SAME still-open descriptor โ EBUSY. */ #define _KERNEL_STRUCTURES #include <sys/types.h> #include <sys/ioctl.h> #include <sys/param.h> #include <sys/ccdvar.h> #include <fcntl.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <errno.h> int main(int argc, char **argv) { struct ccd_ioctl ccio; char *disks[1]; int fd; if (argc < 3) { fprintf(stderr, "usage: %s <ccddev> <component>\n", argv[0]); return (2); } fd = open(argv[1], O_RDWR); if (fd < 0) { perror("open ccd"); return (1); } disks[0] = argv[2]; bzero(&ccio, sizeof(ccio)); ccio.ccio_disks = disks; ccio.ccio_ndisks = 1; ccio.ccio_ileave = 32; ccio.ccio_flags = 0; if (ioctl(fd, CCDIOCSET, &ccio) < 0) { perror("CCDIOCSET"); return (1); } printf("[+] CCDIOCSET ok size=%llu\n", (unsigned long long)ccio.ccio_size); fflush(stdout); /* clear through the SAME fd, still open โ nothing else holds the * device; this must succeed but returns EBUSY */ bzero(&ccio, sizeof(ccio)); if (ioctl(fd, CCDIOCCLR, &ccio) < 0) { printf("[-] CCDIOCCLR(same fd, no other users): %s\n", strerror(errno)); printf("[-] BUG: unit can never be unconfigured this boot\n"); return (1); } printf("[+] CCDIOCCLR ok\n"); return (0); } |