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

iwi_frame_intr frame->len bound too loose: up to 28-byte OOB read past mbuf cluster

Summary

iwi_frame_intr at if_iwi.c:1248-1249: framelen=le16toh(frame->len), capped only at MCLBYTES(2048). But mbuf cluster also holds iwi_hdr(4B)+iwi_frame(24B) prefix. m_len=4+24+framelen then m_adj(m,28) -> window [28, 28+framelen). For framelen in (2020,2048]: window extends 1-28B past cluster. DMA map loaded only MCLBYTES so trailing bytes are uninitialized kernel heap. Remote: malicious AP sends frame with len near 2048 -> OOB read into ieee80211_input. Code has TODO comment XXX >MCLBYTES is bogus. Sibling of DF-1122/DF-1145/DF-1157 WiFi frame len patterns. Fix: cap framelen<=MCLBYTES-28.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1239 Β· 8 files
FileTypeDescriptionSize
fix.diff suggested-fix tighten framelen upper bound to MCLBYTES - sizeof(iwi_hdr) - sizeof(iwi_frame) 1.1 KB view raw
VERDICT.md verdict source-level trace of 28-byte heap leak + dead-code analysis 2.9 KB ↓ raw
build.sh build-script applies fix, builds if_iwi.ko module 339 B view raw
run.sh run-script explains no-trigger on this guest 613 B view raw
env.txt environment uname, cc version, PCI inventory 553 B view raw
build.log build-log kernel build log excerpt proving -Werror clean compile of patched source 31.3 KB 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
VERDICT.md verdict source-level trace of 28-byte heap leak + dead-code analysis
↓ download raw

DF-1239 β€” iwi_frame_intr framelen bound too loose (up to 28B heap leak)

Verdict: NOT REPRODUCED (dead code at runtime β€” no hardware)

Mechanism (source-level, confirmed real)

iwi_frame_intr() at sys/dev/netif/iwi/if_iwi.c:1238 processes received 802.11 frames. The firmware-supplied frame length is bounded too loosely:

// line 1248-1249
framelen = le16toh(frame->len);
if (framelen < IEEE80211_MIN_LEN || framelen > MCLBYTES) {
    ...
    return;
}

The DMA map is loaded with only MCLBYTES (2048) bytes (line 1287-1288):

error = bus_dmamap_load(sc->rxq.data_dmat, data->map,
    mtod(mnew, void *), MCLBYTES, iwi_dma_map_addr, &data->physaddr, 0);

But the mbuf length is set to include the 28-byte prefix:

// line 1319-1320
m->m_pkthdr.len = m->m_len = sizeof(struct iwi_hdr) +    // 4 bytes
    sizeof(struct iwi_frame) + framelen;                  // 24 bytes + framelen

Then m_adj(m, 28) strips the prefix, leaving an mbuf claiming framelen bytes of payload starting at cluster offset 28. For framelen in (2020, 2048], the window [28, 28+framelen) extends 1–28 bytes past the DMA-mapped cluster β†’ ieee80211_input processes uninitialized kernel heap as if it were frame data.

Struct sizes confirmed: iwi_hdr = 4B (4 Γ— uint8_t, __packed), iwi_frame = 24B (reserved1[2]=8 + 6Γ—uint8 + signal/noise=4 + antenna/ control=2 + reserved2[2]=2 + len=2, __packed). Prefix = 28B.

Max safe framelen = MCLBYTES - 28 = 2020. The check allows up to 2048, 28 bytes too loose.

The bug is real in source. A malicious AP that sends a frame with frame->len in (2020, 2048] causes 1–28 bytes of uninitialized kernel heap to be passed to ieee80211_input.

Why it cannot reproduce on this guest

iwi is the Intel PRO/Wireless 2200BG/2915ABG Mini-PCI WiFi driver.

  • NOT in X86_64_GENERIC: only in LINT64.
  • Available as if_iwi.ko, but not loaded on the guest.
  • The QEMU guest has no WiFi card at all β€” pciconf -l shows only bridges, VGA, virtio-net, virtio-blk. QEMU does not emulate Intel 2200BG.
  • Even if kldload if_iwi were run (requires root), no PCI device would match and the driver never attaches β†’ no RX interrupt β†’ no iwi_frame_intr β†’ unreachable.

This is valid hard blocker: dead/unreachable at runtime on this guest. The threat model is a malicious WiFi AP in radio range of a real system with an Intel 2200BG/2915ABG card.

Fix

fix.diff tightens the upper bound from MCLBYTES to MCLBYTES - sizeof(struct iwi_hdr) - sizeof(struct iwi_frame) (=2020). Compiled successfully as if_iwi.ko.

Impact

  • On this guest: none (dead code, no WiFi hardware).
  • On a real system: up to 28 bytes of uninitialized kernel heap leaked to the 802.11 stack per malicious frame. Info leak (stack/heap residue) from a remote (radio-range) attacker. The iwi driver targets an old (2004-era) Mini-PCI card; real-world prevalence is low.

Fix verification

not_testable

compile validated

module/kernel build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

β€”

Verdict

Source-confirmed. iwi_frame_intr framelen MCLBYTES vs cluster-28 -> 28B heap leak. iwi NOT in GENERIC, no WiFi HW.