⬢ DragonFlyBSD Kernel Audit
DF-5530 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5530",
  "status": "reproduced",
  "reproduced": true,
  "impact": "panic",
  "confidence": "certain",
  "verdict": "usbpf_clone_create() publishes the ifnet on ubus->ifp at sys/bus/u4b/usb_pf.c:157 long before it is initialized (if_softc at :164, if_attach at :169, IFF_UP at :170, bpfattach at :177), and nothing serializes usbpf_detach()/usbpf_clone_destroy() (controller detach, usb_controller.c:240, no ifnet_lock/bus lock) against it. A KLD harness driving only production entry points (if_clone_create()/if_clone_destroy() vs the unlocked ubus->ifp read + usbpf_detach() that usb_pf.c:209 performs) panicked the guest twice in under 45 s at usbpf_clone_destroy+0xf, fault VA 0x5c8 = ubus->ifp = NULL with ubus = ifp->if_softc == NULL (strike inside :157-:164). The second sink was reproduced deterministically with a state-identical module: bpfdetach() on a never-bpf-attached ifnet faults at net/bpf.c:1574 (fault VA 0x20 = bp->bif_ifp on bp == NULL - the Interface wasnt attached guard tests bp->bif_ifp instead of bp). Distinct from known DF-1100/DF-2347/DF-2607 (all tap-vs-teardown; this is create-vs-detach with no tap). Both faults are NULL derefs of small offsets: local DoS via a privileged race (SIOCIFCREATE is SYSCAP_RESTRICTEDROOT-gated, net/if.c:2005-2013); no escalation path. fix.diff (publish-after-init + NULL-softc guard + bp==NULL typo fix) was built into a guest kernel: the deterministic sink now prints bpfdetach: usbus0 was not attached with no panic, and the identical race harness survives its full 240 s window (RACE_RESULT=NOHIT) with the usbus clone machinery still functional.",
  "exploit_chain": "",
  "evidence": "panic_race.txt (Fatal trap 12, VA 0x5c8, Stopped at usbpf_clone_destroy+0xf: movq $0,0x5c8(%rax) - from the pure production-path race); panic_sink.txt (VA 0x20, Stopped at bpfdetach.cold.7: movq 0x20,%rax); run.log; build.log; fix_run.log (baseline panic vs fixed-kernel bpfdetach: usbus0 was not attached + 240s NOHIT); VERDICT.md narrative",
  "kernel_refs": [
    "sys/bus/u4b/usb_pf.c:157",
    "sys/bus/u4b/usb_pf.c:164",
    "sys/bus/u4b/usb_pf.c:169",
    "sys/bus/u4b/usb_pf.c:177",
    "sys/bus/u4b/usb_pf.c:188",
    "sys/bus/u4b/usb_pf.c:191",
    "sys/bus/u4b/usb_pf.c:192",
    "sys/bus/u4b/usb_pf.c:207",
    "sys/bus/u4b/usb_pf.c:209",
    "sys/bus/u4b/usb_pf.c:114",
    "sys/bus/u4b/controller/usb_controller.c:240",
    "sys/net/bpf.c:1567",
    "sys/net/bpf.c:1574",
    "sys/net/if.c:2005",
    "sys/net/if.c:2013"
  ],
  "poc_changes": "Seed was code-inspection only; no runnable seed existed. Wrote two KLD rigs: (1) usbpf_race.ko - two kernel threads driving the production SIOCIFCREATE path and the production usbpf_detach() entry against each other on the real xhci usbus0; the detacher strikes only when the published ifnet has not yet set IFF_UP (usb_pf.c:170) to stay strictly inside the :157-:177 window and out of the known DF-2347/2607 double-destroy interleaving (an ifunit()-based filter was discarded after discovering ifunit() panics without ifnet_lock - harness artifact, not a finding); (2) bpfdetach_null.ko - if_alloc(IFT_USB) + xname + production bpfdetach(), the exact state of a :164-:177 strike. Guest needed -device qemu-xhci (vm.sh QEMU_EXTRA) since the default QEMU has no USB controller.",
  "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": 3300,
  "guest_dirty": 0,
  "build_cmd": "sh build_guest.sh   (SYSDIR=/usr/src/sys; kld builds of df5530_race.ko and sink/bpfdetach_null.ko)",
  "run_cmd": "kldload ./df5530_race.ko            # race: panic < 45s (VA 0x5c8); kldload ./sink/bpfdetach_null.ko  # sink: immediate panic (VA 0x20)",
  "code_hash": "5238bf4f9878ccfb015f05b95ed81d40a98c7e53f9da1811ec127ae19ade0caf (usbpf_race.c); 3aa2116772e5972489c1a0584053c125a6af38feb6cfeee2d359c477fd6c3c5b (bpfdetach_null.c)",
  "notes": "Race reproduced on two independent boots (both < 45 s, identical RIP usbpf_clone_destroy+0xf). The bpf.c:1574 typo is a latent defect of its own: ANY caller of bpfdetach() on a not-bpf-attached ifnet faults there; usb_pf.cs create-window race and the double-destroy variant (second usbpf_clone_destroy after a first bpfdetach removed the bpf_if) both reach it. Fixed kernel uname: DragonFly 6.5-DEVELOPMENT #1: Wed Oct  7 00:21:51 UTC 2026.",
  "recommended_fix": "Publish ubus->ifp only after bpfattach() completes (usb_pf.c), guard usbpf_clone_destroy() against if_softc == NULL, and fix bpfdetach()s not-found guard to test bp == NULL (net/bpf.c:1574).",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Applied fix.diff to a clean-source guest tree (patch -p1, all 3 hunks), rebuilt with make -j6 nativekernel KERNCONF=X86_64_GENERIC && make installkernel (zero errors), rebooted. Baseline: race panic < 45 s (usbpf_clone_destroy+0xf, VA 0x5c8) and sink panic at bpfdetach (VA 0x20). Patched: kldload of the sink module returns 0 printing bpfdetach: usbus0 was not attached with no panic, and the identical race harness completes its full 240 s window (RACE_RESULT=NOHIT) with clone create/destroy still functional. Both sinks eliminated.",
  "fix_evidence": "fix_run.log: bpfdetach: usbus0 was not attached / DF5530: bpfdetach() returned (not reached on vulnerable kernel) / RACE_RESULT=NOHIT (no panic in 240s) / vm.sh status up throughout; fix_build.log: >>> Kernel install for X86_64_GENERIC completed on Wed Oct  7 00:26:15 UTC 2026",
  "fix_kernel_uname": "DragonFly dfbsd 6.5-DEVELOPMENT #1: Wed Oct  7 00:21:51 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64"
}