DF-5456 / verdict.json
{ "finding_id": "DF-5456", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "REPRODUCED on the guest (KLD-harness-with-production-code class; no MCS7703 device model exists): every umoscom cfg-callback step is a synchronous EP0 vendor request via ucom_cfg_do_request (1000 ms timeout) whose usb_error_t is discarded at every call site (umoscom.c:524-557), so no chain aborts on device failure. The first-open chain queues 14 sequential 1000 ms requests + 2 x hz/10 pauses on the per-adapter ucom taskqueue: cfg_param 4 writes (umoscom.c:454,457,460,492 + pause usb_serial.c:1636), cfg_open 5 writes (:368,371,377,380,383 + pause :777), line-state 3 writes (:415,:428,:402), status 2 reads (:506,:507). With the real in-kernel usb_process machinery and the exact per-request cost of an unanswered EP0 data stage (lksleep WXFER 1000 ms, usb_request.c:642-644/699-704), the synchronous close(2) behind one first open blocked 13922 ms (A) and 17923 ms with one extra user tcsetattr behind it (A2, double-buffered param task usb_serial.c:1691-1693) -- uninterruptible per usb_serial.c:671-672+955-957 / usb_process.c:385-393, umoscom_cfg_close itself being a no-op (umoscom.c:386-390). Unplug mid-cycle pins the hub event thread identically via ucom_detach->usb_proc_drain (usb_serial.c:394). A device answering at just-under-timeout makes every request succeed with no error to propagate. Fix mechanisms validated at runtime: abort-on-first-error 4109 ms (B), abort+250 ms bound 1229 ms (C).", "exploit_chain": "evil MCS7703 (0x9710:0x7703) inserted; it never answers EP0 vendor data/status stages; every open(2) of /dev/ttyUx occupies the adapters ucom taskqueue ~14.2 s uninterruptibly; close(2) and TIOCMSET/tcsetattr pile up behind it (each tcsetattr +4.1 s, user-amplifiable); pulling the device mid-cycle stalls the USB hub event thread up to the same ~14-18 s per cycle.", "evidence": "run.log ELAPSED lines: MO5456[A]=13922 ms, MO5456[2]=17923 ms, MO5456[B]=4109 ms (fix abort), MO5456[C]=1229 ms (fix abort+250ms), plus full per-task request-accounting traces; build.log (-Werror-clean in-tree kmod build); fix_compile.log RC=0 (11-hunk patched umoscom.ko).", "kernel_refs": [ "sys/bus/u4b/serial/umoscom.c:441-493", "sys/bus/u4b/serial/umoscom.c:361-384", "sys/bus/u4b/serial/umoscom.c:386-390", "sys/bus/u4b/serial/umoscom.c:495-522", "sys/bus/u4b/serial/umoscom.c:524-557", "sys/bus/u4b/serial/usb_serial.c:801-903", "sys/bus/u4b/serial/usb_serial.c:842", "sys/bus/u4b/serial/usb_serial.c:865-880", "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": "Seed concept executed as the DF-5425 family rig: umoscoms exact production counts (4/5/3/2/0 requests per param/open/line-state/status/close task), production first-open queueing order (usb_serial.c:842 param, :865 open, :874-878 line, :880 status), production 1000 ms timeout, real usb_proc_create/msignal/mwait machinery, and the closer mirroring ucom_closes synchronous usb_proc_mwait.", "attempts": 1, "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": 38, "guest_dirty": 1, "build_cmd": "sh build.sh (cd /usr/src/sys/bus/u4b/serial/mo5456 && make; artifacts: umoscomcfgstall.ko)", "run_cmd": "sh run.sh (kldload /root/df5456/umoscomcfgstall.ko; kldunload umoscomcfgstall; dmesg | grep MO5456 | tee run.log)", "code_hash": "7f2ea80509214033c2421c2df892e5d670b097f1dc5413743288659943200020", "notes": "Largest 1000 ms-timeout cfg chain measured in the family this pass (14 requests vs uslcom/uftdi/uvscom 5-6); still Low severity per family precedent (evil-USB precondition, tens-of-seconds scale, not uplcoms 70 s). Guest reset (with-src) after the run.", "recommended_fix": "Bound the cfg-path control timeout (UMOSCOM_CFG_TIMEOUT 250 ms), make umoscom_cfg_write() return the error and abort the cfg_open/cfg_param chains on first failure (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 13922 ms to 4109 ms and phase C (abort + 250 ms bound) to 1229 ms; the 11-hunk fix.diff (error-propagating cfg_write, chain aborts with divisor-latch safety, bounded timeout) compiles the patched production umoscom.ko -Werror-clean RC=0 on the guest (fix_compile.log). A full patched-kernel boot is not required to observe a per-request timeout bound + early-abort behavior that the harness exercises directly.", "fix_evidence": "fix.diff (sha256 a967419288b03465a9174dacc32a35db32056a6fa061ec3e99865d7d5ed4beb4); fix_compile.log (RC=0); run.log phases B/C ELAPSED lines." } |