DF-5476 / verdict.json
{ "finding_id": "DF-5476", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "REPRODUCED on the guest (KLD-harness-with-production-code class; no Belkin F5U103/eTek/GoHubs/Peracom device model exists): every ubsa cfg-callback step is a synchronous EP0 vendor write via ucom_cfg_do_request with a 1000 ms timeout (ubsa.c:359-360) whose usb_error_t is discarded at the only site (ubsa.c:361-364, (ignored)), so no chain aborts on device failure. Pass-2 accounting precision: the first-open cfg_param task is queued before ucom_cfg_open (usb_serial.c:842 vs :865) and bails at :1626-1628 (!LL_READY) -- first-open param is a no-op for every ucom driver -- and ubsa registers no ucom_cfg_open (:777 pause skipped), so first open issues only the coalesced line-state chain DTR+RTS+BREAK-off = 3 x 1000 ms (ubsa.c:374,:384,:394); measured closer block 2877 ms. Every later tcsetattr re-queues the param task (double-buffered, usb_serial.c:1691-1693): 5 x 1000 ms + hz/10 core pause (:1636) = ~5.1 s, or 7 x 1000 ms + pause = ~7.1 s for the B0 hangup variant (case B0 falls through to parity/data/stop/flow, ubsa.c:432-492); measured closer block 7893 ms (one 9600 tcsetattr) and 9974 ms (one B0 tcsetattr) behind first open -- uninterruptible per usb_serial.c:671-672+955-957 / usb_process.c:364-393, ubsa_cfg_close being a 0-request no-op (no callback registered, ubsa.c:216-228). Unplug mid-cycle pins the USB hub event thread identically via ucom_detach->usb_proc_drain (usb_serial.c:394). Each simulated request is the real in-kernel cost of an unanswered EP0 data/status stage (lksleep WXFER 1000 ms, usb_request.c:643/700-704) on the real usb_process taskqueue, per-request unique wait channel (production sleeps on the unique xfer pointer). Fix mechanisms validated at runtime: abort-on-first-error 2035 ms (B), abort+250 ms bound 557 ms (C); patched production ubsa.ko compiles 9/9 hunks clean.", "exploit_chain": "evil adapter (Belkin 050d:0001/0002, eTek 057e:0002, GoHubs 1002:0002/08ff, Peracom 0565:0001, AnyData, Axesstel) inserted; it never answers EP0 vendor data/status stages (or answers at just-under-timeout, making every request succeed with no error anywhere); first open(2) of /dev/ttyUx occupies the adapters ucom taskqueue ~3.0 s uninterruptibly; every tcsetattr adds 5.1 s (7.1 s with B0) while a session holds the tty open (user-amplifiable to arbitrary multiples); close(2) blocks SIGKILL-immune behind the queue (measured 9.97 s with one queued B0 tcsetattr); pulling the device mid-cycle stalls the USB hub event thread up to the same duration per cycle.", "evidence": "run.log ELAPSED lines: UB5476[A]=2877 ms, [2]=7893 ms, [0]=9974 ms (B0), [B]=2035 ms (fix abort), [C]=557 ms (fix abort+250ms), plus absolute per-request START timestamps showing every request sleeping its full ~990 ms (A3s seven B0 requests at 3070/4052/5042/6042/7032/8032/9022 ms); build.log (-Werror-clean in-tree kmod build); fix_compile.log (9/9 hunks, patched production ubsa.ko, zero compiler warnings).", "kernel_refs": [ "sys/bus/u4b/serial/ubsa.c:346-365", "sys/bus/u4b/serial/ubsa.c:359-360", "sys/bus/u4b/serial/ubsa.c:361-364", "sys/bus/u4b/serial/ubsa.c:374", "sys/bus/u4b/serial/ubsa.c:384", "sys/bus/u4b/serial/ubsa.c:394", "sys/bus/u4b/serial/ubsa.c:424-492", "sys/bus/u4b/serial/ubsa.c:433-435", "sys/bus/u4b/serial/ubsa.c:449", "sys/bus/u4b/serial/ubsa.c:460", "sys/bus/u4b/serial/ubsa.c:478", "sys/bus/u4b/serial/ubsa.c:482", "sys/bus/u4b/serial/ubsa.c:491", "sys/bus/u4b/serial/ubsa.c:535-543", "sys/bus/u4b/serial/usb_serial.c:671-672", "sys/bus/u4b/serial/usb_serial.c:771-778", "sys/bus/u4b/serial/usb_serial.c:842", "sys/bus/u4b/serial/usb_serial.c:865", "sys/bus/u4b/serial/usb_serial.c:874-880", "sys/bus/u4b/serial/usb_serial.c:939-957", "sys/bus/u4b/serial/usb_serial.c:394", "sys/bus/u4b/serial/usb_serial.c:1357-1420", "sys/bus/u4b/serial/usb_serial.c:1620-1637", "sys/bus/u4b/serial/usb_serial.c:1691-1693", "sys/bus/u4b/usb_request.c:643", "sys/bus/u4b/usb_request.c:700-704", "sys/bus/u4b/usb_process.c:364-393" ], "poc_changes": "Seed concept executed as the DF-5425/5456 family rig adapted to ubsas exact production shapes: 3/5/7-request chains (line-state / tcsetattr / tcsetattr(B0) with its fall-through-past-the-switch accounting), 0-request open/status/close tasks, the production LL_READY gate that makes the first-open param task bail (usb_serial.c:1626-1628 -- a pass-2 precision the earlier sibling accounting missed), absent core open-pause (no callback), production 1000 ms timeout, real usb_proc machinery, closer mirroring ucom_closes synchronous usb_proc_mwait entered ~150 ms into the chain. Harness v1 fidelity bug caught by absolute-timestamp instrumentation and fixed: simulated requests must sleep on a UNIQUE per-request wait channel (production sleeps on the unique xfer pointer, usb_request.c:643), not on the lock address, or unrelated lockmgr handoffs wake them early (~9 ms instead of 1000 ms).", "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": 30, "guest_dirty": 1, "build_cmd": "sh build.sh (cd /usr/src/sys/bus/u4b/serial/ub5476 && make; artifacts: ubsa5476stall.ko)", "run_cmd": "sh run.sh (dmesg -c; kldload /root/df5476/ubsa5476stall.ko; kldunload ubsa5476stall; dmesg | grep UB5476 | tee /root/df5476/run.log)", "code_hash": "55f61101fbfcdd0cedda62183951d3dd1e5acc88489b2ce252bc7e30a0b0e913", "notes": "Low severity per family precedent (evil-USB precondition, seconds-scale, cf. DF-5421 uchcom / DF-5424 uftdi / DF-5425 uslcom / DF-5449 uvscom / DF-5456 umoscom). B0 variant (7 reqs) is ubsas heaviest per-tcsetattr chain. Negative results this pass: ubsa issues ZERO control-IN reads anywhere (the DF-5455/DF-5448 uninit-read class is structurally absent, ubsa.c:346-365 UT_WRITE_VENDOR_DEVICE/wLength=0/data=NULL); ubsa_intr_callback has the CORRECT >=4-byte gate before consuming the 4-byte status payload (ubsa.c:620) unlike ulpt DF-5438; the B230400/c_ospeed division (ubsa.c:448) is switch-gated to {300..230400} by pre_param+cfg_param cases (no umcs DF-1048-class div-by-zero); attach/detach error paths safe (ucom_detach no-ops unless ATTACHED, usb_serial.c:371-372; ucom_attach self-cleans :344-348). Guest reset (with-src) after the run.", "recommended_fix": "Bound the cfg-path control timeout (UBSA_CFG_TIMEOUT 250 ms) and abort the ubsa_cfg_param() chain on the first failed request via an error-returning ubsa_cfg_request() (full diff in fix.diff).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 1, "fix_verdict": "Mechanism-level validation per family standard: harness phase B (abort-on-first-error) cuts the measured closer block from 9974 ms to 2035 ms and phase C (abort + 250 ms bound) to 557 ms; the 9-hunk fix.diff (error-returning ubsa_cfg_request, chain aborts, bounded UBSA_CFG_TIMEOUT) applies 9/9 clean and compiles the patched production ubsa.ko with zero compiler warnings on the guest (fix_compile.log). A full patched-kernel boot is not required to observe a per-request timeout bound + early-abort behavior the harness exercises directly.", "fix_evidence": "fix.diff (sha256 93d6d19a2b6c255b43fb0bb1ff860724550aae9a17323c4b545001bb3965898b); fix_compile.log (patched production ubsa.ko, only makes Object directory not changed notice, no compiler diagnostics); run.log phases B/C ELAPSED lines." } |