]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
wifi: mac80211: use RCU-safe iteration in ieee80211_csa_finish
authorMaharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Fri, 11 Jul 2025 03:38:46 +0000 (09:08 +0530)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 15 Jul 2025 09:03:23 +0000 (11:03 +0200)
The ieee80211_csa_finish() function currently uses for_each_sdata_link()
to iterate over links of sdata. However, this macro internally uses
wiphy_dereference(), which expects the wiphy->mtx lock to be held.
When ieee80211_csa_finish() is invoked under an RCU read-side critical
section (e.g., under rcu_read_lock()), this leads to a warning from the
RCU debugging framework.

  WARNING: suspicious RCU usage
  net/mac80211/cfg.c:3830 suspicious rcu_dereference_protected() usage!

This warning is triggered because wiphy_dereference() is not safe to use
without holding the wiphy mutex, and it is being used in an RCU context
without the required locking.

Fix this by introducing and using a new macro, for_each_sdata_link_rcu(),
which performs RCU-safe iteration over sdata links using
list_for_each_entry_rcu() and rcu_dereference(). This ensures that the
link pointers are accessed safely under RCU and eliminates the warning.

Fixes: f600832794c9 ("wifi: mac80211: restructure tx profile retrieval for MLO MBSSID")
Signed-off-by: Maharaja Kennadyrajan <maharaja.kennadyrajan@oss.qualcomm.com>
Link: https://patch.msgid.link/20250711033846.40455-1-maharaja.kennadyrajan@oss.qualcomm.com
[unindent like the non-RCU macro]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h

index 9ef280f3b55b0b34bde2903804a9d070f5aeb4f9..b99e39cb808be6855f834844a931d9d3fd12fdff 100644 (file)
@@ -3841,7 +3841,7 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
                 */
                struct ieee80211_link_data *iter;
 
-               for_each_sdata_link(local, iter) {
+               for_each_sdata_link_rcu(local, iter) {
                        if (iter->sdata == sdata ||
                            rcu_access_pointer(iter->conf->tx_bss_conf) != tx_bss_conf)
                                continue;
index 83172eb964c86da7fa91f202aba9ef0fa9f71eb1..084e2673a27ebb484d71e078d190f50c8c2f3d29 100644 (file)
@@ -1226,6 +1226,21 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
        if ((_link = wiphy_dereference((_local)->hw.wiphy,              \
                                       ___sdata->link[___link_id])))
 
+/*
+ * for_each_sdata_link_rcu() must be used under RCU read lock.
+ */
+#define for_each_sdata_link_rcu(_local, _link)                                         \
+       /* outer loop just to define the variables ... */                               \
+       for (struct ieee80211_sub_if_data *___sdata = NULL;                             \
+            !___sdata;                                                                 \
+            ___sdata = (void *)~0 /* always stop */)                                   \
+       list_for_each_entry_rcu(___sdata, &(_local)->interfaces, list)                  \
+       if (ieee80211_sdata_running(___sdata))                                          \
+       for (int ___link_id = 0;                                                        \
+            ___link_id < ARRAY_SIZE((___sdata)->link);                                 \
+            ___link_id++)                                                              \
+       if ((_link = rcu_dereference((___sdata)->link[___link_id])))
+
 #define for_each_link_data(sdata, __link)                                      \
        struct ieee80211_sub_if_data *__sdata = sdata;                          \
        for (int __link_id = 0;                                                 \