# DF-3454 — amrr stale rate index (amn_rix) never revalidated against the active rateset

**File:** `sys/netproto/802_11/wlan/ieee80211_amrr.c`
**Class:** CWE-125 out-of-bounds read (intra-object, kernel pointer bytes disclosed)
**Severity:** Low · **Confidence:** certain (reproduced on QEMU guest)

## Build

```
scp amrroob.c Makefile dfbsd:/root/amrroob/
guest# cd /root/amrroob && make SYSDIR=/usr/src/sys      # -> amrroob.ko
```

## Run

```
guest# kldload /root/amrroob/amrroob.ko     # pulls in wlan_amrr (or uses in-kernel amrr)
guest# sysctl amrroob.run=1                 # ~60s; all output to dmesg/console
guest# dmesg | grep amrroob
guest# kldunload amrroob
```
(see `run.sh`; output lands in `dmesg`, captured in `run.2.log` / `run.log`)

## Expected (vulnerable kernel)

* `PHASE2 ... -> amn_rix=76` — 11n rate index driven to 76 through the public
  `ieee80211_ratectl_*` API (77-entry `ni_htrates` table).
* `PHASE3 ... ratectl_rate() returned rix=76; legacy rs_nrates=12` — after flipping
  the node to a legacy channel, the stale index 76 is used against the 15-byte
  `ni_rates.rs_rates` array: **OOB read at rs_rates[76]** (array ends at rs_rates[14]).
* `PHASE4` walk-down: every failure interval reads one more OOB byte; the value
  lands in `ni->ni_txrate` (masked `& 0x7f`) — i.e. in `SIOCG80211NODE`
  `isi_txrate` and the world-readable `net.wlanX.rate_stats` sysctl.
  rs_rates[18..25] overlay the `ni_chan` **kernel heap pointer**
  (e.g. `0xfffff8008d403a30` → bytes `40 3a 40 8d 00 f8 ff ff` read OOB,
  `0xA5` meshid marker bytes likewise disclosed as `0x25`).
* `PHASE5 tmp-node ... amn_rix=-1 ratectl_rate() returned -1` — the empty-rateset
  path (`ieee80211_tmp_node`): drivers receive rix = -1 (iwm_setrates
  `KASSERT(rix >= 0 && rix < nrates)` ⇒ INVARIANTS panic).

## Expected (patched kernel, fix.diff applied)

* `PHASE3` returns `rix=11` (clamped to `rs_nrates-1`), no reads past
  `rs_rates[14]`, walk-down runs 11→0 **in bounds**, no `0xA5`/pointer-byte
  lines, `PHASE5` returns `0`.

## Fix validation

`fix.diff` applied to guest `/usr/src`, `make nativekernel`, `installkernel`,
reboot, same PoC — see `fix_run.log` / `VERDICT.md`.
NOTE: `ieee80211_amrr.c` is compiled into the base kernel when `wlan` is
built in (`sys/conf/files:1630`) — patching only `wlan_amrr.ko` has no effect;
a kernel rebuild is required.
