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: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
parent
31db78a492
commit
d097ae01eb
1 changed files with 15 additions and 5 deletions
|
@ -802,6 +802,9 @@ static void ieee80211_key_destroy(struct ieee80211_key *key,
|
||||||
|
|
||||||
void ieee80211_key_free_unused(struct ieee80211_key *key)
|
void ieee80211_key_free_unused(struct ieee80211_key *key)
|
||||||
{
|
{
|
||||||
|
if (!key)
|
||||||
|
return;
|
||||||
|
|
||||||
WARN_ON(key->sdata || key->local);
|
WARN_ON(key->sdata || key->local);
|
||||||
ieee80211_key_free_common(key);
|
ieee80211_key_free_common(key);
|
||||||
}
|
}
|
||||||
|
@ -854,7 +857,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||||
* can cause warnings to appear.
|
* can cause warnings to appear.
|
||||||
*/
|
*/
|
||||||
bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
|
bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION;
|
||||||
int ret = -EOPNOTSUPP;
|
int ret;
|
||||||
|
|
||||||
mutex_lock(&sdata->local->key_mtx);
|
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.
|
* the same cipher. Enforce the assumption for pairwise keys.
|
||||||
*/
|
*/
|
||||||
if ((alt_key && alt_key->conf.cipher != key->conf.cipher) ||
|
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;
|
goto out;
|
||||||
|
}
|
||||||
} else if (sta) {
|
} else if (sta) {
|
||||||
struct link_sta_info *link_sta = &sta->deflink;
|
struct link_sta_info *link_sta = &sta->deflink;
|
||||||
int link_id = key->conf.link_id;
|
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 */
|
/* Non-pairwise keys must also not switch the cipher on rekey */
|
||||||
if (!pairwise) {
|
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;
|
goto out;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Silently accept key re-installation without really installing the
|
* Silently accept key re-installation without really installing the
|
||||||
* new version of the key to avoid nonce reuse or replay issues.
|
* new version of the key to avoid nonce reuse or replay issues.
|
||||||
*/
|
*/
|
||||||
if (ieee80211_key_identical(sdata, old_key, key)) {
|
if (ieee80211_key_identical(sdata, old_key, key)) {
|
||||||
ieee80211_key_free_unused(key);
|
|
||||||
ret = -EALREADY;
|
ret = -EALREADY;
|
||||||
goto out;
|
goto unlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
key->local = sdata->local;
|
key->local = sdata->local;
|
||||||
|
@ -930,7 +936,11 @@ int ieee80211_key_link(struct ieee80211_key *key,
|
||||||
ieee80211_key_free(key, delay_tailroom);
|
ieee80211_key_free(key, delay_tailroom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
key = NULL;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
|
ieee80211_key_free_unused(key);
|
||||||
|
unlock:
|
||||||
mutex_unlock(&sdata->local->key_mtx);
|
mutex_unlock(&sdata->local->key_mtx);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Add table
Reference in a new issue