# DF-4620 VERDICT

## Finding
`numPdGainsUsed == 0` path in `ar5413getGainBoundariesAndPdadcsForPowers`
(ar5413.c:397-540). Because the backfill loops decrement uint32 counters past
zero, two array subscripts wrap to element index 0xFFFFFFFF and read at
**array + 0x1FFFFFFFE bytes (+8.59 GB)**:

- :528 `pPdGainBoundaries[ii-1]` (ii==0) — from the caller's stack array
  `gainBoundaries[4]` (ar5413.c:555, kernel stack of `ar5413SetPowerTable`);
  the value is later written to `AR_PHY_TPCRG5` (:639-644).
- :532 `pPDADCValues[kk-1]` (kk==0) — from `priv->pcdacTable` (kernel heap);
  replicated across all 128 pdadc entries and 32 PHY register writes
  (:630-637).

Plus :468 `*pMinCalPower = Pmin_t2[0]` — uninitialized kernel-stack read
(Pmin_t2[] only written when numVpd>0, :435-445) feeding
`ahp->ah_txPowerIndexOffset` (:623-626).

Release kernels reach this: `HALASSERT(1 <= numPdGainsUsed && numPdGainsUsed
<= 3)` (:580) is a no-op without AH_ASSERT (ah_internal.h:665-676; not in
GENERIC). Trigger: EEPROM with xpd_mask==0 for the mode's raw dataset
(produced exactly by `ar2413SetupRawDataset`, ah_eeprom_v3.c:643-671 setting
numVpd=0 for all gains) — i.e., crafted EEPROM, or a degenerately-programmed
card.

## Reproduction (guest)
Mode 2 of the same verbatim-extraction harness (see DF-4619 pack). The guest
userspace fault flavor was first observed as SIGSEGV/SIGBUS at
`si_addr == gb + 0x1FFFFFFFE` (0x8004902c4 + 0x1FFFFFFFE = 0xa004902c2,
exact). To emulate the kernel's direct map (where the +8.6 GB read usually
lands on mapped RAM instead of faulting), the harness mmaps the two exact
wild pages seeded with 0x5A5A — the call then COMPLETES and both wild values
are observed propagating into `gainBoundaries[0]` and `pcdacTable[0]`:

```
gainBoundaries[0] = 0x5a5a   (ar5413.c:528 → TPCRG5)
pcdacTable[0]     = 0x5a5a   (ar5413.c:532 → pdadc table / PHY regs)
minPower out      = 0xd320 / 0xd370 / 0xd300 across runs  (uninit stack, :468)
```

## Impact
In-kernel: wild read at KVA +8.6 GB — mapped RAM → garbage programmed into
radio registers (malfunction); KVA hole → page fault → **panic** (DoS). The
uninit stack read leaks nothing to userspace (values only feed PHY
programming). Gated on attacker-supplied EEPROM → physical/supply-chain
precondition, same class as DF-1766. Recorded impact: dos.

## Fix validation
`fix.diff`: early `return 0` when numPdGainsUsed==0 (after the gain loop,
before :468) + `ar5413SetPowerTable` returns AH_FALSE on 0 gains. Patched
harness run: no wild-read propagation (gainBoundaries[0]=0x0000,
pcdacTable[0]=0xaaaa untouched) and `minPower` stays at its 0x7c7c sentinel —
the uninitialized read never executes. See fix_run.log.

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