DF-4762 / verdict.json
{ "finding_id": "DF-4762", "status": "inconclusive", "reproduced": 0, "impact": "none", "confidence": "likely", "verdict": "NOT runtime-testable on the audit guest: fwe(4) only attaches under an OHCI-1394 FireWire controller and the QEMU guest has none (env.txt: no class 0x0c0010 PCI device; ifconfig -l has no fwe0; QEMU has no 1394 device model at all) - contract status not_testable, mapped to inconclusive for the poc_results enum. Source-level proof stands: fwe_stop() (if_fwe.c:258-281) frees bulkxfer chunks and their mbufs under if_serializer only, while fwohci_rbuf_update() (fwohci.c:2148-2184, interrupt context, crit_enter() only) manipulates the same stdma/stvalid queues and then calls fwe_as_input(), which takes that serializer only after the mutation; FWXFERQ_OPEN/HANDLER guards are cleared AFTER fwohci_irx_disable()s 1s sleep, so a completion racing ifconfig-down/detach walks freed chunks -> UAF write (sxfer->mbuf, m->m_data), m_freem double-free, and freed-mbuf delivery into if_input. Trigger needs admin teardown racing peer-controlled isochronous traffic -> Medium, memcorrupt bucket.", "exploit_chain": "peer streams on stream_ch while root ifconfig down: rbuf_update inserts freed bulkxfer chunk into stvalid (UAF write) / blocked fwe_as_input resumes after kfree -> m_freem() double-free of mbuf cluster (global allocator metadata corruption) plus controlled-offset UAF writes into freed zone memory; full uid0 chain not assessed - no hardware to develop it on.", "evidence": "VERDICT.md (interleavings + path:line proof); run.log (PoC builds BUILD_OK on guest, exits 2 fwe0 not present); env.txt (guest PCI/ifconfig inventory); fix.diff (3-file serializer fix)", "kernel_refs": [ "sys/dev/netif/fwe/if_fwe.c:258", "sys/dev/netif/fwe/if_fwe.c:269", "sys/dev/netif/fwe/if_fwe.c:270", "sys/dev/netif/fwe/if_fwe.c:334", "sys/dev/netif/fwe/if_fwe.c:340", "sys/dev/netif/fwe/if_fwe.c:543", "sys/dev/netif/fwe/if_fwe.c:552", "sys/dev/netif/fwe/if_fwe.c:562", "sys/bus/firewire/fwohci.c:1813", "sys/bus/firewire/fwohci.c:2148", "sys/bus/firewire/fwohci.c:2167", "sys/bus/firewire/fwohci.c:2184", "sys/bus/firewire/fwohci.c:1281" ], "poc_changes": "Authored the trigger from scratch (no seed): if_nametoindex(fwe0) probe + SO_BROADCAST UDP flood for the TX half; the root half (ifconfig down loop) documented in run.sh. No code errors found in own draft; build succeeded first try on guest.", "attempts": 2, "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": 120, "guest_dirty": 0, "build_cmd": "cc -O -o fwe_trigger fwe_trigger.c", "run_cmd": "./fwe_trigger fwe0 (root half on real hw: while :; do ifconfig fwe0 down; ifconfig fwe0 up; done while peer streams)", "code_hash": "9ce2d397e81255dd447f4c4ee1f858b257fb5c74c4cd982afd61aef5d841d1df", "notes": "Contract-status not_testable (guest reachable, target hardware absent) persisted as inconclusive because poc_results.status CHECK enum lacks not_testable. Guest left clean (no panic, nothing dirtied). Distinct from DF-1849 (unbounded read of stream.len, if_fwe.c:560-569). Related minor: detach with in-flight TX xfers leaks up to 127 fw_xfer (bus_generic_detach does not free the softc) - noted in VERDICT.md, not filed.", "recommended_fix": "Serialize RX chunk processing against teardown: clear FWXFERQ_OPEN/HANDLER and hand=NULL in fwe_stop() BEFORE irx_disable(); add fw_xferq.slz serializer taken by fwohci_rbuf_update() around chunk-queue mutation and hand snapshot; fwe_as_input() revalidates hand after acquiring if_serializer.", "fix_status": "not_testable", "fix_baseline_reproduced": 0, "fix_patched_reproduced": 0, "fix_verdict": "fix.diff authored against read-only sys/ after source verification; cannot build/validate on the guest (no OHCI-1394 hardware, fwe driver cannot attach).", "fix_evidence": "fix.diff in this pack" } |