# DF-4374 VERDICT — sysctl read handlers vs ath driver detach lifetime race

**Status: not_reproduced — no Atheros hardware in the audit QEMU guest
(`dev.ath` tree absent, no 0x168c PCI device). Lifetime analysis verified
from source; the race is real but the detach side is privileged, so impact
ceiling is a race-condition kernel panic (DoS).**

## Reproduction attempt (honest)

- Guest: DragonFly 6.5-DEVELOPMENT, `vtnet0 lo0` only; `sysctl -n
  dev.ath.0.slottime` → "unknown oid 'dev.ath'" as both root and user
  (run.log). `pciconf -l` shows no Atheros (0x168c) device.
- `trigger_df4374.sh` executed: reports the absent device and exits.
- Cannot execute the race without ath(4) hardware → `not_reproduced`,
  impact none *observed on this guest*.

## Why the race is real (citations)

1. **Unprivileged read surface.** All `dev.ath.N.*` leaves are created with
   `SYSCTL_ADD_PROC(..., CTLTYPE_INT | CTLFLAG_RW, ...)`. Reads need no
   privilege; only writes are gated (kern_sysctl.c:1446-1447:
   `caps_priv_check(td->td_ucred, SYSCAP_NOSYSCTL_WR)` unless
   CTLFLAG_ANYBODY). Any local user can enter these handlers.

2. **Handlers unlock before touching the HAL.** Representative:
   `ath_sysctl_txantenna` takes ATH_LOCK for `ath_power_set_power_state`
   (if_ath_sysctl.c:256-258), releases it, then calls
   `ath_hal_getantennaswitch(sc->sc_ah)` at :260 with no lock and no
   `sc_invalid` test. Same pattern at :320, :351, :380, :407, :434, :567,
   :606, :631, :656. (slottime/acktimeout/ctstimeout/rxantenna do the read
   under ATH_LOCK but are still exposed to the softc lifetime problem below.)

3. **Driver detach destroys the hardware context while oids are live.**
   `device_detach` (subr_bus.c:2131-2152) runs `DEVICE_DETACH` — for ath:
   `ath_detach` (if_ath.c:1385-1438) stops the chip, frees DMA, and calls
   `ath_hal_detach(sc->sc_ah)` at :1436 (frees the HAL object) — and only
   afterwards calls `device_sysctl_fini(dev)` at :2151, which is what
   removes/frees the dev.ath.N.* oids. The PCI detach then unmaps the
   register BARs.

4. **The sysctl lock protects the oid, not the softc.** Handlers execute
   under the per-oid lockmgr lock (kern_sysctl.c:1460-1482; shared for
   reads). `device_sysctl_fini`/`sysctl_ctx_free` must take the exclusive
   oid lock, so it waits for readers — but that only prevents oid UAF; it
   does nothing to stop ath_detach from freeing `sc_ah` while a reader is
   parked between its ATH_UNLOCK and its HAL call.

5. **Result.** Reader at :260 during/after `ath_hal_detach`:
   - reads `ah->ah_sc`-adjacent state from freed memory (UAF read), and/or
   - executes `OS_REG_READ(ah, ...)` through a bus-space handle whose BAR
     mapping was torn down → kernel-mode access to unmapped device space →
     page fault → panic.

## Impact
Race-condition local DoS (kernel panic). The reader side is unprivileged but
the detach side requires root (kldunload if_ath) or physical hot-removal —
per the audit rubric this is **Low** ("narrow trigger ... requires specific
hardware or already-privileged user" for the triggering half).

## Fix validation
Not possible on this guest (no ath hardware). `fix.diff` shows the pattern:
check `sc_invalid` under ATH_LOCK and keep the lock across the HAL
interaction so `ath_detach`'s ATH_LOCK-serialized teardown cannot proceed
underneath the reader; apply the same shape to every listed handler.
fix_status: not_testable (hardware absent).

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