Commit d097ae01 authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: mac80211: fix potential key leak



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: default avatarJohannes Berg <johannes.berg@intel.com>
parent 31db78a4
Loading
Loading
Loading
Loading
+15 −5
Original line number Diff line number Diff line
@@ -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,18 +900,19 @@ 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;
		}
	}

	/*
	 * Silently accept key re-installation without really installing the
	 * 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;