⬢ DragonFlyBSD Kernel Audit
DF-5421 / verdict.json
← back to finding ↓ download raw
{
  "finding_id": "DF-5421",
  "status": "reproduced",
  "reproduced": true,
  "impact": "dos",
  "confidence": "certain",
  "verdict": "Mechanism-level reproduction with production machinery: uchcom_cfg_param() (uchcom.c:652-666) chains 12 sequential synchronous EP0 vendor requests per tcsetattr and uchcom_cfg_open() (uchcom.c:622-631) 2 more per open(2), each via void helpers that discard the usb_error_t of a 1000 ms-timeout control transfer (uchcom.c:369-399, 381-382, 397-398), so no step ever aborts. An evil CH340/CH341 (VID/PID-only probe, uchcom.c:193-196, 293) that never answers the control data stage makes each request eat its full timeout (usb_request.c:642-644, 699-704): ~12.1 s occupancy of the per-adapter ucom taskqueue per tcsetattr. A harness on the production usb_proc_create/msignal/mwait machinery, with uchcoms exact request counts and per-request cost, shows the closer thread (ucom_closes synchronous usb_proc_mwait, usb_serial.c:671-672+955-957, uninterruptible cv_wait usb_process.c:385-393) blocked 13888/13887 ms behind open+1 tcsetattr and 25772/25767 ms behind open+2 tcsetattr (local amplification via the sc_param_task double buffer, usb_serial.c:1691-1693); unplug mid-cycle stalls the USB hub event thread identically via ucom_detachs usb_proc_drain (usb_serial.c:394) -- the DF-5367 mechanism, uchcom instance. fix.diff (error propagation + chain abort) measures 2101/2132 ms and compiles -Werror-clean as the production uchcom.ko. No CH341 device model exists on the guest, hence the KLD-harness evidence class; no memory corruption (ucom_pre_param validates the rate before cfg_param runs, so the divisor math is never fed garbage).",
  "exploit_chain": "evil USB device with WCH CH340/CH341 VID/PID enumerates as uchcom, then never answers vendor control data stages -> open(/dev/cuaU*) queues cfg_open (~2.1 s); every tcsetattr costs ~12.1 s of sc_tq occupancy; close(2) blocks uninterruptibly behind queued tasks (~14 s single cycle, ~26 s with two queued tsetattrs); unplug during a cycle pins the per-bus USB hub event thread via usb_proc_drain for the in-flight chain (~12 s); an unprivileged user with the tty open repeats indefinitely. Availability-only impact.",
  "evidence": "run.log/run.2.log lines HX5421[A]: closer: unblocked ELAPSED=13888/13887 ms, HX5421[2]: ... 25772/25767 ms, HX5421[B]: ... 2101/2132 ms; VERDICT.md tables all 12+2 requests with uchcom.c line cites and traces the close/unplug blocking path; build.log/fix_compile.log show -Werror-clean builds of harness and patched production driver",
  "kernel_refs": [
    "sys/bus/u4b/serial/uchcom.c:652-666",
    "sys/bus/u4b/serial/uchcom.c:622-631",
    "sys/bus/u4b/serial/uchcom.c:369-399",
    "sys/bus/u4b/serial/uchcom.c:578-584",
    "sys/bus/u4b/serial/usb_serial.c:671-672",
    "sys/bus/u4b/serial/usb_serial.c:1691-1693",
    "sys/bus/u4b/serial/usb_serial.c:394",
    "sys/bus/u4b/usb_request.c:642-644",
    "sys/bus/u4b/usb_request.c:699-704",
    "sys/bus/u4b/usb_process.c:385-393"
  ],
  "poc_changes": "No seed PoC existed; authored from scratch on the DF-5367/DF-5383 harness pattern. Two fixes during bring-up: (1) -Werror unused-function -> wired cfg_open into every phase (production open->tcsetattr->close shape, which strengthened the demo); (2) phase B initially modeled the aborting request as instant (137 ms) which overstated the fix -> corrected to charge the one real 1000 ms timeout before abort (B~2.1 s).",
  "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/hx5421 && make (in-tree kmod build, -Werror clean; see build.sh)",
  "run_cmd": "kldload /root/df5421/uchcomcfgstall.ko; kldunload uchcomcfgstall; dmesg | grep HX5421 (see run.sh)",
  "code_hash": "e876ac3b69176448395b0ec3679251496d598270780ed66b3346910a06e2d888",
  "notes": "Guest cleaned after runs (scratch + in-tree hx5421 dir removed, /usr/src uchcom.c md5-verified pristine 3616dd7e880405bb1eeb0271b4be6712, no harness klds loaded). Severity Low, consistent with the family calibration (DF-5367 16-18 s Low, DF-5383 16 s Low; DF-5407 is Medium because uplcom pins the SHARED bus explore thread at attach for ~70 s -- uchcom defers all requests to cfg time and pins only its per-adapter tq plus the hub thread during drain).",
  "recommended_fix": "Propagate usb_error_t through the uchcom vendor-request helpers and abort cfg_param/cfg_open on the first failed request (full diff in fix.diff); optionally also bound the cfg-path control timeout (1000 -> 100-250 ms) to cover slow-but-successful evil devices",
  "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, host repo); the patched production driver compiles -Werror-clean as the in-tree uchcom.ko kmod on the guest (fix_compile.log RC=0, uchcom.ko produced); harness phase B with the abort-on-first-error mechanism measures the closer block at 2101/2132 ms vs 13888/25772 ms baseline (12.1 s per chain -> ~1.1 s per chain against a silent device). Scope caveat: mechanism + compile level; end-to-end with a physical crafted CH341 is not possible on this guest (no device model); the slow-but-successful-device variant additionally needs the timeout bound noted in recommended_fix.",
  "fix_evidence": "fix.diff (sha256 5f7d53dc6a251fa0276a8253b84df6d1aff7f13f9d484a1ec523a16efee7ec83); fix_compile.log; run.log/run.2.log HX5421[B]: closer: unblocked ELAPSED=2101/2132 ms; VERDICT.md Fix validation section"
}