DF-1075 / df1075_harness.c
/* * DF-1075 harness โ kernel module that replicates the exact allocation+write * pattern of the kue(4) driver bug described in if_kue.c. * * The real bug is: kue_attach() does * sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, ...) * BEFORE the device descriptor is read (so KUE_MCFILTCNT==0 โ kmalloc(0)). * DragonFly's slab returns ZERO_LENGTH_PTR=(void*)-8 for kmalloc(0) * (kern_slaballoc.c:888-891), the NULL check passes, and later * kue_setmulti() does memcpy(&sc->sc_mcfilters[i*6], ..., 6) which writes * to the unmapped sentinel address โ page fault โ panic. * * This guest has no USB hardware, so the actual kue(4) driver cannot attach. * This module reproduces the SAME primitive (kmalloc(0) + memcpy) to prove * the mechanism panics on this exact kernel build. It is loaded as root * purely for primitive characterization (not an unprivileged escalation โ * the real trigger requires plugging in a USB device). * * Build: see Makefile * Load: kldload ./df1075_harness.ko * Effect: immediate kernel panic (Fatal trap 12, page fault at 0xFFFFFFFFFFFFFFF8) */ #include <sys/param.h> #include <sys/module.h> #include <sys/kernel.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/errno.h> #include <sys/types.h> /* Matches kue(4): ETHER_ADDR_LEN from net/ethernet.h */ #define HARNESS_ETHER_ADDR_LEN 6 /* Matches the kue(4) allocation exactly: kmalloc(0 * 6) */ #define HARNESS_NFILTERS_AT_ATTACH 0 /* sc_desc is zero-init at kue_attach time */ MALLOC_DECLARE(M_HARNESS); MALLOC_DEFINE(M_HARNESS, "df1075_harness", "DF-1075 harness"); static int df1075_modevent(module_t mod, int type, void *arg) { char *mcfilters; char fake_mac[HARNESS_ETHER_ADDR_LEN] = {0x33, 0x33, 0x00, 0x00, 0x00, 0x01}; switch (type) { case MOD_LOAD: /* * STEP 1 โ replicate kue_attach() if_kue.c:488-493: * sc->sc_mcfilters = kmalloc(KUE_MCFILTCNT(sc) * ETHER_ADDR_LEN, * M_USBDEV, M_WAITOK); * if (sc->sc_mcfilters == NULL) goto detach; * KUE_MCFILTCNT(sc) reads sc_desc.kue_mcastfilt which is zero * at kue_attach() time, so size=0. */ mcfilters = kmalloc(HARNESS_NFILTERS_AT_ATTACH * HARNESS_ETHER_ADDR_LEN, M_HARNESS, M_WAITOK); kprintf("DF-1075: kmalloc(0) returned %p (ZERO_LENGTH_PTR expected %p)\n", mcfilters, (void *)-8); kprintf("DF-1075: NULL check would %s (bug: sentinel is non-NULL)\n", (mcfilters == NULL) ? "FAIL (correctly caught)" : "PASS (BUG: missed)"); if (mcfilters == NULL) { /* does not happen on DragonFly */ return (ENOMEM); } /* * STEP 2 โ replicate kue_setmulti() if_kue.c:383-385: * memcpy(KUE_MCFILT(sc, i), * LLADDR((struct sockaddr_dl *)ifma->ifma_addr), * ETHER_ADDR_LEN); * KUE_MCFILT(sc, 0) = &sc->sc_mcfilters[0] = ZERO_LENGTH_PTR+0 * Writing 6 bytes to (void*)-8 โ page fault โ panic. */ kprintf("DF-1075: about to memcpy 6 bytes into &mcfilters[0] = %p\n", &mcfilters[0]); kprintf("DF-1075: THIS SHOULD PANIC WITH: Fatal trap 12: page fault\n"); memcpy(&mcfilters[0], fake_mac, HARNESS_ETHER_ADDR_LEN); /* NOTREACHED โ panic above */ kprintf("DF-1075: SURVIVED (unexpected โ slab behavior may differ)\n"); return (0); case MOD_UNLOAD: return (0); default: return (EOPNOTSUPP); } } static moduledata_t df1075_mod = { "df1075_harness", df1075_modevent, NULL }; DECLARE_MODULE(df1075_harness, df1075_mod, SI_SUB_EXEC, SI_ORDER_ANY); MODULE_VERSION(df1075_harness, 1); |