# DF-2357 — Wrong TX frame-size bound causes 16-byte overflow of USB DMA buffer

`sys/bus/u4b/wlan/if_rum.c` — `rum_bulk_write_callback` (lines 1057-1065)

## What this pack proves

Driving the **verbatim, sha256-gated** `if_rum.c` (compiled into a kernel
module with only the USB transfer-engine and node-completion externals
interposed) through the real raw-xmit chain
(`rum_raw_xmit` -> `rum_tx_raw` -> `tx_q` -> `rum_bulk_write_callback`
-> **real** `usbd_copy_in` / `usbd_m_copy_in` into an instrumented
2080-byte DMA buffer with canary):

| frame len | stock driver behavior | fixed driver behavior |
|-----------|------------------------|-----------------------|
| 2048      | sent, submit_len 2072, canary clean            | identical (bit-identical zone) |
| 2056      | sent, submit_len 2080 == bufsize, canary clean | identical (bit-identical zone) |
| 2057      | **1 byte past buffer** (0x6f = frame byte 2056, attacker pattern) | dropped, canary clean |
| 2060      | **4 bytes past buffer**                        | dropped |
| 2064      | **8 bytes past buffer**                        | dropped |
| 2072      | **16 bytes past buffer**, submit_len 2096 > 2080 | dropped |
| 2073      | truncated to 2072 -> **16 bytes past**         | dropped |
| 2346      | truncated to 2072 -> **16 bytes past**         | dropped |
| direct callback, 3000 | clamped to 2072 -> **16 bytes past** | dropped |

The canary bytes are exactly the frame pattern bytes at offsets
2056..2071 — the overflow content is fully attacker-controlled.

## How to reproduce (guest, as root)

```
cd /root/DF-2357
sh build.sh          # sha256-gates if_rum.c, builds rumtest.ko + rumfix.ko
sh run.sh            # loads rumtest.ko then rumfix.ko, captures dmesg
cat run.baseline.log # stock driver: canary hits
cat run.fixed.log    # fixed driver: drops, bit-identical in-range
```

## Files

- `rumtest/rumtest.c` — the harness (interposition + fake USB xfer engine
  + canary-instrumented DMA buffer + test driver)
- `rumtest/Makefile`, `rumfix/Makefile` — kld module builds
- `rumfix/rumfix.c` — same harness compiled around `if_rum_fixed.c`
- `if_rum_fixed.c` — verbatim if_rum.c + `fix.diff` (generated by build.sh)
- `fix.diff` — the verified fix (git-apply-able at repo root)
- `build.baseline.log`, `build.fixed.log` — full compiler output
- `run.baseline.log`, `run.fixed.log`, `run.2.log`, `run.3.log` — full
  runtime output (runs 2 and 3 are stability repeats; 5x canary_hits=16
  each, deterministic)
- `env.txt` — guest uname / compiler / memory / kldstat
- `VERDICT.md` — full narrative incl. exploitability ceiling analysis
- `verdict.json`, `manifest.json`

## Layout constants

- `MCLBYTES` = 2048 (`sys/sys/param.h:497`, MCLSHIFT 11)
- `RT2573_TX_DESC_SIZE` = 24 (`if_rumreg.h:22`, packed `struct rum_tx_desc`)
- transfer bufsize = 2048+24+8 = **2080** (`if_rum.c:438`)
- frame capacity after descriptor = **2056**; stock check allows **2072**
  -> 16-byte window (frames 2057..2072) plus truncate-then-overflow for
  any larger frame (e.g. max 802.11 frame 2346 -> clamped to 2072)
