DF-5464 / icu_msiabi_neg.c
/* * DF-5464 crasher #1: msi_alloc(count = -2600000) -> the scan loop walks * 'i' far below zero and reads icu_irqmaps[0][i] (icu_abi.c:476) at * ~41.6 MB below the array, which is below KERNBASE * (icu_irqmaps @ 0xffffffff81a00420, kernel image starts * 0xffffffff80200000): unmapped -> kernel-mode page fault -> panic. * * Second loop iteration only: i starts at icu_abi_msi_start (0), * maps[0][0] is ICU_IMT_LEGACY (!= UNUSED) so the first iteration * 'continue's, then i += count = -26000000*... i.e. i = -2600000. * * On an INVARIANTS kernel this panics at the powerof2/count KASSERTs * (icu_abi.c:460-461) instead. */ #include <sys/param.h> #include <sys/kernel.h> #include <sys/module.h> #include <sys/systm.h> #include <sys/machintr.h> extern struct machintr_abi MachIntrABI_ICU; static int zone[8]; static int icu_neg_modevent(module_t mod __unused, int type, void *data __unused) { int rc; switch (type) { case MOD_LOAD: kprintf("icu_msiabi_neg: calling ICU msi_alloc(count=-2600000," " cpu0): expect kernel page fault on icu_irqmaps[0]" "[-2600000] (icu_abi.c:476)\n"); rc = MachIntrABI_ICU.msi_alloc(zone, -2600000, 0); kprintf("icu_msiabi_neg: SURVIVED, rc=%d (unexpected on a " "production kernel)\n", rc); return 0; case MOD_UNLOAD: return 0; default: return EOPNOTSUPP; } } static moduledata_t icu_msiabi_neg_mod = { "icu_msiabi_neg", icu_neg_modevent, NULL }; DECLARE_MODULE(icu_msiabi_neg, icu_msiabi_neg_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE); MODULE_VERSION(icu_msiabi_neg, 1); |