wifi: mac80211: fix potential key leak
authorJohannes Berg <johannes.berg@intel.com>
Tue, 19 Sep 2023 06:34:16 +0000 (08:34 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 25 Sep 2023 06:40:07 +0000 (08:40 +0200)
When returning from ieee80211_key_link(), the key needs to
have been freed or successfully installed. This was missed
in a number of error paths, fix it.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/key.c

index 84ba20c..0665ff5 100644 (file)
@@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key,
 
 void ieee80211_key_free_unused(struct ieee80211_key *key)
 {
+       if (!key)
+               return;
+
        WARN_ON(key->sdata || key->local);
        ieee80211_key_free_common(key);
 }
@@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
         * can cause warnings to appear.
         */
        bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
-       int ret = -EOPNOTSUPP;
+       int ret;
 
        mutex_lock(&sdata->local->key_mtx);
 
@@ -868,8 +871,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
                 * the same cipher. Enforce the assumption for pairwise keys.
                 */
                if ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
-                   (old_key && old_key->conf.cipher != key->conf.cipher))
+                   (old_key && old_key->conf.cipher != key->conf.cipher)) {
+                       ret = -EOPNOTSUPP;
                        goto out;
+               }
        } else if (sta) {
                struct link_sta_info *link_sta = &sta->deflink;
                int link_id = key->conf.link_id;
@@ -895,8 +900,10 @@ int ieee80211_key_link(struct ieee80211_key *key,
 
        /* Non-pairwise keys must also not switch the cipher on rekey */
        if (!pairwise) {
-               if (old_key && old_key->conf.cipher != key->conf.cipher)
+               if (old_key && old_key->conf.cipher != key->conf.cipher) {
+                       ret = -EOPNOTSUPP;
                        goto out;
+               }
        }
 
        /*
@@ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key,
         * new version of the key to avoid nonce reuse or replay issues.
         */
        if (ieee80211_key_identical(sdata, old_key, key)) {
-               ieee80211_key_free_unused(key);
                ret = -EALREADY;
-               goto out;
+               goto unlock;
        }
 
        key->local = sdata->local;
@@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key,
                ieee80211_key_free(key, delay_tailroom);
        }
 
+       key = NULL;
+
  out:
+       ieee80211_key_free_unused(key);
+ unlock:
        mutex_unlock(&sdata->local->key_mtx);
 
        return ret;