cfg80211: allow connect keys only with default (TX) key
authorJohannes Berg <johannes.berg@intel.com>
Tue, 13 Sep 2016 15:08:23 +0000 (17:08 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 15 Sep 2016 14:45:41 +0000 (16:45 +0200)
There's no point in allowing connect keys when one of them
isn't also configured as the TX key, it would just confuse
drivers and probably cause them to pick something for TX.
Disallow this confusing and erroneous configuration.

As wpa_supplicant will always send NL80211_ATTR_KEYS, even
when there are no keys inside, allow that and treat it as
though the attribute isn't present at all.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/wireless/ibss.c
net/wireless/nl80211.c
net/wireless/sme.c
net/wireless/wext-sme.c

index 896cbb20b6e11037bb6a1bb3b92073c88424bc61..eafdfa5798ae4a734368e4a0d3d2ac41e0f357a6 100644 (file)
@@ -114,6 +114,9 @@ static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
                }
        }
 
+       if (WARN_ON(connkeys && connkeys->def < 0))
+               return -EINVAL;
+
        if (WARN_ON(wdev->connect_keys))
                kzfree(wdev->connect_keys);
        wdev->connect_keys = connkeys;
@@ -289,7 +292,7 @@ int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev,
 
        wdev->wext.ibss.privacy = wdev->wext.default_key != -1;
 
-       if (wdev->wext.keys) {
+       if (wdev->wext.keys && wdev->wext.keys->def != -1) {
                ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
                if (!ck)
                        return -ENOMEM;
index 71af96e8a947ada8b7745c3a013a2d847a98dbde..f2a77c3daa59b8f9def389bbd947c40bc7e9f2b5 100644 (file)
@@ -848,6 +848,15 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
        struct nlattr *key;
        struct cfg80211_cached_keys *result;
        int rem, err, def = 0;
+       bool have_key = false;
+
+       nla_for_each_nested(key, keys, rem) {
+               have_key = true;
+               break;
+       }
+
+       if (!have_key)
+               return NULL;
 
        result = kzalloc(sizeof(*result), GFP_KERNEL);
        if (!result)
@@ -895,6 +904,11 @@ nl80211_parse_connkeys(struct cfg80211_registered_device *rdev,
                        *no_ht = true;
        }
 
+       if (result->def < 0) {
+               err = -EINVAL;
+               goto error;
+       }
+
        return result;
  error:
        kfree(result);
index add6824c44fd70af60feee7d4380d1bb935fee7f..c08a3b57dca1268b0f57d5c20cd1e47a16676043 100644 (file)
@@ -1043,6 +1043,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
                                connect->crypto.ciphers_pairwise[0] = cipher;
                        }
                }
+       } else {
+               if (WARN_ON(connkeys))
+                       return -EINVAL;
        }
 
        wdev->connect_keys = connkeys;
index f6523a4387cce6298e6d959682cb2ca0e23485c6..88f1f6931ab8e030bce4ce224ee5d6484798274e 100644 (file)
@@ -42,7 +42,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
        if (!wdev->wext.connect.ssid_len)
                return 0;
 
-       if (wdev->wext.keys) {
+       if (wdev->wext.keys && wdev->wext.keys->def != -1) {
                ck = kmemdup(wdev->wext.keys, sizeof(*ck), GFP_KERNEL);
                if (!ck)
                        return -ENOMEM;