Heap OOB read in PREQ processing when target count is 0: (ndest-1) wraps to SIZE_MAX
Summary
verify_mesh_preq_len(:311) accepts ndest==0. Alloc sizeof(*preq)+(ndest-1)*sizeof(target) -> (0-1)=SIZE_MAX*sizeof(target) wraps to tiny alloc ~34 bytes. hwmp_recv_preq(:1005) unconditionally derefs preq_targets[0] (offset 34-44, 11 bytes past alloc). Remote: mesh peer sends PREQ with target count 0. Heap OOB read ~11 bytes adjacent slab -> info leak/route corruption.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0349 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| VERDICT.md | verdict | source-trace confirmed OOB read, no WiFi HW | 2.5 KB | β raw |
| README.md | readme | status explanation | 770 B | β raw |
| fix.diff | suggested-fix | reject ndest<1 in verify_mesh_preq_len; compiles on GENERIC | 731 B | view raw |
| ../fix_build_combined.log | build-log | Combined 41-finding kernel build (rc=0, -Werror clean) | 5.6 MB | β download |
| ../fix_build_summary.txt | build-summary | Summary of the combined 41-finding kernel build | 826 B | view raw |
DF-0349 PoC β WiFi HWMP PREQ OOB read
Status: REAL (source-trace confirmed), not testable on this guest
The OOB read is confirmed by tracing:
- verify_mesh_preq_len() accepts ndest==0
- kmalloc(sizeof(*preq) + (ndest-1)*sizeof(target)) wraps to 34 bytes
- Slab rounds to 40 bytes; preq_targets[0] at offset 34-44 β 5 bytes OOB
- hwmp_recv_preq() at :1005 unconditionally reads preq_targets[0]
Not testable because:
- No WiFi hardware on this guest
- wlan module not loaded at runtime
- Requires a remote mesh peer sending crafted PREQ frames
The code IS compiled into GENERIC (device wlan +
IEEE80211_SUPPORT_MESH).
Fix
See fix.diff β rejects ndest < 1 in verify_mesh_preq_len().
Verified to compile cleanly on GENERIC.
DF-0349 β Heap OOB read in PREQ processing when target count is 0
Verdict: REAL (source-trace confirmed) β not testable on this guest (no WiFi HW)
Mechanism
verify_mesh_preq_len() at sys/netproto/802_11/wlan/ieee80211_hwmp.c:311-336
returns ndest which can be 0 (reads a byte from the frame at
:320/:324). The length check at :328 passes with ndest==0
when iefrm[1] == IEEE80211_MESHPREQ_BASE_SZ (26). Returns 0 β the
if (ndest < 0) guard at :426 does NOT catch 0.
The caller at :431-433:
preq = kmalloc(sizeof(*preq) +
(ndest - 1) * sizeof(*preq->preq_targets), ...);
With ndest=0:
- (ndest - 1) = -1 (int)
- Implicit conversion to size_t β SIZE_MAX (0xFFFFFFFFFFFFFFFF)
- SIZE_MAX * sizeof(target) = wraps: sizeof(*preq) - sizeof(target)
= 45 - 11 = 34 bytes allocated
preq_targets[0] starts at offset 34 in the struct. DragonFly's slab
allocator (zoneindex() at kern_slaballoc.c:642-645) rounds 34 β
40 bytes (next multiple of 8). So:
- Bytes 34-39: within the 40-byte slab chunk (padding, zeroed by M_ZERO)
- Bytes 40-44: 5 bytes OOB β past the slab chunk into adjacent
object or slab metadata
hwmp_recv_preq() at :1005 unconditionally derefs
PREQ_TADDR(0) = preq->preq_targets[0].target_addr (offset 35-40)
and PREQ_TSEQ(0) (offset 41-44), reading 5 bytes of OOB heap.
The OOB bytes are used as:
- An ethernet address for ether_sprintf() (printed to kernel log)
- A lookup key for ieee80211_mesh_rt_find()
Privilege / testability
- Remote-triggerable: any WiFi mesh peer can send a crafted PREQ with
target_count=0. - The wlan + mesh code IS compiled into the GENERIC kernel
(
device wlan,options IEEE80211_SUPPORT_MESH). - But requires WiFi hardware to receive mesh frames β none on this guest.
- The
wlanmodule is not loaded at runtime (no WiFi interfaces).
This is a valid hard blocker: the code path is unreachable at runtime on this guest (no WiFi hardware to receive PREQ frames).
Fix
fix.diff β add if (ndest < 1) rejection in
verify_mesh_preq_len() after the length check. A PREQ with zero
targets is invalid per IEEE 802.11s and would cause the OOB. The fix
is compiled and verified to build cleanly on GENERIC.
Impact
Remote heap OOB read (~5 bytes) from an unauthenticated WiFi mesh peer. Info leak of adjacent slab data + potential route corruption (the OOB bytes are used as a route lookup key). Realistic only in a mesh WiFi deployment with HWMP routing enabled.
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. HWMP PREQ ndest=0 -> kmalloc wrap -> 5B OOB read past slab chunk. No WiFi HW. Fix compiles on GENERIC.
No comments yet.