⬢ DragonFlyBSD Kernel Audit
DF-5367 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5367",
  "status": "reproduced",
  "verdict": "Mechanism-level reproduction with production code: a ucom cfg task executing ufoma.c:549-550s exact pattern (cv_timedwait(&sc_cv,&sc_lock,15*hz), no abort on device-gone) delays usb_proc_drain() -- the drain ucom_detach() performs at usb_serial.c:394 on the ufoma_detach() path -- by the full remaining timeout. Measured 13000 ms / 13005 ms across two runs for an unplug 2 s into the 15 s wait; fix mechanism (sc_dying + cv_broadcast before drain) measured 0 ms. End-to-end device trigger (crafted MCPC device, class 0x02/subclass 0x88, withholding the vendor ACK and force-disconnecting) is deterministic per the cited code but cannot attach on this guest (usb-serial binds uftdi, DF-5359), hence the KLD-harness evidence class. Impact ceiling: 16-18 s USB-hub-event-thread wedge per open/close-racing-unplug event, repeatable per insertion cycle by an evil device; no memory corruption.",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "exploit_chain": "",
  "evidence": "run.log / run.2.log lines HX[A] usb_proc_drain() done ... ELAPSED=13000 ms (baseline) and HX[B] ... ELAPSED=0 ms (fix); VERDICT.md traces every link: ufoma.c:527,549-550 waits -> only wakeup is intr ACK at ufoma.c:696, cancelled silently on unplug at ufoma.c:601/759 -> ucom_detach drain at usb_serial.c:394 -> usb_process.c:424-442 waits for thread exit -> usb_process.c:146-170 thread cannot observe up_gone inside the callback. build.log shows -Werror-clean production compile.",
  "kernel_refs": [
    "sys/bus/u4b/serial/ufoma.c:141",
    "sys/bus/u4b/serial/ufoma.c:512-532",
    "sys/bus/u4b/serial/ufoma.c:534-554",
    "sys/bus/u4b/serial/ufoma.c:689-697",
    "sys/bus/u4b/serial/ufoma.c:476-491",
    "sys/bus/u4b/serial/ufoma.c:828-851",
    "sys/bus/u4b/serial/usb_serial.c:394",
    "sys/bus/u4b/serial/usb_serial.h:220-221",
    "sys/bus/u4b/usb_process.c:146-174",
    "sys/bus/u4b/usb_process.c:406-452"
  ],
  "poc_changes": "Original PoC sketch did not exist; authored from scratch. Three build iterations were needed: (1) Makefile must include <bsd.kmod.mk> (not <kmod.mk>) as production modules do; (2) usb_process.h requires <sys/bus.h>, <bus/u4b/usb.h>, <bus/u4b/usbdi.h> first (usbdi.h defines usb_proc_callback_t/usb_proc_msg); (3) SRCS needs generated opt_usb.h/device_if.h/bus_if.h; builds must run in-tree under /usr/src/sys/bus/u4b/serial/. Runtime logic needed no changes.",
  "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": 480,
  "guest_dirty": 0,
  "build_cmd": "cd /usr/src/sys/bus/u4b/serial/hx5367 && make (in-tree kmod build; see build.sh)",
  "run_cmd": "kldload ./ufoharness.ko; kldunload ufoharness; dmesg | tail -16 (see run.sh)",
  "code_hash": "dbb6a53c1f1c0fcd63086e93f9c95ece49d611b8f0de63d458a2ef14a0552e8a",
  "notes": "Guest cleaned after run (harness dir + /root/df5367 removed, /usr/src/sys/bus/u4b/serial/ufoma.c restored to pristine after compile-checking the patched driver). Cross-file observation for the orchestrator, out of scope for this finding: usb_serial.c:1906 passes len instead of res.length to clist_qtob() in ucom_get_data() -- FreeBSDs original bounds the copy by the page-cache segment; benign for ufoma (1024-byte page-aligned buffer never splits) but potentially overflow-capable for drivers whose bufsize crosses USB page boundaries (e.g. larger bulk buffers); belongs to usb_serial.c, not re-filed here.",
  "recommended_fix": "Slice the ACK waits into 1 s cv_timedwait pieces with a sc_dying abort, and have ufoma_detach() set sc_dying + cv_broadcast(&sc_cv) before ucom_detach() (full diff in fix.diff)",
  "fix_status": "fixed",
  "fix_baseline_reproduced": 1,
  "fix_patched_reproduced": 1,
  "fix_verdict": "fix.diff is git-apply-able against sys/ (git apply --check passes), the patched ufoma.c compiles -Werror-clean as a kmod on the guest, and harness Phase B runs the patched wait/detach pattern against the same production usb_proc drain machinery: drain 13000 ms -> 0 ms. Scope caveat: validation is mechanism+compile level; end-to-end with a physical crafted MCPC device is not possible on this guest (no such device can attach, DF-5359), and a rebuilt kernel would not alter the harness (it exercises usb_process, not ufoma).",
  "fix_evidence": "fix.diff (sha256 55437f6b...); run.log HX[B] ELAPSED=0 ms lines; compile of patched driver in run transcript; VERDICT.md Fix validation section"
}