]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
mac80211: fix a crash triggered by CSA with AP VLAN enabled
authorFelix Fietkau <nbd@nbd.name>
Thu, 5 Mar 2026 17:12:09 +0000 (17:12 +0000)
committerFelix Fietkau <nbd@nbd.name>
Thu, 5 Mar 2026 17:25:59 +0000 (18:25 +0100)
Fix getting the correct operating channel for stations on VLAN

Signed-off-by: Felix Fietkau <nbd@nbd.name>
package/kernel/mac80211/patches/subsys/330-mac80211-fix-crash-in-ieee80211_chan_bw_change-for-A.patch [new file with mode: 0644]
package/kernel/mac80211/patches/subsys/350-mac80211-allow-scanning-while-on-radar-channel.patch

diff --git a/package/kernel/mac80211/patches/subsys/330-mac80211-fix-crash-in-ieee80211_chan_bw_change-for-A.patch b/package/kernel/mac80211/patches/subsys/330-mac80211-fix-crash-in-ieee80211_chan_bw_change-for-A.patch
new file mode 100644 (file)
index 0000000..6693829
--- /dev/null
@@ -0,0 +1,39 @@
+From: Felix Fietkau <nbd@nbd.name>
+Date: Thu, 5 Mar 2026 17:04:11 +0000
+Subject: [PATCH] mac80211: fix crash in ieee80211_chan_bw_change for AP_VLAN
+ stations
+
+ieee80211_chan_bw_change() iterates all stations and accesses
+link->reserved.oper via sta->sdata->link[link_id]. For stations on
+AP_VLAN interfaces (e.g. 4addr WDS clients), sta->sdata points to
+the VLAN sdata, whose link never participates in chanctx reservations.
+This leaves link->reserved.oper zero-initialized with chan == NULL,
+causing a NULL pointer dereference in __ieee80211_sta_cap_rx_bw()
+when accessing chandef->chan->band during CSA.
+
+Resolve the VLAN sdata to its parent AP sdata using get_bss_sdata()
+before accessing link data.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Felix Fietkau <nbd@nbd.name>
+---
+
+--- a/net/mac80211/chan.c
++++ b/net/mac80211/chan.c
+@@ -441,13 +441,15 @@ static void ieee80211_chan_bw_change(str
+       rcu_read_lock();
+       list_for_each_entry_rcu(sta, &local->sta_list,
+                               list) {
+-              struct ieee80211_sub_if_data *sdata = sta->sdata;
++              struct ieee80211_sub_if_data *sdata;
+               enum ieee80211_sta_rx_bandwidth new_sta_bw;
+               unsigned int link_id;
+               if (!ieee80211_sdata_running(sta->sdata))
+                       continue;
++              sdata = get_bss_sdata(sta->sdata);
++
+               for (link_id = 0; link_id < ARRAY_SIZE(sta->sdata->link); link_id++) {
+                       struct ieee80211_link_data *link =
+                               rcu_dereference(sdata->link[link_id]);
index c4fd726b812f107739cc305ff8115e55b60acdc1..9e934f24ffe46fbe1bb923f537fd295133a308fe 100644 (file)
@@ -48,7 +48,7 @@
        if (sdata->wdev.links[link_id].cac_started)
 --- a/net/mac80211/chan.c
 +++ b/net/mac80211/chan.c
-@@ -644,10 +644,11 @@ ieee80211_find_chanctx(struct ieee80211_
+@@ -646,10 +646,11 @@ ieee80211_find_chanctx(struct ieee80211_
        return NULL;
  }
  
@@ -61,7 +61,7 @@
        struct ieee80211_link_data *link;
        struct ieee80211_channel *chan;
        int radio_idx;
-@@ -658,14 +659,25 @@ bool ieee80211_is_radar_required(struct
+@@ -660,14 +661,25 @@ bool ieee80211_is_radar_required(struct
                return false;
  
        for_each_sdata_link(local, link) {