aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-06-19 07:05:42 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-06-19 12:55:39 -0400
commit959867fa55d0cb55fb3d08656e5e62607167617f (patch)
treeaeac7b16c571f062380fa99508d64df7cc1f4565 /net
parent86e8cf98de3e74bbfb0003501e0004bf1e5e2618 (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')
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/wireless/mlme.c8
2 files changed, 12 insertions, 11 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);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index a61a44bc6cf0..dd6f79d7bd2e 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -131,16 +131,18 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr)
131} 131}
132EXPORT_SYMBOL(cfg80211_auth_timeout); 132EXPORT_SYMBOL(cfg80211_auth_timeout);
133 133
134void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr) 134void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss)
135{ 135{
136 struct wireless_dev *wdev = dev->ieee80211_ptr; 136 struct wireless_dev *wdev = dev->ieee80211_ptr;
137 struct wiphy *wiphy = wdev->wiphy; 137 struct wiphy *wiphy = wdev->wiphy;
138 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); 138 struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
139 139
140 trace_cfg80211_send_assoc_timeout(dev, addr); 140 trace_cfg80211_send_assoc_timeout(dev, bss->bssid);
141 141
142 nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL); 142 nl80211_send_assoc_timeout(rdev, dev, bss->bssid, GFP_KERNEL);
143 cfg80211_sme_assoc_timeout(wdev); 143 cfg80211_sme_assoc_timeout(wdev);
144
145 cfg80211_put_bss(wiphy, bss);
144} 146}
145EXPORT_SYMBOL(cfg80211_assoc_timeout); 147EXPORT_SYMBOL(cfg80211_assoc_timeout);
146 148