DF-5531 / verdict.json
{ "finding_id": "DF-5531", "status": "reproduced", "reproduced": true, "impact": "none", "confidence": "certain", "verdict": "DragonFly disabled FreeBSDs bpf_peers_present early-out in usbpf_xfertap (sys/bus/u4b/usb_pf.c:364-367, #if 0 XXX this is not needed on dragonfly), and DragonFlys bpf only assigns ifp->if_bpf while a listener is attached (net/bpf.c:297/324), with bpf_tap() NULL-safe (bpf.c:1245). Net effect, measured live on the guest: with a root-created usbus0 clone and NO listener (dmesg: bus ifp=0xfffff8008fd1e480 if_bpf=0), every call of the production usbpf_xfertap() performs the full precompute + kmalloc(totlen) + complete payload usbd_copy_out + kfree for nothing - 1094-1256 cycles/call for a 4 KiB transfer versus 25-34 cycles for the only remaining early-out (bus->ifp == NULL), a 36-44x overhead, and on the SUBMIT paths this runs while holding the USB BUS lock (usb_transfer.c:2630/2813), taxing every transfer on the controller for as long as an unwatched tap clone exists. No memory-safety impact (buffer fully initialized, bpf_tap NULL-checked), so impact class is none and severity Info; the realistic ceiling is a root-armed availability/performance degradation, worst for isochronous traffic. One-line fix: add if (bus->ifp->if_bpf == NULL) return; after the existing check.", "exploit_chain": "", "evidence": "run.log + run.2.log: DF5531: bus ifp=0xfffff8008fd1e480 if_bpf=0 (expect NULL: no listener) then (A) ifp set, if_bpf==NULL : 1094 cycles/call vs (B) ifp NULL (early-return) : 25 cycles/call, ratio 43.5x (run 2 on a fresh boot: 1256 vs 34 = 36.2x); tap_cost.c is the KLD rig invoking the global usbpf_xfertap() against the real usbus0 softc", "kernel_refs": [ "sys/bus/u4b/usb_pf.c:362", "sys/bus/u4b/usb_pf.c:364", "sys/bus/u4b/usb_pf.c:368", "sys/bus/u4b/usb_pf.c:381", "sys/bus/u4b/usb_pf.c:468", "sys/bus/u4b/usb_pf.c:488", "sys/net/bpf.c:297", "sys/net/bpf.c:324", "sys/net/bpf.c:1245", "sys/bus/u4b/usb_transfer.c:2630", "sys/bus/u4b/usb_transfer.c:2813" ], "poc_changes": "No seed existed. tap_cost.c fabricates a minimal 8x512 BULK-OUT usb_xfer (PIO page_caches, zeroed flags_int = HOST mode OUT so SUBMIT copies every frame) and points xroot->bus at the REAL usbus0 softc obtained via devclass_find(\"usbus\"), so header fields (bus->bdev/parent) are production objects; times usbpf_xfertap(xfer, USBPF_XFERTAP_SUBMIT) with the clone present (if_bpf NULL) against a bus->ifp-NULL control. Guest needed -device qemu-xhci.", "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": 300, "guest_dirty": 0, "build_cmd": "sh build.sh (SYSDIR=/usr/src/sys; builds df5531_tapcost.ko)", "run_cmd": "sh run.sh (ifconfig usbus0 create; kldload ./df5531_tapcost.ko; dmesg; kldunload; ifconfig usbus0 destroy)", "code_hash": "a00dfb589bbe5d7d79c68fb29e924161507f07ba971739b09fd7009ea94d1194", "notes": "Two runs on independent boots: 43.5x and 36.2x - consistent. fix.diff restores the early-out DragonFly-style; not rebuilt into the DF-5530 fix kernel (Info severity, one-line guard provably short-circuits before the kmalloc at usb_pf.c:381).", "recommended_fix": "Restore the listener early-out: after the bus->ifp NULL check at usb_pf.c:362, add if (bus->ifp->if_bpf == NULL) return;.", "fix_status": "not_testable", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 0, "fix_verdict": "Info-severity finding: no kernel rebuild performed for the one-line guard (the DF-5530 validation kernel in the same session carried only DF-5530s hunks). The guard is code-obvious: it returns at usb_pf.c:362-363 territory, before usbpf_xfer_precompute_size (:368) and the kmalloc (:381), so case (A) collapses to case (B) timing; baseline behavior itself is reproduced (36-44x).", "fix_evidence": "fix.diff (one hunk, patch --dry-run verified); VERDICT.md" } |