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

iwi_checkforqos unbounded notif->len allows up to 292-byte OOB read past RX mbuf on crafted ASSOC RESP

Summary

iwi_notification_intr at if_iwi.c:1554-1556: calls iwi_checkforqos with len=le16toh(notif->len)-sizeof(assoc)-1. Embedded ASSOC RESP frame at cluster offset 28 (iwi_hdr+notif+assoc). notif->len from firmware up to 65535, iwi_checkforqos guard at :1378 only enforces len<IEEE80211_MAX_LEN(2313). len=2312 -> efrm=cluster+28+2312=cluster+2340, 292B past 2048B cluster. IE walk at :1401-1410 derefs frm[0]/frm[1]/iswmeoui(frm)[4B] in OOB region. Rogue AP pads ASSOC RESP with vendor IEs to ~2312B. Fix: clamp len to MCLBYTES-28.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-1240 Β· 8 files
FileTypeDescriptionSize
fix.diff suggested-fix guard underflow + clamp notif->len to cluster space before calling iwi_checkforqos 1.5 KB view raw
VERDICT.md verdict source-level trace of ~292B OOB read + dead-code analysis 2.7 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 ~292B OOB read + dead-code analysis
↓ download raw

DF-1240 β€” iwi_checkforqos unbounded notif->len (OOB read up to ~292B)

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

Mechanism (source-level, confirmed real)

iwi_notification_intr() at sys/dev/netif/iwi/if_iwi.c:1455 handles firmware notifications. For the ASSOCIATION notification, it calls:

// line 1545-1556
assoc = (struct iwi_notif_association *)(notif + 1);
switch (assoc->state) {
case IWI_ASSOC_SUCCESS:
    ...
    iwi_checkforqos(vap,
        (const struct ieee80211_frame *)(assoc+1),
        le16toh(notif->len) - sizeof(*assoc) - 1);  // <-- len from firmware

notif->len is a firmware-supplied uint16_t (0–65535). The subtraction le16toh(notif->len) - sizeof(*assoc) - 1 can also underflow to a huge int value if notif->len < 13.

Inside iwi_checkforqos (line 1368), the guard at 1378 is too loose:

if (!(sizeof(*wh)+8 < len && len < IEEE80211_MAX_LEN) || ...)  // IEEE80211_MAX_LEN=2313
    return;
frm = (const uint8_t *)&wh[1];
efrm = ((const uint8_t *) wh) + len;   // <-- can point past cluster

The frame wh = (assoc+1) sits at cluster offset 28 (iwi_hdr=4 + iwi_notif=12 + assoc=12). The cluster is MCLBYTES (2048). So safe len max = 2048 βˆ’ 28 = 2020. But the guard allows up to 2312, which is 292 bytes past the cluster. The IE walk at lines 1401–1410 dereferences frm[] and efrm which are now OOB in the mbuf cluster / adjacent kernel heap.

Struct sizes confirmed: iwi_hdr=4B, iwi_notif=12B (reserved[2]=8 + type=1 + flags=1 + len=2), iwi_notif_association=12B (state=1 + pad[11]=11). Prefix before frame = 4+12+12 = 28B.

The bug is real in source. A malicious AP / compromised firmware can drive efrm up to ~292 bytes past the DMA cluster, causing an OOB read in iwi_checkforqos.

Why it cannot reproduce on this guest

Same as DF-1239: iwi (Intel PRO/Wireless 2200BG/2915ABG) is not in GENERIC, not loaded, no WiFi hardware on the QEMU guest. The notification interrupt path is unreachable.

Valid hard blocker: dead/unreachable at runtime. Threat model is a malicious WiFi AP or compromised firmware on a real system with the card.

Fix

fix.diff guards the subtraction against underflow and clamps the result to the actual cluster space (MCLBYTES - sizeof(iwi_hdr) - sizeof(iwi_notif) - sizeof(*assoc) = 2020). Compiled successfully as if_iwi.ko.

Impact

  • On this guest: none (dead code, no WiFi hardware).
  • On a real system: OOB read of up to ~292 bytes of kernel heap per association-response notification, from a remote (radio-range) attacker via a malicious AP. Could leak kernel pointers (defeating KASLR on systems that have it) or adjacent slab data. Low real-world prevalence due to the old (2004-era) hardware.

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_checkforqos IEEE80211_MAX_LEN vs cluster-28 -> ~292B OOB read. iwi NOT in GENERIC, no WiFi HW.