diff options
author | Johannes Berg <johannes.berg@intel.com> | 2017-11-13 05:33:55 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2017-11-20 11:01:31 -0500 |
commit | 33ddd81e2bd5d9970b9f01ab383ba45035fa41ee (patch) | |
tree | 8ac9805306fbd178c65b8cf42eef0bc1f19118f2 | |
parent | 67bd52386125ce1159c0581cbcd2740addf33cd4 (diff) |
mac80211: properly free requested-but-not-started TX agg sessions
When deleting a station or otherwise tearing down all aggregation
sessions, make sure to delete requested but not yet started ones,
to avoid the following scenario:
* session is requested, added to tid_start_tx[]
* ieee80211_ba_session_work() runs, gets past BLOCK_BA check
* ieee80211_sta_tear_down_BA_sessions() runs, locks &sta->ampdu_mlme.mtx,
e.g. while deleting the station - deleting all active sessions
* ieee80211_ba_session_work() continues since tear down flushes it, and
calls ieee80211_tx_ba_session_handle_start() for the new session, arms
the timer for it
* station deletion continues to __cleanup_single_sta() and frees the
session struct, while the timer is armed
Reported-by: Fengguang Wu <fengguang.wu@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
-rw-r--r-- | net/mac80211/agg-tx.c | 5 |
1 files changed, 5 insertions, 0 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 3680b380e70c..5f8ab5be369f 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -330,6 +330,11 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | |||
330 | 330 | ||
331 | spin_lock_bh(&sta->lock); | 331 | spin_lock_bh(&sta->lock); |
332 | 332 | ||
333 | /* free struct pending for start, if present */ | ||
334 | tid_tx = sta->ampdu_mlme.tid_start_tx[tid]; | ||
335 | kfree(tid_tx); | ||
336 | sta->ampdu_mlme.tid_start_tx[tid] = NULL; | ||
337 | |||
333 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 338 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
334 | if (!tid_tx) { | 339 | if (!tid_tx) { |
335 | spin_unlock_bh(&sta->lock); | 340 | spin_unlock_bh(&sta->lock); |