⬢ DragonFlyBSD Kernel Audit
DF-4762 / verdict.json
← back to finding ↓ download raw
{
  "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"
}