# DF-2356 — Unvalidated hardware frame length in RX (sys/bus/u4b/wlan/if_rum.c)

## Verdict: NOT REPRODUCED (HW-gated); REAL BUG IN SOURCE (defense-in-depth fix warranted)

## Hardware gate (why the PoC cannot run on this guest)

`rum` is the Ralink RT2501USB/RT2601USB 802.11bgn driver. It attaches only when
a matching Ralink USB wifi dongle (VID 0x148f / 0x0411 etc.) is plugged in. The
audit QEMU/KVM guest has **no USB device and no wifi interface**:

```
$ usbconfig list               # No device match or lack of permissions.
$ ifconfig -l                  # vtnet0 lo0   (no wlan/rum)
$ pciconf -l | grep -iE "ralink|148f"   # (no Ralink USB wifi chip)
$ kldstat                      # kernel + ehci.ko + xhci.ko only
```

The RX path `rum_bulk_read_callback` runs only when the `rum` driver has
attached to a Ralink USB device and is receiving frames. With no such device the
path never executes. The unprivileged `maxx` user cannot plug a USB dongle into
the QEMU guest, and there is no adjacent rogue AP threat (no radio at all).

## Source trace — the bug is REAL (sys/bus/u4b/wlan/if_rum.c)

In `rum_bulk_read_callback` (`if_rum.c:1127-...`):
```c
usbd_xfer_status(xfer, &len, NULL, NULL, NULL);          /* actual USB xfer len */
...
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) goto tr_setup;
len -= RT2573_RX_DESC_SIZE;                              /* if_rum.c:1157 */
...
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);                /* if_rum.c:1198, cluster=MCLBYTES=2048, NOT zeroed */
usbd_copy_out(pc, RT2573_RX_DESC_SIZE, mtod(m, uint8_t *), len);  /* if_rum.c:1208 — bounded to <=2048 */
...
flags = le32toh(sc->sc_rx_desc.flags);                   /* device-controlled */
...
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;      /* if_rum.c:1221 — device-controlled 12-bit, max 4095 */
```

The descriptor's 12-bit length field (`(flags >> 16) & 0xfff`, range 0-4095) is
taken **directly from the device RX descriptor** and assigned to the mbuf's
`m_len`/`m_pkthdr.len` with **no comparison against the actual USB transfer
length `len` or the cluster capacity MCLBYTES (2048)**. `usbd_copy_out` only
wrote `len` (≤ 2048) bytes into the non-zeroed cluster. Two consequences:

1. Offsets `[len, m_len)` (when `m_len > len`) read **uninitialised cluster
   memory** — stale kernel heap exposed to `ieee80211_input`, radiotap and bpf
   listeners (`/dev/bpf*`, monitor mode) — an info leak.
2. Offsets `[MCLBYTES, m_len)` (when `m_len > 2048`, possible since the field
   max is 4095) are a **heap OOB read past the cluster allocation** into
   adjacent slab objects.

Both sibling Ralink drivers close exactly this hole:
- `if_mtw.c:2488` — `if (__predict_false(len > dmalen - rxwisize)) goto fail;`
- `if_run.c:2783` — `if (__predict_false(len > dmalen))` clamp.

Attacker: a malicious USB device presenting Ralink VID/PID, or a wireless
adjacent-network rogue AP sending crafted frames; `/dev/wlan0` monitor mode +
bpf/tcpdump harvests leaked kernel heap bytes.

## Exploit chain status

Not pursuable — primitive (heap OOB read / uninit info leak) requires a Ralink
USB wifi dongle or adjacent radio (absent) — valid Phase-6 hard blocker: dead
path at runtime on this guest. Read-only primitive; no escalation.

## PoC changes

None. No Ralink USB wifi dongle on guest; verified by source trace only.

## Recommended fix

Clamp the mbuf length to `min(device_reported_len, len)` (and to MCLBYTES),
matching the sibling drivers' guard. See `fix.diff` (matches finding proposal:
add the `len > dmalen`-style guard rum's siblings already have).
