mac80211: fix work removal on deauth request
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. 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>
This commit is contained in:
parent
65e8b0ccb6
commit
bc4934bc61
|
@ -2750,7 +2750,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||||
{
|
{
|
||||||
struct ieee80211_local *local = sdata->local;
|
struct ieee80211_local *local = sdata->local;
|
||||||
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
|
||||||
struct ieee80211_work *wk;
|
|
||||||
u8 bssid[ETH_ALEN];
|
u8 bssid[ETH_ALEN];
|
||||||
bool assoc_bss = false;
|
bool assoc_bss = false;
|
||||||
|
|
||||||
|
@ -2763,30 +2762,47 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
|
||||||
assoc_bss = true;
|
assoc_bss = true;
|
||||||
} else {
|
} else {
|
||||||
bool not_auth_yet = false;
|
bool not_auth_yet = false;
|
||||||
|
struct ieee80211_work *tmp, *wk = NULL;
|
||||||
|
|
||||||
mutex_unlock(&ifmgd->mtx);
|
mutex_unlock(&ifmgd->mtx);
|
||||||
|
|
||||||
mutex_lock(&local->mtx);
|
mutex_lock(&local->mtx);
|
||||||
list_for_each_entry(wk, &local->work_list, list) {
|
list_for_each_entry(tmp, &local->work_list, list) {
|
||||||
if (wk->sdata != sdata)
|
if (tmp->sdata != sdata)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (wk->type != IEEE80211_WORK_DIRECT_PROBE &&
|
if (tmp->type != IEEE80211_WORK_DIRECT_PROBE &&
|
||||||
wk->type != IEEE80211_WORK_AUTH &&
|
tmp->type != IEEE80211_WORK_AUTH &&
|
||||||
wk->type != IEEE80211_WORK_ASSOC &&
|
tmp->type != IEEE80211_WORK_ASSOC &&
|
||||||
wk->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
tmp->type != IEEE80211_WORK_ASSOC_BEACON_WAIT)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (memcmp(req->bss->bssid, wk->filter_ta, ETH_ALEN))
|
if (memcmp(req->bss->bssid, tmp->filter_ta, ETH_ALEN))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
not_auth_yet = wk->type == IEEE80211_WORK_DIRECT_PROBE;
|
not_auth_yet = tmp->type == IEEE80211_WORK_DIRECT_PROBE;
|
||||||
list_del_rcu(&wk->list);
|
list_del_rcu(&tmp->list);
|
||||||
free_work(wk);
|
synchronize_rcu();
|
||||||
|
wk = tmp;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
mutex_unlock(&local->mtx);
|
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
|
* If somebody requests authentication and we haven't
|
||||||
* sent out an auth frame yet there's no need to send
|
* sent out an auth frame yet there's no need to send
|
||||||
|
|
Loading…
Reference in New Issue