summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2011-06-08 13:27:29 +0200
committerJohn W. Linville <linville@tuxdriver.com>2011-06-08 14:19:05 -0400
commitf3209bea110cade12e2b133da8b8499689cb0e2e (patch)
tree27346021a1b6a50b49a6a27696a1f01f18655f7c /net
parent43e4e0b94984b45d52048e3ac027cac15c718b65 (diff)
downloadlinux-f3209bea110cade12e2b133da8b8499689cb0e2e.tar.gz
linux-f3209bea110cade12e2b133da8b8499689cb0e2e.tar.bz2
linux-f3209bea110cade12e2b133da8b8499689cb0e2e.zip
mac80211: fix IBSS teardown race
Ignacy reports that sometimes after leaving an IBSS joining a new one didn't work because there still were stations on the list. He fixed it by flushing stations when attempting to join a new IBSS, but this shouldn't be happening in the first case. When I looked into it I saw a race condition in teardown that could cause stations to be added after flush, and thus cause this situation. Ignacy confirms that after applying my patch he hasn't seen this happen again. Reported-by: Ignacy Gawedzki <i@lri.fr> Debugged-by: Ignacy Gawedzki <i@lri.fr> Tested-by: Ignacy Gawedzki <i@lri.fr> Cc: stable@kernel.org Signed-off-by: Johannes Berg <johannes.berg@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net')
-rw-r--r--net/mac80211/ibss.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 421eaa6b0c2b..56c24cabf26d 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -965,6 +965,10 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
mutex_lock(&sdata->u.ibss.mtx);
+ sdata->u.ibss.state = IEEE80211_IBSS_MLME_SEARCH;
+ memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
+ sdata->u.ibss.ssid_len = 0;
+
active_ibss = ieee80211_sta_active_ibss(sdata);
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -999,8 +1003,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
kfree_skb(skb);
skb_queue_purge(&sdata->skb_queue);
- memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
- sdata->u.ibss.ssid_len = 0;
del_timer_sync(&sdata->u.ibss.timer);