iwn5000_rx_calib_results: signed integer underflow on firmware length and unbounded heap copy from RX buffer
Summary
iwn5000_rx_calib_results at if_iwn.c:3364: len=(le32toh(desc->len)&0x3fff)-4 with no check that masked desc->len>=4. Underflow to negative int. kmalloc(len) fails for huge size_t (caught at :3396). But for any positive len larger than actual DMA payload (e.g. firmware reports 16379 bytes but RX mbuf only carries 200 bytes), memcpy(sc->calibcmd[idx].buf, calib, len) at :3405 copies len bytes from offset 8 in 4KB mbuf -> reads up to ~12KB past mbuf cluster. calibcmd replayed to runtime firmware via iwn5000_send_calibration providing path back out. Triggered by buggy/compromised firmware or DMA injection. Fix: bound len both above and below against IWN_RBUF_SIZE.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-1124 Β· 11 files| File | Type | Description | Size | |
|---|---|---|---|---|
| harness.c | trigger-source | demonstrates underflow + OOB-read for 4 firmware-length cases | 3.0 KB | view raw |
| fix.diff | suggested-fix | clamp len to [0, IWN_RBUF_SIZE - sizeof(*desc)] | 726 B | view raw |
| build.sh | build-script | cc -O2 -o harness harness.c | 95 B | view raw |
| run.sh | run-script | timeout 10 ./harness | 67 B | view raw |
| build.log | build-log | final successful build | 13 B | view raw |
| run.log | run-log | decisive run showing all 4 cases | 1.2 KB | view raw |
| env.txt | environment | uname, cc version, pciconf (no Intel WiFi) | 403 B | view raw |
| VERDICT.md | verdict | full narrative + info-leak ceiling | 2.9 KB | β raw |
| README.md | readme | finding summary + build/run/expected | 1.5 KB | β 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-1124 β Signed integer underflow + OOB read in iwn5000_rx_calib_results (Intel WiFi)
Finding
iwn5000_rx_calib_results at sys/dev/netif/iwn/if_iwn.c:3364:
len = (le32toh(desc->len) & 0x3fff) - 4;
lenis a signedint. If(desc->len & 0x3fff) < 4, underflows to negative βkmalloc((size_t)len)= huge β ENOMEM (caught at:3396).- If firmware reports e.g. masked len = 16380,
len= 16376;kmallocsucceeds, thenmemcpy(sc->calibcmd[idx].buf, calib, len)at:3405reads 16376 bytes fromcalib = desc + 1inside a 4 KiB RX mbuf β up to ~12 KiB OOB read (info leak / panic). Thecalibcmdbuffer is later replayed to runtime firmware viaiwn5000_send_calibration.
Reachability on this guest
NOT reachable. No Intel WiFi adapter is present. if_iwn.ko is loadable
but never attaches. The bug requires buggy/compromised firmware or DMA
injection. Latent.
A userspace harness demonstrates both the underflow case and the OOB-read case for various firmware-supplied lengths.
Build / Run / Expected
cc -O2 -o harness harness.c # build.sh ./harness # run.sh # Expected: shows underflow (-4 β kmalloc(18446744073709551612)) and # OOB read (len=16376 from 4096-byte mbuf β 12288 bytes OOB)
Files
harness.cβ demonstrates underflow and OOB-read for 4 firmware-length cases.fix.diffβ addsif (len < 0 || len > (int)(IWN_RBUF_SIZE - sizeof(*desc))) return;.build.log/run.log/env.txtβ captured outputs.
VERDICT β DF-1124
Verdict: REPRODUCED (primitive) / NOT REACHABLE on guest (HW-gated)
The cited bug is real and confirmed by source trace + userspace demonstration of both the underflow and OOB-read cases. It is a latent info-leak / panic primitive requiring an Intel WiFi adapter and buggy/compromised firmware or DMA injection.
Mechanism (confirmed path:line)
iwn5000_rx_calib_results(sys/dev/netif/iwn/if_iwn.c:3350-3406) processes a calibration result notification from the firmware.:3364:len = (le32toh(desc->len) & 0x3fff) - 4;βlenis a signedint. The maskeddesc->lencomes from the firmware/DMA and is untrusted.- Underflow case: if
(desc->len & 0x3fff) < 4,lengoes negative.kmalloc(len, ...)at:3395promoteslentosize_tβ enormous allocation β ENOMEM (caught at:3396, returns). Benign for tiny masked lens. - OOB-read case: if firmware reports e.g. masked len = 16380,
len= kmalloc(16376)succeeds. Thenmemcpy(sc->calibcmd[idx].buf, calib, len)at:3405reads 16376 bytes starting atcalib = desc + 1which lives inside a 4 KiB (IWN_RBUF_SIZE) RX mbuf cluster β reads up to ~12 KiB past the mbuf boundary. Thecalibcmdbuffer is later replayed to runtime firmware viaiwn5000_send_calibration, providing a data-exfiltration path.
Reproduction (userspace harness)
The harness exercises four firmware-length scenarios:
- masked=0 β underflow to len=-4 β kmalloc(18446744073709551612) β ENOMEM
- masked=3 β underflow to len=-1 β kmalloc(18446744073709551615) β ENOMEM
- masked=16380 β len=16376 β 12288 bytes OOB read past 4 KiB mbuf
- masked=200 β len=196 β benign (within mbuf)
Impact ceiling
- Per-call: up to ~12 KiB kernel heap OOB read, contents exfiltrated to
firmware via calibration replay β info leak. On default GENERIC
(INVARIANTS ON), the OOB read may hit a poisoned/poison-checked slab and
panic; on
noinvit's a silent info leak. - Privilege: requires Intel WiFi adapter + malicious firmware or DMA injection (attacker controls the wire). Not a local unpriv path.
- Realistic: remote via compromised firmware/PCIe; niche.
Fix
fix.diff clamps len both ways after computing it:
if (len < 0 || len > (int)(IWN_RBUF_SIZE - sizeof(*desc)))
return;
IWN_RBUF_SIZE = 4096 (if_iwnreg.h:54). The upper bound is exactly
the bytes available in the RX mbuf after the desc header, since
calib = desc + 1.
Validated: if_iwn.ko builds with RC=0 after applying the fix.
Fix validation
- Patch applies cleanly:
Hunk #1 succeeded at 3362. makeinsys/dev/netif/iwn/β all firmware modules +if_iwn.kolinked,IWN_RC=0.- Cannot boot-test (no Intel WiFi);
fix_status: not_testable.
PoC changes
harness.cwritten from scratch. Demonstrates four firmware-length scenarios showing both the underflow-to-ENOMEM and the OOB-read-of-12288 cases.
Fix verification
not_testablecompile validated
module build rc=0
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source+harness. iwn5000_rx_calib signed underflow -> 12KB OOB read from mbuf. No Intel WiFi HW.
No comments yet.