Remote heap buffer overflow via oversized Mesh ID IE in sta_add: memcpy 2+meshid[1] into se_meshid[34] with no bounds check
| Field | Value |
|---|---|
| ID | DF-0393 |
| Status | new |
| Severity | Critical |
| CVSS 3.1 | CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H |
| CWE | CWE-122 Heap-based Buffer Overflow |
| File | sys/netproto/802_11/wlan/ieee80211_scan_sta.c |
| Lines | 310-312 |
| Area | netproto (802.11 WiFi) |
| Confidence | certain |
| Discovered | 2026-07-01 |
| Reported | pending |
Summary
When a WiFi interface in scanning mode receives a beacon or probe-response
frame containing a Mesh ID information element with a length byte greater
than 32, the scan subsystem copies the IE into a fixed-size 34-byte struct
field (se_meshid[2+IEEE80211_MESHID_LEN]) without any bounds check. The
copy size 2+meshid[1] can reach 257, overflowing the field by up to ~223
bytes with attacker-controlled data, corrupting adjacent pointer fields in
the heap-allocated scan entry. This is reachable by any unauthenticated
attacker within radio range and can be triggered with a single crafted frame
during the automatic background scan interval.
Root cause
sta_add() in sys/netproto/802_11/wlan/ieee80211_scan_sta.c:310-312:
#ifdef IEEE80211_SUPPORT_MESH
if (sp->meshid != NULL && sp->meshid[1] != 0)
memcpy(ise->se_meshid, sp->meshid, 2+sp->meshid[1]);
#endif
ise->se_meshid is declared as uint8_t se_meshid[2+IEEE80211_MESHID_LEN]
in sys/netproto/802_11/ieee80211_scan.h:282, where
IEEE80211_MESHID_LEN == 32 (sys/netproto/802_11/ieee80211.h:200), giving
a destination of exactly 34 bytes.
sp->meshid[1] is the IE length byte from the attacker-controlled
beacon/probe-response frame. As a uint8_t, it can be up to 255, making the
copy size 2+255 = 257 โ overflowing se_meshid by 223 bytes.
The Mesh ID IE is not validated upstream. The generic beacon parser
ieee80211_parse_beacon() in sys/netproto/802_11/wlan/ieee80211_input.c:621-622
simply assigns:
case IEEE80211_ELEMID_MESHID:
scan->meshid = frm;
with no IEEE80211_VERIFY_ELEMENT() call and no BPARSE_* status
bit for an oversized Mesh ID. This contrasts with the mesh-specific receive
path (ieee80211_mesh.c:2075) which correctly validates with
IEEE80211_VERIFY_ELEMENT(meshid, IEEE80211_MESHID_LEN, ...).
IEEE80211_SUPPORT_MESH is enabled by default in the generic kernel
(sys/config/X86_64_GENERIC:256).
Threat model & preconditions
- Attacker position: unauthenticated, within WiFi radio range of the target interface.
- Privileges gained or impact: remote kernel heap corruption with full
attacker-controlled data. Immediate kernel panic (DoS). With heap grooming
of the
M_80211_SCANslab, controlled read/write of kernel memory and potential remote code execution. - Required config or capabilities: none. The target interface must be scanning (which occurs automatically every few seconds when associated via background scan, or during any manual/active scan in sta, hostap, ibss, or mbss modes).
- Reachability: send a single 802.11 beacon or probe-response frame with
a Mesh ID IE whose length byte exceeds 32. The frame must have a valid
fixed header and valid/absent SSID and rates IEs so that
ieee80211_parse_beacon()returns successfully.
Proof of concept
PoC source: findings/poc/DF-0393/poc.py
Build & run
# Requires a WiFi adapter in monitor/inject mode (e.g. ath9k) python3 poc.py --iface wlan0mon --target <victim-bssid>
Expected output
The victim kernel panics with a heap corruption fault:
Fatal trap 12: page fault while in kernel mode virtual address = 0x<corrupted pointer from se_ies> cpuid = 0 KDB: stack backtrace: #0 ... #1 sta_add at ieee80211_scan_sta.c:312 #2 sta_rx_mgmt at ieee80211_scan_sta.c:... #3 ieee80211_deliver_l2 ...
Impact
- Remote unauthenticated kernel heap overflow โ the most severe class of WiFi vulnerability. Any device within radio range can exploit it.
- The overflow corrupts
struct ieee80211_scan_entryfields immediately followingse_meshid:se_ies(astruct ieee80211_iescontaining numerous IE data pointers),se_age, and the TAILQ/LIST link pointers (se_list,se_hash). These corrupted pointers are later dereferenced byieee80211_ies_expand(),select_bss(),sta_iterate(), andadhoc_age(). - Reliable kernel panic from corrupted pointer dereference.
- Potential remote code execution with heap grooming: the attacker can
flood beacons to fill the
M_80211_SCANslab with controlled data, then trigger the overflow to overwrite a function pointer or vtable entry. - This is distinct from DF-0285 (which targeted the mesh-specific receive
path in
ieee80211_mesh.c). DF-0393 targets the generic beacon parsing path used by ALL operating modes (sta, hostap, ibss, mbss).
Recommended fix
Bounds-check the Mesh ID length before copying, matching the SSID/rates protection pattern:
--- a/sys/netproto/802_11/wlan/ieee80211_scan_sta.c
+++ b/sys/netproto/802_11/wlan/ieee80211_scan_sta.c
@@ -308,8 +308,12 @@ sta_add(const struct ieee80211_scanparams *sp,
ise->se_capinfo = sp->capinfo;
#ifdef IEEE80211_SUPPORT_MESH
- if (sp->meshid != NULL && sp->meshid[1] != 0)
- memcpy(ise->se_meshid, sp->meshid, 2+sp->meshid[1]);
+ if (sp->meshid != NULL && sp->meshid[1] != 0) {
+ uint8_t mlen = sp->meshid[1];
+ if (mlen > IEEE80211_MESHID_LEN)
+ mlen = IEEE80211_MESHID_LEN;
+ memcpy(ise->se_meshid, sp->meshid, 2 + mlen);
+ }
#endif
Additionally, for defense-in-depth, add validation in
ieee80211_parse_beacon() (ieee80211_input.c:621-622):
case IEEE80211_ELEMID_MESHID:
scan->meshid = frm;
+ IEEE80211_VERIFY_ELEMENT(scan->meshid,
+ IEEE80211_MESHID_LEN, status |= IEEE80211_BPARSE_MESHID_INVALID);
break;
References
- DF-0285: Same class of overflow in the mesh-specific receive path
(
ieee80211_mesh.c:2063-2064) โ that path has upstream validation but a separate overflow site. - IEEE 802.11-2020 ยง9.4.2.113 Mesh ID element: max length 32 octets.
IEEE80211_VERIFY_ELEMENTmacro is defined insys/netproto/802_11/wlan/ieee80211_input.h.
Timeline
- 2026-07-01 Discovered during automated audit.
- 2026-07-01 Reported to DragonFlyBSD security contact (pending).
PoC verification
Evidence pack
findings/poc/DF-0393 ยท 2 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | file | 2.0 KB | โ raw | |
| poc.py | file | 3.8 KB | view raw |
DF-0393 PoC โ Remote Mesh ID heap overflow in ieee80211_scan_sta.c
Summary
Sends a crafted 802.11 beacon with an oversized Mesh ID information element
(length byte = 200, exceeding the 32-byte maximum). The scan subsystem
copies 2 + 200 = 202 bytes into the 34-byte se_meshid field, overflowing
by ~168 bytes into adjacent heap-allocated struct fields including IE
pointers and list links.
Build
pip install scapy
Run
# Put WiFi adapter in monitor mode sudo airmon-ng start wlan0 # Run the PoC on the monitor interface sudo python3 poc.py --iface wlan0mon --count 100
Expected output
The victim kernel panics with a page fault when dereferencing a corrupted
pointer from the overflowed se_ies struct or se_list/se_hash links:
Fatal trap 12: page fault while in kernel mode virtual address = 0xdeadbeef41414141 cpuid = 0 KDB: stack backtrace: #0 mi_switch+0x... #1 sta_add+0x... at ieee80211_scan_sta.c:312 #2 sta_rx_mgmt+0x... at ieee80211_scan_sta.c:... #3 ieee80211_deliver_l2+0x... #4 ieee80211_input+0x...
How it works
ieee80211_parse_beacon()(ieee80211_input.c:621-622) stores the Mesh ID IE pointer without length validation.sta_add()(ieee80211_scan_sta.c:312) executesmemcpy(ise->se_meshid, sp->meshid, 2 + sp->meshid[1]).ise->se_meshidis 34 bytes; the copy writes 202 bytes.- The 168 overflow bytes corrupt:
-
se_ies(struct of IE data pointers) -se_age(int) -se_list/se_hash(TAILQ/LIST link pointers) - When the scan table is subsequently walked (select_bss, sta_iterate, adhoc_age, ieee80211_ies_expand), corrupted pointers are dereferenced โ kernel panic.
Notes
- The victim interface must be in scanning mode (background scan runs automatically every few seconds when associated).
IEEE80211_SUPPORT_MESHis compiled in by default in X86_64_GENERIC.- This is the same class of bug as DF-0285 but in a different code path (generic beacon parser vs. mesh-specific receive path).
Confirmed kernel references
โ
Detail
Evidence (decisive lines)
โ
Verdict
inconclusive