]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: mac80211: use monitor sdata with driver only if desired
authorJohannes Berg <johannes.berg@intel.com>
Thu, 25 Jul 2024 16:48:36 +0000 (18:48 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 26 Jul 2024 10:30:49 +0000 (12:30 +0200)
In commit 0d9c2beed116 ("wifi: mac80211: fix monitor channel
with chanctx emulation") I changed mac80211 to always have an
internal monitor_sdata to have something to have the chanctx
bound to.

However, if the driver didn't also have the WANT_MONITOR flag
this would cause mac80211 to allocate it without telling the
driver (which was intentional) but also use it for later APIs
to the driver without it ever having known about it which was
_not_ intentional.

Check through the code and only use the monitor_sdata in the
relevant places (TX, MU-MIMO follow settings, TX power, and
interface iteration) when the WANT_MONITOR flag is set.

Cc: stable@vger.kernel.org
Fixes: 0d9c2beed116 ("wifi: mac80211: fix monitor channel with chanctx emulation")
Reported-by: ZeroBeat <ZeroBeat@gmx.de>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219086
Tested-by: Lorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20240725184836.25d334157a8e.I02574086da2c5cf0e18264ce5807db6f14ffd9c0@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/tx.c
net/mac80211/util.c

index 85cb71de370f297fa948c590729e0c7764fb25b3..b02b84ce2130761354829ee17b5ea9d85f8d1f81 100644 (file)
@@ -114,7 +114,7 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
 
        /* apply all changes now - no failures allowed */
 
-       if (monitor_sdata)
+       if (monitor_sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
                ieee80211_set_mu_mimo_follow(monitor_sdata, params);
 
        if (params->flags) {
@@ -3053,6 +3053,9 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
                sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 
                if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
+                       if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
+                               return -EOPNOTSUPP;
+
                        sdata = wiphy_dereference(local->hw.wiphy,
                                                  local->monitor_sdata);
                        if (!sdata)
@@ -3115,7 +3118,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
        if (has_monitor) {
                sdata = wiphy_dereference(local->hw.wiphy,
                                          local->monitor_sdata);
-               if (sdata) {
+               if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
                        sdata->deflink.user_power_level = local->user_power_level;
                        if (txp_type != sdata->vif.bss_conf.txpower_type)
                                update_txp_type = true;
index 72a9ba8bc5fd9764068e00d42755f3ba922418de..edba4a31844fb6251f35e249ea59ea74e951de2f 100644 (file)
@@ -1768,7 +1768,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
                        break;
                }
                sdata = rcu_dereference(local->monitor_sdata);
-               if (sdata) {
+               if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
                        vif = &sdata->vif;
                        info->hw_queue =
                                vif->hw_queue[skb_get_queue_mapping(skb)];
@@ -3957,7 +3957,8 @@ begin:
                        break;
                }
                tx.sdata = rcu_dereference(local->monitor_sdata);
-               if (tx.sdata) {
+               if (tx.sdata &&
+                   ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
                        vif = &tx.sdata->vif;
                        info->hw_queue =
                                vif->hw_queue[skb_get_queue_mapping(skb)];
index ced19ce7c51a33198dbec12362318040dc82a597..c7ad9bc5973a0e9076e3d8fc7b594d63d842feed 100644 (file)
@@ -776,7 +776,7 @@ static void __iterate_interfaces(struct ieee80211_local *local,
        sdata = rcu_dereference_check(local->monitor_sdata,
                                      lockdep_is_held(&local->iflist_mtx) ||
                                      lockdep_is_held(&local->hw.wiphy->mtx));
-       if (sdata &&
+       if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF) &&
            (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
             sdata->flags & IEEE80211_SDATA_IN_DRIVER))
                iterator(data, sdata->vif.addr, &sdata->vif);