diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-06-19 07:05:42 -0400 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-06-19 12:55:39 -0400 |
commit | 959867fa55d0cb55fb3d08656e5e62607167617f (patch) | |
tree | aeac7b16c571f062380fa99508d64df7cc1f4565 /net/mac80211/mlme.c | |
parent | 86e8cf98de3e74bbfb0003501e0004bf1e5e2618 (diff) |
cfg80211: require passing BSS struct back to cfg80211_assoc_timeout
Doing so will allow us to hold the BSS (not just ref it) over the
association process, thus ensuring that it doesn't time out and
gets invisible to the user (e.g. in 'iw wlan0 link'.)
This also fixes a leak in mac80211 where it doesn't always release
the BSS struct properly in all cases where calling this function.
This leak was reported by Ben Greear.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 15 |
1 files changed, 7 insertions, 8 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 34d54fe81483..ae31968d42d3 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -2795,8 +2795,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
2795 | if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { | 2795 | if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { |
2796 | /* oops -- internal error -- send timeout for now */ | 2796 | /* oops -- internal error -- send timeout for now */ |
2797 | ieee80211_destroy_assoc_data(sdata, false); | 2797 | ieee80211_destroy_assoc_data(sdata, false); |
2798 | cfg80211_put_bss(sdata->local->hw.wiphy, bss); | 2798 | cfg80211_assoc_timeout(sdata->dev, bss); |
2799 | cfg80211_assoc_timeout(sdata->dev, mgmt->bssid); | ||
2800 | return; | 2799 | return; |
2801 | } | 2800 | } |
2802 | sdata_info(sdata, "associated\n"); | 2801 | sdata_info(sdata, "associated\n"); |
@@ -3513,13 +3512,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata) | |||
3513 | time_after(jiffies, ifmgd->assoc_data->timeout)) { | 3512 | time_after(jiffies, ifmgd->assoc_data->timeout)) { |
3514 | if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || | 3513 | if ((ifmgd->assoc_data->need_beacon && !ifmgd->have_beacon) || |
3515 | ieee80211_do_assoc(sdata)) { | 3514 | ieee80211_do_assoc(sdata)) { |
3516 | u8 bssid[ETH_ALEN]; | 3515 | struct cfg80211_bss *bss = ifmgd->assoc_data->bss; |
3517 | |||
3518 | memcpy(bssid, ifmgd->assoc_data->bss->bssid, ETH_ALEN); | ||
3519 | 3516 | ||
3520 | ieee80211_destroy_assoc_data(sdata, false); | 3517 | ieee80211_destroy_assoc_data(sdata, false); |
3521 | 3518 | cfg80211_assoc_timeout(sdata->dev, bss); | |
3522 | cfg80211_assoc_timeout(sdata->dev, bssid); | ||
3523 | } | 3519 | } |
3524 | } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) | 3520 | } else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started) |
3525 | run_again(sdata, ifmgd->assoc_data->timeout); | 3521 | run_again(sdata, ifmgd->assoc_data->timeout); |
@@ -4445,8 +4441,11 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) | |||
4445 | cancel_work_sync(&ifmgd->chswitch_work); | 4441 | cancel_work_sync(&ifmgd->chswitch_work); |
4446 | 4442 | ||
4447 | sdata_lock(sdata); | 4443 | sdata_lock(sdata); |
4448 | if (ifmgd->assoc_data) | 4444 | if (ifmgd->assoc_data) { |
4445 | struct cfg80211_bss *bss = ifmgd->assoc_data->bss; | ||
4449 | ieee80211_destroy_assoc_data(sdata, false); | 4446 | ieee80211_destroy_assoc_data(sdata, false); |
4447 | cfg80211_assoc_timeout(sdata->dev, bss); | ||
4448 | } | ||
4450 | if (ifmgd->auth_data) | 4449 | if (ifmgd->auth_data) |
4451 | ieee80211_destroy_auth_data(sdata, false); | 4450 | ieee80211_destroy_auth_data(sdata, false); |
4452 | del_timer_sync(&ifmgd->timer); | 4451 | del_timer_sync(&ifmgd->timer); |