DF-3866 / layout_proof.c
/* * DF-3866 — kernel-side layout proof for the emu10kx ihandler[-1] OOB. * * This module does NOT touch hardware. It re-declares, verbatim, the * field prefix of `struct emu_sc_info` from sys/dev/sound/pci/emu10kx.c * lines 307..334 (everything up to and including ihandler[]), using the * guest kernel's real types (struct lock, struct sbuf, device_t, * bus_space_tag_t, struct cdev, struct resource). Compiling it against * the running kernel ABI proves where ihandler[-1] lands. * * Build: see build.sh Run: kldload ./lay.ko; dmesg | grep DF3866 */ #include <sys/param.h> #include <sys/types.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/bus.h> #include <sys/rman.h> #include <sys/sbuf.h> #include <sys/queue.h> #include <sys/lock.h> #include <sys/mutex.h> #include <sys/sysctl.h> #include <sys/conf.h> #define EMU_MAX_IRQ_CONSUMERS 32 /* emu10kx.c:250 */ /* verbatim from emu10kx.c:300-305 */ struct emu_intr_handler { void* softc; uint32_t intr_mask; uint32_t inte_mask; uint32_t(*irq_func) (void *softc, uint32_t irq); }; /* * Verbatim field-for-field prefix of `struct emu_sc_info` * (emu10kx.c:307-334), same order, same types. */ struct proof_sc { struct lock lock; struct lock rw; /* Hardware exclusive access lock */ device_t dev; device_t pcm[6]; /* RT_COUNT */ device_t midi[2]; uint32_t type; uint32_t rev; bus_space_tag_t st; bus_space_handle_t sh; struct cdev *cdev; /* /dev/emu10kx character device */ struct lock emu10kx_lock; int emu10kx_isopen; struct sbuf emu10kx_sbuf; int emu10kx_bufptr; struct resource *reg; struct resource *irq; void *ih; struct emu_intr_handler ihandler[EMU_MAX_IRQ_CONSUMERS]; }; static int lay_modevent(module_t mod __unused, int cmd, void *data __unused) { size_t oh, oreg, oirq, oih, sz; if (cmd != MOD_LOAD) return (0); sz = sizeof(struct emu_intr_handler); oh = __offsetof(struct proof_sc, ihandler); oreg= __offsetof(struct proof_sc, reg); oirq= __offsetof(struct proof_sc, irq); oih = __offsetof(struct proof_sc, ih); kprintf("DF3866: sizeof(struct emu_intr_handler)=%zu\n", sz); kprintf("DF3866: offsetof(reg)=%zu irq=%zu ih=%zu ihandler=%zu\n", oreg, oirq, oih, oh); kprintf("DF3866: ihandler[-1] spans [%zu,%zu)\n", oh - sz, oh); if (oh - sz == oreg && oh - 16 == oirq && oh - 8 == oih) kprintf("DF3866: PROVEN: ihandler[-1] overlays {reg, irq, ih} " "-> emu_intr_unregister(-1) NULLs sc->reg, sc->irq, sc->ih " "and smears the high/low dwords of the irq pointer\n"); else kprintf("DF3866: layout differs from expectation " "(prefix struct divergence?)\n"); return (0); } static moduledata_t lay_mod = { "lay", lay_modevent, NULL }; DECLARE_MODULE(lay, lay_mod, SI_SUB_DRIVERS, SI_ORDER_ANY); |