{
  "finding_id": "DF-5351",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "Reproduced on a production-behaviour kernel (X86_64_GENERIC minus INVARIANTS; stock GENERIC ships without INVARIANTS): ioapic_abi_msi_alloc_intern() performs no runtime validation of the driver-supplied count, so msi_alloc(count=64) returns success and writes 32 words past the callers 32-int contract array (intrs[j]=intr, ioapic_abi.c:1295; reference caller uses on-stack int irqs[32], pci.c:1952), and msi_alloc(count=128) additionally reads/writes ioapic_irqmaps[cpuid][192..255] one row past the 192-entry per-CPU row and feeds OOB-read msi_intr[192..255] values into setidt() over the IPI gates - the guest died with RIP=0x6970695f (_ipi string bytes) proving the IDT smash. Fix (runtime count validation returning EINVAL) makes both counts fail cleanly with no corruption and no crash while legal allocations keep working.",
  "exploit_chain": "Driver (KLD, i.e. already-privileged code, or malicious PCIe device whose MMC field advertises 128 messages plus a driver forwarding pci_msi_count()) -> MachIntrABI.msi_alloc(intrs, count>32, cpuid) -> intrs[j]=intr OOB write past caller array (kernel stack in pci.c) -> for count>=128: ioapic_irqmaps row-crossing writes + msi_setup(192..255) -> msi_intr[] OOB read + setidt() IPI-gate smash -> next IPI jumps to garbage RIP (observed 0x6970695f) -> crash/panic. No unprivileged entry point exists (no sysctl/ioctl/dev surface; boot-tunable path is DF-1037), so impact is dos-class, not uid0.",
  "evidence": "run.log (canary: zone[32]=160  <-- OOB write past 32-int contract, 32/96 canary words past zone[31] overwritten); panic_row128.txt (msi_alloc(count=128, cpu5) ... rc=0 then Stopped at 0x6970695f: kernel: type 12 trap); run_fixed.log (msi_alloc rc=22 both counts, no crash, msix count=1 round trip OK); VERDICT.md full narrative",
  "kernel_refs": [
    "sys/platform/pc64/apic/ioapic_abi.c:1256",
    "sys/platform/pc64/apic/ioapic_abi.c:1269",
    "sys/platform/pc64/apic/ioapic_abi.c:1295",
    "sys/platform/pc64/apic/ioapic_abi.c:1296",
    "sys/platform/pc64/apic/ioapic_abi.c:1321",
    "sys/platform/pc64/apic/ioapic_abi.c:1330",
    "sys/sys/systm.h:94",
    "sys/bus/pci/pci.c:1952",
    "sys/platform/pc64/x86_64/msi.c:433"
  ],
  "poc_changes": "Fixed DECLARE_MODULE to the moduledata_t form (DFly master signature); in-tree kmod build recipe (SYSDIR relative + device_if.h/bus_if.h as generated SRCS); row128 crasher targets cpu ncpus-1 so the crossed row is the all-zero successor row; count=64 canary buffer is 128 ints with only [0..31] inside the ABI contract",
  "attempts": 4,
  "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #0: Sat Oct  3 07:28:45 UTC 2026     root@dfbsd:/usr/obj/usr/src/sys/X86_64_NOINV  x86_64 (baseline runs; fix runs on #1 08:38:15 same config)",
  "runtime_sec": 5400,
  "guest_dirty": 1,
  "build_cmd": "sh build.sh (in-tree kmod build in /usr/src/sys/modules/msiabi via /usr/src/sys/conf/kmod.mk)",
  "run_cmd": "kldload /usr/obj/usr/src/sys/modules/msiabi/msiabi_probe.ko   # canary proof; then msiabi_row128.ko  # crash",
  "code_hash": "74f8d0d9ece297dddde23c5fcc8e43a72c63b6c543f1671d90c2c2e2590fe6a4 (msiabi_probe.c); 0bea3f4c339c31319fa9f507162e45b8ea19483dd3c932da9c4c90e0a9da181b (msiabi_row128.c)",
  "notes": "Baseline runs 1-2 executed on the first X86_64_NOINV build (uname #0 07:28:45); a vm.sh reset reverted that kernel before run 3, so the DF-5352 production run and both fix runs used rebuilds (#0 08:13:01 baseline-for-5352 / #1 08:38:15 fixed). count=0 livelock and count<0 OOB-read-walk variants are code-evident (i += count) but not separately executed. Guest returned via vm.sh reset with-src.",
  "recommended_fix": "Validate count/cpuid at run time in ioapic_abi_msi_alloc_intern (return EINVAL for count<=0, >32 or non-power-of-2) and in ioapic_abi_msi_release_intern (early return), replacing INVARIANTS-only KASSERTs as the sole guard",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "fix.diff applied to guest /usr/src/sys/platform/pc64/apic/ioapic_abi.c, kernel rebuilt (X86_64_NOINV #1 08:38:15) and rebooted; identical PoCs re-run: msi_alloc(count=64) and (count=128) both return EINVAL(22), zero canary words overwritten, no crash, and the legal count=1 MSI-X round trip still succeeds (run_fixed.log). Bad behavior gone, no regression.",
  "fix_evidence": "findings/poc/DF-5351/run_fixed.log; fix.diff"
}