# DF-4315 VERDICT — not_reproduced on the audit guest (no ath NIC); OOB-read mechanics proven in source

## Reproduced?

**No — impossible on this guest by construction.** `ifconfig -l` shows only
`vtnet0 lo0`; `pciconf -l` has no vendor-0x168c (Atheros) device (`run.log`,
`env.txt`). The ath driver never attaches, `ath_rx_pkt`/`ath_rx_tap` never
execute. Recorded as `not_reproduced / reproduced=0 / impact=none` for the
observable-on-this-guest result (the audit vocabulary has no separate
"device absent" status).

## Why the finding stands (source-level proof)

*Sentinel creation* — `sys/dev/netif/ath/ath_hal/ah.c:571-583`
(`ath_hal_setupratetable` equivalent): every one of the 256
`rateCodeToIndex[]` entries starts as `(uint8_t)-1`; only the current mode's
codes are overwritten with real indices.

*Device-fed index* — `ar5416_recv.c:200` (`RXSTATUS_RATE`, 8-bit
`AR_RxRate`, `ar5416desc.h:336-337`), `ar5212_recv.c:276`
(`MS(ds_rxstatus0, AR_RcvRate)`). No masking/validating in between; the HAL
copies the descriptor word into `rs->rs_rate`.

*OOB use* — `if_ath_rx.c:577-579`:

```c
rix = rt->rateCodeToIndex[rs->rs_rate];   /* uint8_t; 0xff when unmapped */
sc->sc_rx_th.wr_rate = sc->sc_hwmap[rix].ieeerate;   /* sc_hwmap[32]! */
sc->sc_rx_th.wr_flags = sc->sc_hwmap[rix].rxflags;
```

`sc_hwmap` is declared `... sc_hwmap[32]` at `if_athvar.h:716` and populated
only for `i < 32` (`if_ath.c:6211-6233`). Index 255 reads an 8-byte record at
byte offset 2040 of a 256-byte array — roughly 1.8 KB past its end. The
`ath_softc` struct continues well past `sc_hwmap` (rx/tx queues, task
structures, locks...), so the read does not fault; it returns bytes of
unrelated softc state.

*Leak surface* — `sc_rx_th` is the radiotap template; for every received
frame while a monitor VAP is up, `wr_rate`/`wr_flags` are copied into the
radiotap header seen by BPF listeners (`ieee80211_radiotap_rx_all`,
`if_ath_rx.c:874-879`). Two attacker-influenced-timing bytes of intra-softc
memory per frame — visible only to privileged BPF readers on DFly.

*Second consumer* — `if_ath_rx.c:988-990` passes the sentinel to
`ath_led_event(sc, rix)`; `if_ath_led.c:185-194` indexes
`sc->sc_hwmap[rix].ledon/.ledoff` with `rix == 255` and no check — OOB read
feeding LED blink timings (no further memory-safety consequence). The debug
dump path `if_ath_rx.c:900-903` is a third consumer.

*Reachability* — requires a received frame whose hw rate code is absent from
the currently-loaded mode table. Realistic instances: monitor mode on
AR5212-class parts receiving XR-coded frames; monitor mode on 11n parts
receiving MCS codes above the loaded table's chain count; scan/mode-change
windows where `sc_curmode` no longer matches the frames still in flight.
Everything hinges on RF/hardware state, which is exactly why this is Low
severity: no write primitive, privileged-only visibility, weak content.

## Fix validation

`fix.diff` clamps the 0xFF sentinel to index 0 at all three sites in this
file (`git apply --check` clean). Runtime validation on this guest is
impossible (no ath hardware → `fix_status: not_testable`); the clamp is
trivially sound by inspection: index 0 is always populated
(`if_ath.c:6211-6233` initialises all 32 entries), so behaviour degrades to
"report base rate" instead of reading OOB softc bytes.

## Notes / exclusions

- DF-1517 (rs_datalen OOB) is a different root cause in the same function;
  not re-reported.
- DF-1667 covers the EDMA m_rxpending double-free (different file,
  `if_ath_rx_edma.c`).
- The RX antenna field, the classic sibling of this bug, is already clamped
  in-tree (`if_ath_rx.c:828-835`); `ast_rx_phy[]` is guarded at `:696-697`;
  `keyix` is bounds-checked in net80211 (`ieee80211_node.c:1679`).

## Fix status (batch validation)
Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest `make -j6 nativekernel KERNCONF=X86_64_GENERIC` completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.
