Re: [PATCH 2/2] wifi: rtw89: fix OOB read in __rtw89_wow_parse_akm()
From: Maxim Skokov
Date: Sat Sep 05 2026 - 19:43:50 EST
On Sun, Aug 30, 2026 at 02:31:53PM +0000, Tristan Madani wrote:
> skb->len is the total frame length, not the length of the IE portion.
> The IEs in an association request start at offset 28 (24-byte header +
> 4-byte fixed fields), so the correct IE length is skb->len minus that
> offset. Passing the full frame length causes cfg80211_find_ie() to walk
> up to 28 bytes past the end of the skb data buffer, triggering a
> slab-out-of-bounds read.
The length passed to cfg80211_find_ie() is indeed wrong and the fix looks
correct to me. I did try to reproduce the reported slab-out-of-bounds
though, and I don't think it is reachable. If I'm wrong about this,
I'd be glad to be corrected.
cfg80211_find_ie() walks the elements via for_each_element(), which is
bounded by _data + _datalen and never dereferences past it. With
ies = skb->data + 28 and len = skb->len, the highest byte the walk can
touch is skb->data + 28 + skb->len - 1, i.e. exactly 28 bytes past
skb_tail_pointer(), as you describe.
What follows skb_tail_pointer(), however, is the skb tailroom and then
struct skb_shared_info, and both live inside the same allocation.
sizeof(struct skb_shared_info) is 320 bytes on x86_64, so even with zero
tailroom the 28-byte overread stays within the object and KASAN has
nothing to report.
Measured on RTL8851BE (rtw89_8851be) with a kprobe on
__rtw89_wow_parse_akm(), on a real association request:
skb->len tailroom overread slack to end of allocation
160 1552 28 1872
So the defect is a read of uninitialised memory inside the skb rather
than an out-of-bounds access -- KMSAN territory, not KASAN. The
practical consequence is that on a network with no RSN IE (an open BSS,
where mac80211 emits no RSN element at all), the walk continues into the
tailroom and may match a bogus element with id 48, after which
rtw_wow->akm is set from garbage.
That is still worth fixing, but it may be worth rewording the commit
message, since the "slab-out-of-bounds" wording is what justifies the
Cc: stable here. The same reasoning applies to patch 1/2.
One more thing in the same function, which this patch does not address:
rsn_ie = (struct rtw89_rsn_ie *)rsn;
rtw_wow->akm = rsn_ie->akm_cipher_suite.type;
struct rtw89_rsn_ie is 20 bytes and akm_cipher_suite.type sits at offset
19, but cfg80211_find_ie() only validates the element header. A minimal
RSN element with datalen = 2 (version only) makes that read land 15
bytes past the end of the element, and with the length fix applied it can
still reach past the end of the frame when the element sits at the tail.
Checking rsn[1] before the cast would close that too.
Thanks,
Maxim