# DF-3429 — DWDS discovery staged frames leak on age-out (remote DoS)

## Build / Run
- No userland build: kernel-side defect.
- `./run.sh` — documents the hardware gate on the audit guest (no radio
  attaches; `ifconfig -C` shows no usable wlandev), so the path cannot be
  exercised in QEMU. All analysis is line-verified against both this tree
  and FreeBSD HEAD (identical defect inherited).

## Mechanism (path:line)
1. Attacker (authorized station of an AP vap) sends 4-address data frames.
2. `hostap_input` → `dir == DSTODS && ni->ni_wdsvap == NULL` + authorized →
   `ieee80211_dwds_discover(ni, m)` (`ieee80211_hostap.c:654-667`).
3. `ieee80211_dwds_discover` (`ieee80211_wds.c:321-338`) tags the mbuf with
   the MAC hash and appends it to `ic->ic_stageq` with a finite TTL.
4. If a WDS vap is plumbed, `wds_flush` (`ieee80211_wds.c:102-122`) pulls
   the frames back out — no leak.
5. If NOT serviced, `ieee80211_node_timeout` fires every
   `IEEE80211_INACT_WAIT` and calls
   `ieee80211_ageq_age(&ic->ic_stageq, IEEE80211_INACT_WAIT)`
   (`ieee80211_node.c:2255`) — **return value (list of expired frames)
   ignored**. `ieee80211_ageq_age` (`ieee80211_ageq.c:162-185`) removes the
   expired frames and *returns them for the caller to free*. They are
   dropped on the floor: permanent leak of mbuf + 2KB cluster per frame.

## Impact
Remote, unauthenticated-after-association kernel memory exhaustion:
sustained 4-addr frames at rate R ≈ R × 2KB/s leaked forever. Queue bound
(`aq_maxlen = ic_max_keyix * 8`) only bounds the backlog, not the leak.
Prerequisite: AP-mode vap with DWDS-capable setup and discovery events not
consumed (daemon absent/restarting) — a common field state.

## Upstream
FreeBSD HEAD `sys/net80211/ieee80211_node.c:2568` has the identical bare
`ieee80211_ageq_age(&ic->ic_stageq, IEEE80211_INACT_WAIT);` — inherited
defect; upstream disclosure recommended together with the DFly fix.

## Verdict
`inconclusive` — mechanics certain from source; runtime verification
hardware-gated (QEMU guest has no 802.11 radio; `wlan_gate.txt`).
