# DF-3429 VERDICT — stageq expired-frame leak (DWDS discovery)

**status: inconclusive | reproduced: 0 | impact: none demonstrated (hw-gated) | finding severity: Medium (remote memory-exhaustion DoS)**

## Reproduced?
No — and *cannot be*, on this guest: exercising the path requires an
802.11 radio (driver → ieee80211com → AP vap → associated station sending
4-addr frames). The QEMU guest has none: `kldload if_iwm`/`if_run` attach no
device, `pciconf -l` lists zero wireless controllers, `ifconfig -C` shows
the `wlan` cloner but no wlandev exists (`wlan_gate.txt`). The mechanics are
nevertheless certain from source, with an upstream cross-check:

- `ieee80211_ageq_age()` (`sys/netproto/802_11/wlan/ieee80211_ageq.c:162-185`)
  removes expired frames and **returns** them as an m_nextpkt list
  ("The list of removed frames is returned to the caller" — its own comment,
  `ageq.c:157-159`).
- `ieee80211_node_timeout()` (`ieee80211_node.c:2255`) calls it as a bare
  statement — the returned list is unreachable → leaked (mbuf + cluster
  per frame; staged DWDS frames are raw RX frames, not M_ENCAP, so no node
  ref rides along — pure mbuf/cluster leak).
- Producer: `ieee80211_dwds_discover` (`ieee80211_wds.c:333-337`) appends
  every authorized station's 4-addr frame to `ic->ic_stageq` with a finite
  TTL (`(ni_intval * ic_lintval << 2) / 1024` s — the DF-0618 expression;
  normal values ≈ tens of seconds).
- Gate: `ieee80211_hostap.c:654-667` — requires `ieee80211_node_is_authorized(ni)`,
  i.e. attacker must complete association (+802.1X if enabled). Open/PSK
  networks: trivial.
- FreeBSD HEAD comparison: identical bare call at
  `sys/net80211/ieee80211_node.c:2568` (fetched 2026-09-12) — inherited.

## Why "inconclusive" and not "not_reproduced"
The classification difference matters: nothing about the code failed to
behave — the environment cannot host the behavior at all. If a USB radio
were passed through, the trigger is: AP vap up, associate, send 4-addr
frames for ~TTL+20s with no WDS vap created, observe
`netstat -m`/`mbstat` cluster count monotonically increase with no mbuf
returned (or `vmstat -m` M_MBUFCL growth), repeatable across runs.

## Fix
Consume the returned list in `ieee80211_node_timeout`:
`struct mbuf *m; m = ieee80211_ageq_age(...); if (m != NULL) ieee80211_ageq_mfree(m);`
(`ieee80211_ageq_mfree` applies M_ENCAP node-ref rules — `ageq.c:87-98`).
See fix.diff (against node.c).  Fix-status `not_testable` (hw-gated).

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