DF-5302 / verdict.json
{ "finding_id": "DF-5302", "status": "reproduced", "reproduced": true, "impact": "panic", "confidence": "certain", "verdict": "Deterministic kernel NULL-pointer WRITE panic in the production fwohci_db_init() (fwohci.c:1253) whenever dbch->ndb == 0: STAILQ_LAST() of the still-empty db_trq ring is NULL and the ring-closure store writes to address 0x0. ndb arrives unvalidated from user space (FW_SSTBUF rx.npacket*nchunk == 0 via fwdev.c:504-506 -> fwdma_malloc_multiseg(n=0) returns a valid am at fwdma.c:153-161 -> FW_SRSTREAM -> fwohci_irx_enable fwohci.c:1606-1608; TX twin at fwohci.c:1485). Verified on the QEMU guest with a KLD harness that compiles the unmodified production fwohci.c and calls the production fwohci_irx_enable(): Fatal trap 12, fault VA 0x0, supervisor write data, stopped at fwohci_db_init.cold.11: movq $0,0. Hardware-gated for the ioctl plumbing (no FireWire controller on the guest), so the harness replaces only bus_space and the bus state. Impact ceiling is local DoS (fixed address 0, NULL content; not redirectable). fix.diff (3 hunks) applied inside the guest /usr/src: identical trigger returns EINVAL with invalid iso rx buffer spec and the guest stays up - fix validated.", "exploit_chain": "operator-group user: open /dev/fw0.0 -> ioctl FW_SSTBUF{rx.npacket=0} -> ioctl FW_SRSTREAM -> fwdev_allocbuf succeeds with 0-element buffer -> fwohci_irx_enable -> fwohci_db_init -> NULL+0 write -> kernel panic (local DoS; no uid0 route: the faulting address is fixed at 0x0).", "evidence": "panic.txt: fault virtual address = 0x0 / supervisor write data / Stopped at fwohci_db_init.cold.11: movq $0,0; run.log (baseline), fix_run.log (SURVIVED ... returned 22 (EINVAL), guest up); VERDICT.md for the full static chain fwdev.c:504->fwdma.c:153->fwohci.c:1606->1253.", "kernel_refs": [ "sys/bus/firewire/fwohci.c:1253", "sys/bus/firewire/fwohci.c:1606", "sys/bus/firewire/fwohci.c:1485", "sys/bus/firewire/fwdev.c:504", "sys/bus/firewire/fwdev.c:108", "sys/bus/firewire/fwdma.c:153" ], "poc_changes": "No seed PoC existed. Harness authored fresh: KLD includes the production fwohci.c (globals -D-renamed), calls production fwohci_irx_enable() with the fwdev_allocbuf state for npacket=0; bus_space faked with a MEM-space tag over plain kernel memory (x86_64 bus_space_write_4 is then a direct store).", "attempts": 4, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 240, "guest_dirty": 0, "build_cmd": "sh build.sh (cd /root/df5302 && make; compiles production /sys/bus/firewire/fwohci.c into df5302.ko)", "run_cmd": "sh run.sh (kldload /root/df5302/df5302.ko; sysctl kern.df5302_fire=1)", "code_hash": "ee628ed09368d18b165aea6b2d04ee98a12d4a42694566a15bb694391e216528", "notes": "Also covers the 65536*65536 int-overflow-to-zero variant. Related known findings in the same trust boundary: DF-2293 (psize=0 div0), DF-2298 (fwdma n-overflow OOB accessors) - this is the fwohci.c-side sink neither of those covers.", "recommended_fix": "Validate ndb!=0 in fwohci_irx_enable/fwohci_itxbuf_enable (EINVAL) and guard fwohci_db_init against ndb==0 (see fix.diff).", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": true, "fix_verdict": "Baseline (unpatched /usr/src): Fatal trap 12 write at 0x0 in fwohci_db_init, guest down. After patch -p1 < fix.diff + module rebuild with the patched production source: fwohci: invalid iso rx buffer spec (bnpacket=0 bnchunk=8) + SURVIVED fwohci_irx_enable, returned 22, guest up. Panic gone, clean EINVAL.", "fix_evidence": "fix_run.log, fix_build.log, fix.diff (hunks at fwohci.c:1193/1492/1619 after application)." } |