((struct rt2860_node *)ni)->wcid read from nodes allocated as plain ieee80211_node (missing ic_node_alloc override)
Summary
struct rt2860_node extends ieee80211_node with wcid, and rt2860_ampdu_rx_start/stop (live under IEEE80211_HT) read it - but the driver never overrides ic_node_alloc (attach hooks only node_free), so nodes are exactly sizeof(ieee80211_node): every wcid load reads 1 byte past the heap object and the garbage value (0-255) RMWs MMIO WCID_ENTRY(w)+4. OOB read of one heap byte per BA session start/stop; value never disclosed, impact limited to wrong WCID attribute word in hardware (robustness). HW_CRYPTO readers are compiled out. Fix: node allocator + maintain wcid in newassoc.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-3751 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| README.md | β | 1.8 KB | β raw | |
| fix.diff | β | 1.5 KB | view raw | |
| verdict.json | β | 2.8 KB | view raw | |
| env.txt | β | 275 B | view raw | |
| manifest.json | β | 966 B | view raw |
DF-3751 β rt2860 reads rt2860_node.wcid from nodes allocated as plain ieee80211_node (OOB read)
struct rt2860_node (rt2860var.h:102-107) adds wcid (+ two dead rate-index arrays)
after the embedded ieee80211_node, and four sites cast a net80211 node to it and read
->wcid:
rt2860_ampdu_rx_startrt2860.c:919 andrt2860_ampdu_rx_stoprt2860.c:934 β live (#ifdef IEEE80211_HTis satisfied in default builds), invoked by net80211 whenever an 802.11n Block-Ack session starts/stops for a node;rt2860_set_keyrt2860.c:3266 /rt2860_delete_keyrt2860.c:3349 β dead (HW_CRYPTOis not defined anywhere in the tree).
But the driver never overrides ic->ic_node_alloc (attach hooks only
ic_node_free, rt2860.c:352-353), so net80211 allocates nodes with the generic
node_alloc = kmalloc(sizeof(struct ieee80211_node), M_80211_NODE, M_INTWAIT|M_ZERO)
(wlan/ieee80211_node.c:917-923). Every ((struct rt2860_node *)ni)->wcid load reads
one byte past the end of the heap allocation (allocator size-class padding or the
next slab chunk). The garbage wcid (0-255) then indexes
RT2860_WCID_ENTRY(wcid) + 4 = MMIO 0x1800 + 8*wcid + 4 (max 0x1ffc β inside the
register aperture): a read-modify-write of the wrong WCID attribute word on every BA
session event. No kernel-memory disclosure of the OOB byte; no kernel-RAM write.
Severity: Low (CWE-125, wrong-HW-config / robustness).
Fix (fix.diff): give the driver its own rt2860_node_alloc
(kmalloc(sizeof(struct rt2860_node)), matching rt2860_node_free's existing hook)
and actually maintain rn->wcid in rt2860_newassoc (which was clearly the original
intent β the field is otherwise written nowhere).
Status: source-certain; not runnable β audit guest has no Ralink NIC (env.txt).
Fix verification
not_testableFix restores the author-intended node layout (struct rt2860_node exists precisely for wcid); compile-consistent; runtime validation needs hardware.
fix.diff (git apply --check passes against pristine sys/)
Confirmed kernel references
Detail
Evidence (decisive lines)
VERDICT.md (alloc-site proof), fix.diff (adds rt2860_node_alloc + sets rn->wcid in newassoc; git apply --check passes)
PoC changes
Analysis-only; no runtime PoC possible without the NIC.
Verified recommended fix
Install ic_node_alloc = rt2860_node_alloc (kmalloc sizeof(struct rt2860_node)) and set ((struct rt2860_node *)ni)->wcid = wcid in rt2860_newassoc.
Verdict
The driver declares struct rt2860_node { struct ieee80211_node ni; uint8_t wcid; ... } (rt2860var.h:102-107) and reads ((struct rt2860_node )ni)->wcid in the live AMPDU callbacks rt2860_ampdu_rx_start (rt2860.c:919) and rt2860_ampdu_rx_stop (rt2860.c:934) -- and in the compiled-out HW_CRYPTO key paths (rt2860.c:3266/3349; HW_CRYPTO is never defined anywhere in the tree) -- but never installs an ic_node_alloc override (no 'node_alloc' in the file; attach hooks only ic_node_free at rt2860.c:353). net80211's generic node_alloc allocates exactly sizeof(struct ieee80211_node) (wlan/ieee80211_node.c:917-923), so the wcid load reads one byte past the end of the heap object; the value (allocator padding / adjacent slab bytes) then indexes MMIO RT2860_WCID_ENTRY(wcid)+4 (0x1800+8wcid+4 <= 0x1ffc -- inside the register aperture, so no kernel-RAM write). Impact: an out-of-bounds read feeding a wrong-hardware-register RMW for every BA session start/stop; the byte read is not disclosed to the attacker. Certain at source level, low impact. Not reproduced: guest has no Ralink NIC (env.txt).
No comments yet.