# DF-4660 — VERDICT

**REPRODUCED** (impact: dos / memcorrupt — intra-object heap OOB write; hardware-gated trigger)

## What was run

Verbatim-extraction harness on the DragonFly 6.5-DEVELOPMENT guest
(dfbsd-qemu; uname in env.txt): the *real* kernel function bodies of
`sys/dev/netif/ath/ath_hal/ar5212/ar2413.c:245-496` were extracted at build
time from the guest's pristine /usr/src (md5 `0589bc4f179fb76901aa6fd0f9865e23`
== audit tree) and compiled unmodified against a faithful `struct ar2413State`
(member order from ar2413.c:35-57; bank row counts 1,1,1,27,3 counted from the
shipped `ar5212.ini`; runtime-printed offsets: pcdacTable@72, Bank1Data@328,
vpdTable_I@1484, sizeof 2000 — matches the kernel object's layout).

## Result (run.log, reproducible across runs — run.log "repeat" section)

With an EEPROM-shaped crafted dataset (xpd_mask=0xF, Pmin pattern
{0,58,58,58} as pwr_t4 = {0,4,8,12} / {116,...}, TPCRG5 overlap 15 — the
4-bit field maximum, ar5212phy.h), `numPdGainsUsed=4` and the three unguarded
`pPDADCValues[kk++]` loops (ar2413.c:453, :462, :476) drove kk to **168**
while `pPDADCValues` is `priv->pcdacTable[PWR_TABLE_SIZE_2413=128]`
(ar2413.c:37; wired at ar2413.c:510 and ar2413.c:747):

```
first clobbered u16 cell 0 bytes past array end, last 79 bytes past
(value 0x007f) => kk ran to 168
```

=> 40 uint16 cells (80 bytes) written past the array into
`Bank1Data[1]/Bank2Data[1]/Bank3Data[1]/Bank6Data[27]/Bank7Data[3]`
(detected via 0xAAAAAAAA canary). The corrupted banks are subsequently
programmed to the RF hardware at ar2413.c:206-210 (`HAL_INI_WRITE_BANK`).

kk-bound arithmetic: each gain contributes up to
`pPdGainBoundaries[ii] (≤63, clamped) + pdGainOverlap_t2 (≤15) − Pmin_t2[ii]`
entries; with 4 gains ≥ 3+63+6·15 = 156 > 128 minimum-guaranteed; measured 168.

## Why this is the same bug as DF-4619/DF-4648

ar2413.c:451-479 is line-for-line the ar2316/ar5413 loop (only types of the
Vpd tables' helpers differ); DragonFly carries all three RF backends.

## Exploitation ceiling

Gated on attacker-supplied AR2413 hardware with crafted EEPROM (v3 EEPROM
image, physical/supply-chain). In-kernel this is a heap intra-object overflow
inside the 2000-byte `ath_hal_malloc` allocation: values constrained
(pdadc clamped 0/127), overflow lands in RF-bank scratch that is immediately
rewritten from the ini on the next reset path. Realistic ceiling: radio
misprogramming / crash (DoS). No info leak, no privilege-escalation route.

## Fix validation (fix_run.log)

fix.diff (git-apply-able, verified `git apply --check` against the pristine
tree) adds `kk < PWR_TABLE_SIZE_2413` guards to all three loops. Patched
harness (same verbatim extraction from the patched copy): mode 1 reports
`DF-4660: NO overflow detected` (bank canary intact). Baseline vs patched
recorded in run.log / fix_run.log.

## Known findings NOT re-reported here

DF-1796 (numChannels==0 OOB read in the same function, pass 1) is distinct.
The sibling wraps found in the same function are filed separately as
DF-4661 (numPdGainsUsed==0) and DF-4662 (flat-curve wrap).

## 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.
