# DF-3969 verdict — certain NULL-check gap, race-gated DoS (rt2560 sibling of DF-3968)

## Reproduced?
No Ralink NIC on the audit guest (env.txt: pciconf shows no vendor 0x1814
device), so the destroy-vs-scan race could not be exercised. Source-level
certainty is high and the pattern is the *proven* DF-3968 family applied to
the rt2560 driver:

- rt2560.c:2566-2574: `vap = ic->ic_scan->ss_vap; ... rt2560_set_bssid(sc,
  vap->iv_bss->ni_bssid);` — no NULL check; `rt2560_enable_tsf_sync(sc)` is
  called first and derefs its own unchecked vap first.
- rt2560.c:2277,2284: `vap = TAILQ_FIRST(&ic->ic_vaps); ...
  tmp = 16 * vap->iv_bss->ni_intval;` — no NULL check.
- Call site: ieee80211_scan_sw.c:796-798 — `scan_end()` drops the COM lock
  around `ic->ic_scan_end(ic)` and re-acquires after, explicitly warning
  that scan state can change during the driver call.
- Tear side: ieee80211_scan.c:147-155 — `ieee80211_scan_vdetach(vap)` (under
  IEEE80211_LOCK, from ieee80211_vap_delete) sets `ss->ss_vap = NULL` and the
  vap leaves ic_vaps; nothing re-validates either the driver's TAILQ_FIRST
  snapshot or its ss_vap copy.
- rt2560.c:2691 (`init_locked`) shows the codebase already knows the pattern
  needs a guard: `rt2560_set_macaddr(sc, vap ? vap->iv_myaddr :
  ic->ic_macaddr)` — the two functions fixed here simply lack it.

⇒ `ifconfig wlanX destroy` racing a completing background scan on the last
vap ⇒ NULL deref ⇒ panic (local DoS; destroy is privileged). Not exploitable
beyond DoS: both faults are pure reads at small fixed offsets of NULL.

## Fix
fix.diff adds NULL guards in rt2560_scan_end (early return when ss_vap is
NULL) and rt2560_enable_tsf_sync (early return when TAILQ_FIRST is NULL) —
two-line defense, same shape as the accepted DF-3968 fix. Validated:
`git apply --check` clean on sys/; applied on the guest /usr/src copy and
the if_ral.ko module rebuilt clean with -Werror (build.log). Runtime
validation needs the NIC.

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