ms_known_gates gate entries are never freed: unauthenticated GANN spam exhausts kernel heap and leaks across vap destroy
Summary
Every accepted GANN from a new gate address kmallocs a struct ieee80211_mesh_gate_route into ms_known_gates; the list has no removal path anywhere in sys/ (only INSERT_TAIL), no aging, and mesh_vdetach frees vap->iv_mesh without walking it. Any mesh peer injects GANNs with fresh gann_addr values for unbounded permanent kernel heap growth (~40 bytes per 19-byte frame); vap destroy/recreate cycles accumulate. VERIFIED: 500 GANN frames -> 80211mesh_gt zone 503 in-use/19.6K; destroy -> still 503; second vap cycle +100 -> 603, leaked again (control zone correctly returns to 0). Remote unauthenticated (post-auto-peering) memory exhaustion; permanent leak across vap churn. Fix validated (flush in mesh_vdetach under MESH_RT_LOCK): 201 -> 0 after destroy.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3288 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.2 KB | β raw | |
| run.sh | β | 111 B | view raw | |
| run.log | β | 732 B | view raw | |
| verdict.json | β | 2.4 KB | view raw | |
| manifest.json | β | 538 B | view raw |
DF-3288 β ms_known_gates gate entries are never freed: unauthenticated GANN spam grows kernel heap without bound and leaks across vap destroy
File: sys/netproto/802_11/wlan/ieee80211_mesh.c (pass 2 audit)
What
Every accepted GANN action frame from a new gate address allocates a
struct ieee80211_mesh_gate_route (:2662-2676) and links it into
ms->ms_known_gates:
if (found == 0) {
gr = kmalloc(ALIGN(sizeof(struct ieee80211_mesh_gate_route)),
M_80211_MESH_GT_RT, M_INTWAIT | M_ZERO);
IEEE80211_ADDR_COPY(gr->gr_addr, ie.gann_addr);
TAILQ_INSERT_TAIL(&ms->ms_known_gates, gr, gr_next);
}
ms_known_gates has no removal path anywhere in sys/ (only
INSERT_TAIL at :907 and :2675; verified by grep), no aging, and
mesh_vdetach (:646-659) frees vap->iv_mesh without walking the gate
list. Consequences:
- any mesh peer (established = one beacon + 2 action frames) injects
GANNs with fresh
gann_addrvalues β one ~40-byte kmalloc each, forever β unauthenticated remote kernel memory exhaustion; - destroying the mesh vap leaks the whole table β the entries outlive the vap; recreate/destroy cycles accumulate.
(Note: DF-0289 already covers the gr_route dangling-pointer aspect of the gate table; this finding is the missing free / unbounded growth, a different defect at different lines.)
Reproduced (stock kernel, vmstat -m)
# after 500 injected GANNs (sysctl kern.fwm_count=500; kern.fwm_step=20) 80211mesh_gt 503 19.6K 0 390M 503 # after `ifconfig wlan0 destroy` after vap destroy: 80211mesh_gt 503 19.6K 0 390M 503 <-- LEAKED # recreate vap, 100 more GANNs, destroy again: 80211mesh_gt 603 23.6K 0 390M 603 80211mesh_gt 603 23.6K 0 390M 603 <-- accumulates forever
Meanwhile 80211mesh_rt returns to 0 on destroy β only the gate table
leaks.
Build / run
sh findings/poc/DF-3286/build.sh # shared harness sh findings/poc/DF-3288/run.sh # 500 GANNs, destroy, vmstat -m
Threat
Remote unauthenticated (post-peering) kernel heap exhaustion; ~40 bytes per 19-byte action frame, no ceiling, permanent across vap churn. CWE-401. Severity Medium.
Fix verification
fixed200 GANNs -> 201 in-use; ifconfig wlan0 destroy -> in-use 0 (baseline: 503 persisted); mesh_vdetach now flushes ms_known_gates
['fix.log: vmstat -m 201 -> 0 after destroy']
Confirmed kernel references
Detail
Exploit chain
attacker peers (1 beacon + OPEN + CONFIRM) -> floods 19-byte GANN action frames with unique gann_addr -> one kmalloc per frame, never freed -> kernel memory exhaustion -> OOM/degradation of the mesh node (and of any later vap that shares the zone accounting)
Evidence (decisive lines)
run.log: vmstat -m 503 -> destroy -> 503 -> +100 -> 603 -> destroy -> 603
PoC changes
harness step 20 (count-configurable GANN flood with fresh gate addrs); observation via vmstat -m zone 80211mesh_gt
Verified recommended fix
flush ms_known_gates in mesh_vdetach (fix.diff hunk 7); consider aging entries when their route expires
Verdict
ms_known_gates gate entries (kmalloc M_80211_MESH_GT_RT) have no free path anywhere in sys/ and are not flushed in mesh_vdetach. 500 injected GANN action frames with fresh gate addresses grew the 80211mesh_gt zone to 503 entries / 19.6K; ifconfig wlan0 destroy freed none of them; a second vap cycle added 100 more (603/23.6K) and leaked them again. Unauthenticated (post-auto-peering) remote unbounded kernel heap growth, permanent across vap churn.
No comments yet.