[PATCH] wifi: mac80211: only accept IBSS channel switch from our own BSSID
From: Yingjie Cao
Date: Tue Jun 23 2026 - 05:08:03 EST
ieee80211_rx_bss_info() acts on a channel switch announcement (CSA)
carried in a received beacon or probe response before it verifies that
the frame's BSSID matches our own IBSS; it only checks that the SSID
matches. ieee80211_rx_mgmt_spectrum_mgmt() acts on a spectrum management
(channel switch) action frame without checking the BSSID at all.
Because of this, any station in radio range that knows the IBSS SSID
(which is broadcast in cleartext) can inject a beacon or action frame
carrying a CSA element that points at an unsupported channel. The switch
then fails in ieee80211_ibss_process_chanswitch(), which queues
csa_connection_drop_work and tears the whole IBSS down. The members
rejoin and the attacker repeats, resulting in a persistent,
unauthenticated denial of service. Encrypted IBSS networks are equally
affected because beacons are not protected. Since both of these CSA
entry points are IBSS-specific, the impact is confined to IBSS (ad-hoc)
mode; managed-mode CSA is handled separately in mlme.c and is unaffected.
Only honour a channel switch that originates from our own IBSS, i.e.
when the BSSID matches. A CSA carried in a beacon from a foreign BSSID
that merely shares our SSID is now ignored; such a beacon remains a
candidate for the normal IBSS merge path. A channel switch coming from a
station in our own IBSS keeps working exactly as before.
Fixes: cd7760e62c2a ("mac80211: add support for CSA in IBSS mode")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Yingjie Cao <yingjcao@xxxxxxxxxxx>
---
net/mac80211/ibss.c | 19 +++++++++++++++----
1 file changed, 15 insertions(+), 4 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 97292ff51475..6440fd915aa5 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -895,6 +895,10 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
if (mgmt->u.action.action_code != WLAN_ACTION_SPCT_CHL_SWITCH)
return;
+ /* only act on channel switch frames coming from our own IBSS */
+ if (!ether_addr_equal(mgmt->bssid, sdata->u.ibss.bssid))
+ return;
+
if (!sdata->vif.bss_conf.csa_active)
ieee80211_ibss_process_chanswitch(sdata, elems, false);
}
@@ -1111,14 +1115,21 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
sdata->u.ibss.ssid_len))
goto put_bss;
- /* process channel switch */
- if (sdata->vif.bss_conf.csa_active ||
- ieee80211_ibss_process_chanswitch(sdata, elems, true))
+ /* don't process beacons while a channel switch is in progress */
+ if (sdata->vif.bss_conf.csa_active)
goto put_bss;
/* same BSSID */
- if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid))
+ if (ether_addr_equal(cbss->bssid, sdata->u.ibss.bssid)) {
+ /*
+ * Only act on a channel switch announcement that comes from
+ * our own IBSS (i.e. matching BSSID). Acting on a CSA from a
+ * foreign BSSID that merely shares our SSID would let any
+ * station force us off-channel or tear the cell down.
+ */
+ ieee80211_ibss_process_chanswitch(sdata, elems, true);
goto put_bss;
+ }
/* we use a fixed BSSID */
if (sdata->u.ibss.fixed_bssid)
--
2.39.5 (Apple Git-154)