mesh_parse_meshgate_action ignores the GANN IE's declared length: OOB read of up to 15 bytes re-broadcast to the mesh
Summary
The IE walk only guarantees frm[1]+2 bytes present, but the MESHGANN case copies the full 17-byte struct (15 payload bytes) without checking gann_len==IEEE80211_MESHGANN_BASE_SZ. A GANN IE declaring len=0 at the end of a frame padded past ieee80211_parse_action's total-length check makes the parser read 15 bytes beyond the IE; the parsed values are stored in the (leaking) gate table and re-broadcast in the propagated GANN, exfiltrating stale mbuf-cluster contents over the air. VERIFIED: captured victim re-broadcast carries every beyond-IE marker byte ('tx[29] ... b1 b3 b4 b5 b6 b7 b8 b9 b9 b9 b9 be bd'). Remote (established peer) bounded kernel-memory info leak over the air to all mesh nodes; leaked values also persist in the gate table. Distinct from DF-0286/0288. Fix validated (require full-size GANN IE): short GANN no longer propagated.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3290 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 2.3 KB | β raw | |
| run.sh | β | 111 B | view raw | |
| run.log | β | 868 B | view raw | |
| verdict.json | β | 2.4 KB | view raw | |
| manifest.json | β | 475 B | view raw |
DF-3290 β mesh_parse_meshgate_action reads the 15-byte GANN body regardless of the IE's declared length; OOB bytes re-broadcast
File: sys/netproto/802_11/wlan/ieee80211_mesh.c (pass 2 audit)
What
mesh_parse_meshgate_action (:2574-2602) only guarantees that
frm[1] + 2 bytes of each IE are present (loop VERIFY_LENGTH at :2583),
then copies the full 17-byte GANN structure for any
IEEE80211_ELEMID_MESHGANN element without comparing gann_len to
IEEE80211_MESHGANN_BASE_SZ (15):
case IEEE80211_ELEMID_MESHGANN:
gannie = (const struct ieee80211_meshgann_ie *) frm;
/* copies gann_flags..gann_interval: 15 bytes past ie+len */
ie->gann_seq = le32dec(&gannie->gann_seq); ...
A GANN IE declaring len=0 (or <15) placed at the end of a frame that
is padded to satisfy ieee80211_parse_action's total length check
(input.c requires only β₯17 bytes of action body) makes the parser read
up to 15 bytes beyond the IE's declared extent β stale mbuf/cluster
data. The parsed values (gate addr, seq, ttl, interval) are then
re-broadcast in the propagated GANN (ieee80211_send_action at
:2702), disclosing those bytes to every mesh node in radio range.
Distinct from DF-0286 (lmetric total-length check) and DF-0288
(meshpeering early decode): this is the per-IE length check missing in
the GANN walk.
Reproduced (stock kernel)
Injected (harness step 21): action body = 0d 02 (cat/act) + padding
IE 00 06 PPΓ6 + GANN IE header 7d 00 (declared len=0) + 15
trailing marker bytes (00 0d B2 B3..B8 B9Γ4 BD BE) that the parser must
NOT attribute to the IE.
Victim re-broadcast (captured at the radio):
tx[29] fc0=d0 len=43: ... 0d 02 7d 0f 00 0e b1 b3 b4 b5 b6 b7 b8 b9 b9 b9 b9 be bd
β propagated GANN carries gate addr b3:b4:b5:b6:b7:b8, seq 0xb9b9b9b9, ttl 0xb1, interval 0xbebd β every one of the 15 bytes read from beyond the len=0 IE.
Build / run
sh findings/poc/DF-3286/build.sh sh findings/poc/DF-3290/run.sh
Threat
Remote (established peer) OOB read of up to 15 bytes past the IE into
stale mbuf-cluster contents, exfiltrated over the air to the whole mesh.
kernleak bucket. Severity Low (bounded stale-data read; needs mesh vap).
CWE-125. Fix: require frm[1] == IEEE80211_MESHGANN_BASE_SZ.
Fix verification
fixedshort GANN (IE len=0) no longer propagated (baseline re-broadcast the markers); rejected by the new frm[1] != MESHGANN_BASE_SZ check
['fix.log: no len-43 propagated frame after step 21']
Confirmed kernel references
Detail
Exploit chain
established peer sends CAT_MESH GANN action whose GANN IE declares len=0, padded so the total-length check passes and the trailing bytes double as a final valid IE -> parser reads 15 bytes past the IE -> gate stored from those bytes -> GANN re-broadcast to the whole mesh carries the out-of-bounds bytes
Evidence (decisive lines)
run.log: tx[29] propagated GANN containing the beyond-IE markers b3..be
PoC changes
harness step 21; the 15 trailing bytes double as a valid final IE (00 0d ...) so the walk survives to the propagation stage
Verified recommended fix
reject GANN IEs whose frm[1] != IEEE80211_MESHGANN_BASE_SZ (fix.diff hunk 6)
Verdict
mesh_parse_meshgate_action copies the 15-byte GANN body from any MESHGANN IE without checking gann_len, while the IE walk only guarantees frm[1]+2 bytes present. A GANN IE declaring len=0 at the end of a padded action frame made the victim parse 15 bytes beyond the IE and re-broadcast them: the propagated GANN (captured at the radio) carried the marker bytes as gate addr b3:b4:b5:b6:b7:b8, seq 0xb9b9b9b9, ttl 0xb1, interval 0xbebd. Remote OOB read (up to 15 bytes of stale mbuf data) exfiltrated over the air.
No comments yet.