Commit 8f4fa087 authored by Johannes Berg's avatar Johannes Berg

wifi: mac80211: use monitor sdata with driver only if desired

In commit 0d9c2bee ("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: 0d9c2bee ("wifi: mac80211: fix monitor channel with chanctx emulation")
Reported-by: default avatarZeroBeat <ZeroBeat@gmx.de>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=219086Tested-by: default avatarLorenzo Bianconi <lorenzo@kernel.org>
Link: https://patch.msgid.link/20240725184836.25d334157a8e.I02574086da2c5cf0e18264ce5807db6f14ffd9c0@changeidSigned-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 1722389b
...@@ -114,7 +114,7 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata, ...@@ -114,7 +114,7 @@ static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
/* apply all changes now - no failures allowed */ /* 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); ieee80211_set_mu_mimo_follow(monitor_sdata, params);
if (params->flags) { if (params->flags) {
...@@ -3053,6 +3053,9 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, ...@@ -3053,6 +3053,9 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
if (!ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF))
return -EOPNOTSUPP;
sdata = wiphy_dereference(local->hw.wiphy, sdata = wiphy_dereference(local->hw.wiphy,
local->monitor_sdata); local->monitor_sdata);
if (!sdata) if (!sdata)
...@@ -3115,7 +3118,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, ...@@ -3115,7 +3118,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
if (has_monitor) { if (has_monitor) {
sdata = wiphy_dereference(local->hw.wiphy, sdata = wiphy_dereference(local->hw.wiphy,
local->monitor_sdata); local->monitor_sdata);
if (sdata) { if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
sdata->deflink.user_power_level = local->user_power_level; sdata->deflink.user_power_level = local->user_power_level;
if (txp_type != sdata->vif.bss_conf.txpower_type) if (txp_type != sdata->vif.bss_conf.txpower_type)
update_txp_type = true; update_txp_type = true;
......
...@@ -1768,7 +1768,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local, ...@@ -1768,7 +1768,7 @@ static bool __ieee80211_tx(struct ieee80211_local *local,
break; break;
} }
sdata = rcu_dereference(local->monitor_sdata); sdata = rcu_dereference(local->monitor_sdata);
if (sdata) { if (sdata && ieee80211_hw_check(&local->hw, WANT_MONITOR_VIF)) {
vif = &sdata->vif; vif = &sdata->vif;
info->hw_queue = info->hw_queue =
vif->hw_queue[skb_get_queue_mapping(skb)]; vif->hw_queue[skb_get_queue_mapping(skb)];
...@@ -3957,7 +3957,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw, ...@@ -3957,7 +3957,8 @@ struct sk_buff *ieee80211_tx_dequeue(struct ieee80211_hw *hw,
break; break;
} }
tx.sdata = rcu_dereference(local->monitor_sdata); 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; vif = &tx.sdata->vif;
info->hw_queue = info->hw_queue =
vif->hw_queue[skb_get_queue_mapping(skb)]; vif->hw_queue[skb_get_queue_mapping(skb)];
......
...@@ -776,7 +776,7 @@ static void __iterate_interfaces(struct ieee80211_local *local, ...@@ -776,7 +776,7 @@ static void __iterate_interfaces(struct ieee80211_local *local,
sdata = rcu_dereference_check(local->monitor_sdata, sdata = rcu_dereference_check(local->monitor_sdata,
lockdep_is_held(&local->iflist_mtx) || lockdep_is_held(&local->iflist_mtx) ||
lockdep_is_held(&local->hw.wiphy->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 || (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
sdata->flags & IEEE80211_SDATA_IN_DRIVER)) sdata->flags & IEEE80211_SDATA_IN_DRIVER))
iterator(data, sdata->vif.addr, &sdata->vif); iterator(data, sdata->vif.addr, &sdata->vif);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment