diff mbox series

wifi: mac80211: handle connection loss in __ieee80211_disconnect

Message ID 20221025203443.410121-2-prestwoj@gmail.com (mailing list archive)
State Rejected
Delegated to: Johannes Berg
Headers show
Series Fix __ieee80211_disconnect when not associated | expand

Commit Message

James Prestwood Oct. 25, 2022, 8:34 p.m. UTC
The ieee80211_connection_loss() can be called during times when the
kernels state is in flux, such as after a successful authentication
but prior to successful association. This can result in the kernel
never telling userspace due to __ieee80211_disconnect bailing out
if !ifmgd->associated. This has been seen out in the wild on
iwlwifi:

[503619.324379] wlan0: disconnect from AP d0:15:a6:70:e1:20 for new auth to d0:15:a6:70:b5:40
[503619.367204] wlan0: authenticate with d0:15:a6:70:b5:40
[503619.367233] wlan0: bad VHT capabilities, disabling VHT
[503619.367236] wlan0: Invalid HE elem, Disable HE
[503619.367237] wlan0: 80 MHz not supported, disabling VHT
[503619.371184] wlan0: send auth to d0:15:a6:70:b5:40 (try 1/3)
[503619.406401] wlan0: authenticated
[503620.270833] iwlwifi 0000:00:14.3: Not associated and the session protection is over already...
[503620.270943] wlan0: Connection to AP d0:15:a6:70:b5:40 lost

At this point userspace has received a CMD_AUTHENTICATE event but
nothing else. No disconnect or anything to indicate something is
wrong. Userspace supplicants expect _something_ to come after a
successful authentication.

This patch modifies __ieee80211_disconnect() to call
cfg80211_disconnect which will ultimately send a disconnect event
to userspace notifying it of the situation.

Signed-off-by: James Prestwood <prestwoj@gmail.com>
---
 net/mac80211/mlme.c | 5 +++++
 1 file changed, 5 insertions(+)

Comments

Johannes Berg Jan. 18, 2023, 4:04 p.m. UTC | #1
On Tue, 2022-10-25 at 13:34 -0700, James Prestwood wrote:
> The ieee80211_connection_loss() can be called during times when the
> kernels state is in flux, such as after a successful authentication
> but prior to successful association. This can result in the kernel
> never telling userspace due to __ieee80211_disconnect bailing out
> if !ifmgd->associated. This has been seen out in the wild on
> iwlwifi:
> 
> [503619.324379] wlan0: disconnect from AP d0:15:a6:70:e1:20 for new auth to d0:15:a6:70:b5:40
> [503619.367204] wlan0: authenticate with d0:15:a6:70:b5:40
> [503619.367233] wlan0: bad VHT capabilities, disabling VHT
> [503619.367236] wlan0: Invalid HE elem, Disable HE
> [503619.367237] wlan0: 80 MHz not supported, disabling VHT
> [503619.371184] wlan0: send auth to d0:15:a6:70:b5:40 (try 1/3)
> [503619.406401] wlan0: authenticated
> [503620.270833] iwlwifi 0000:00:14.3: Not associated and the session protection is over already...
> [503620.270943] wlan0: Connection to AP d0:15:a6:70:b5:40 lost
> 
> At this point userspace has received a CMD_AUTHENTICATE event but
> nothing else. No disconnect or anything to indicate something is
> wrong. Userspace supplicants expect _something_ to come after a
> successful authentication.
> 

I'm not sure I understand this scenario - there's nothing wrong with
this, is there?

The way I read this is that userspace simply asked for auth, but then
didn't (quickly enough) ask for assoc? Or got a comeback or something
(though we would log that too, I think)?

Userspace got a successful NL80211_CMD_AUTHENTICATE event at this point,
but didn't associate (yet anyway).

You could argue that iwlwifi shouldn't be waiting for an association if
nobody ever requested association, but that's a driver bug, and
shouldn't cause any problem with state between userspace and kernel.

johannes
diff mbox series

Patch

diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index fc764984d687..5c88cf717fb2 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -3270,6 +3270,11 @@  static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
 
 	sdata_lock(sdata);
 	if (!ifmgd->associated) {
+		if (ifmgd->connection_loss)
+			cfg80211_disconnected(sdata->wdev.netdev,
+					      WLAN_REASON_UNSPECIFIED, NULL, 0,
+					      true, GFP_KERNEL);
+
 		sdata_unlock(sdata);
 		return;
 	}