# VERDICT — DF-4526

**Status: not_reproduced on the guest (hardware-gated: no ath(4) radio
exists in QEMU). Impact if the gate is met: kernel NULL-deref panic
(local DoS). The defect is code-certain; the userspace harness proves
the faulting instruction executes under attach-time state.**

## The bug

`ar5416AniControl()` (sys/dev/netif/ath/ath_hal/ar5416/ar5416_ani.c:172)
guards only HAL_ANI_PRESENT (:190) and HAL_ANI_MODE (:193) against a
missing current channel. All level/threshold commands dereference
`params` (NULL whenever `ah_curani == NULL`, :178-185) or `aniState`
itself:

* :230 `params->maxNoiseImmunityLevel` (HAL_ANI_NOISE_IMMUNITY_LEVEL)
* :317 `params->maxFirstepLevel` (HAL_ANI_FIRSTEP_LEVEL)
* :336 `params->maxSpurImmunityLevel` (HAL_ANI_SPUR_IMMUNITY_LEVEL)
* :296 `aniState->ofdmWeakSigDetectOff = !on` (NULL WRITE)
* :310 `aniState->cckWeakSigThreshold = high` (NULL WRITE)

## Why it is reachable

1. ar5416 softc is zeroed at allocation (ar5416_attach.c:312) →
   `ah_curani == NULL` after attach; the pointer is only published in
   `ar5416AniReset()` (ar5416_ani.c:561), which runs on the first
   channel set.
2. `ar5416Attach()` sets `ah_ani_function = 0xffffffff`
   (ar5416_attach.c:244) → the command gate at ar5416_ani.c:217 passes
   for every command.
3. `HAL_DIAG_ANI_CMD` (ar5212_misc.c:1098-1103) passes user (cmd, param)
   straight to `AH5212(ah)->ah_aniControl()`; ar5416 routes its diag
   interface through the same handler (ar5416_misc.c:530,557). The
   SIOCGATHDIAG entry has no privilege check (if_ath_ioctl.c:299-300 —
   DF-2059/DF-4320), so on `options ATH_DIAGAPI` kernels any local user
   with a socket can trigger the panic between driver attach and first
   channel tune (e.g. immediately after boot, before ifconfig sets a
   channel).

Result in-kernel: read of `*(int *)0x4`-ish or write to `*(uint8_t *)3`
→ page fault → `Fatal trap 12` panic. Panic-only; no corruption
primitive (fixed low address, fixed size).

## Verification performed

* Full code-path trace (cited lines) from ioctl entry to faulting
  instruction — no intervening guard exists.
* `ani_null_deref` harness (this pack): replicates the dispatch with
  `ah_curani=NULL`, `ah_ani_function=0xffffffff`; `--deref` mode
  executes the NULL load and receives SIGSEGV on exactly the replicated
  instruction; `--fixed` shows the proposed guard returns AH_FALSE.
  Ran on the audit guest (BUILD_OK; outputs in run.log).
* Hardware gate: `pciconf -l` on the audit guest shows no Atheros PCI
  device; QEMU 7.2 has no ath HAL emulation; the ath driver cannot
  attach → in-kernel execution impossible in this environment.

## Fix

One-line guard (fix.diff):

```diff
+	if (aniState == AH_NULL) {
+		HALDEBUG(ah, HAL_DEBUG_ANI, "%s: no current ani state\n", __func__);
+		return AH_FALSE;
+	}
```
placed after the HAL_ANI_PRESENT/HAL_ANI_MODE handling, before the
function gate. (Upstream ar5212_ani.c has the same shape and would take
the same guard.)

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