iwn_rx_compressed_ba: unbounded firmware-supplied qid indexes sc->txq[] and sc->qid2tap[] (OOB array access / NULL deref)
Summary
iwn_rx_compressed_ba at if_iwn.c:3266-3270: qid=le16toh(ba->qid) correctly byte-swapped at :3266 but lines 3267-3268 use RAW ba->qid (uint16) as array index into sc->txq[IWN5000_NTXQUEUES=20] and sc->qid2tap[20] with NO bounds check. tap=sc->qid2tap[ba->qid] dereferenced at :3269 without NULL check. Any firmware compressed_ba with qid>=20 OOB-reads both arrays; any compressed_ba for TID whose aggregation was torn down (qid2tap[qid]=NULL via iwn_ampdu_tx_stop :7532) causes NULL deref panic in interrupt thread. Reachable: associated AP/attacker sends DELBA then Compressed BlockAck for same TID. Remote DoS minimum, OOB memory corruption if OOB qid slot contains non-NULL value. Fix: bounds-check qid<sc->ntxqs and NULL-check tap before deref.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1122 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | bounds-check qid<sc->ntxqs, use swapped qid consistently, NULL-check tap before deref | 1.3 KB | view raw |
| iwn_fix_build.log | build-log | if_iwn.ko rebuilt from patched source (with DF-1123) under -Werror, rc=0 | 21.4 KB | view raw |
| VERDICT.md | verdict | full line-by-line trace + fix rationale | 3.0 KB | β raw |
| README.md | readme | why there is no .c trigger | 1.4 KB | β raw |
| env.txt | environment | uname, cc version, kldstat | 383 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-1122 β iwn_rx_compressed_ba: unbounded firmware qid (OOB array read / NULL deref)
This finding has no userspace trigger: the bug is in the firmware-notification
handler iwn_rx_compressed_ba (sys/dev/netif/iwn/if_iwn.c:3250-3270), invoked
from the RX interrupt path when the Intel WiFi firmware posts a Compressed
BlockAck notification. The qid field comes from firmware/DMA, not from any
syscall. The realistic trigger is:
- a hostile/buggy associated access point sending DELBA followed by a
Compressed BlockAck for the same TID (so
sc->qid2tap[qid]was NULLed byiwn_ampdu_tx_stopatif_iwn.c:7532), causing the NULL-deref panic at:3269(tid = tap->txa_tid); or - a firmware/PHY notification with
ba->qid >= IWN5000_NTXQUEUES (20), causing an out-of-bounds read ofsc->txq[](:3267) andsc->qid2tap[](:3268).
Preconditions on this guest: if_iwn.ko ships in /boot/kernel but is NOT
loaded and there is no Intel Wireless (iwn) hardware in the QEMU guest, so
the driver never attaches and the RX path is dead. The bug is therefore
source-confirmed latent β real in compiled module code, unreachable at
runtime here. See VERDICT.md for the line-by-line trace.
There is no .c trigger file because no syscall drives the path; the "trigger"
is a hostile radio/firmware event, which cannot be synthesized without the NIC.
DF-1122 β VERDICT
Verdict
SOURCE-CONFIRMED (real bug), NOT REPRODUCED AT RUNTIME on this guest.
The unbounded firmware qid index and the unchecked tap dereference are
traced line-by-line in compiled module source. It does not fire here because the
iwn driver never attaches (no Intel WiFi HW). Dormant code path, not a false
positive (if_iwn.ko ships in /boot/kernel).
Mechanism (source trace)
iwn_rx_compressed_ba (sys/dev/netif/iwn/if_iwn.c:3250-3270) handles a
firmware Compressed BlockAck notification (RX interrupt path; ba is DMA'd
from firmware):
- :3266 qid = le16toh(ba->qid); β byte-swapped into the local qid.
- :3267 txq = &sc->txq[ba->qid]; β indexes sc->txq[] (sized
IWN5000_NTXQUEUES = 20, if_iwnvar.h:299) with the raw ba->qid
(uint16_t, 0..65535) β no bounds check.
- :3268 tap = sc->qid2tap[ba->qid]; β same raw index into sc->qid2tap[]
(sized IWN5000_NTXQUEUES = 20, if_iwnvar.h:393) β no bounds check.
- :3269 tid = tap->txa_tid; β dereferences tap without a NULL check.
Two consequences:
1. OOB array read β any notification with ba->qid >= 20 reads past both
arrays. (On x86 le16toh is identity, so qid == ba->qid; the raw-vs-swapped
mismatch is moot, but the missing bounds check is the bug regardless.)
2. NULL-deref panic β sc->qid2tap[qid] is set to NULL when aggregation is
torn down: iwn_ampdu_tx_stop (if_iwn.c:7532) and :3303/:3874. A
notification for a TID whose aggregation was torn down (hostile AP sends
DELBA then a Compressed BlockAck for the same TID) makes tap == NULL β
panic in the interrupt thread. Remote DoS minimum; OOB memory corruption if
the OOB qid2tap slot happens to hold a non-NULL value.
There is no userspace syscall trigger β the qid comes from firmware/DMA, not
from any ioctl. The realistic trigger is a hostile/buggy associated AP or
firmware.
Why not reproduced here
No Intel Wireless (iwn) hardware in the QEMU guest; if_iwn.ko is not loaded
(kldstat shows only kernel/ehci/xhci) and never attaches, so the RX path is
dead. The trigger cannot be synthesized without the NIC.
Fix
fix.diff bounds-checks qid >= sc->ntxqs (sc->ntxqs is the per-device queue
count, 16 or 20, used consistently as the bound elsewhere β e.g.
iwn_addba_request:7425), uses the byte-swapped qid consistently for both
array indexes, and NULL-checks tap before dereferencing β returning early
(with a debug print) in either case. Matches the finding's proposal.
Fix validation (compile)
Applies (git apply --check clean) and compiles: if_iwn.ko rebuilt
from patched source (with DF-1123's fix also applied) under -Werror,
if_iwn.c compiled clean, rc=0. Runtime before/after is not_testable (no
iwn HW; the trigger is a firmware/radio event that cannot be synthesized here).
Exploit chain
None β the primitive is firmware/radio-triggered and unreachable at runtime on this guest; impact ceiling is remote DoS (NULL deref) / OOB read on a HW-equipped host.
Fix verification
not_testablecompile validated -Werror
module rebuild rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. iwn_rx_compressed_ba raw ba->qid indexes txq[20]/qid2tap[20] unbounded + NULL tap deref. No WiFi HW.
No comments yet.