aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--include/net/cfg80211.h16
-rw-r--r--net/mac80211/mlme.c15
-rw-r--r--net/wireless/mlme.c8
3 files changed, 20 insertions, 19 deletions
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index e3a39fc9a296..7b0730aeb892 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1459,7 +1459,8 @@ const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie);
1459 * This structure provides information needed to complete IEEE 802.11 1459 * This structure provides information needed to complete IEEE 802.11
1460 * authentication. 1460 * authentication.
1461 * 1461 *
1462 * @bss: The BSS to authenticate with. 1462 * @bss: The BSS to authenticate with, the callee must obtain a reference
1463 * to it if it needs to keep it.
1463 * @auth_type: Authentication type (algorithm) 1464 * @auth_type: Authentication type (algorithm)
1464 * @ie: Extra IEs to add to Authentication frame or %NULL 1465 * @ie: Extra IEs to add to Authentication frame or %NULL
1465 * @ie_len: Length of ie buffer in octets 1466 * @ie_len: Length of ie buffer in octets
@@ -1497,11 +1498,10 @@ enum cfg80211_assoc_req_flags {
1497 * 1498 *
1498 * This structure provides information needed to complete IEEE 802.11 1499 * This structure provides information needed to complete IEEE 802.11
1499 * (re)association. 1500 * (re)association.
1500 * @bss: The BSS to associate with. If the call is successful the driver 1501 * @bss: The BSS to associate with. If the call is successful the driver is
1501 * is given a reference that it must release, normally via a call to 1502 * given a reference that it must give back to cfg80211_send_rx_assoc()
1502 * cfg80211_send_rx_assoc(), or, if association timed out, with a 1503 * or to cfg80211_assoc_timeout(). To ensure proper refcounting, new
1503 * call to cfg80211_put_bss() (in addition to calling 1504 * association requests while already associating must be rejected.
1504 * cfg80211_send_assoc_timeout())
1505 * @ie: Extra IEs to add to (Re)Association Request frame or %NULL 1505 * @ie: Extra IEs to add to (Re)Association Request frame or %NULL
1506 * @ie_len: Length of ie buffer in octets 1506 * @ie_len: Length of ie buffer in octets
1507 * @use_mfp: Use management frame protection (IEEE 802.11w) in this association 1507 * @use_mfp: Use management frame protection (IEEE 802.11w) in this association
@@ -3522,11 +3522,11 @@ void cfg80211_rx_assoc_resp(struct net_device *dev,
3522/** 3522/**
3523 * cfg80211_assoc_timeout - notification of timed out association 3523 * cfg80211_assoc_timeout - notification of timed out association
3524 * @dev: network device 3524 * @dev: network device
3525 * @addr: The MAC address of the device with which the association timed out 3525 * @bss: The BSS entry with which association timed out.
3526 * 3526 *
3527 * This function may sleep. The caller must hold the corresponding wdev's mutex. 3527 * This function may sleep. The caller must hold the corresponding wdev's mutex.
3528 */ 3528 */
3529void cfg80211_assoc_timeout(struct net_device *dev, const u8 *addr); 3529void cfg80211_assoc_timeout(struct net_device *dev, struct cfg80211_bss *bss);
3530 3530
3531/** 3531/**
3532 * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame 3532 * cfg80211_tx_mlme_mgmt - notification of transmitted deauth/disassoc frame
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