DF-5528 / verdict.json
{ "finding_id": "DF-5528", "status": "untested", "reproduced": false, "impact": "none", "confidence": "likely", "verdict": "fwohci_pci_detach() (sys/bus/firewire/fwohci_pci.c:341-386) discards bus_generic_detach()s error at :350, force-deletes the firewire child at :351-354 regardless of its detach state, and returns unconditional success at :385; if any fwohci->firewire->{sbp,fwe,dcons_crom} child ever vetoes detach, the parent nonetheless unregisters the IRQ, unmaps the BAR (zeroing bst/bsh), and frees the OHCI DMA rings underneath a still-attached, orphaned firewire child whose self-re-arming watchdog callout (firewire.c:402-403, only stopped at firewire.c:468-471 inside the never-completed firewire_detach) then writes MMIO through a null bus handle -> page-0 kernel write/panic, plus UAF on the freed descriptor rings and a lying kldunload success. The defect is certain at the code level (traced through subr_bus.c:1284-1310 and :2128-2154) but LATENT in this tree: sbp_detach (sbp.c:2016-2058), fwe_detach (if_fwe.c:284-295), dcons_crom_detach (dcons_crom.c:190-207) and fwdev_destroydev (fwdev.c:809-817) all return 0 unconditionally today, so firewire_detach cannot currently fail and the normal path is clean. Untested because the trigger requires physical FireWire OHCI hardware (PCI 0c/10/10) plus a vetoing child: the audit QEMU guest has no such device (run.log: pciconf -l shows only i440fx/virtio, zero class=0c10 functions, no fwohci/firewire dmesg lines, no FW KLDs) and a compile-the-core KLD harness cannot express a newbus parent/child detach-protocol bug. Inherited verbatim from FreeBSD (verified against freebsd-src release/13.4.0 sys/dev/firewire/fwohci_pci.c, whose detach also swallows the error).", "exploit_chain": "", "evidence": "read VERDICT.md sections 1-3 for the line-cited veto-path trace; run.log lines === PCI device classes === (no 0c10 device) and === dmesg fwohci/firewire === NONE; fix.diff applies cleanly (git apply --check OK)", "kernel_refs": [ "sys/bus/firewire/fwohci_pci.c:350", "sys/bus/firewire/fwohci_pci.c:351-354", "sys/bus/firewire/fwohci_pci.c:375-379", "sys/bus/firewire/fwohci_pci.c:385", "sys/kern/subr_bus.c:1292", "sys/bus/firewire/firewire.c:402-403", "sys/bus/firewire/firewire.c:468-471" ], "poc_changes": "no seed PoC existed; the pack carries a source-level lifecycle trace plus a guest hardware-gating check (check_guest.sh) instead of a runnable trigger", "attempts": 1, "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": 30, "guest_dirty": 0, "build_cmd": "none (hardware-gated; see build.sh)", "run_cmd": "./dfbsd-qemu/vm.sh run_root pciconf -l; dmesg | grep -i -E \"fwohci|firewire\" (full form: ./check_guest.sh; output: run.log)", "code_hash": "207b22d9863da4d521e48b7840d9ddb8b738b5b338fceaee1eccf501cf9280cc", "notes": "Low severity: latent trigger, requires root-initiated kldunload/devctl detach or CardBus surprise removal (DRIVER_MODULE(fwohci, cardbus) at fwohci_pci.c:491) plus a firewire-bus child with an EBUSY guard, which none has today. Adjacent items verified and NOT filed: NULL-cookie bus_teardown_intr in the setup_intr-failure path (fwohci_pci.c:361-368) is harmless (pci_teardown_intr masks INTx; nexus_teardown_intr returns -1 for NULL); the whole-detach-under-crit including sbp_detachs hz/2 tsleep is legal in DF (per-thread critcount); sc->dummy_dma (fwohci.c:693) is never freed in fwohci_detach - an fwohci.c-rooted leak noted for the orchestrator since that file is closed this pass.", "recommended_fix": "Propagate bus_generic_detach()s error out of fwohci_pci_detach() before releasing any resource or deleting the child (fix.diff); mirror in the suspend paths already-correct pattern at fwohci_pci.c:395-397.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff (git apply --check OK against sys/bus/firewire/fwohci_pci.c) captures err = bus_generic_detach(self) and returns it after crit_exit() before any teardown, exactly matching the working suspend-path error handling; not runtime-validated because the baseline itself is hardware-gated (no OHCI controller on the guest, no vetoing child in the tree).", "fix_evidence": "fix.diff hunk @@ -342,12 +342,24 @@; git apply --check output GIT APPLY CHECK: OK; sys/ verified untouched (git status --short sys/ empty)" } |