mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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)
 | 
			
		||||
{
 | 
			
		||||
	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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue