From: Zhao Li <enderaoelyther@gmail.com> mainline inclusion from mainline-v7.2-rc4 commit 57d503ce32eccfa7650065ca4c560f7e29a2e676 category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/17512 CVE: CVE-2026-68470 Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=... -------------------------------- Extension frames only have the extension header at the regular 802.11 header offset. The generic RX path can still reach helpers and interface dispatch code that read regular header address fields before unsupported extension subtypes are dropped. mac80211 currently only handles S1G beacon extension frames. Drop other extension subtypes before they can reach regular-header RX processing. For S1G beacons, linearize the SKB with the management-frame path and require the fixed S1G beacon header, including optional fixed fields indicated by frame control, before generic RX dispatch. Route S1G beacons through the station/default-link RX path without regular-header station lookup. Avoid regular-header address reads in the mac80211 RX paths that process S1G extension beacons, including accept-frame, duplicate-detection, address-copy, and MLO address-translation paths. Also make ieee80211_get_bssid() length-safe before returning the S1G source-address pointer. Fixes: 09a740ce352e ("mac80211: receive and process S1G beacons") Cc: stable@vger.kernel.org Signed-off-by: Zhao Li <enderaoelyther@gmail.com> Link: https://patch.msgid.link/20260611161943.91069-5-enderaoelyther@gmail.com Signed-off-by: Johannes Berg <johannes.berg@intel.com> Conflicts: net/mac80211/rx.c [Commit 57d503ce32ec built the S1G-beacon handling on top of ieee80211_rx_for_interface() and ieee80211_s1g_optional_len(), which do not exist in this tree (no include/linux/ieee80211-s1g.h). The equivalent logic is inlined into __ieee80211_rx_handle_packet(): S1G beacons are dispatched with a NULL sta (skipping the regular-header addr2 station lookup), and the optional-header length check is expressed with the existing ieee80211_next_tbtt_present(). ieee80211_prepare_and_rx_handle() needs no S1G shortcut because this tree does not have the SW-crypto/MLO address-copy paths.] Co-authored-by: BackportAgent@deepseek-v4-flash Signed-off-by: Hulk Robot <hulkrobot@huawei.com> Signed-off-by: Lu Jialin <lujialin4@huawei.com> --- net/mac80211/rx.c | 30 ++++++++++++++++++++++++++---- net/mac80211/util.c | 3 +++ 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 65fea564c9c0..ba25540c4013 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -1429,6 +1429,9 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx) if (status->flag & RX_FLAG_DUP_VALIDATED) return RX_CONTINUE; + if (ieee80211_is_ext(hdr->frame_control)) + return RX_CONTINUE; + /* * Drop duplicate 802.11 retransmissions * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery") @@ -4051,8 +4054,12 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx) struct ieee80211_hdr *hdr = (void *)skb->data; struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type); - bool multicast = is_multicast_ether_addr(hdr->addr1) || - ieee80211_is_s1g_beacon(hdr->frame_control); + bool multicast; + + if (ieee80211_is_s1g_beacon(hdr->frame_control)) + return sdata->vif.type == NL80211_IFTYPE_STATION && bssid; + + multicast = is_multicast_ether_addr(hdr->addr1); switch (sdata->vif.type) { case NL80211_IFTYPE_STATION: @@ -4639,6 +4646,19 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, err = -ENOBUFS; else err = skb_linearize(skb); + } else if (ieee80211_is_s1g_beacon(fc)) { + size_t s1g_hdr_len = offsetof(struct ieee80211_ext, + u.s1g_beacon.variable); + + if (ieee80211_next_tbtt_present(fc)) + s1g_hdr_len += 3; + + if (skb->len < s1g_hdr_len) + err = -ENOBUFS; + else + err = skb_linearize(skb); + } else if (ieee80211_is_ext(fc)) { + err = -EINVAL; } else { err = !pskb_may_pull(skb, ieee80211_hdrlen(fc)); } @@ -4714,7 +4734,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, continue; } - rx.sta = sta_info_get_bss(prev, hdr->addr2); + rx.sta = ieee80211_is_s1g_beacon(hdr->frame_control) ? + NULL : sta_info_get_bss(prev, hdr->addr2); rx.sdata = prev; ieee80211_prepare_and_rx_handle(&rx, skb, false); @@ -4722,7 +4743,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, } if (prev) { - rx.sta = sta_info_get_bss(prev, hdr->addr2); + rx.sta = ieee80211_is_s1g_beacon(hdr->frame_control) ? + NULL : sta_info_get_bss(prev, hdr->addr2); rx.sdata = prev; if (ieee80211_prepare_and_rx_handle(&rx, skb, true)) diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e49355cbb1ce..8e27e191945d 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -67,6 +67,9 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, if (ieee80211_is_s1g_beacon(fc)) { struct ieee80211_ext *ext = (void *) hdr; + if (len < offsetofend(struct ieee80211_ext, u.s1g_beacon.sa)) + return NULL; + return ext->u.s1g_beacon.sa; } -- 2.43.0