# DF-3749 — rt2860 wcid2ni[] dangling-pointer UAF: TX-status drain dereferences freed nodes

## Severity / class
High (remote-reachable use-after-free write in hostap/IBSS operation). CWE-416.

## Reproduce
**Precondition: Ralink RT2860/RT3xxx NIC (if_ral.ko), interface in hostap mode
(`ifconfig wlan0 create wlandev ral0 mode 11ng hostap`), attacker as an associated
802.11 station in range.**

1. Attacker station associates → `rt2860_newassoc` stores a **borrowed** (unrefcounted)
   pointer: `sc->wcid2ni[wcid] = ni;` (rt2860.c:887).
2. Attacker exchanges some traffic so the AP transmits data frames to it
   (`txwi->wcid = IEEE80211_AID(ni_associd)`, rt2860.c:1587) — the MAC latches a
   per-frame entry into the 16-deep TX_STAT_FIFO on completion.
3. Attacker sends a deauth frame. RX processing (`rt2860_rx_intr` → `ieee80211_input`,
   RAL_UNLOCKed window at rt2860.c:1382-1393) → `ieee80211_node_leave` → the node is
   freed once the last reference drops. **`rt2860_node_free` (rt2860.c:897-911) clears
   only the hardware WCID table — `sc->wcid2ni[wcid]` is never cleared anywhere in the
   driver (grep: set at :887, read at :1137, no other references).**
4. Any subsequent TX interrupt on the AP drains the stats FIFO
   (`rt2860_drain_stats_fifo` runs from every `rt2860_tx_intr`, rt2860.c:1174, and from
   MAC_INT_2, rt2860.c:1475-1476): a TX-status entry for the dead station's wcid that
   was latched late (or left in the FIFO around teardown — TXD-done writeback and the
   MCU's stat-FIFO write are independent hardware paths with no ordering guarantee;
   stats for retried frames land long after the ring slot completed) yields
   `ni = sc->wcid2ni[wcid]` → freed node →
   `ieee80211_ratectl_tx_complete(ni->ni_vap, ni, …)` (rt2860.c:1157-1163) →
   `amrr_tx_complete` reads `ni->ni_rctls` from freed memory and **writes**
   `amn->amn_txcnt++ / amn->amn_retrycnt += …` (wlan/ieee80211_amrr.c:363-370),
   plus `if_inc_counter(ni->ni_vap->iv_ifp,…)` (rt2860.c:1162).

**Expected observation on hardware:** kernel panic or heap corruption shortly after a
station that was actively transmitting traffic disassociates/deauths under AP load.
Use-after-free is deterministic at the *pointer* level (every teardown leaves a
dangling entry); the deref depends on the stats-FIFO vs node-free interleaving, so
repeat deauth-under-load cycles.

## Status on this audit's guest
No Ralink NIC on the QEMU guest (env.txt) — runtime reproduction impossible; the
lifetime defect itself is source-certain (see VERDICT.md).
