diff mbox

[RFC] cfg80211: Fix handling of previous_auth deauth

Message ID a194a41b3f1376f035113d4f443038eb2e64264f.1307403076.git.pstew@chromium.org (mailing list archive)
State Not Applicable, archived
Headers show

Commit Message

Paul Stewart June 6, 2011, 11 p.m. UTC
The WLAN_REASON_PREV_AUTH_NOT_VALID DEAUTH message is sent
to remove current successful authentications, not to to abort
a new authentication attempts.  Therefore, filter this reason
code out when deciding whether to remove authtry_bsses[] entries.

This is the least invasive change which prevents this issue
from appearing.  It doesn't address the fact that the mac80211
code still retries authentications if it is DEAUTHed for some
other reason during authentication.  If one of those retries
succeeds the client can do nothing with it sicne authtry_bsses[]
has been cleared.

Signed-off-by: Paul Stewart <pstew@chromium.org>
---
 net/wireless/mlme.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

Comments

Johannes Berg June 8, 2011, 11:02 a.m. UTC | #1
On Mon, 2011-06-06 at 16:00 -0700, Paul Stewart wrote:
> The WLAN_REASON_PREV_AUTH_NOT_VALID DEAUTH message is sent
> to remove current successful authentications, not to to abort
> a new authentication attempts.  Therefore, filter this reason
> code out when deciding whether to remove authtry_bsses[] entries.
> 
> This is the least invasive change which prevents this issue
> from appearing.  

Maybe I'm confused -- what's "this issue"?

> It doesn't address the fact that the mac80211
> code still retries authentications if it is DEAUTHed for some
> other reason during authentication.  If one of those retries
> succeeds the client can do nothing with it sicne authtry_bsses[]
> has been cleared.

So basically you're getting a deauth while trying to auth? Rather than a
rejected auth? Hmm.

It seems mac80211 shouldn't pass such up since it isn't actually
connected. But then we just pass them up and rely on cfg80211 to sort it
out. Why do we even attempt to remove something from authtry_bsses when
receiving a deauth frame? This only makes sense when we sent it
ourselves and want to abort the authentication that way I guess?

johannes


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 8, 2011, 11:44 a.m. UTC | #2
[you should send as text, the list won't accept html]

>         Maybe I'm confused -- what's "this issue"?

> Sorry.  I covered the issue in a previous post but it wasn't threaded
> in.   Here's a summary:
> 
> 
> If you read the IEEE docs just right, they say that if an AP believes
> a STA is authenticated, but it receives an AUTH request, it should
> send a DEAUTH downstream with PREV_AUTH_NOT_VALID.  Some APs actually
> do this.  The STA and AP can fall out of sync, eg, if the STA reboots
> unexpectedly.  What happens then is that the a mac80211 STA will send
> an AUTH, and get a DEAUTH  which will clear authtry_bssess[].
>  mac80211 keeps retrying, though, and the second time the AP sends a
> successful AUTH response and marks the STA authenticated again.
>  Meanwhile cfg80211 doesn't have any state in authtry_bsses[] for the
> AP so it drops the successful reply on the floor.  Thus the state
> mismatch perpetuates.


Right, makes sense.

>         It seems mac80211 shouldn't pass such up since it isn't
>         actually
>         connected. But then we just pass them up and rely on cfg80211
>         to sort it
>         out. Why do we even attempt to remove something from
>         authtry_bsses when
>         receiving a deauth frame? This only makes sense when we sent
>         it
>         ourselves and want to abort the authentication that way I
>         guess?
>         
> It's a little confusing to me that the same function is in charge of
> outgoing and incoming packets, but yes, I see no point in removing
> anything from authtry_bsses[] for a received DEAUTH since it is not
> applicable.

Yeah, indeed. Would not modifying authtry_bsses for a _received_ DEAUTH
fix it?

johannes


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Johannes Berg June 8, 2011, 11:50 a.m. UTC | #3
On Wed, 2011-06-08 at 04:48 -0700, Paul Stewart wrote:

> >> It's a little confusing to me that the same function is in charge of
> >> outgoing and incoming packets, but yes, I see no point in removing
> >> anything from authtry_bsses[] for a received DEAUTH since it is not
> >> applicable.
> >
> > Yeah, indeed. Would not modifying authtry_bsses for a _received_ DEAUTH
> > fix it?
> 
> Sure, it would.  How do I differentiate between received and
> transmitted DEAUTH?  They seem to go through the same function, or
> maybe I'm wrong.  Do I check the MAC in the mgmt header? :-)

I think you have to check the address, yeah.

johannes

--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 493b939..48e965d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -150,6 +150,7 @@  void __cfg80211_send_deauth(struct net_device *dev,
 	const u8 *bssid = mgmt->bssid;
 	int i;
 	bool found = false, was_current = false;
+	u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
 
 	ASSERT_WDEV_LOCK(wdev);
 
@@ -170,7 +171,9 @@  void __cfg80211_send_deauth(struct net_device *dev,
 			break;
 		}
 		if (wdev->authtry_bsses[i] &&
-		    memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid, ETH_ALEN) == 0) {
+		    memcmp(wdev->authtry_bsses[i]->pub.bssid, bssid,
+			   ETH_ALEN) == 0 &&
+		    reason_code != WLAN_REASON_PREV_AUTH_NOT_VALID) {
 			cfg80211_unhold_bss(wdev->authtry_bsses[i]);
 			cfg80211_put_bss(&wdev->authtry_bsses[i]->pub);
 			wdev->authtry_bsses[i] = NULL;
@@ -185,11 +188,8 @@  void __cfg80211_send_deauth(struct net_device *dev,
 	nl80211_send_deauth(rdev, dev, buf, len, GFP_KERNEL);
 
 	if (wdev->sme_state == CFG80211_SME_CONNECTED && was_current) {
-		u16 reason_code;
 		bool from_ap;
 
-		reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
-
 		from_ap = memcmp(mgmt->sa, dev->dev_addr, ETH_ALEN) != 0;
 		__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
 	} else if (wdev->sme_state == CFG80211_SME_CONNECTING) {