cfg80211/mac80211: avoid state mishmash on deauth
authorStanislaw Gruszka <sgruszka@redhat.com>
Mon, 15 Oct 2012 12:52:41 +0000 (14:52 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 15 Oct 2012 15:21:34 +0000 (17:21 +0200)
Avoid situation when we are on associate state in mac80211 and
on disassociate state in cfg80211. This can results on crash
during modules unload (like showed on this thread:
http://marc.info/?t=134373976300001&r=1&w=2) and possibly other
problems.

Reported-by: Pedro Francisco <pedrogfrancisco@gmail.com>
Cc: stable@vger.kernel.org
Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
net/mac80211/mlme.c
net/wireless/mlme.c

index 1b49890822449df661d576219181b10c64d57a6c..f8cd4cf3fad870d97204e3cf281d72e137db146c 100644 (file)
@@ -1218,6 +1218,7 @@ struct cfg80211_deauth_request {
        const u8 *ie;
        size_t ie_len;
        u16 reason_code;
+       bool local_state_change;
 };
 
 /**
index e714ed8bb198727c6738c1e3ae7650243dd2a07e..e510a33fec76071e34cbcc118f3927b79e423c47 100644 (file)
@@ -3549,6 +3549,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
+       bool tx = !req->local_state_change;
 
        mutex_lock(&ifmgd->mtx);
 
@@ -3565,12 +3566,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
        if (ifmgd->associated &&
            ether_addr_equal(ifmgd->associated->bssid, req->bssid)) {
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
-                                      req->reason_code, true, frame_buf);
+                                      req->reason_code, tx, frame_buf);
        } else {
                drv_mgd_prepare_tx(sdata->local, sdata);
                ieee80211_send_deauth_disassoc(sdata, req->bssid,
                                               IEEE80211_STYPE_DEAUTH,
-                                              req->reason_code, true,
+                                              req->reason_code, tx,
                                               frame_buf);
        }
 
index 8016fee0752b0325a20409b7b1b93b5433c73872..904a7f36832531cbe2fa3d50f220b94775eaf8a9 100644 (file)
@@ -457,20 +457,14 @@ int __cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,
                .reason_code = reason,
                .ie = ie,
                .ie_len = ie_len,
+               .local_state_change = local_state_change,
        };
 
        ASSERT_WDEV_LOCK(wdev);
 
-       if (local_state_change) {
-               if (wdev->current_bss &&
-                   ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
-                       cfg80211_unhold_bss(wdev->current_bss);
-                       cfg80211_put_bss(&wdev->current_bss->pub);
-                       wdev->current_bss = NULL;
-               }
-
+       if (local_state_change && (!wdev->current_bss ||
+           !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
                return 0;
-       }
 
        return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 }