aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
authorLachlan Hodges <lachlan.hodges@morsemicro.com>2025-06-03 15:35:38 +1000
committerJohannes Berg <johannes.berg@intel.com>2025-06-05 11:32:16 +0200
commit1e1f706fc2ce90eaaf3480b3d5f27885960d751c (patch)
tree5775ccb7969b2684280857d242b3fdaf22fd1c13 /net/wireless
parentMerge tag 'net-next-6.16' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next (diff)
downloadlinux-rng-1e1f706fc2ce90eaaf3480b3d5f27885960d751c.tar.xz
linux-rng-1e1f706fc2ce90eaaf3480b3d5f27885960d751c.zip
wifi: cfg80211/mac80211: correctly parse S1G beacon optional elements
S1G beacons are not traditional beacons but a type of extension frame. Extension frames contain the frame control and duration fields, followed by zero or more optional fields before the frame body. These optional fields are distinct from the variable length elements. The presence of optional fields is indicated in the frame control field. To correctly locate the elements offset, the frame control must be parsed to identify which optional fields are present. Currently, mac80211 parses S1G beacons based on fixed assumptions about the frame layout, without inspecting the frame control field. This can result in incorrect offsets to the "variable" portion of the frame. Properly parse S1G beacon frames by using the field lengths defined in IEEE 802.11-2024, section 9.3.4.3, ensuring that the elements offset is calculated accurately. Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results") Fixes: cd418ba63f0c ("mac80211: convert S1G beacon to scan results") Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com> Link: https://patch.msgid.link/20250603053538.468562-1-lachlan.hodges@morsemicro.com Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/scan.c18
1 files changed, 7 insertions, 11 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index ddd3a97f6609..e8a4fe44ec2d 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -3250,6 +3250,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
const u8 *ie;
size_t ielen;
u64 tsf;
+ size_t s1g_optional_len;
if (WARN_ON(!mgmt))
return NULL;
@@ -3264,12 +3265,11 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
ext = (void *) mgmt;
- if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
- min_hdr_len = offsetof(struct ieee80211_ext,
- u.s1g_short_beacon.variable);
- else
- min_hdr_len = offsetof(struct ieee80211_ext,
- u.s1g_beacon.variable);
+ s1g_optional_len =
+ ieee80211_s1g_optional_len(ext->frame_control);
+ min_hdr_len =
+ offsetof(struct ieee80211_ext, u.s1g_beacon.variable) +
+ s1g_optional_len;
} else {
/* same for beacons */
min_hdr_len = offsetof(struct ieee80211_mgmt,
@@ -3285,11 +3285,7 @@ cfg80211_inform_bss_frame_data(struct wiphy *wiphy,
const struct ieee80211_s1g_bcn_compat_ie *compat;
const struct element *elem;
- if (ieee80211_is_s1g_short_beacon(mgmt->frame_control))
- ie = ext->u.s1g_short_beacon.variable;
- else
- ie = ext->u.s1g_beacon.variable;
-
+ ie = ext->u.s1g_beacon.variable + s1g_optional_len;
elem = cfg80211_find_elem(WLAN_EID_S1G_BCN_COMPAT, ie, ielen);
if (!elem)
return NULL;