{
  "finding_id": "DF-5656",
  "status": "not_reproduced",
  "verdict": "The three SYSUNINIT unload hooks in sys/bus/u4b/usb_dynamic.c:101-144 reset the global USB dispatch pointers and then wait with a fixed tsleep(...,hz) - a 1-second sleep that is the only thing preventing an in-flight consumer (usb_dev.c:1710 unprivileged quirk GET dispatch; usb_device.c:2614/2186/1727; usb_request.c:475-495) that is delayed >1s across the read-to-call gap from executing module text freed by kldunload. The grace period itself was measured live: 12/12 kldunload usb_template iterations each took exactly 1.00s (run.log). On the GENERIC guest usb_quirk is compiled in (sys/conf/files:3028; kldload refused already loaded or in kernel), so the quirk variant is shutdown-only there; usb_template is the live-unloadable module (sys/conf/files:3032). The actual corruption did not manifest: the victim must be preempted >1s between pointer read and indirect call during a root-initiated unload - not forceable unprivileged, and the only live-unloadable module has no firing host-side consumer on this guest. Honest not_reproduced for the corruption; the structural defect is certain from code plus the live grace measurement. Secondary sink for the quirk module: usb_quirk.c:1089-1095 runs lockuninit(&usb_quirk_lock) right after the grace - production KKASSERT panic if a thread still holds/waits on the lock.",
  "reproduced": false,
  "impact": "none",
  "confidence": "likely",
  "exploit_chain": "",
  "evidence": "run.log: 12x iter N: unload=1s (the tsleep grace period measured live); run.2.log: [spam] fd=3 (unprivileged uid=1001) ... done: ok=156989 (unprivileged dispatch through usb_quirk_ioctl_p at ~10^5/s) and kldload: cant load usb_quirk: module already loaded or in kernel (quirk compiled into GENERIC); build.log: clean build of the consumer PoC; env.txt: guest uname + kldstat.",
  "kernel_refs": [
    "sys/bus/u4b/usb_dynamic.c:101-114",
    "sys/bus/u4b/usb_dynamic.c:116-130",
    "sys/bus/u4b/usb_dynamic.c:132-144",
    "sys/bus/u4b/usb_dev.c:1710",
    "sys/bus/u4b/usb_device.c:1727",
    "sys/bus/u4b/usb_device.c:2186",
    "sys/bus/u4b/usb_device.c:2614",
    "sys/bus/u4b/usb_request.c:336-341",
    "sys/bus/u4b/quirk/usb_quirk.c:1089-1095",
    "sys/conf/files:3028",
    "sys/conf/files:3032"
  ],
  "poc_changes": "Seed PoC did not exist; authored quirk_get_spam.c from scratch. First build failed (ENOIOCTL is a kernel-internal -3 constant, not visible to userland); fixed by classifying the stub path by observed errno. Note: the guest libcs printf %f prints 0.0 for the atofd duration argument (cosmetic tool quirk, loop duration honored).",
  "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": 220,
  "guest_dirty": 0,
  "build_cmd": "cc -O2 -o quirk_get_spam quirk_get_spam.c (guest, /root/df5656)",
  "run_cmd": "./race_root.sh 20 8; then: i=0; while [ $i -lt 12 ]; do kldload usb_template; u0=$(date +%s); kldunload usb_template; u1=$(date +%s); echo unload=$((u1-u0))s; i=$((i+1)); done",
  "code_hash": "410d09e4a1413764dff4cef23d4fc7d03dc546f325768158adb2cf74652f59da",
  "notes": "Guest left clean (kldstat: kernel+ehci+xhci only, all test modules unloaded, no panic, no reset needed). Skipped deliberately: racing kldunload usb_template against kldunload xhci to force the only host-side consumer (usb_temp_unsetup_p from usbd_free_device) - nanosecond window, negligible probability, real risk of wedging the guest. fix.diff wraps the five reachable dispatch sites with a shared usb_dyn_lock and takes it exclusive in the unload hooks, replacing the tsleep; the gadget-only usb_handle_request.c:644 site is intentionally unwrapped (no in-tree caller; would create a BUS->dyn vs dyn->BUS lock inversion - documented in VERDICT.md section 5).",
  "recommended_fix": "Replace the tsleep(1s) grace in usb_quirk_unload/usb_temp_unload/usb_bus_unload with a real quiescence barrier: global lockmgr lock held shared by consumers across pointer-read+call and exclusive by the unload hooks around the pointer resets (see fix.diff).",
  "fix_status": "not_testable",
  "fix_baseline_reproduced": 0,
  "fix_patched_reproduced": 0,
  "fix_verdict": "Patched-kernel validation not performed: the finding is Low/root-gated and the corruption never reproduced on baseline, so there is no observable bad behavior whose disappearance a fix build would prove. fix.diff is coherent and git-apply --check clean; it removes the racy sleep entirely (exclusive lockmgr acquisition proves quiescence), which by construction closes the read-to-call gap and the lockuninit-on-live-lock hazard (usb_quirk.c:1093).",
  "fix_evidence": "git apply --check fix.diff => APPLIES CLEAN (unmodified sys/ tree); diff hunks cover usb_dynamic.c hooks (tsleep removed, LK_EXCLUSIVE around resets), usb_dynamic.h (USB_DYN_RLOCK/RUNLOCK), and the five consumer dispatch sites."
}