2012-01-30 15:41:26 +00:00
|
|
|
From bc4934bc61d0a11fd62c5187ff83645628f8be8b Mon Sep 17 00:00:00 2001
|
|
|
|
From: Johannes Berg <johannes.berg@intel.com>
|
2012-01-20 14:38:57 +00:00
|
|
|
Date: Wed, 18 Jan 2012 14:10:25 +0100
|
2012-01-30 15:41:26 +00:00
|
|
|
Subject: [PATCH 4/8] mac80211: fix work removal on deauth request
|
2012-01-20 14:38:57 +00:00
|
|
|
|
|
|
|
When deauth is requested while an auth or assoc
|
|
|
|
work item is in progress, we currently delete it
|
|
|
|
without regard for any state it might need to
|
|
|
|
clean up. Fix it by cleaning up for those items.
|
|
|
|
|
|
|
|
In the case Pontus found, the problem manifested
|
|
|
|
itself as such:
|
|
|
|
|
|
|
|
authenticate with 00:23:69:aa:dd:7b (try 1)
|
|
|
|
authenticated
|
|
|
|
failed to insert Dummy STA entry for the AP (error -17)
|
|
|
|
deauthenticating from 00:23:69:aa:dd:7b by local choice (reason=2)
|
|
|
|
|
|
|
|
It could also happen differently if the driver
|
|
|
|
uses the tx_sync callback.
|
|
|
|
|
|
|
|
We can't just call the ->done() method of the work
|
|
|
|
items because that will lock up due to the locking
|
|
|
|
in cfg80211. This fix isn't very clean, but that
|
|
|
|
seems acceptable since I have patches pending to
|
|
|
|
remove this code completely.
|
|
|
|
|
2012-01-30 15:41:26 +00:00
|
|
|
Cc: stable@vger.kernel.org
|
|
|
|
Reported-by: Pontus Fuchs <pontus.fuchs@gmail.com>
|
|
|
|
Tested-by: Pontus Fuchs <pontus.fuchs@gmail.com>
|
|
|
|
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
|
|
|
|
Signed-off-by: John W. Linville <linville@tuxdriver.com>
|
2012-01-20 14:38:57 +00:00
|
|
|
---
|
|
|
|
net/mac80211/mlme.c | 38 +++++++++++++++++++++++++++-----------
|
2012-01-30 15:41:26 +00:00
|
|
|
1 files changed, 27 insertions(+), 11 deletions(-)
|
2012-01-20 14:38:57 +00:00
|
|
|
|
2012-01-30 15:41:26 +00:00
|
|
|
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
|
|
|
|
index ecb4c84..295be92 100644
|
|
|
|
--- a/net/mac80211/mlme.c
|
|
|
|
+++ b/net/mac80211/mlme.c
|
|
|
|
@@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
2012-01-20 14:38:57 +00:00
|
|
|
{
|
|
|
|
struct ieee80211_local *local = sdata->local;
|
|
|
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
|
|
|
- struct ieee80211_work *wk;
|
|
|
|
u8 bssid[ETH_ALEN];
|
|
|
|
bool assoc_bss = false;
|
|
|
|
|
2012-01-30 15:41:26 +00:00
|
|
|
@@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
2012-01-20 14:38:57 +00:00
|
|
|
assoc_bss = true;
|
|
|
|
} else {
|
|
|
|
bool not_auth_yet = false;
|
|
|
|
+ struct ieee80211_work *tmp, *wk = NULL;
|
|
|
|
|
|
|
|
mutex_unlock(&ifmgd->mtx);
|
|
|
|
|
|
|
|
mutex_lock(&local->mtx);
|
|
|
|
- list_for_each_entry(wk, &local->work_list, list) {
|
|
|
|
- if (wk->sdata != sdata)
|
|
|
|
+ list_for_each_entry(tmp, &local->work_list, list) {
|
|
|
|
+ if (tmp->sdata != sdata)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
- if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
|
|
|
|
- wk->type != IEEE80211_WORK_AUTH &&
|
|
|
|
- wk->type != IEEE80211_WORK_ASSOC &&
|
|
|
|
- wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
|
|
|
+ if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
|
|
|
|
+ tmp->type != IEEE80211_WORK_AUTH &&
|
|
|
|
+ tmp->type != IEEE80211_WORK_ASSOC &&
|
|
|
|
+ tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
- if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
|
|
|
|
+ if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN))
|
|
|
|
continue;
|
|
|
|
|
|
|
|
- not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
|
|
|
|
- list_del_rcu(&wk->list);
|
|
|
|
- free_work(wk);
|
|
|
|
+ not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
|
|
|
|
+ list_del_rcu(&tmp->list);
|
|
|
|
+ synchronize_rcu();
|
|
|
|
+ wk = tmp;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
mutex_unlock(&local->mtx);
|
|
|
|
|
|
|
|
+ if (wk && wk->type == IEEE80211_WORK_ASSOC) {
|
|
|
|
+ /* clean up dummy sta & TX sync */
|
|
|
|
+ sta_info_destroy_addr(wk->sdata, wk->filter_ta);
|
|
|
|
+ if (wk->assoc.synced)
|
|
|
|
+ drv_finish_tx_sync(local, wk->sdata,
|
|
|
|
+ wk->filter_ta,
|
|
|
|
+ IEEE80211_TX_SYNC_ASSOC);
|
|
|
|
+ } else if (wk && wk->type == IEEE80211_WORK_AUTH) {
|
|
|
|
+ if (wk->probe_auth.synced)
|
|
|
|
+ drv_finish_tx_sync(local, wk->sdata,
|
|
|
|
+ wk->filter_ta,
|
|
|
|
+ IEEE80211_TX_SYNC_AUTH);
|
|
|
|
+ }
|
|
|
|
+ kfree(wk);
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* If somebody requests authentication and we haven't
|
|
|
|
* sent out an auth frame yet there's no need to send
|
2012-01-30 15:41:26 +00:00
|
|
|
--
|
|
|
|
1.7.4.4
|
2012-01-20 14:38:57 +00:00
|
|
|
|