DF-4986 / df4986_primitive.c
/* * DF-4986 PoC — primitive reproduction of the sink: * * mfi_pci.c:281 / mfi_pci.c:294-299 -> mfi_free(sc) * mfi.c:1074 -> callout_terminate(&sc->mfi_watchdog_callout) * * mfi_watchdog_callout is only initialized by callout_init_mp() at * mfi.c:741, i.e. at the very END of mfi_attach(). Any attach failure * before that line (firmware not READY -> mfi.c:413-417 ENXIO, verbuf/tb/ * comms/frames/sense DMA failures, bus_setup_intr failure at mfi.c:672/683, * config_intrhook failure, aen setup failure, or the parent-DMA-tag failure * at mfi_pci.c:271-282 which reaches mfi_free() before mfi_attach() ran at * all) unwinds through mfi_free(), which terminates a callout that was only * ever bzero'd by mfi_pci.c:230. * * callout_terminate() (sys/kern/kern_timeout.c:1104) does: * KKASSERT(cc->flags & CALLOUT_DID_INIT); * A bzero'd callout has flags == 0, so on any kernel built with INVARIANTS * (stock X86_64_GENERIC, sys/config/X86_64_GENERIC:56) this panics. * * This module reproduces exactly that call on the running kernel without * needing LSI MegaRAID hardware: bzero a callout, terminate it. * * Expected: immediate kernel panic * assertion "cc->flags & CALLOUT_DID_INIT" failed in callout_terminate * (on a kernel built without INVARIANTS the module simply loads and the * terminate is a no-op — that is also a valid, documented outcome.) */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/callout.h> static struct callout co; /* == sc->mfi_watchdog_callout after bzero(sc) */ static int df4986_modevent(module_t mod, int type, void *arg) { switch (type) { case MOD_LOAD: bzero(&co, sizeof(co)); /* mfi_pci.c:230 bzero(sc, sizeof(*sc)) */ kprintf("DF4986: terminating never-initialized callout " "(mfi_free @ mfi.c:1074 path)\n"); callout_terminate(&co); /* <-- KKASSERT fires here */ kprintf("DF4986: survived: kernel built without INVARIANTS\n"); return (0); case MOD_UNLOAD: return (0); default: return (EOPNOTSUPP); } } static moduledata_t df4986_mod = { "df4986", df4986_modevent, NULL }; DECLARE_MODULE(df4986, df4986_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); |