forked from mirrors/linux
		
	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
	
	 Johannes Berg
						Johannes Berg