β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-0349

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)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0349 Β· 5 files
FileTypeDescriptionSize
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
README.md readme status explanation
↓ download 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.

VERDICT.md verdict source-trace confirmed OOB read, no WiFi HW
↓ download raw

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 wlan module 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_testable

compile 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.