lkml.org 
[lkml]   [2017]   [Oct]   [31]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.13 40/43] cfg80211: fix connect/disconnect edge cases
    Date
    4.13-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Johannes Berg <johannes.berg@intel.com>

    commit 51e13359cd5ea34acc62c90627603352956380af upstream.

    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.

    Signed-off-by: Johannes Berg <johannes.berg@intel.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    net/wireless/sme.c | 50 +++++++++++++++++++++++++++++++++++++++++---------
    1 file changed, 41 insertions(+), 9 deletions(-)

    --- a/net/wireless/sme.c
    +++ b/net/wireless/sme.c
    @@ -522,11 +522,6 @@ static int cfg80211_sme_connect(struct w
    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_reg

    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_reg

    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_
    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;
    }


    \
     
     \ /
      Last update: 2017-10-31 11:02    [W:3.047 / U:0.012 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site