# DF-5449 VERDICT — uvscom cfg-chain synchronous EP0 stall (family class)

**Status: REPRODUCED (production taskqueue machinery + production request
counts/timeouts) — impact: local DoS (uninterruptible close(2), hub-event-
thread stall on unplug); fix mechanism validated + patched module compiled
clean.**

## What was run

KLD-harness-with-production-code, identical evidence class to the proven
family findings DF-5367/5383/5421/5424/5425 (no SUNTAC VID:PID device model
exists for QEMU). The harness drives the **real in-kernel `usb_process`
machinery** (`usb_proc_create`/`msignal`/`mwait`) — the same taskqueue
(`sc_super_ucom.sc_tq`, usb_serial.c:322) that ucom's cfg callbacks run on
and that `ucom_close()`'s synchronous `usb_proc_mwait()`
(usb_serial.c:671-672, 955-957) and `ucom_detach()`'s `usb_proc_drain()`
(usb_serial.c:394) block on. Each timed-out EP0 vendor request is modeled by
its exact production cost: an `lksleep("WXFER", 1000 ms)`
(usb_request.c:642-644 + 699-704 — what a silent evil device that never
answers the data stage costs).

## The production chain being modeled (uvscom.c)

open(2), first open of the tty, queues in order:
1. `uvscom_cfg_open` → `uvscom_cfg_read_status` — 1× EP0 READ_STATUS,
   1000 ms timeout (uvscom.c:634-641, 714-734)
2. core pause hz/10 (usb_serial.c:777)
3. `uvscom_cfg_set_dtr` + `uvscom_cfg_set_rts` — 2× EP0 LINE_CTL writes
   (uvscom.c:470-497; queued by ucom_open:874 `ucom_modem(DTR|RTS)`)
4. `uvscom_cfg_set_break` — 1× EP0 LINE_CTL write (uvscom.c:499-512;
   queued by ucom_open:878 `ucom_break(sc,0)`)

= 4 × 1000 ms + 100 ms ≈ 4.1 s of uninterruptible taskqueue occupancy per
open. Errors from every request are **discarded** (uvscom.c:708-711,
729-732: `"...(ignored)"`), so the chain marches on through timeouts.

close(2) is synchronous against that queue: `ucom_shutdown()` HUPCL →
`uvscom_cfg_set_dtr(0)` 1 write (usb_serial.c:694-696), then cfg_close →
`uvscom_cfg_write(UVSCOM_SHUTDOWN)` 1 write (uvscom.c:643-651) with
`usb_proc_mwait()` — uninterruptible. Unplug mid-cycle stalls the USB hub
event thread the same way plus behind the per-device enum lock every request
holds (usb_request.c:467).

(The tcsetattr chain — 2 more writes — is currently dead due to the DF-5447
pre_param inversion; this harness models the open+close cycle that IS
reachable today. With DF-5447 fixed, each tcsetattr adds ~2.1 s,
user-amplifiable via the double-buffered sc_param_task[2].)

## Baseline (run.log, run.2.log)

```
HX5449[A]: closer: HUPCL line task + queue cfg_close + usb_proc_mwait()
           (uninterruptible, usb_serial.c:671-672) behind the open chain
HX5449[A]: closer: unblocked  ELAPSED=5932 ms     (run 1)
HX5449[A]: closer: unblocked  ELAPSED=5929 ms     (run 2)
```

≈ 5.9-6.1 s of SIGKILL-immune block for a close(2) racing an open(2)
(hz=100 tick rounding explains the delta from the theoretical 6100 ms).
Task-level traces in the log show the exact production shape:
cfg-open(READ_STATUS) → line DTR+RTS → line BREAK → HUPCL → cfg-close.

## Fix validation

`fix.diff` (error propagation: `uvscom_cfg_write` returns `usb_error_t`;
`uvscom_cfg_param` aborts after the first failed request; cfg-path control
timeout bounded 1000 → 250 ms):

- Applied to the guest's /usr/src copy (on top of the DF-5447 fix, hunks
  offset cleanly), the **production uvscom.ko module compiled -Werror
  clean, RC=0** (fix_compile.log).
- Harness phase B models the fixed driver (abort-on-first-error + 250 ms):

```
HX5449[B]: closer: unblocked  ELAPSED=1285 ms     (run 1)
HX5449[B]: closer: unblocked  ELAPSED=1277 ms     (run 2)
```

≈ 1.3 s vs ≈ 5.9 s baseline — the previously-observed multi-second
uninterruptible occupancy collapses. Baseline vs patched both recorded.

## Honest scope notes

- The harness models the *device-side* timing (a request the device never
  answers) because no SUNTAC hardware model exists; everything on the
  kernel side (taskqueue, double-buffered messages, uninterruptible mwait,
  drain semantics, production request counts and timeouts) is the real
  in-kernel production code path.
- The closer's HUPCL task uses a dedicated message buffer; production
  re-uses the line-state double buffer, which *can* merge it with a still-
  pending open task (shortening the worst case to ~5.1 s). The recorded
  5.9 s is the unmerged worst case.
- Severity Low, consistent with the family (DF-5424 uftdi ~5.2 s open /
  DF-5425 uslcom ~8.2 s close, both Low): exposure requires a malicious or
  malfunctioning USB device with a SUNTAC VID:PID, or physical possession
  of an adapter, and the block is bounded (~6.1 s per open+close cycle).

## Environment

env.txt: DragonFly 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026,
X86_64_GENERIC, cc 8.3. Guest left pristine (uvscom.c md5
a58a99ef02d63a2d2e7f7b661f5224b3 restored; harness dirs and scratch
removed; no leftover KLDs — kldstat shows only kernel + ehci + xhci).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
