# DF-5447 — uvscom_pre_param() inverted switch: every baud rate (including all
# 11 supported ones) is rejected with EINVAL

## The bug (production code, sys/bus/u4b/serial/uvscom.c:514-533)

```c
static int
uvscom_pre_param(struct ucom_softc *ucom, struct termios *t)
{
	switch (t->c_ospeed) {
		case B150:
		case B300:
		...
		case B115200:
		default:
		return (EINVAL);      <-- EVERY path, supported speeds included
	}
	return (0);                       <-- unreachable (dead code)
}
```

All eleven case labels (the exact speeds the hardware supports and that
`uvscom_cfg_param()` uvscom.c:543-579 knows how to program) fall straight into
`return (EINVAL)`. The trailing `return (0)` is unreachable. This is a
transcription inversion of the NetBSD original (NetBSD uvscom.c
`uvscom_pre_param` returns 0 for the listed speeds and EINVAL only for
`default:`).

## Impact

`ucom_param()` (sys/bus/u4b/serial/usb_serial.c:1678-1684) uses the
`ucom_pre_param` callback to validate termios and **bails out with the error
before queueing `ucom_cfg_param`** (usb_serial.c:1691-1693). Consequence on a
live uvscom adapter:

- every `tcsetattr(2)` / TIOCSETA on /dev/ttyU0.* (or the cua device) fails
  with EINVAL — the port can never be programmed (baud, parity, stop bits);
- `ucom_open()`'s own initial programming call (usb_serial.c:842,
  `ucom_param(tp, &t)`, error discarded) also fails silently, so
  `uvscom_cfg_param()` **never executes at all** — the device is never given
  UVSCOM_SET_SPEED / UVSCOM_SET_PARAM (uvscom.c:581,614);
- the tty is stuck at the default termios forever. Fails closed (EINVAL), no
  memory-safety impact — a functional kill of the serial port.

An attacker who supplies a crafted "SUNTAC" USB adapter (or a user of a real
one) gets a /dev/ttyU0 that silently never works: every stty fails. Driver is
dead weight for its entire user base.

## Evidence class

No SUNTAC VID:PID device model exists for the QEMU guest —
**KLD-harness-with-production-code**: the harness `#include`s the production
`sys/bus/u4b/serial/uvscom.c` verbatim (module-registration macros neutered so
it does not double-register on uhub) and calls the *real, static*
`uvscom_pre_param()` for every supported speed. Baseline: all return EINVAL.
After fix.diff: supported speeds return 0, B230400 returns EINVAL.

## Reproduce

```
./build.sh    # in-tree kmod build: cd /usr/src/sys/bus/u4b/serial/hx5447 && make
./run.sh      # kldload the harness; dmesg shows per-speed results
```

Expected baseline dmesg: `UVS5447[A]: pre_param(B9600) = 35 (EINVAL)` for ALL
eleven supported speeds, `UVS5447[A]: SUPPORTED speeds accepted: 0/11 (BUG)`.
Expected after fix.diff (phase B rerun): `accepted: 11/11`, B230400 = EINVAL.

## Files
- `uvscom_preparam_harness.c` — production-code KLD harness
- `Makefile`, `build.sh`, `run.sh`
- `build.log`, `run.log`, `run.fixed.log` — full untrimmed output
- `fix.diff` — git-apply-able fix (restore intended switch)
- `VERDICT.md`, `manifest.json`, `verdict.json`
