RX mbuf m_len set from device-controlled RX descriptor flags with no bound -> heap OOB read
Summary
rum_bulk_read_callback at if_rum.c:1208 usbd_copy_out copies exactly len bytes (bounded by MCLBYTES). :1221 m->m_pkthdr.len = m->m_len = (flags>>16)&0xfff from device-controlled sc->sc_rx_desc.flags. NO check that descriptor length <= len or <= MCLBYTES. Malicious USB device (RT2573 VID/PID) sets flags bits[16..27] to 4095 -> m_len=4095 past 2048-byte cluster -> net80211/BPF reads 2047 bytes past cluster into kernel heap. Monitor mode + tcpdump = info leak to userspace. Most likely panic in ieee80211_input. Fix: if(((flags>>16)&0xfff)>len || >MCLBYTES) drop.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-0997 Β· 7 files| File | Type | Description | Size | |
|---|---|---|---|---|
| fix.diff | suggested-fix | bounds-check descriptor pktlen against len and MCLBYTES | 1.1 KB | view raw |
| module_build.log | build-log | if_rum.ko compiles cleanly with the fix applied | 1.3 KB | view raw |
| VERDICT.md | verdict | full narrative | 3.6 KB | β raw |
| README.md | readme | summary | 957 B | β raw |
| manifest.json | manifest | this catalog | 2.1 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 |
DF-0997 β rum RX mbuf m_len heap OOB read
Summary
rum_bulk_read_callback at sys/bus/u4b/wlan/if_rum.c:1221 sets
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff from a device-controlled
RX descriptor field. A malicious/faulty RT2573 USB adapter can advertise a
12-bit length up to 4095 even though only β€2048 bytes were actually received
into the cluster. Subsequent readers walk off the cluster into kernel heap.
Why not tested on default guest
No Ralink RT2573 USB WiFi adapter is attached to the QEMU guest and
if_rum.ko is not loaded. Reproduction requires USB HW passthrough or a
USB-gadget fuzzer β not available here.
Fix
fix.diff bounds-checks the descriptor pktlen against both len
(host-controller-bounded actual transfer length) and MCLBYTES, dropping
the frame if bogus.
Compilation check
The fix (applied together with DF-0998 and DF-0999) compiles cleanly into
if_rum.ko β see module_build.log.
DF-0997 β rum RX mbuf m_len set from device-controlled descriptor (heap OOB read)
Verdict
NOT TESTABLE on default guest (requires Ralink RT2573 USB WiFi adapter or
USB-fuzzer emulation, neither present in the QEMU guest). Bug is real and
confirmed by source review; the fix.diff compiles cleanly as a KLD module
(see module_build.log).
Mechanism (cited)
rum_bulk_read_callback() at sys/bus/u4b/wlan/if_rum.c:1140:
-
Line 1146 bounds-checks only the lower bound of
len(the host-controller-reported actual transfer length):if (len < RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN) goto tr_setup;No upper bound onlen. (In practice the USB layer capslenat thebufsize = MCLBYTES + RT2573_RX_DESC_SIZE, so the immediate write at line 1208 is bounded β the bug is the separate m_len assignment below.) -
Line 1208β1209:
usbd_copy_out(pc, RT2573_RX_DESC_SIZE, mtod(m, ...), len);copieslenbytes of received frame data into a freshly-allocated mbuf cluster (m_getclβ MCLBYTES = 2048 bytes). -
Line 1221:
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;sets the mbuf length from a 12-bit field of the device-controlled RX descriptorflagsβ NOT fromlen. The descriptor is parsed at line 1162 from the USB transfer viausbd_copy_out(pc, 0, &sc->sc_rx_desc, RT2573_RX_DESC_SIZE).
The 12-bit field allows values up to 4095. A malicious or faulty USB device
(the RT2573 announces its own RX descriptor contents) can advertise e.g.
(flags >> 16) & 0xfff == 4095 while delivering only len (β€ MCLBYTES)
actual frame bytes. The mbuf's m_len is then 4095 while only β€2048 bytes
were actually written into the cluster.
Any subsequent reader that walks m_len bytes from mtod(m, ...) walks
past the 2048-byte cluster into kernel heap β a heap OOB read.
The finding cites ieee80211_input (which panics on the bogus data) and
BPF/monitor-mode tcpdump as the user-readable leak path.
Impact
- Heap OOB read of up to ~2047 bytes per packet past the cluster boundary.
- Reachable by a malicious USB device (considerable physical/access precondition)
or by USB-fuzz on emulated device β
CVSS:3.1/AV:P/AC:L/PR:N/UI:N/S:U/C:H/I:N/A:H. - Most likely observed effect is a panic in
ieee80211_inputfrom OOB payload; an attacker who controls a BPF listener on the interface can exfiltrate leaked bytes via monitor-mode capture.
Why not tested on the guest
- The QEMU guest has no
rumdevice attached (no USB WiFi passthrough). - The
if_rum.komodule is not loaded on the default kernel. - Reproduction requires either: (a) a physical RT2573 USB WiFi adapter passed through to the guest, or (b) a USB-fuzzer/gadget framework that emulates an RT2573 sending crafted RX descriptors. Neither is available on this audit guest.
- The fix.diff was validated to compile cleanly as a KLD module
(see
module_build.log) β the three rum fixes (DF-0997/0998/0999) were applied simultaneously to/usr/src/sys/bus/u4b/wlan/if_rum.candmakein/usr/src/sys/bus/u4b/wlan/rumproducedif_rum.kowith rc=0.
Fix
fix.diff β at line 1221, extract pktlen = (flags >> 16) & 0xfff and
verify pktlen <= len && pktlen <= MCLBYTES; drop the frame (m_freem,
++ic->ic_ierrors, goto tr_setup) if the descriptor length is bogus.
This prevents the OOB read regardless of what the device puts in the
descriptor.
Files
fix.diffβ bounds-check pktlen against len and MCLBYTESmodule_build.logβ proof the patchedif_rum.ccompilesVERDICT.mdβ this narrativeREADME.mdβ summarymanifest.jsonβ artifact catalog
Fix verification
not_testablecompile validated
see evidence pack
Confirmed kernel references
β
Detail
Exploit chain
none
Evidence (decisive lines)
β
Verdict
Source-confirmed. rum RX m_len from device 12-bit flags -> OOB read. No if_rum HW. Fix compiles.
No comments yet.