summaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2017-11-13 11:33:55 +0100
committerJohannes Berg <johannes.berg@intel.com>2017-11-20 17:01:31 +0100
commit33ddd81e2bd5d9970b9f01ab383ba45035fa41ee (patch)
tree8ac9805306fbd178c65b8cf42eef0bc1f19118f2 /net/mac80211
parent67bd52386125ce1159c0581cbcd2740addf33cd4 (diff)
downloadlinux-33ddd81e2bd5d9970b9f01ab383ba45035fa41ee.tar.gz
linux-33ddd81e2bd5d9970b9f01ab383ba45035fa41ee.tar.bz2
linux-33ddd81e2bd5d9970b9f01ab383ba45035fa41ee.zip
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/agg-tx.c5
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,
spin_lock_bh(&sta->lock);
+ /* free struct pending for start, if present */
+ tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
+ kfree(tid_tx);
+ sta->ampdu_mlme.tid_start_tx[tid] = NULL;
+
tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
if (!tid_tx) {
spin_unlock_bh(&sta->lock);