Skip to content

Commit 0c0ee14

Browse files
committed
wifi: mac80211: correctly identify S1G short beacon
JIRA: https://issues.redhat.com/browse/RHEL-114891 commit c5fd399 Author: Lachlan Hodges <lachlan.hodges@morsemicro.com> Date: Tue Jul 1 17:55:41 2025 +1000 wifi: mac80211: correctly identify S1G short beacon mac80211 identifies a short beacon by the presence of the next TBTT field, however the standard actually doesn't explicitly state that the next TBTT can't be in a long beacon or even that it is required in a short beacon - and as a result this validation does not work for all vendor implementations. The standard explicitly states that an S1G long beacon shall contain the S1G beacon compatibility element as the first element in a beacon transmitted at a TBTT that is not a TSBTT (Target Short Beacon Transmission Time) as per IEEE80211-2024 11.1.3.10.1. This is validated by 9.3.4.3 Table 9-76 which states that the S1G beacon compatibility element is only allowed in the full set and is not allowed in the minimum set of elements permitted for use within short beacons. Correctly identify short beacons by the lack of an S1G beacon compatibility element as the first element in an S1G beacon frame. Fixes: 9eaffe5 ("cfg80211: convert S1G beacon to scan results") Signed-off-by: Simon Wadsworth <simon@morsemicro.com> Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com> Link: https://patch.msgid.link/20250701075541.162619-1-lachlan.hodges@morsemicro.com Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: Jose Ignacio Tornos Martinez <jtornosm@redhat.com>
1 parent 476e880 commit 0c0ee14

File tree

2 files changed

+38
-14
lines changed

2 files changed

+38
-14
lines changed

include/linux/ieee80211.h

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -662,18 +662,6 @@ static inline bool ieee80211_s1g_has_cssid(__le16 fc)
662662
(fc & cpu_to_le16(IEEE80211_S1G_BCN_CSSID));
663663
}
664664

665-
/**
666-
* ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon
667-
* @fc: frame control bytes in little-endian byteorder
668-
* Return: whether or not the frame is an S1G short beacon,
669-
* i.e. it is an S1G beacon with 'next TBTT' flag set
670-
*/
671-
static inline bool ieee80211_is_s1g_short_beacon(__le16 fc)
672-
{
673-
return ieee80211_is_s1g_beacon(fc) &&
674-
(fc & cpu_to_le16(IEEE80211_S1G_BCN_NEXT_TBTT));
675-
}
676-
677665
/**
678666
* ieee80211_is_atim - check if IEEE80211_FTYPE_MGMT && IEEE80211_STYPE_ATIM
679667
* @fc: frame control bytes in little-endian byteorder
@@ -4911,6 +4899,39 @@ static inline bool ieee80211_is_ftm(struct sk_buff *skb)
49114899
return false;
49124900
}
49134901

4902+
/**
4903+
* ieee80211_is_s1g_short_beacon - check if frame is an S1G short beacon
4904+
* @fc: frame control bytes in little-endian byteorder
4905+
* @variable: pointer to the beacon frame elements
4906+
* @variable_len: length of the frame elements
4907+
* Return: whether or not the frame is an S1G short beacon. As per
4908+
* IEEE80211-2024 11.1.3.10.1, The S1G beacon compatibility element shall
4909+
* always be present as the first element in beacon frames generated at a
4910+
* TBTT (Target Beacon Transmission Time), so any frame not containing
4911+
* this element must have been generated at a TSBTT (Target Short Beacon
4912+
* Transmission Time) that is not a TBTT. Additionally, short beacons are
4913+
* prohibited from containing the S1G beacon compatibility element as per
4914+
* IEEE80211-2024 9.3.4.3 Table 9-76, so if we have an S1G beacon with
4915+
* either no elements or the first element is not the beacon compatibility
4916+
* element, we have a short beacon.
4917+
*/
4918+
static inline bool ieee80211_is_s1g_short_beacon(__le16 fc, const u8 *variable,
4919+
size_t variable_len)
4920+
{
4921+
if (!ieee80211_is_s1g_beacon(fc))
4922+
return false;
4923+
4924+
/*
4925+
* If the frame does not contain at least 1 element (this is perfectly
4926+
* valid in a short beacon) and is an S1G beacon, we have a short
4927+
* beacon.
4928+
*/
4929+
if (variable_len < 2)
4930+
return true;
4931+
4932+
return variable[0] != WLAN_EID_S1G_BCN_COMPAT;
4933+
}
4934+
49144935
struct element {
49154936
u8 id;
49164937
u8 datalen;

net/mac80211/mlme.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7201,6 +7201,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
72017201
struct ieee80211_bss_conf *bss_conf = link->conf;
72027202
struct ieee80211_vif_cfg *vif_cfg = &sdata->vif.cfg;
72037203
struct ieee80211_mgmt *mgmt = (void *) hdr;
7204+
struct ieee80211_ext *ext = NULL;
72047205
size_t baselen;
72057206
struct ieee802_11_elems *elems;
72067207
struct ieee80211_local *local = sdata->local;
@@ -7226,7 +7227,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
72267227
/* Process beacon from the current BSS */
72277228
bssid = ieee80211_get_bssid(hdr, len, sdata->vif.type);
72287229
if (ieee80211_is_s1g_beacon(mgmt->frame_control)) {
7229-
struct ieee80211_ext *ext = (void *) mgmt;
7230+
ext = (void *)mgmt;
72307231
variable = ext->u.s1g_beacon.variable +
72317232
ieee80211_s1g_optional_len(ext->frame_control);
72327233
}
@@ -7413,7 +7414,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_link_data *link,
74137414
}
74147415

74157416
if ((ncrc == link->u.mgd.beacon_crc && link->u.mgd.beacon_crc_valid) ||
7416-
ieee80211_is_s1g_short_beacon(mgmt->frame_control))
7417+
(ext && ieee80211_is_s1g_short_beacon(ext->frame_control,
7418+
parse_params.start,
7419+
parse_params.len)))
74177420
goto free;
74187421
link->u.mgd.beacon_crc = ncrc;
74197422
link->u.mgd.beacon_crc_valid = true;

0 commit comments

Comments
 (0)