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

Unvalidated hardware frame length in RX path allows heap OOB read / uninitialized-memory info leak

Summary

In rum_bulk_read_callback mbuf reported length (m_pkthdr.len m_len) taken directly from 12-bit field in device-supplied RX descriptor ((flags>>16)&0xfff max 4095) without comparison against actual USB transfer length len or mbuf cluster capacity (MCLBYTES=2048). usbd_copy_out only writes len bytes (<=2048) into freshly-allocated non-zeroed cluster but mbuf advertises up to 4095 bytes. Subsequent readers (ieee80211_input radiotap/bpf listeners) walk offsets [len m_len) uninitialized cluster memory and offsets [MCLBYTES m_len) heap OOB read past cluster allocation. m_getcl returns non-zeroed cluster so stale kernel heap exposed. Both sibling Ralink drivers (if_mtw.c:2488 if_run.c:2783) close this exact hole. Attacker: malicious USB device presenting Ralink VID/PID. /dev/wlan0 monitor mode + bpf/tcpdump harvests leaked kernel heap bytes.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2356 Β· 6 files
FileTypeDescriptionSize
VERDICT.md verdict gate analysis + unvalidated RX frame-len trace (siblings guard, rum does not) 3.5 KB ↓ raw
fix.diff suggested-fix clamp mbuf len to min(dev_len, xfer_len, MCLBYTES) 832 B view raw
build.sh build-script documents HW gate 157 B view raw
run.sh run-script prints gate proof 275 B view raw
env.txt environment guest env 1.1 KB view raw
wifi_gate.txt gate-proof usbconfig empty, no wlan iface 311 B view raw
VERDICT.md verdict gate analysis + unvalidated RX frame-len trace (siblings guard, rum does not)
↓ download raw

DF-2356 β€” Unvalidated hardware frame length in RX (sys/bus/u4b/wlan/if_rum.c)

Verdict: NOT REPRODUCED (HW-gated); REAL BUG IN SOURCE (defense-in-depth fix warranted)

Hardware gate (why the PoC cannot run on this guest)

rum is the Ralink RT2501USB/RT2601USB 802.11bgn driver. It attaches only when a matching Ralink USB wifi dongle (VID 0x148f / 0x0411 etc.) is plugged in. The audit QEMU/KVM guest has no USB device and no wifi interface:

$ usbconfig list               # No device match or lack of permissions.
$ ifconfig -l                  # vtnet0 lo0   (no wlan/rum)
$ pciconf -l | grep -iE "ralink|148f"   # (no Ralink USB wifi chip)
$ kldstat                      # kernel + ehci.ko + xhci.ko only

The RX path rum_bulk_read_callback runs only when the rum driver has attached to a Ralink USB device and is receiving frames. With no such device the path never executes. The unprivileged maxx user cannot plug a USB dongle into the QEMU guest, and there is no adjacent rogue AP threat (no radio at all).

Source trace β€” the bug is REAL (sys/bus/u4b/wlan/if_rum.c)

In rum_bulk_read_callback (if_rum.c:1127-...):

usbd_xfer_status(xfer, &len, NULL, NULL, NULL);          /* actual USB xfer len */
...
if (len < (int)(RT2573_RX_DESC_SIZE + IEEE80211_MIN_LEN)) goto tr_setup;
len -= RT2573_RX_DESC_SIZE;                              /* if_rum.c:1157 */
...
m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);                /* if_rum.c:1198, cluster=MCLBYTES=2048, NOT zeroed */
usbd_copy_out(pc, RT2573_RX_DESC_SIZE, mtod(m, uint8_t *), len);  /* if_rum.c:1208 β€” bounded to <=2048 */
...
flags = le32toh(sc->sc_rx_desc.flags);                   /* device-controlled */
...
m->m_pkthdr.len = m->m_len = (flags >> 16) & 0xfff;      /* if_rum.c:1221 β€” device-controlled 12-bit, max 4095 */

The descriptor's 12-bit length field ((flags >> 16) & 0xfff, range 0-4095) is taken directly from the device RX descriptor and assigned to the mbuf's m_len/m_pkthdr.len with no comparison against the actual USB transfer length len or the cluster capacity MCLBYTES (2048). usbd_copy_out only wrote len (≀ 2048) bytes into the non-zeroed cluster. Two consequences:

  1. Offsets [len, m_len) (when m_len > len) read uninitialised cluster memory β€” stale kernel heap exposed to ieee80211_input, radiotap and bpf listeners (/dev/bpf*, monitor mode) β€” an info leak.
  2. Offsets [MCLBYTES, m_len) (when m_len > 2048, possible since the field max is 4095) are a heap OOB read past the cluster allocation into adjacent slab objects.

Both sibling Ralink drivers close exactly this hole: - if_mtw.c:2488 β€” if (__predict_false(len > dmalen - rxwisize)) goto fail; - if_run.c:2783 β€” if (__predict_false(len > dmalen)) clamp.

Attacker: a malicious USB device presenting Ralink VID/PID, or a wireless adjacent-network rogue AP sending crafted frames; /dev/wlan0 monitor mode + bpf/tcpdump harvests leaked kernel heap bytes.

Exploit chain status

Not pursuable β€” primitive (heap OOB read / uninit info leak) requires a Ralink USB wifi dongle or adjacent radio (absent) β€” valid Phase-6 hard blocker: dead path at runtime on this guest. Read-only primitive; no escalation.

PoC changes

None. No Ralink USB wifi dongle on guest; verified by source trace only.

Clamp the mbuf length to min(device_reported_len, len) (and to MCLBYTES), matching the sibling drivers' guard. See fix.diff (matches finding proposal: add the len > dmalen-style guard rum's siblings already have).

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not_testable: PoC cannot run on this guest (HW-gated, no target device). fix.diff validated by git apply --check (clean) + line-accurate source trace confirming it closes the cited path.

git apply --check findings/poc/DF-2356/fix.diff -> OK (clean apply). No runtime test possible (HW-gated).
↓ fix.diffn/a (no target HW/device on this guest)

Confirmed kernel references

Detail

Exploit chain

none β€” valid hard blocker (driver/device path dead at runtime on this guest: no target HW / no attached device). No unprivileged->root path.

Evidence (decisive lines)

usbconfig list -> No device match or lack of permissions.; pciconf -l -> no target controller HW; ifconfig -l -> vtnet0 lo0; kldstat -> kernel/ehci/xhci only; ls /dev/<target> -> No such file or directory; id maxx -> uid=1001 groups=1001 (not operator). Source confirmed at cited lines.

PoC changes

Created findings/poc/DF-2356/{VERDICT.md,fix.diff,build.sh,run.sh,env.txt,gate_proof.txt,manifest.json}. No PoC source (HW-gated).

Verified recommended fix

clamp device-reported length to len and MCLBYTES. Full git-apply-able diff in findings/poc/DF-2356/fix.diff (git apply --check OK).

Verdict

NOT REPRODUCED (HW-gated). The bug is REAL in source (traced line-by-line). rum unvalidated hardware frame length in RX (m_len device-controlled up to 4095 > MCLBYTES=2048 OOB read + uninit leak); no Ralink USB wifi. Gate confirmed via usbconfig list (No device match / no /dev/ugen*), pciconf -l (no target controller HW), ifconfig (vtnet0 lo0 only), kldstat (no target module), and ls /dev (no target nodes). maxx (uid 1001, not in operator) cannot reach any /dev/usbctl write path.