ieee80211_ht_wds_init never assigns tap->txa_ni: guaranteed NULL-deref panic in addba_timeout/ampdu_tx_stop/bar_timeout for legacy WDS nodes with HT
Summary
struct ieee80211_tx_ampdu.txa_ni has exactly one writer in the tree - ieee80211_ht_node_init (:1084). Legacy WDS peer nodes are instead initialized by ieee80211_ht_wds_init, which sets txa_tid but not txa_ni; nodes are kmalloc'd M_ZERO so txa_ni is NULL forever while the node is marked NODE_HT|NODE_AMPDU, arming the TX aggregation path. addba_timeout, ampdu_tx_stop and bar_timeout all deref tap->txa_ni->ni_ic unconditionally. Reachable config: HT radio + 'wlanmode wds wlanbssid <peer> wdslegacy' vap with 'ifconfig <wds> ht' (IOC_HTCONF has no opmode restriction); >=64 pps BE traffic -> ADDBA request; peer silence (dead link or attacker-controlled peer) -> 250ms later addba_timeout panics the kernel. REPRODUCED on stock INVARIRICS guest (fw2.c software radio + wdslegacy vap + paced traffic): 'Fatal trap 12 ... fault VA = 0x8 / Stopped at addba_timeout+0x6: movq 0x8(%rdi),%rax' within ~250ms. Remote-adjacent-triggerable DoS of any 11n legacy-WDS link; fixed NULL+8 read, no exploitation primitive. Fix validated (txa_ni = ni in the WDS loop): PoC no longer panics, guest survives repeated timeouts.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3312 Β· 15 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fw2.c | β | 9.9 KB | view raw | |
| Makefile | β | 150 B | β download | |
| build.sh | β | 143 B | view raw | |
| run.sh | β | 111 B | view raw | |
| fixcheck.sh | β | 1.6 KB | view raw | |
| build.log | β | 5.6 KB | view raw | |
| run.log | β | 3.0 KB | view raw | |
| run.2.log | β | 3.0 KB | view raw | |
| panic.txt | β | 2.1 KB | view raw | |
| patched_run.txt | β | 1.2 KB | view raw | |
| fix.log | β | 1.4 KB | view raw | |
| fix.diff | β | 422 B | view raw | |
| env.txt | β | 258 B | view raw | |
| verdict.json | β | 4.3 KB | view raw | |
| manifest.json | β | 1.3 KB | view raw |
Fix verification
fixedOne-line fix.diff applied to guest /usr/src, nativekernel rebuilt+installed (#1 Sep 10 14:40:48), rebooted, exact baseline PoC re-run: tap->txa_ni now 0xfffff80118743400, ADDBA request armed (txa_flags=0xb) and timed out repeatedly with no trap; guest stayed up (dmesg fatal-trap count 0). Bad behavior gone.
fix.log, patched_run.txt
Confirmed kernel references
- sys/netproto/802_11/wlan/ieee80211_ht.c:1248
- sys/netproto/802_11/wlan/ieee80211_ht.c:1084
- sys/netproto/802_11/wlan/ieee80211_ht.c:1772
- sys/netproto/802_11/wlan/ieee80211_ht.c:1731
- sys/netproto/802_11/wlan/ieee80211_ht.c:2282
- sys/netproto/802_11/wlan/ieee80211_node.c:1350
- sys/netproto/802_11/wlan/ieee80211_wds.c:200
- sys/netproto/802_11/wlan/ieee80211_ioctl.c:2972
Detail
Exploit chain
HT radio + legacy WDS vap ('wlanmode wds wlanbssid
Evidence (decisive lines)
["run.log: decisive baseline run β 'tap->txa_ni = 0', txa_flags=0xb (ADDBA pending), then 'Fatal trap 12 ... fault virtual address = 0x8 ... Stopped at addba_timeout+0x6: movq 0x8(%rdi),%rax', current process Idle (callout)", 'panic.txt: full serial-console capture of the trap', "patched_run.txt: fixed-kernel rerun β 'tap->txa_ni = 0xfffff80118743400', same traffic + ADDBA pending, no trap", 'fix.log: patch apply + nativekernel build/install + post-PoC status (guest up, 0 fatal traps)', 'fw2.c: software-radio KLD (HT 11ng fake radio, WDS-capable, paced-traffic sysctl kern.fw2_fire)']
PoC changes
Two harness fixes vs first draft: (1) take one ieee80211_ref_node per frame (ieee80211_vap_pkt_send_dest consumes a node ref per call -- first run UAF'd in ieee80211_tx_complete, PoC bug not finding bug); (2) assign ic_raw_xmit/ic_transmit AFTER ieee80211_ifattach (proto_attach overwrites them with null_raw_xmit, cosmetic). Finding-side PoC seed: none existed (pass-2 new finding); trigger sequence matches analysis exactly.
Verified recommended fix
Assign tap->txa_ni = ni in ieee80211_ht_wds_init (mirrors ieee80211_ht_node_init:1084); see fix.diff -- validated by kernel rebuild.
Verdict
Legacy WDS peer nodes initialized by ieee80211_ht_wds_init get NODE_HT|NODE_AMPDU but tap->txa_ni is never assigned (only ieee80211_ht_node_init:1084 assigns it); with HT re-enabled on the WDS vap (HTCONF ioctl, no opmode restriction) and >=64 pps BE traffic the stack sends an ADDBA request, and 250 ms of peer silence makes addba_timeout() deref NULL txa_ni -> deterministic page fault at va 0x8 in softclock context. Reproduced twice on the stock INVARIANTS guest; one-line fix (txa_ni = ni in ieee80211_ht_wds_init) validated by nativekernel rebuild: identical PoC no longer panics, tap->txa_ni non-NULL, guest stays up. Remote-peer-triggerable DoS (panic) on WDS+11n deployments; no exploitation primitive (fixed NULL+8 read).
No comments yet.