# DF-2079: Heap buffer overflow in ath_ioctl_spectral GET_PARAMS

## Verdict: NOT REPRODUCED (HW-gated) — source-confirmed real bug

## Reachability
**NOT reachable on this QEMU guest.** `ath_ioctl_spectral()` is in `if_ath_spectral.c`,
part of the `ath(4)` driver compiled into GENERIC (`device ath`). However, no Atheros WiFi
PCI hardware is present:
- `ifconfig ath0 create` → "SIOCIFCREATE2: Invalid argument" (no ath(4) attach possible)
- PCI survey: no Atheros wireless chip (only virtio-net)

The spectral ioctl is reached via `SIOCATHDIAG` on an `athN` interface — which requires
a real Atheros NIC.

## Mechanism (source-confirmed)
`ath_ioctl_spectral()` at `sys/dev/netif/ath/ath/if_ath_spectral.c:180-293`:
1. Line 187: `outsize = ad->ad_out_size` — **user-controlled** output buffer size
2. Line 210-218: if `ATH_DIAG_DYN` flag set, `outdata = kmalloc(outsize, M_TEMP, M_INTWAIT)`
   — allocates user-controlled size
3. Line 225-230: `SPECTRAL_CONTROL_GET_PARAMS` case:
   - Line 227: `outsize = sizeof(HAL_SPECTRAL_PARAM)` — reassigned **after** allocation
   - Line 230: `memcpy(pe, &peout, sizeof(*pe))` — writes `sizeof(HAL_SPECTRAL_PARAM)` bytes
     (~36 bytes) into the `outdata` buffer

If user sets `ad_out_size < sizeof(HAL_SPECTRAL_PARAM)` (e.g. `ad_out_size=1`), the
`kmalloc(1)` allocates a tiny buffer, but `memcpy` writes 36 bytes → **heap overflow**.

Additionally, line 201: `indata = kmalloc(insize, ...)` where `insize = ad->ad_in_size`
is also user-controlled with no upper bound check — potential large allocation DoS.

## Primitive
- Class: heap buffer overflow (OOB write)
- Overflow size: up to `sizeof(HAL_SPECTRAL_PARAM) - 1` bytes past allocation
- Attacker controls allocation size via `ad_out_size` → can target specific slab bucket

## Fix
`fix.diff`: Add size validation before the memcpy in `SPECTRAL_CONTROL_GET_PARAMS`:
if `outdata != NULL && outsize < sizeof(HAL_SPECTRAL_PARAM)`, return `EINVAL`.
