⬢ DragonFlyBSD Kernel Audit
DF-5789 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5789",
  "status": "reproduced",
  "verdict": "devclass_delete_driver() (sys/kern/subr_bus.c:888-897) detaches a multi-unit drivers devices one at a time and returns on the first detach veto, after having irreversibly destroyed the bindings of every earlier unit (softc freed by device_set_driver(dev,NULL) at subr_bus.c:2150->1944, sysctl tree freed at 2151, devclass entry dropped at 2146-2147). Verified live: a two-unit driver whose unit 1 vetoes leaves unit 0 permanently dead (state=DS_NOTPRESENT, driver=NULL, softc=NULL, dev.dfveto.0 sysctl tree gone, zombie visible to unprivileged hw.bus.devices readers) while the kld stays loaded and every unload retry fails - the dead unit cannot re-attach because bus_generic_driver_added (subr_bus.c:3007-3016) only re-probes on new-driver registration. Wedge lasts as long as the veto (open umass device / mounted fs / DF-5544-class driver bug) persists; persistent vetoes require reboot. Driver-module unload is root-only, but unprivileged users can hold the veto open. No memory corruption in this path itself.",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "exploit_chain": "kldload rig.ko (dfveto0 detachable + dfveto1 veto) -> kldunload rig -> devclass_delete_driver detaches dfveto0 irreversibly, then dfveto1 returns EBUSY -> unload fails with module still loaded -> dfveto0 dead (state=0/driver=0/softc=0, dev.dfveto.0 gone) -> unpriv walker shows zombie -> every kldunload retry fails -> hardware unit lost until veto clears AND module is manually reloaded; persistent veto => reboot",
  "evidence": "run5789.log (kldunload Device busy + dev.dfveto.0 subtree gone + walker zombie [110] dfveto0 state=NOTPRESENT); rig.txt dmesg (dfveto0: detached then dfveto1: DETACH VETO, then DF5789: dfveto0 state=0 driver=0 softc=0); fixrun5789.log (patched kernel: same EBUSY but dfveto0 back to state=3 with driver bound)",
  "kernel_refs": [
    "sys/kern/subr_bus.c:888",
    "sys/kern/subr_bus.c:893",
    "sys/kern/subr_bus.c:1944",
    "sys/kern/subr_bus.c:2128",
    "sys/kern/subr_bus.c:2146",
    "sys/kern/subr_bus.c:2150",
    "sys/kern/subr_bus.c:3007"
  ],
  "poc_changes": "PoC authored fresh (no seed): KLD with two drivers on nexus (dfveto: identify adds wired units via BUS_ADD_CHILD so nexus_print_child gets its ivars - a raw device_add_child panicked nexus_print_child, which is a nexus.c assumption, not the target bug; dfleak: 8192-byte softc for DF-5790); walker.c reproduces libdevctls hw.bus.devices walk for the unprivileged zombie view; kernel-thread not needed since this path does not self-deadlock.",
  "attempts": 3,
  "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": 840,
  "guest_dirty": 0,
  "build_cmd": "cd /root/df5789 && make KERNBUILDDIR=/usr/obj/usr/src/sys/X86_64_GENERIC && cc -O -o walker walker.c",
  "run_cmd": "cd /root/df5789 && sh run5789.sh",
  "code_hash": "376cd004b0eed058cce2f3f12a3bf3436ddacfba583102218f7680f222fefc90",
  "notes": "Recovery semantics verified: after the veto clears and the module finally unloads, reloading the module revives the dead unit (bus_generic_driver_added re-probe), so permanent = for the duration of the veto. Second reserved-ID rig run also validated the DF-5790 fix on the same kernel build. Guest reset to clean-source snapshot after validation.",
  "recommended_fix": "devclass_delete_driver(): snapshot dcs device list with devclass_get_devices() and on the first device_detach() veto re-probe (device_probe_and_attach) the units already detached before returning the error; see fix.diff",
  "fix_status": "fixed",
  "fix_baseline_reproduced": true,
  "fix_patched_reproduced": true,
  "fix_verdict": "fix.diff applied to guest /usr/src, quickkernel built (#1 Mon Oct 12 18:33:11 UTC 2026), installed, rebooted: kldunload still correctly fails Device busy but the previously-killed unit returns to DS_ATTACHED with its driver bound and sysctl node present (fixrun5789.log); baseline kernel showed the unit dead with no sysctl node. Bad behavior gone.",
  "fix_evidence": "fixrun5789.log vs run5789.log; kbuild.log/kinstall.log; dmesg DF5789: dfveto0 ... state=3 driver=0xffffffff82600880 on patched kernel vs state=0 driver=0 softc=0 on stock"
}