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) | 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,8 +900,10 @@ 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; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	/*
 | 	/*
 | ||||||
|  | @ -904,9 +911,8 @@ int ieee80211_key_link(struct ieee80211_key *key, | ||||||
| 	 * 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…
	
		Reference in a new issue
	
	 Johannes Berg
						Johannes Berg