It was possible to connect STA when AP CSA was in progress which clearly was a bug. Deny attempts to increase chanctx refcount or create chanctx. This effectively denies starting a new interface and radar detection while CSA is in progress. Existing interfaces (including those with active CSA) can be stopped though. Signed-off-by: Michal Kazior <michal.kazior@xxxxxxxxx> --- net/mac80211/chan.c | 7 +++++++ net/mac80211/ieee80211_i.h | 1 + net/mac80211/util.c | 18 ++++++++++++++++++ 3 files changed, 26 insertions(+) diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index f43613a..9057b66 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c @@ -517,6 +517,13 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev)); + /* Do not allow an interface to bind to channel contexts during CSA as + * it would end up with the interface being dragged to a different + * channel once CSA completes. It's safe to unbind from channel + * contexts though. */ + if (ieee80211_is_csa_active(local)) + return -EBUSY; + mutex_lock(&local->chanctx_mtx); __ieee80211_vif_release_channel(sdata); diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index a6cda02..763a0ca 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1465,6 +1465,7 @@ int __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, int ieee80211_channel_switch(struct wiphy *wiphy, struct cfg80211_csa_settings *params, int num_params); +bool ieee80211_is_csa_active(struct ieee80211_local *local); /* interface handling */ int ieee80211_iface_init(void); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 676dc09..3e77c41 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -2775,3 +2775,21 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local, ps->dtim_count = dtim_count; } + +bool ieee80211_is_csa_active(struct ieee80211_local *local) +{ + struct ieee80211_sub_if_data *sdata; + + lockdep_assert_held(&local->mtx); + + rcu_read_lock(); + list_for_each_entry_rcu(sdata, &local->interfaces, list) { + if (sdata->vif.csa_active) { + rcu_read_unlock(); + return true; + } + } + rcu_read_unlock(); + + return false; +} -- 1.8.4.rc3 -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html