# DF-5456 — umoscom(4) cfg callbacks chain 14 sequential 1000 ms-timeout EP0 vendor requests with discarded errors on first open (4 param + 5 open + 3 line-state + 2 status): evil MCS7703 stretches one open(2) to ~14.2 s of uninterruptible ucom-taskqueue occupancy, blocks close(2) SIGKILL-immune behind it, stalls the USB hub event thread on unplug, and every later tcsetattr adds ~4.1 s (user-amplifiable)

Production file: `sys/bus/u4b/serial/umoscom.c`. Evidence class:
**KLD-harness-with-production-code** (no MCS7703 device model on the QEMU
guest; same rig family as DF-5425 uslcom / DF-5424 uftdi / DF-5449 uvscom).

## What the harness is

`mo5456stall_harness.c` drives the REAL in-kernel u4b `usb_process`
machinery (`usb_proc_create`/`msignal`/`mwait`/`drain`) — the same
taskqueue ucom's cfg callbacks run on — with umoscom's exact production
request counts and the production 1000 ms per-request timeout. Each
"request" is one `lksleep("WXFER", 1000ms)`, the exact production cost of
an EP0 data/status stage an evil device never answers
(usb_request.c:642-644, 699-704).

## Build

```
sh build.sh     # /usr/src/sys/bus/u4b/serial/mo5456 + make (in-tree kmod)
```

## Run

```
sh run.sh       # kldload umoscomcfgstall.ko (all phases at MOD_LOAD); dmesg
```

## Expected (decisive) output

```
MO5456[A]:  closer: unblocked  ELAPSED=13922 ms   first-open chain + close(2)
MO5456[2]:  closer: unblocked  ELAPSED=17923 ms   + 1 extra user tcsetattr
MO5456[B]:  closer: unblocked  ELAPSED=4109 ms    fix #1: abort on first error
MO5456[C]:  closer: unblocked  ELAPSED=1229 ms    fix #1+#2: abort + 250 ms
```

Production chain accounting (first open, evil silent device):

| task | queued at | requests | umoscom.c |
|---|---|---|---|
| cfg_param | usb_serial.c:842 | 4 × write | :454,:457,:460,:492 (+hz/10 pause :1636) |
| cfg_open | usb_serial.c:865 | 5 × write | :368,:371,:377,:380,:383 (+hz/10 pause :777) |
| line-state | usb_serial.c:874-878 | 3 × write | :415 (DTR), :428 (RTS), :402 (BREAK-off) |
| status | usb_serial.c:880 | 2 × read | :506 (LSR), :507 (MSR) |
| **total** | | **14 × 1000 ms + 2 × 100 ms** | ≈ **14.2 s** |

Every later tcsetattr re-queues cfg_param (double-buffered,
usb_serial.c:1691-1693): +4.1 s each, unprivileged-user amplification.
close(2) is synchronous against the queue (`ucom_queue_command` →
`usb_proc_mwait`, usb_serial.c:671-672 + 955-957, uninterruptible
`cv_wait` per usb_process.c:385-393) — umoscom_cfg_close itself is a
no-op (umoscom.c:386-390), so the closer purely waits out what is queued
in front of it. Unplug mid-cycle stalls the USB hub event thread via
`ucom_detach()` → `usb_proc_drain()` (usb_serial.c:394). A
slow-but-answer-at-999 ms evil device makes every request *succeed*
with no error at all — same occupancy, no error to propagate.

## Fix

`fix.diff` — bound the cfg-path control timeout (1000 → 250 ms via
`UMOSCOM_CFG_TIMEOUT`), make `umoscom_cfg_write()` return the
`usb_error_t`, abort the cfg_open/cfg_param chains on the first failed
request (divisor-latch safety preserved: the final LCR write still closes
the latch whenever execution gets past it). Runtime mechanism validated
by phases B/C; patched `umoscom.ko` builds -Werror-clean
(`fix_compile.log`, RC=0).
