DF-5487 / verdict.json
{ "finding_id": "DF-5487", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "Mechanism-level reproduction with production machinery (same evidence class as the proven family findings DF-5367/5383/5421/5424/5425/5449/5456/5476): uvisor_cfg_close() issues the drivers ONLY cfg-path EP0 request -- one CLOSE_NOTIFICATION vendor control-IN at a 1000 ms timeout with the usb_error_t discarded (uvisor.c:529-545, request at 539-540, error at 541-544) -- and close(2) waits for it uninterruptibly (ucom_queue_command -> usb_proc_mwait, usb_serial.c:671-672 + 955-957). uvisors cfg surface is the familys smallest: uvisor_cfg_open() is empty (uvisor.c:519-523, open chain = 0 requests + core hz/10 pause usb_serial.c:777) and there are no param/status/line callbacks (uvisor.c:224-231), so tcsetattr is free. Harness on the real usb_process taskqueue: a close(2) issued 50 ms behind an open blocks ELAPSED=1080/1093 ms across two runs (SIGKILL-immune) while the evil Visor NAKs the vendor data stage (WXFER cost, usb_request.c:642-644); unplug stalls the hub event thread identically via usb_proc_drain (usb_serial.c:394) plus the per-device enum lock (usb_request.c:467). Fix mechanism (UVISOR_CFG_TIMEOUT 250 ms bound) demonstrated at ELAPSED=346/363 ms and the fully patched production uvisor.ko compiled -Werror-clean RC=0 on the guest.", "exploit_chain": "Evil USB adapter with a Handspring/Palm VID:PID from uvisor_devs[] (e.g. HANDSPRING 082d:0100, uvisor.c:254) enumerates as uvisor and NAKs the CLOSE_NOTIFICATION vendor data stage -> the single cfg-close request eats its full 1000 ms timeout -> every close(2) of /dev/ttyUxx blocks ~1 s SIGKILL-immune behind usb_proc_mwait; yanking the device mid-cycle stalls the per-bus USB hub event thread the same ~1 s via ucom_detach -> usb_proc_drain; repeatable per open/close cycle but bounded at ~1 s -- the weakest member of the family (DF-5476 ~10 s, DF-5456 ~14 s, DF-5449 ~6.1 s, all Low).", "evidence": "run.log/run.2.log: HX5487[A]: closer: unblocked ELAPSED=1080 ms / 1093 ms (baseline) and HX5487[B]: ... ELAPSED=346 ms / 363 ms (fix mechanism); task-level trace shows cfg-open (EMPTY, 0 reqs + hz/10 pause) -> line tasks (0 reqs) -> cfg-close (1 x 1000 ms, error DISCARDED) with the closer in usb_proc_mwait throughout; build.log: -Werror kmod build; fix_compile.log: patched production uvisor.ko RC=0.", "kernel_refs": [ "sys/bus/u4b/serial/uvisor.c:529-545", "sys/bus/u4b/serial/uvisor.c:519-523", "sys/bus/u4b/serial/uvisor.c:224-231", "sys/bus/u4b/serial/usb_serial.c:671-672", "sys/bus/u4b/serial/usb_serial.c:955-957", "sys/bus/u4b/serial/usb_serial.c:394", "sys/bus/u4b/serial/usb_serial.h:220-221", "sys/bus/u4b/usb_request.c:642-644", "sys/bus/u4b/usb_request.c:467" ], "poc_changes": "No seed PoC existed; authored from scratch on the DF-5449 harness pattern with uvisors production chain shape (0 requests per open chain, 1 per close chain, 1000 ms). One bring-up iteration: none needed beyond the pattern (first build -Werror clean).", "attempts": 2, "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": 90, "guest_dirty": 0, "build_cmd": "cd /usr/src/sys/bus/u4b/serial/hx5487 && make (in-tree kmod build, -Werror clean; see build.sh)", "run_cmd": "kldload /root/df5487/uvisorcfgstall.ko; kldunload uvisorcfgstall; dmesg | grep HX5487 (see run.sh)", "code_hash": "f73a9c3d3bdaf1a272f02d82fdb0bb491d8b8dc0b30898a69fbc03fc0b2195d1", "notes": "Guest cleaned after runs (harness dirs removed, uvisor.c md5 restored/unchanged 28d0d390d06dd00f9dbfc03106b453a7). Severity Low, consistent with family: bounded ~1 s per close cycle, requires an evil/malfunctioning Visor-VID:PID device. Negative results recorded in VERDICT.md: no DF-5384-class detach-on-never-attached (ucom_detach guarded, usb_serial.c:376-377); no param/status chains to stall. fix.diff git-apply --check passes against the host repo tree.", "recommended_fix": "Bound the cfg-path control timeout to 250 ms (UVISOR_CFG_TIMEOUT) for the CLOSE_NOTIFICATION request (full diff in fix.diff).", "fix_status": "fixed", "fix_baseline_reproduced": 1, "fix_patched_reproduced": 1, "fix_verdict": "fix.diff applied to the guests /usr/src copy: the production uvisor.ko compiled -Werror-clean RC=0 (fix_compile.log); harness phase B models the fixed drivers timeout bound: closer ELAPSED drops from ~1.08-1.09 s to ~0.35-0.36 s across two runs. The full-second uninterruptible occupancy is GONE under the fix mechanism.", "fix_evidence": "fix.diff (sha256 f73a9c3d... is the harness; fix.diff itself verified by git apply --check on host + guest patch -p5); fix_compile.log (RC=0); run.log/run.2.log phase-B lines; VERDICT.md Fix validation." } |