FAILED: patch "[PATCH] cfg80211: fix connect/disconnect edge cases" failed to apply to 4.4-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 4.4-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
Quoted 1 line
From
51e13359cd5ea34acc62c90627603352956380afMon Sep 17 00:00:00 2001
From: Johannes Berg <[email protected]>
Date: Tue, 17 Oct 2017 21:56:20 +0200
Subject: [PATCH] cfg80211: fix connect/disconnect edge cases
If we try to connect while already connected/connecting, but this fails, we set ssid_len=0 but leave current_bss hanging, leading to errors.
Check all of this better, first of all ensuring that we can't try to connect to a different SSID while connected/ing; ensure that prev_bssid is set for re-association attempts even in the case of the driver supporting the connect() method, and don't reset ssid_len in the failure cases.
While at it, also reset ssid_len while disconnecting unless we were connected and expect a disconnected event, and warn on a successful connection without ssid_len being set.
net/wireless/sme.c +41 -9
@@ -522,11 +522,6 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,return -EOPNOTSUPP ;if (wdev->current_bss) { -if (!prev_bssid) -return -EALREADY ; -if (prev_bssid && - !ether_addr_equal (prev_bssid, wdev->current_bss->pub.bssid)) -return -ENOTCONN ;cfg80211_unhold_bss (wdev->current_bss);cfg80211_put_bss (wdev->wiphy, &wdev->current_bss->pub); wdev->current_bss =NULL ;
@@ -1063,11 +1058,35 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,ASSERT_WDEV_LOCK (wdev); -if (WARN_ON (wdev->connect_keys)) { -kzfree (wdev->connect_keys); - wdev->connect_keys =NULL ; +/* +* If we have an ssid_len, we're trying to connect or are +* already connected, so reject a new SSID unless it's the +* same (which is the case for re-association.) +*/ +if (wdev->ssid_len && + (wdev->ssid_len != connect->ssid_len || +memcmp (wdev->ssid, connect->ssid, wdev->ssid_len))) +return -EALREADY ; + +/* +* If connected, reject (re-)association unless prev_bssid +* matches the current BSSID. +*/ +if (wdev->current_bss) { +if (!prev_bssid) +return -EALREADY ; +if (!ether_addr_equal (prev_bssid, wdev->current_bss->pub.bssid)) +return -ENOTCONN ; } +/* +* Reject if we're in the process of connecting with WEP, +* this case isn't very interesting and trying to handle +* it would make the code much more complex. +*/ +if (wdev->connect_keys) +return -EINPROGRESS ; +cfg80211_oper_and_ht_capa (&connect->ht_capa_mask, rdev->wiphy.ht_capa_mod_mask);
@@ -1118,7 +1137,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,if (err) { wdev->connect_keys =NULL ; - wdev->ssid_len =0 ; +/* +* This could be reassoc getting refused, don't clear +* ssid_len in that case. +*/ +if (!wdev->current_bss) + wdev->ssid_len =0 ;return err; }
@@ -1145,6 +1169,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,else if (wdev->ssid_len) err =rdev_disconnect (rdev, dev, reason); +/* +* Clear ssid_len unless we actually were fully connected, +* in which case cfg80211_disconnected() will take care of +* this later. +*/ +if (!wdev->current_bss) + wdev->ssid_len =0 ; +return err; }