DF-5466 / verdict.json
{ "finding_id": "DF-5466", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "REPRODUCED on a production-behaviour kernel via the pure boot-config route: hw.icu.msi_start=\"-32\" in /boot/loader.conf (kenn confirmed -32; icu_abi_initmap() runs unconditionally at machdep.c:2785) poisons icu_abi_msi_start to -32 because kgetenv_int/strtoq accepts the sign and the &~0x1f mask never range-checks (icu_abi.c:323-324). The first ICU MSI allocation then scans from i=-32: on cpu1 the window icu_irqmaps[1][-32..-1] aliases cpu0s row tail [160..191] (all UNUSED) so it succeeds \u2014 msi_alloc returns rc=0 with NEGATIVE vectors (zone[0]=-32 zone[31]=-1), performs OOB map writes (icu_abi.c:495-496) and calls msi_setup(-32..-1, 1) (icu_abi.c:499), whose msi_intr[-32..-1] OOB reads (msi.c:433, rodata garbage) feed setidt(0..31, ..., cpu1) \u2014 overwriting cpu1s exception gates 0..31. The rigs int3 on cpu1 then produced a TRIPLE FAULT: the serial console shows triggering int3 immediately followed by the bootloader menu with zero trap text (#BP->smashed gate->fetch #PF->smashed gate->#DF->smashed gate->cold reset). No INVARIANTS KASSERT exists on this path \u2014 every kernel config is equally affected. Fix (clamp msi_start into [0, IDT_HWI_VECTORS)) validated on a rebuilt kernel with the SAME boot knob still set: allocation lands legally at vectors 32..63 (zone[0]=32), no OOB, no smash, guest healthy.", "exploit_chain": "root sets hw.icu.msi_start=-32 in loader.conf (or kenv) -> boot-time icu_abi_initmap() computes -32 (icu_abi.c:323-324) -> any ICU MSI alloc (on ICU-ABI machines: first PCI MSI probe at boot via nexus.c:595; here: KLD trigger) -> icu_abi.c:473 loop with negative i -> OOB read/write at icu_irqmaps[cpuid][-32..-1] (previous cpus row) + intrs[j]=-32+j + msi_setup(-32+j) -> msi_intr[-k] OOB read (rodata) + setidt(0..31, garbage, cpu) = arbitrary-cpu exception-gate overwrite -> any exception on that cpu redirects RIP to OOB-read kernel data -> triple fault / RIP-controlled crash. On a real ICU-ABI machine this fires during boot with no KLD involved.", "evidence": "run.log + panic_triplefault.txt (serial: rc=0 zone[0]=-32 zone[31]=-1, gates 0..31 of cpu1 smashed, triggering int3 immediately followed by the bootloader menu \u2014 triple fault with no dump; post-reset fresh dmesg/uptime confirm the reset); run_fixed.log (same knob, clamped: zone[0]=32, no smash)", "kernel_refs": [ "sys/platform/pc64/icu/icu_abi.c:323", "sys/platform/pc64/icu/icu_abi.c:473", "sys/platform/pc64/icu/icu_abi.c:495", "sys/platform/pc64/icu/icu_abi.c:499", "sys/platform/pc64/x86_64/machdep.c:2785", "sys/platform/pc64/x86_64/msi.c:433", "sys/kern/kern_environment.c:379" ], "poc_changes": "Boot-config variant written fresh: no ksetenv/initmap hacks \u2014 the knob is set in /boot/loader.conf and a reboot lets the real boot-time initmap() parse it; the trigger module only calls msi_alloc and, if negative vectors were allocated, pins to cpu1 (lwkt_migratecpu) and executes int3 to exercise the smashed gate deterministically (on a fixed kernel zone[0]>=0 and the int3 is skipped).", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Mon Oct 5 22:59:13 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_NOINV x86_64", "runtime_sec": 600, "guest_dirty": 0, "build_cmd": "sh build.sh (guest /usr/src/sys/modules/icu_abi_probe, in-tree kmod.mk; see build.log)", "run_cmd": "echo hw.icu.msi_start=\"-32\" >> /boot/loader.conf && reboot && kldload /usr/obj/usr/src/sys/modules/icu_abi_probe/icu_msi_start.ko", "code_hash": "ad403473a5a8caa5cb05540f81d7d95fcf34a5b8abd0f012de7804f0f6e9579d (icu_msi_start.c)", "notes": "ICU twin of DF-1037 (hw.ioapic.msi_start, ioapic_abi.c:753-754 \u2014 identical unvalidated-parse pattern; that pass-1 finding was Info/unverified; this pack verifies the class end-to-end and shows the exception-gate smash, suggesting the ioapic twin deserves re-verification too). Deterministic window choice: cpu1s [-32..-1] aliases cpu0s [160..191] which initmap() leaves UNUSED. The crash is a silent triple fault (cold reset, no dump) \u2014 stronger than a normal panic: no forensic trace survives on the console.", "recommended_fix": "Range-check icu_abi_msi_start after the mask in icu_abi_initmap() (if (<0 || >=IDT_HWI_VECTORS) = 0), mirroring DF-1037s suggested fix for the ioapic twin (see fix.diff).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff applied to guest /usr/src/sys/platform/pc64/icu/icu_abi.c, X86_64_NOINV rebuilt and rebooted WITH THE SAME BOOT KNOB still in /boot/loader.conf (kenv hw.icu.msi_start = -32 verified at runtime): the trigger module now gets rc=0 zone[0]=32 zone[31]=63 \u2014 a legal allocation at vectors 32..63 after the clamp \u2014 prints no gate smash, exiting cleanly and returns; guest healthy in the same boot (run_fixed.log). Bad behavior gone with the boot config unchanged.", "fix_evidence": "run_fixed.log (rc=0 zone[0]=32 zone[31]=63, allocation not OOB (fixed or clamped kernel?) -- no gate smash, exiting cleanly; uptime continuous)" } |