mac80211: validate cipher scheme PN length better
Currently, a cipher scheme can advertise an arbitrarily long sequence counter, but mac80211 only supports up to 16 bytes and the initial value from userspace will be truncated. Fix two things: * don't allow the driver to register anything longer than the 16 bytes that mac80211 reserves space for * require userspace to specify a starting value with the correct length (or none at all) Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
					parent
					
						
							
								a31cf1c69e
							
						
					
				
			
			
				commit
				
					
						e3a55b5399
					
				
			
		
					 2 changed files with 10 additions and 5 deletions
				
			
		|  | @ -485,15 +485,17 @@ ieee80211_key_alloc(u32 cipher, int idx, size_t key_len, | ||||||
| 		break; | 		break; | ||||||
| 	default: | 	default: | ||||||
| 		if (cs) { | 		if (cs) { | ||||||
| 			size_t len = (seq_len > IEEE80211_MAX_PN_LEN) ? | 			if (seq_len && seq_len != cs->pn_len) { | ||||||
| 						IEEE80211_MAX_PN_LEN : seq_len; | 				kfree(key); | ||||||
|  | 				return ERR_PTR(-EINVAL); | ||||||
|  | 			} | ||||||
| 
 | 
 | ||||||
| 			key->conf.iv_len = cs->hdr_len; | 			key->conf.iv_len = cs->hdr_len; | ||||||
| 			key->conf.icv_len = cs->mic_len; | 			key->conf.icv_len = cs->mic_len; | ||||||
| 			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) | 			for (i = 0; i < IEEE80211_NUM_TIDS + 1; i++) | ||||||
| 				for (j = 0; j < len; j++) | 				for (j = 0; j < seq_len; j++) | ||||||
| 					key->u.gen.rx_pn[i][j] = | 					key->u.gen.rx_pn[i][j] = | ||||||
| 							seq[len - j - 1]; | 							seq[seq_len - j - 1]; | ||||||
| 			key->flags |= KEY_FLAG_CIPHER_SCHEME; | 			key->flags |= KEY_FLAG_CIPHER_SCHEME; | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -768,8 +768,11 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local) | ||||||
| 			suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; | 			suites[w++] = WLAN_CIPHER_SUITE_BIP_GMAC_256; | ||||||
| 		} | 		} | ||||||
| 
 | 
 | ||||||
| 		for (r = 0; r < local->hw.n_cipher_schemes; r++) | 		for (r = 0; r < local->hw.n_cipher_schemes; r++) { | ||||||
| 			suites[w++] = cs[r].cipher; | 			suites[w++] = cs[r].cipher; | ||||||
|  | 			if (WARN_ON(cs[r].pn_len > IEEE80211_MAX_PN_LEN)) | ||||||
|  | 				return -EINVAL; | ||||||
|  | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	local->hw.wiphy->cipher_suites = suites; | 	local->hw.wiphy->cipher_suites = suites; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Johannes Berg
				Johannes Berg