# DF-2959 — clist_qtob called with unclamped `len` in ucom_get_data TX path (heap OOB write, latent)

## What

`sys/bus/u4b/serial/usb_serial.c` `ucom_get_data()` (the tty→USB data pump):

```c
1898        usbd_get_page(pc, offset, &res);
1899
1900        /* Buffer bigger than max requested data */
1901        if (res.length > len) {
1902            res.length = len;              /* segment clamped to request */
1903        }
1904        /* copy data directly into USB buffer */
1905        SET(tp->t_state, TS_BUSY);
1906        cnt = clist_qtob(&tp->t_outq, res.buffer, len);   /* BUG: len, not res.length */
```

`usbd_get_page()` (sys/bus/u4b/usb_busdma.c:80-125) returns the contiguous
segment starting at `offset`:

* single-segment DMA buffer (`ismultiseg == 0`): `res.length = (usb_size_t)-1`
  → after the clamp it equals `len` → harmless;
* multi-segment / page-scattered cache (`ismultiseg != 0`):
  `res.length = USB_PAGE_SIZE - (offset % USB_PAGE_SIZE)` — as short as
  **1 byte**;
* Case 1b (`pc->buffer == NULL`): `res.buffer = page->buffer + offset` — a
  per-USB-page buffer allocation, NOT part of one large KVA mapping.

`clist_qtob()` (sys/kern/tty_subr.c:127-149) copies `n = min(len, c_cc)`
bytes of tty output data to `res.buffer` and returns the count. Passing the
**uncapped `len`** (the driver's whole bulk-out buffer size, e.g.
`UPLCOM_BULK_BUF_SIZE` at uplcom.c:838) instead of the clamped
`res.length` makes the copy run past the contiguous segment whenever
`t_outq.c_cc > res.length` — writing attacker-supplied tty bytes (whatever
the user `write()`d to /dev/ttyU*) past the end of a USB page buffer
(heap OOB write, length up to `len - res.length`, content and timing
attacker-controlled). The RX twin in the same file (usb_serial.c:2004-2032)
does it correctly: `buf = res.buffer; cnt = res.length; clist_btoq(buf, cnt, …)`,
confirming the TX line is a defect, not a design choice.

## Reachability (honest)

* Requires a USB serial adapter attached and its /dev/ttyU* open (driver
  runs ucom_get_data from the bulk-out TX callback). No privileged ioctl is
  involved — any user able to write the device node triggers the copy.
* In the common x86 configuration the serial drivers allocate a
  single-segment (≤1 page) bulk buffer → `ismultiseg == 0` →
  `res.length = -1` → clamp makes `res.length == len` → **bug masked**.
  The overflow needs a multi-segment (page-scattered / multi-page) TX page
  cache or a Case-1b (non-KVA) buffer, which the stock serial drivers do
  not normally produce. Treated as a latent heap-overflow / correctness
  defect (the clamp exists and is then ignored), not a demonstrated
  exploit path.
* QEMU guest: `ucom.ko`/`uplcom.ko`/`uftdi.ko` are present but no USB
  hardware is attached (`ls /dev/ttyU*` → No such file or directory), so the
  path cannot be exercised on the audit guest.

## Fix

Pass the clamped segment length (see fix.diff — mirrors the RX path).

## Reproduce

Static-analysis finding; no runnable trigger was possible on the audit
guest (no USB device). See VERDICT.md.
