]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: mac80211: bounds-check link_id in ieee80211_ml_epcs
authorAlexandru Hossu <hossu.alexandru@gmail.com>
Fri, 15 May 2026 10:29:08 +0000 (12:29 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 20 May 2026 09:04:17 +0000 (11:04 +0200)
IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID is 0x000f, so link_id extracted
from a PRIO_ACCESS ML element PER_STA_PROFILE subelement can be 0..15.
sdata->link[] has IEEE80211_MLD_MAX_NUM_LINKS (15) entries (indices 0..14),
making index 15 out-of-bounds.

A connected WiFi 7 AP can trigger this by sending an EPCS Enable Response
action frame with a PER_STA_PROFILE subelement where link_id = 15.  The
unsolicited-notification path (dialog_token = 0) is reachable any time
EPCS is already enabled, without any prior client request.

sdata->link[15] reads into the first word of sdata->activate_links_work
(a wiphy_work whose embedded list_head is non-NULL after INIT_LIST_HEAD),
so the NULL check on the result does not catch the invalid access.  The
garbage pointer is then passed to ieee80211_sta_wmm_params(), which
dereferences link->sdata and crashes the kernel.

The same class of bug was fixed for ieee80211_ml_reconfiguration() by
commit 162d331d833d ("wifi: mac80211: bounds-check link_id in
ieee80211_ml_reconfiguration").

Fixes: de86c5f60839 ("wifi: mac80211: Add support for EPCS configuration")
Signed-off-by: Alexandru Hossu <hossu.alexandru@gmail.com>
Link: https://patch.msgid.link/20260515102908.1653088-1-hossu.alexandru@gmail.com
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/mlme.c

index 0a0f27836d5706215f1bcec9e66fcff668c0bad4..ca1d29daf01900e1b6d8ebfedb11b41418ec933c 100644 (file)
@@ -11232,6 +11232,9 @@ static void ieee80211_ml_epcs(struct ieee80211_sub_if_data *sdata,
                control = get_unaligned_le16(pos);
                link_id = control & IEEE80211_MLE_STA_EPCS_CONTROL_LINK_ID;
 
+               if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+                       continue;
+
                link = sdata_dereference(sdata->link[link_id], sdata);
                if (!link)
                        continue;