summaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2016-12-08 11:22:09 -0500
committerJohannes Berg <johannes.berg@intel.com>2016-12-09 06:57:49 -0500
commite6f462df9acd2a3295e5d34eb29e2823220cf129 (patch)
treed37ebb6de38029d804d0eb6abbe2a495d5de1558 /net/mac80211/mlme.c
parent2fa436b3a2a7009c11a3bc03fe0ff4c26e80fd87 (diff)
cfg80211/mac80211: fix BSS leaks when abandoning assoc attempts
When mac80211 abandons an association attempt, it may free all the data structures, but inform cfg80211 and userspace about it only by sending the deauth frame it received, in which case cfg80211 has no link to the BSS struct that was used and will not cfg80211_unhold_bss() it. Fix this by providing a way to inform cfg80211 of this with the BSS entry passed, so that it can clean up properly, and use this ability in the appropriate places in mac80211. This isn't ideal: some code is more or less duplicated and tracing is missing. However, it's a fairly small change and it's thus easier to backport - cleanups can come later. Cc: stable@vger.kernel.org Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c21
1 files changed, 12 insertions, 9 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index d157b250ff77..098ce9b179ee 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2518,7 +2518,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
2518} 2518}
2519 2519
2520static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata, 2520static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2521 bool assoc) 2521 bool assoc, bool abandon)
2522{ 2522{
2523 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data; 2523 struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
2524 2524
@@ -2541,6 +2541,9 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
2541 mutex_lock(&sdata->local->mtx); 2541 mutex_lock(&sdata->local->mtx);
2542 ieee80211_vif_release_channel(sdata); 2542 ieee80211_vif_release_channel(sdata);
2543 mutex_unlock(&sdata->local->mtx); 2543 mutex_unlock(&sdata->local->mtx);
2544
2545 if (abandon)
2546 cfg80211_abandon_assoc(sdata->dev, assoc_data->bss);
2544 } 2547 }
2545 2548
2546 kfree(assoc_data); 2549 kfree(assoc_data);
@@ -2773,7 +2776,7 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
2773 bssid, reason_code, 2776 bssid, reason_code,
2774 ieee80211_get_reason_code_string(reason_code)); 2777 ieee80211_get_reason_code_string(reason_code));
2775 2778
2776 ieee80211_destroy_assoc_data(sdata, false); 2779 ieee80211_destroy_assoc_data(sdata, false, true);
2777 2780
2778 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len); 2781 cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
2779 return; 2782 return;
@@ -3182,14 +3185,14 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
3182 if (status_code != WLAN_STATUS_SUCCESS) { 3185 if (status_code != WLAN_STATUS_SUCCESS) {
3183 sdata_info(sdata, "%pM denied association (code=%d)\n", 3186 sdata_info(sdata, "%pM denied association (code=%d)\n",
3184 mgmt->sa, status_code); 3187 mgmt->sa, status_code);
3185 ieee80211_destroy_assoc_data(sdata, false); 3188 ieee80211_destroy_assoc_data(sdata, false, false);
3186 event.u.mlme.status = MLME_DENIED; 3189 event.u.mlme.status = MLME_DENIED;
3187 event.u.mlme.reason = status_code; 3190 event.u.mlme.reason = status_code;
3188 drv_event_callback(sdata->local, sdata, &event); 3191 drv_event_callback(sdata->local, sdata, &event);
3189 } else { 3192 } else {
3190 if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) { 3193 if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
3191 /* oops -- internal error -- send timeout for now */ 3194 /* oops -- internal error -- send timeout for now */
3192 ieee80211_destroy_assoc_data(sdata, false); 3195 ieee80211_destroy_assoc_data(sdata, false, false);
3193 cfg80211_assoc_timeout(sdata->dev, bss); 3196 cfg80211_assoc_timeout(sdata->dev, bss);
3194 return; 3197 return;
3195 } 3198 }
@@ -3202,7 +3205,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
3202 * recalc after assoc_data is NULL but before associated 3205 * recalc after assoc_data is NULL but before associated
3203 * is set can cause the interface to go idle 3206 * is set can cause the interface to go idle
3204 */ 3207 */
3205 ieee80211_destroy_assoc_data(sdata, true); 3208 ieee80211_destroy_assoc_data(sdata, true, false);
3206 3209
3207 /* get uapsd queues configuration */ 3210 /* get uapsd queues configuration */
3208 uapsd_queues = 0; 3211 uapsd_queues = 0;
@@ -3901,7 +3904,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3901 .u.mlme.status = MLME_TIMEOUT, 3904 .u.mlme.status = MLME_TIMEOUT,
3902 }; 3905 };
3903 3906
3904 ieee80211_destroy_assoc_data(sdata, false); 3907 ieee80211_destroy_assoc_data(sdata, false, false);
3905 cfg80211_assoc_timeout(sdata->dev, bss); 3908 cfg80211_assoc_timeout(sdata->dev, bss);
3906 drv_event_callback(sdata->local, sdata, &event); 3909 drv_event_callback(sdata->local, sdata, &event);
3907 } 3910 }
@@ -4040,7 +4043,7 @@ void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata)
4040 WLAN_REASON_DEAUTH_LEAVING, 4043 WLAN_REASON_DEAUTH_LEAVING,
4041 false, frame_buf); 4044 false, frame_buf);
4042 if (ifmgd->assoc_data) 4045 if (ifmgd->assoc_data)
4043 ieee80211_destroy_assoc_data(sdata, false); 4046 ieee80211_destroy_assoc_data(sdata, false, true);
4044 if (ifmgd->auth_data) 4047 if (ifmgd->auth_data)
4045 ieee80211_destroy_auth_data(sdata, false); 4048 ieee80211_destroy_auth_data(sdata, false);
4046 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, 4049 cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf,
@@ -4949,7 +4952,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4949 IEEE80211_STYPE_DEAUTH, 4952 IEEE80211_STYPE_DEAUTH,
4950 req->reason_code, tx, 4953 req->reason_code, tx,
4951 frame_buf); 4954 frame_buf);
4952 ieee80211_destroy_assoc_data(sdata, false); 4955 ieee80211_destroy_assoc_data(sdata, false, true);
4953 ieee80211_report_disconnect(sdata, frame_buf, 4956 ieee80211_report_disconnect(sdata, frame_buf,
4954 sizeof(frame_buf), true, 4957 sizeof(frame_buf), true,
4955 req->reason_code); 4958 req->reason_code);
@@ -5024,7 +5027,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
5024 sdata_lock(sdata); 5027 sdata_lock(sdata);
5025 if (ifmgd->assoc_data) { 5028 if (ifmgd->assoc_data) {
5026 struct cfg80211_bss *bss = ifmgd->assoc_data->bss; 5029 struct cfg80211_bss *bss = ifmgd->assoc_data->bss;
5027 ieee80211_destroy_assoc_data(sdata, false); 5030 ieee80211_destroy_assoc_data(sdata, false, false);
5028 cfg80211_assoc_timeout(sdata->dev, bss); 5031 cfg80211_assoc_timeout(sdata->dev, bss);
5029 } 5032 }
5030 if (ifmgd->auth_data) 5033 if (ifmgd->auth_data)