mac80211: backport security fixes
This mainly affects scanning and beacon parsing, especially with MBSSID enabled Fixes: CVE-2022-41674 Fixes: CVE-2022-42719 Fixes: CVE-2022-42720 Fixes: CVE-2022-42721 Fixes: CVE-2022-42722 Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
		| @@ -0,0 +1,110 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Mon, 20 Sep 2021 15:40:07 +0200 | ||||||
|  | Subject: [PATCH] mac80211: mesh: clean up rx_bcn_presp API | ||||||
|  |  | ||||||
|  | commit a5b983c6073140b624f64e79fea6d33c3e4315a0 upstream. | ||||||
|  |  | ||||||
|  | We currently pass the entire elements to the rx_bcn_presp() | ||||||
|  | method, but only need mesh_config. Additionally, we use the | ||||||
|  | length of the elements to calculate back the entire frame's | ||||||
|  | length, but that's confusing - just pass the length of the | ||||||
|  | frame instead. | ||||||
|  |  | ||||||
|  | Link: https://lore.kernel.org/r/20210920154009.a18ed3d2da6c.I1824b773a0fbae4453e1433c184678ca14e8df45@changeid | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/ieee80211_i.h | ||||||
|  | +++ b/net/mac80211/ieee80211_i.h | ||||||
|  | @@ -645,10 +645,9 @@ struct ieee80211_if_ocb { | ||||||
|  |   */ | ||||||
|  |  struct ieee802_11_elems; | ||||||
|  |  struct ieee80211_mesh_sync_ops { | ||||||
|  | -	void (*rx_bcn_presp)(struct ieee80211_sub_if_data *sdata, | ||||||
|  | -			     u16 stype, | ||||||
|  | -			     struct ieee80211_mgmt *mgmt, | ||||||
|  | -			     struct ieee802_11_elems *elems, | ||||||
|  | +	void (*rx_bcn_presp)(struct ieee80211_sub_if_data *sdata, u16 stype, | ||||||
|  | +			     struct ieee80211_mgmt *mgmt, unsigned int len, | ||||||
|  | +			     const struct ieee80211_meshconf_ie *mesh_cfg, | ||||||
|  |  			     struct ieee80211_rx_status *rx_status); | ||||||
|  |   | ||||||
|  |  	/* should be called with beacon_data under RCU read lock */ | ||||||
|  | --- a/net/mac80211/mesh.c | ||||||
|  | +++ b/net/mac80211/mesh.c | ||||||
|  | @@ -1354,8 +1354,8 @@ static void ieee80211_mesh_rx_bcn_presp( | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	if (ifmsh->sync_ops) | ||||||
|  | -		ifmsh->sync_ops->rx_bcn_presp(sdata, | ||||||
|  | -			stype, mgmt, &elems, rx_status); | ||||||
|  | +		ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, len, | ||||||
|  | +					      elems.mesh_config, rx_status); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) | ||||||
|  | --- a/net/mac80211/mesh_sync.c | ||||||
|  | +++ b/net/mac80211/mesh_sync.c | ||||||
|  | @@ -3,6 +3,7 @@ | ||||||
|  |   * Copyright 2011-2012, Pavel Zubarev <pavel.zubarev@gmail.com> | ||||||
|  |   * Copyright 2011-2012, Marco Porsch <marco.porsch@s2005.tu-chemnitz.de> | ||||||
|  |   * Copyright 2011-2012, cozybit Inc. | ||||||
|  | + * Copyright (C) 2021 Intel Corporation | ||||||
|  |   */ | ||||||
|  |   | ||||||
|  |  #include "ieee80211_i.h" | ||||||
|  | @@ -35,12 +36,12 @@ struct sync_method { | ||||||
|  |  /** | ||||||
|  |   * mesh_peer_tbtt_adjusting - check if an mp is currently adjusting its TBTT | ||||||
|  |   * | ||||||
|  | - * @ie: information elements of a management frame from the mesh peer | ||||||
|  | + * @cfg: mesh config element from the mesh peer (or %NULL) | ||||||
|  |   */ | ||||||
|  | -static bool mesh_peer_tbtt_adjusting(struct ieee802_11_elems *ie) | ||||||
|  | +static bool mesh_peer_tbtt_adjusting(const struct ieee80211_meshconf_ie *cfg) | ||||||
|  |  { | ||||||
|  | -	return (ie->mesh_config->meshconf_cap & | ||||||
|  | -			IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING) != 0; | ||||||
|  | +	return cfg && | ||||||
|  | +	       (cfg->meshconf_cap & IEEE80211_MESHCONF_CAPAB_TBTT_ADJUSTING); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  void mesh_sync_adjust_tsf(struct ieee80211_sub_if_data *sdata) | ||||||
|  | @@ -76,11 +77,11 @@ void mesh_sync_adjust_tsf(struct ieee802 | ||||||
|  |  	} | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | ||||||
|  | -				   u16 stype, | ||||||
|  | -				   struct ieee80211_mgmt *mgmt, | ||||||
|  | -				   struct ieee802_11_elems *elems, | ||||||
|  | -				   struct ieee80211_rx_status *rx_status) | ||||||
|  | +static void | ||||||
|  | +mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, u16 stype, | ||||||
|  | +			      struct ieee80211_mgmt *mgmt, unsigned int len, | ||||||
|  | +			      const struct ieee80211_meshconf_ie *mesh_cfg, | ||||||
|  | +			      struct ieee80211_rx_status *rx_status) | ||||||
|  |  { | ||||||
|  |  	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | ||||||
|  |  	struct ieee80211_local *local = sdata->local; | ||||||
|  | @@ -101,10 +102,7 @@ static void mesh_sync_offset_rx_bcn_pres | ||||||
|  |  	 */ | ||||||
|  |  	if (ieee80211_have_rx_timestamp(rx_status)) | ||||||
|  |  		t_r = ieee80211_calculate_rx_timestamp(local, rx_status, | ||||||
|  | -						       24 + 12 + | ||||||
|  | -						       elems->total_len + | ||||||
|  | -						       FCS_LEN, | ||||||
|  | -						       24); | ||||||
|  | +						       len + FCS_LEN, 24); | ||||||
|  |  	else | ||||||
|  |  		t_r = drv_get_tsf(local, sdata); | ||||||
|  |   | ||||||
|  | @@ -119,7 +117,7 @@ static void mesh_sync_offset_rx_bcn_pres | ||||||
|  |  	 * dot11MeshNbrOffsetMaxNeighbor non-peer non-MBSS neighbors | ||||||
|  |  	 */ | ||||||
|  |   | ||||||
|  | -	if (elems->mesh_config && mesh_peer_tbtt_adjusting(elems)) { | ||||||
|  | +	if (mesh_peer_tbtt_adjusting(mesh_cfg)) { | ||||||
|  |  		msync_dbg(sdata, "STA %pM : is adjusting TBTT\n", | ||||||
|  |  			  sta->sta.addr); | ||||||
|  |  		goto no_sync; | ||||||
| @@ -0,0 +1,82 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Mon, 20 Sep 2021 15:40:08 +0200 | ||||||
|  | Subject: [PATCH] mac80211: move CRC into struct ieee802_11_elems | ||||||
|  |  | ||||||
|  | commit c6e37ed498f958254b5459253199e816b6bfc52f upstream. | ||||||
|  |  | ||||||
|  | We're currently returning this value, but to prepare for | ||||||
|  | returning the allocated structure, move it into there. | ||||||
|  |  | ||||||
|  | Link: https://lore.kernel.org/r/20210920154009.479b8ebf999d.If0d4ba75ee38998dc3eeae25058aa748efcb2fc9@changeid | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/ieee80211_i.h | ||||||
|  | +++ b/net/mac80211/ieee80211_i.h | ||||||
|  | @@ -1530,6 +1530,7 @@ struct ieee80211_csa_ie { | ||||||
|  |  struct ieee802_11_elems { | ||||||
|  |  	const u8 *ie_start; | ||||||
|  |  	size_t total_len; | ||||||
|  | +	u32 crc; | ||||||
|  |   | ||||||
|  |  	/* pointers to IEs */ | ||||||
|  |  	const struct ieee80211_tdls_lnkie *lnk_id; | ||||||
|  | @@ -2089,10 +2090,10 @@ static inline void ieee80211_tx_skb(stru | ||||||
|  |  	ieee80211_tx_skb_tid(sdata, skb, 7); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | ||||||
|  | -			       struct ieee802_11_elems *elems, | ||||||
|  | -			       u64 filter, u32 crc, u8 *transmitter_bssid, | ||||||
|  | -			       u8 *bss_bssid); | ||||||
|  | +void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | ||||||
|  | +				struct ieee802_11_elems *elems, | ||||||
|  | +				u64 filter, u32 crc, u8 *transmitter_bssid, | ||||||
|  | +				u8 *bss_bssid); | ||||||
|  |  static inline void ieee802_11_parse_elems(const u8 *start, size_t len, | ||||||
|  |  					  bool action, | ||||||
|  |  					  struct ieee802_11_elems *elems, | ||||||
|  | --- a/net/mac80211/mlme.c | ||||||
|  | +++ b/net/mac80211/mlme.c | ||||||
|  | @@ -4102,10 +4102,11 @@ static void ieee80211_rx_mgmt_beacon(str | ||||||
|  |  	 */ | ||||||
|  |  	if (!ieee80211_is_s1g_beacon(hdr->frame_control)) | ||||||
|  |  		ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); | ||||||
|  | -	ncrc = ieee802_11_parse_elems_crc(variable, | ||||||
|  | -					  len - baselen, false, &elems, | ||||||
|  | -					  care_about_ies, ncrc, | ||||||
|  | -					  mgmt->bssid, bssid); | ||||||
|  | +	ieee802_11_parse_elems_crc(variable, | ||||||
|  | +				   len - baselen, false, &elems, | ||||||
|  | +				   care_about_ies, ncrc, | ||||||
|  | +				   mgmt->bssid, bssid); | ||||||
|  | +	ncrc = elems.crc; | ||||||
|  |   | ||||||
|  |  	if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) && | ||||||
|  |  	    ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) { | ||||||
|  | --- a/net/mac80211/util.c | ||||||
|  | +++ b/net/mac80211/util.c | ||||||
|  | @@ -1469,10 +1469,10 @@ static size_t ieee802_11_find_bssid_prof | ||||||
|  |  	return found ? profile_len : 0; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | -u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | ||||||
|  | -			       struct ieee802_11_elems *elems, | ||||||
|  | -			       u64 filter, u32 crc, u8 *transmitter_bssid, | ||||||
|  | -			       u8 *bss_bssid) | ||||||
|  | +void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, | ||||||
|  | +				struct ieee802_11_elems *elems, | ||||||
|  | +				u64 filter, u32 crc, u8 *transmitter_bssid, | ||||||
|  | +				u8 *bss_bssid) | ||||||
|  |  { | ||||||
|  |  	const struct element *non_inherit = NULL; | ||||||
|  |  	u8 *nontransmitted_profile; | ||||||
|  | @@ -1524,7 +1524,7 @@ u32 ieee802_11_parse_elems_crc(const u8 | ||||||
|  |   | ||||||
|  |  	kfree(nontransmitted_profile); | ||||||
|  |   | ||||||
|  | -	return crc; | ||||||
|  | +	elems->crc = crc; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, | ||||||
| @@ -0,0 +1,80 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Mon, 20 Sep 2021 15:40:09 +0200 | ||||||
|  | Subject: [PATCH] mac80211: mlme: find auth challenge directly | ||||||
|  |  | ||||||
|  | commit 49a765d6785e99157ff5091cc37485732496864e upstream. | ||||||
|  |  | ||||||
|  | There's no need to parse all elements etc. just to find the | ||||||
|  | authentication challenge - use cfg80211_find_elem() instead. | ||||||
|  | This also allows us to remove WLAN_EID_CHALLENGE handling | ||||||
|  | from the element parsing entirely. | ||||||
|  |  | ||||||
|  | Link: https://lore.kernel.org/r/20210920154009.45f9b3a15722.Ice3159ffad03a007d6154cbf1fb3a8c48489e86f@changeid | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/ieee80211_i.h | ||||||
|  | +++ b/net/mac80211/ieee80211_i.h | ||||||
|  | @@ -1540,7 +1540,6 @@ struct ieee802_11_elems { | ||||||
|  |  	const u8 *supp_rates; | ||||||
|  |  	const u8 *ds_params; | ||||||
|  |  	const struct ieee80211_tim_ie *tim; | ||||||
|  | -	const u8 *challenge; | ||||||
|  |  	const u8 *rsn; | ||||||
|  |  	const u8 *rsnx; | ||||||
|  |  	const u8 *erp_info; | ||||||
|  | @@ -1594,7 +1593,6 @@ struct ieee802_11_elems { | ||||||
|  |  	u8 ssid_len; | ||||||
|  |  	u8 supp_rates_len; | ||||||
|  |  	u8 tim_len; | ||||||
|  | -	u8 challenge_len; | ||||||
|  |  	u8 rsn_len; | ||||||
|  |  	u8 rsnx_len; | ||||||
|  |  	u8 ext_supp_rates_len; | ||||||
|  | --- a/net/mac80211/mlme.c | ||||||
|  | +++ b/net/mac80211/mlme.c | ||||||
|  | @@ -2889,17 +2889,17 @@ static void ieee80211_auth_challenge(str | ||||||
|  |  { | ||||||
|  |  	struct ieee80211_local *local = sdata->local; | ||||||
|  |  	struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data; | ||||||
|  | +	const struct element *challenge; | ||||||
|  |  	u8 *pos; | ||||||
|  | -	struct ieee802_11_elems elems; | ||||||
|  |  	u32 tx_flags = 0; | ||||||
|  |  	struct ieee80211_prep_tx_info info = { | ||||||
|  |  		.subtype = IEEE80211_STYPE_AUTH, | ||||||
|  |  	}; | ||||||
|  |   | ||||||
|  |  	pos = mgmt->u.auth.variable; | ||||||
|  | -	ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems, | ||||||
|  | -			       mgmt->bssid, auth_data->bss->bssid); | ||||||
|  | -	if (!elems.challenge) | ||||||
|  | +	challenge = cfg80211_find_elem(WLAN_EID_CHALLENGE, pos, | ||||||
|  | +				       len - (pos - (u8 *)mgmt)); | ||||||
|  | +	if (!challenge) | ||||||
|  |  		return; | ||||||
|  |  	auth_data->expected_transaction = 4; | ||||||
|  |  	drv_mgd_prepare_tx(sdata->local, sdata, &info); | ||||||
|  | @@ -2907,7 +2907,8 @@ static void ieee80211_auth_challenge(str | ||||||
|  |  		tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | | ||||||
|  |  			   IEEE80211_TX_INTFL_MLME_CONN_TX; | ||||||
|  |  	ieee80211_send_auth(sdata, 3, auth_data->algorithm, 0, | ||||||
|  | -			    elems.challenge - 2, elems.challenge_len + 2, | ||||||
|  | +			    (void *)challenge, | ||||||
|  | +			    challenge->datalen + sizeof(*challenge), | ||||||
|  |  			    auth_data->bss->bssid, auth_data->bss->bssid, | ||||||
|  |  			    auth_data->key, auth_data->key_len, | ||||||
|  |  			    auth_data->key_idx, tx_flags); | ||||||
|  | --- a/net/mac80211/util.c | ||||||
|  | +++ b/net/mac80211/util.c | ||||||
|  | @@ -1120,10 +1120,6 @@ _ieee802_11_parse_elems_crc(const u8 *st | ||||||
|  |  			} else | ||||||
|  |  				elem_parse_failed = true; | ||||||
|  |  			break; | ||||||
|  | -		case WLAN_EID_CHALLENGE: | ||||||
|  | -			elems->challenge = pos; | ||||||
|  | -			elems->challenge_len = elen; | ||||||
|  | -			break; | ||||||
|  |  		case WLAN_EID_VENDOR_SPECIFIC: | ||||||
|  |  			if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && | ||||||
|  |  			    pos[2] == 0xf2) { | ||||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -0,0 +1,115 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Fri, 1 Oct 2021 21:11:08 +0200 | ||||||
|  | Subject: [PATCH] mac80211: fix memory leaks with element parsing | ||||||
|  |  | ||||||
|  | commit 8223ac199a3849257e86ec27865dc63f034b1cf1 upstream. | ||||||
|  |  | ||||||
|  | My previous commit 5d24828d05f3 ("mac80211: always allocate | ||||||
|  | struct ieee802_11_elems") had a few bugs and leaked the new | ||||||
|  | allocated struct in a few error cases, fix that. | ||||||
|  |  | ||||||
|  | Fixes: 5d24828d05f3 ("mac80211: always allocate struct ieee802_11_elems") | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Link: https://lore.kernel.org/r/20211001211108.9839928e42e0.Ib81ca187d3d3af7ed1bfeac2e00d08a4637c8025@changeid | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/agg-rx.c | ||||||
|  | +++ b/net/mac80211/agg-rx.c | ||||||
|  | @@ -499,13 +499,14 @@ void ieee80211_process_addba_request(str | ||||||
|  |  		elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable, | ||||||
|  |  					       ies_len, true, mgmt->bssid, NULL); | ||||||
|  |  		if (!elems || elems->parse_error) | ||||||
|  | -			return; | ||||||
|  | +			goto free; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	__ieee80211_start_rx_ba_session(sta, dialog_token, timeout, | ||||||
|  |  					start_seq_num, ba_policy, tid, | ||||||
|  |  					buf_size, true, false, | ||||||
|  |  					elems ? elems->addba_ext_ie : NULL); | ||||||
|  | +free: | ||||||
|  |  	kfree(elems); | ||||||
|  |  } | ||||||
|  |   | ||||||
|  | --- a/net/mac80211/ibss.c | ||||||
|  | +++ b/net/mac80211/ibss.c | ||||||
|  | @@ -1659,11 +1659,11 @@ void ieee80211_ibss_rx_queued_mgmt(struc | ||||||
|  |  				mgmt->u.action.u.chan_switch.variable, | ||||||
|  |  				ies_len, true, mgmt->bssid, NULL); | ||||||
|  |   | ||||||
|  | -			if (!elems || elems->parse_error) | ||||||
|  | -				break; | ||||||
|  | - | ||||||
|  | -			ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len, | ||||||
|  | -							rx_status, elems); | ||||||
|  | +			if (elems && !elems->parse_error) | ||||||
|  | +				ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, | ||||||
|  | +								skb->len, | ||||||
|  | +								rx_status, | ||||||
|  | +								elems); | ||||||
|  |  			kfree(elems); | ||||||
|  |  			break; | ||||||
|  |  		} | ||||||
|  | --- a/net/mac80211/mlme.c | ||||||
|  | +++ b/net/mac80211/mlme.c | ||||||
|  | @@ -3374,8 +3374,10 @@ static bool ieee80211_assoc_success(stru | ||||||
|  |  			bss_ies = kmemdup(ies, sizeof(*ies) + ies->len, | ||||||
|  |  					  GFP_ATOMIC); | ||||||
|  |  		rcu_read_unlock(); | ||||||
|  | -		if (!bss_ies) | ||||||
|  | -			return false; | ||||||
|  | +		if (!bss_ies) { | ||||||
|  | +			ret = false; | ||||||
|  | +			goto out; | ||||||
|  | +		} | ||||||
|  |   | ||||||
|  |  		bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len, | ||||||
|  |  						   false, mgmt->bssid, | ||||||
|  | @@ -4358,13 +4360,11 @@ void ieee80211_sta_rx_queued_mgmt(struct | ||||||
|  |  					mgmt->u.action.u.chan_switch.variable, | ||||||
|  |  					ies_len, true, mgmt->bssid, NULL); | ||||||
|  |   | ||||||
|  | -			if (!elems || elems->parse_error) | ||||||
|  | -				break; | ||||||
|  | - | ||||||
|  | -			ieee80211_sta_process_chanswitch(sdata, | ||||||
|  | -						 rx_status->mactime, | ||||||
|  | -						 rx_status->device_timestamp, | ||||||
|  | -						 elems, false); | ||||||
|  | +			if (elems && !elems->parse_error) | ||||||
|  | +				ieee80211_sta_process_chanswitch(sdata, | ||||||
|  | +								 rx_status->mactime, | ||||||
|  | +								 rx_status->device_timestamp, | ||||||
|  | +								 elems, false); | ||||||
|  |  			kfree(elems); | ||||||
|  |  		} else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { | ||||||
|  |  			struct ieee802_11_elems *elems; | ||||||
|  | @@ -4384,17 +4384,17 @@ void ieee80211_sta_rx_queued_mgmt(struct | ||||||
|  |  					mgmt->u.action.u.ext_chan_switch.variable, | ||||||
|  |  					ies_len, true, mgmt->bssid, NULL); | ||||||
|  |   | ||||||
|  | -			if (!elems || elems->parse_error) | ||||||
|  | -				break; | ||||||
|  | +			if (elems && !elems->parse_error) { | ||||||
|  | +				/* for the handling code pretend it was an IE */ | ||||||
|  | +				elems->ext_chansw_ie = | ||||||
|  | +					&mgmt->u.action.u.ext_chan_switch.data; | ||||||
|  | + | ||||||
|  | +				ieee80211_sta_process_chanswitch(sdata, | ||||||
|  | +								 rx_status->mactime, | ||||||
|  | +								 rx_status->device_timestamp, | ||||||
|  | +								 elems, false); | ||||||
|  | +			} | ||||||
|  |   | ||||||
|  | -			/* for the handling code pretend this was also an IE */ | ||||||
|  | -			elems->ext_chansw_ie = | ||||||
|  | -				&mgmt->u.action.u.ext_chan_switch.data; | ||||||
|  | - | ||||||
|  | -			ieee80211_sta_process_chanswitch(sdata, | ||||||
|  | -						 rx_status->mactime, | ||||||
|  | -						 rx_status->device_timestamp, | ||||||
|  | -						 elems, false); | ||||||
|  |  			kfree(elems); | ||||||
|  |  		} | ||||||
|  |  		break; | ||||||
| @@ -0,0 +1,41 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Wed, 28 Sep 2022 21:56:15 +0200 | ||||||
|  | Subject: [PATCH] wifi: cfg80211: fix u8 overflow in | ||||||
|  |  cfg80211_update_notlisted_nontrans() | ||||||
|  |  | ||||||
|  | commit aebe9f4639b13a1f4e9a6b42cdd2e38c617b442d upstream. | ||||||
|  |  | ||||||
|  | In the copy code of the elements, we do the following calculation | ||||||
|  | to reach the end of the MBSSID element: | ||||||
|  |  | ||||||
|  | 	/* copy the IEs after MBSSID */ | ||||||
|  | 	cpy_len = mbssid[1] + 2; | ||||||
|  |  | ||||||
|  | This looks fine, however, cpy_len is a u8, the same as mbssid[1], | ||||||
|  | so the addition of two can overflow. In this case the subsequent | ||||||
|  | memcpy() will overflow the allocated buffer, since it copies 256 | ||||||
|  | bytes too much due to the way the allocation and memcpy() sizes | ||||||
|  | are calculated. | ||||||
|  |  | ||||||
|  | Fix this by using size_t for the cpy_len variable. | ||||||
|  |  | ||||||
|  | This fixes CVE-2022-41674. | ||||||
|  |  | ||||||
|  | Reported-by: Soenke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Tested-by: Soenke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") | ||||||
|  | Reviewed-by: Kees Cook <keescook@chromium.org> | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/wireless/scan.c | ||||||
|  | +++ b/net/wireless/scan.c | ||||||
|  | @@ -2238,7 +2238,7 @@ cfg80211_update_notlisted_nontrans(struc | ||||||
|  |  	size_t new_ie_len; | ||||||
|  |  	struct cfg80211_bss_ies *new_ies; | ||||||
|  |  	const struct cfg80211_bss_ies *old; | ||||||
|  | -	u8 cpy_len; | ||||||
|  | +	size_t cpy_len; | ||||||
|  |   | ||||||
|  |  	lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock); | ||||||
|  |   | ||||||
| @@ -0,0 +1,47 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Wed, 28 Sep 2022 22:01:37 +0200 | ||||||
|  | Subject: [PATCH] wifi: cfg80211/mac80211: reject bad MBSSID elements | ||||||
|  |  | ||||||
|  | commit 8f033d2becc24aa6bfd2a5c104407963560caabc upstream | ||||||
|  |  | ||||||
|  | Per spec, the maximum value for the MaxBSSID ('n') indicator is 8, | ||||||
|  | and the minimum is 1 since a multiple BSSID set with just one BSSID | ||||||
|  | doesn't make sense (the # of BSSIDs is limited by 2^n). | ||||||
|  |  | ||||||
|  | Limit this in the parsing in both cfg80211 and mac80211, rejecting | ||||||
|  | any elements with an invalid value. | ||||||
|  |  | ||||||
|  | This fixes potentially bad shifts in the processing of these inside | ||||||
|  | the cfg80211_gen_new_bssid() function later. | ||||||
|  |  | ||||||
|  | I found this during the investigation of CVE-2022-41674 fixed by the | ||||||
|  | previous patch. | ||||||
|  |  | ||||||
|  | Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") | ||||||
|  | Fixes: 78ac51f81532 ("mac80211: support multi-bssid") | ||||||
|  | Reviewed-by: Kees Cook <keescook@chromium.org> | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/util.c | ||||||
|  | +++ b/net/mac80211/util.c | ||||||
|  | @@ -1413,6 +1413,8 @@ static size_t ieee802_11_find_bssid_prof | ||||||
|  |  	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) { | ||||||
|  |  		if (elem->datalen < 2) | ||||||
|  |  			continue; | ||||||
|  | +		if (elem->data[0] < 1 || elem->data[0] > 8) | ||||||
|  | +			continue; | ||||||
|  |   | ||||||
|  |  		for_each_element(sub, elem->data + 1, elem->datalen - 1) { | ||||||
|  |  			u8 new_bssid[ETH_ALEN]; | ||||||
|  | --- a/net/wireless/scan.c | ||||||
|  | +++ b/net/wireless/scan.c | ||||||
|  | @@ -2103,6 +2103,8 @@ static void cfg80211_parse_mbssid_data(s | ||||||
|  |  	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) { | ||||||
|  |  		if (elem->datalen < 4) | ||||||
|  |  			continue; | ||||||
|  | +		if (elem->data[0] < 1 || (int)elem->data[0] > 8) | ||||||
|  | +			continue; | ||||||
|  |  		for_each_element(sub, elem->data + 1, elem->datalen - 1) { | ||||||
|  |  			u8 profile_len; | ||||||
|  |   | ||||||
| @@ -0,0 +1,94 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Wed, 28 Sep 2022 22:07:15 +0200 | ||||||
|  | Subject: [PATCH] wifi: mac80211: fix MBSSID parsing use-after-free | ||||||
|  |  | ||||||
|  | commit ff05d4b45dd89b922578dac497dcabf57cf771c6 | ||||||
|  |  | ||||||
|  | When we parse a multi-BSSID element, we might point some | ||||||
|  | element pointers into the allocated nontransmitted_profile. | ||||||
|  | However, we free this before returning, causing UAF when the | ||||||
|  | relevant pointers in the parsed elements are accessed. | ||||||
|  |  | ||||||
|  | Fix this by not allocating the scratch buffer separately but | ||||||
|  | as part of the returned structure instead, that way, there | ||||||
|  | are no lifetime issues with it. | ||||||
|  |  | ||||||
|  | The scratch buffer introduction as part of the returned data | ||||||
|  | here is taken from MLO feature work done by Ilan. | ||||||
|  |  | ||||||
|  | This fixes CVE-2022-42719. | ||||||
|  |  | ||||||
|  | Fixes: 5023b14cf4df ("mac80211: support profile split between elements") | ||||||
|  | Co-developed-by: Ilan Peer <ilan.peer@intel.com> | ||||||
|  | Signed-off-by: Ilan Peer <ilan.peer@intel.com> | ||||||
|  | Reviewed-by: Kees Cook <keescook@chromium.org> | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/ieee80211_i.h | ||||||
|  | +++ b/net/mac80211/ieee80211_i.h | ||||||
|  | @@ -1611,6 +1611,14 @@ struct ieee802_11_elems { | ||||||
|  |   | ||||||
|  |  	/* whether a parse error occurred while retrieving these elements */ | ||||||
|  |  	bool parse_error; | ||||||
|  | + | ||||||
|  | +	/* | ||||||
|  | +	 * scratch buffer that can be used for various element parsing related | ||||||
|  | +	 * tasks, e.g., element de-fragmentation etc. | ||||||
|  | +	 */ | ||||||
|  | +	size_t scratch_len; | ||||||
|  | +	u8 *scratch_pos; | ||||||
|  | +	u8 scratch[]; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  |  static inline struct ieee80211_local *hw_to_local( | ||||||
|  | --- a/net/mac80211/util.c | ||||||
|  | +++ b/net/mac80211/util.c | ||||||
|  | @@ -1478,24 +1478,25 @@ struct ieee802_11_elems *ieee802_11_pars | ||||||
|  |  	u8 *nontransmitted_profile; | ||||||
|  |  	int nontransmitted_profile_len = 0; | ||||||
|  |   | ||||||
|  | -	elems = kzalloc(sizeof(*elems), GFP_ATOMIC); | ||||||
|  | +	elems = kzalloc(sizeof(*elems) + len, GFP_ATOMIC); | ||||||
|  |  	if (!elems) | ||||||
|  |  		return NULL; | ||||||
|  |  	elems->ie_start = start; | ||||||
|  |  	elems->total_len = len; | ||||||
|  |   | ||||||
|  | -	nontransmitted_profile = kmalloc(len, GFP_ATOMIC); | ||||||
|  | -	if (nontransmitted_profile) { | ||||||
|  | -		nontransmitted_profile_len = | ||||||
|  | -			ieee802_11_find_bssid_profile(start, len, elems, | ||||||
|  | -						      transmitter_bssid, | ||||||
|  | -						      bss_bssid, | ||||||
|  | -						      nontransmitted_profile); | ||||||
|  | -		non_inherit = | ||||||
|  | -			cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, | ||||||
|  | -					       nontransmitted_profile, | ||||||
|  | -					       nontransmitted_profile_len); | ||||||
|  | -	} | ||||||
|  | +	elems->scratch_len = len; | ||||||
|  | +	elems->scratch_pos = elems->scratch; | ||||||
|  | + | ||||||
|  | +	nontransmitted_profile = elems->scratch_pos; | ||||||
|  | +	nontransmitted_profile_len = | ||||||
|  | +		ieee802_11_find_bssid_profile(start, len, elems, | ||||||
|  | +					      transmitter_bssid, | ||||||
|  | +					      bss_bssid, | ||||||
|  | +					      nontransmitted_profile); | ||||||
|  | +	non_inherit = | ||||||
|  | +		cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE, | ||||||
|  | +				       nontransmitted_profile, | ||||||
|  | +				       nontransmitted_profile_len); | ||||||
|  |   | ||||||
|  |  	crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter, | ||||||
|  |  					  crc, non_inherit); | ||||||
|  | @@ -1524,8 +1525,6 @@ struct ieee802_11_elems *ieee802_11_pars | ||||||
|  |  	    offsetofend(struct ieee80211_bssid_index, dtim_count)) | ||||||
|  |  		elems->dtim_count = elems->bssid_index->dtim_count; | ||||||
|  |   | ||||||
|  | -	kfree(nontransmitted_profile); | ||||||
|  | - | ||||||
|  |  	elems->crc = crc; | ||||||
|  |   | ||||||
|  |  	return elems; | ||||||
| @@ -0,0 +1,41 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Thu, 29 Sep 2022 21:50:44 +0200 | ||||||
|  | Subject: [PATCH] wifi: cfg80211: ensure length byte is present before | ||||||
|  |  access | ||||||
|  |  | ||||||
|  | commit 567e14e39e8f8c6997a1378bc3be615afca86063 upstream. | ||||||
|  |  | ||||||
|  | When iterating the elements here, ensure the length byte is | ||||||
|  | present before checking it to see if the entire element will | ||||||
|  | fit into the buffer. | ||||||
|  |  | ||||||
|  | Longer term, we should rewrite this code using the type-safe | ||||||
|  | element iteration macros that check all of this. | ||||||
|  |  | ||||||
|  | Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") | ||||||
|  | Reported-by: Soenke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/wireless/scan.c | ||||||
|  | +++ b/net/wireless/scan.c | ||||||
|  | @@ -304,7 +304,8 @@ static size_t cfg80211_gen_new_ie(const | ||||||
|  |  	tmp_old = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen); | ||||||
|  |  	tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + 2 : ie; | ||||||
|  |   | ||||||
|  | -	while (tmp_old + tmp_old[1] + 2 - ie <= ielen) { | ||||||
|  | +	while (tmp_old + 2 - ie <= ielen && | ||||||
|  | +	       tmp_old + tmp_old[1] + 2 - ie <= ielen) { | ||||||
|  |  		if (tmp_old[0] == 0) { | ||||||
|  |  			tmp_old++; | ||||||
|  |  			continue; | ||||||
|  | @@ -364,7 +365,8 @@ static size_t cfg80211_gen_new_ie(const | ||||||
|  |  	 * copied to new ie, skip ssid, capability, bssid-index ie | ||||||
|  |  	 */ | ||||||
|  |  	tmp_new = sub_copy; | ||||||
|  | -	while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) { | ||||||
|  | +	while (tmp_new + 2 - sub_copy <= subie_len && | ||||||
|  | +	       tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) { | ||||||
|  |  		if (!(tmp_new[0] == WLAN_EID_NON_TX_BSSID_CAP || | ||||||
|  |  		      tmp_new[0] == WLAN_EID_SSID)) { | ||||||
|  |  			memcpy(pos, tmp_new, tmp_new[1] + 2); | ||||||
| @@ -0,0 +1,87 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Fri, 30 Sep 2022 23:44:23 +0200 | ||||||
|  | Subject: [PATCH] wifi: cfg80211: fix BSS refcounting bugs | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  |  | ||||||
|  | commit 0b7808818cb9df6680f98996b8e9a439fa7bcc2f upstream. | ||||||
|  |  | ||||||
|  | There are multiple refcounting bugs related to multi-BSSID: | ||||||
|  |  - In bss_ref_get(), if the BSS has a hidden_beacon_bss, then | ||||||
|  |    the bss pointer is overwritten before checking for the | ||||||
|  |    transmitted BSS, which is clearly wrong. Fix this by using | ||||||
|  |    the bss_from_pub() macro. | ||||||
|  |  | ||||||
|  |  - In cfg80211_bss_update() we copy the transmitted_bss pointer | ||||||
|  |    from tmp into new, but then if we release new, we'll unref | ||||||
|  |    it erroneously. We already set the pointer and ref it, but | ||||||
|  |    need to NULL it since it was copied from the tmp data. | ||||||
|  |  | ||||||
|  |  - In cfg80211_inform_single_bss_data(), if adding to the non- | ||||||
|  |    transmitted list fails, we unlink the BSS and yet still we | ||||||
|  |    return it, but this results in returning an entry without | ||||||
|  |    a reference. We shouldn't return it anyway if it was broken | ||||||
|  |    enough to not get added there. | ||||||
|  |  | ||||||
|  | This fixes CVE-2022-42720. | ||||||
|  |  | ||||||
|  | Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Fixes: a3584f56de1c ("cfg80211: Properly track transmitting and non-transmitting BSS") | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/wireless/scan.c | ||||||
|  | +++ b/net/wireless/scan.c | ||||||
|  | @@ -143,18 +143,12 @@ static inline void bss_ref_get(struct cf | ||||||
|  |  	lockdep_assert_held(&rdev->bss_lock); | ||||||
|  |   | ||||||
|  |  	bss->refcount++; | ||||||
|  | -	if (bss->pub.hidden_beacon_bss) { | ||||||
|  | -		bss = container_of(bss->pub.hidden_beacon_bss, | ||||||
|  | -				   struct cfg80211_internal_bss, | ||||||
|  | -				   pub); | ||||||
|  | -		bss->refcount++; | ||||||
|  | -	} | ||||||
|  | -	if (bss->pub.transmitted_bss) { | ||||||
|  | -		bss = container_of(bss->pub.transmitted_bss, | ||||||
|  | -				   struct cfg80211_internal_bss, | ||||||
|  | -				   pub); | ||||||
|  | -		bss->refcount++; | ||||||
|  | -	} | ||||||
|  | + | ||||||
|  | +	if (bss->pub.hidden_beacon_bss) | ||||||
|  | +		bss_from_pub(bss->pub.hidden_beacon_bss)->refcount++; | ||||||
|  | + | ||||||
|  | +	if (bss->pub.transmitted_bss) | ||||||
|  | +		bss_from_pub(bss->pub.transmitted_bss)->refcount++; | ||||||
|  |  } | ||||||
|  |   | ||||||
|  |  static inline void bss_ref_put(struct cfg80211_registered_device *rdev, | ||||||
|  | @@ -1743,6 +1737,8 @@ cfg80211_bss_update(struct cfg80211_regi | ||||||
|  |  		new->refcount = 1; | ||||||
|  |  		INIT_LIST_HEAD(&new->hidden_list); | ||||||
|  |  		INIT_LIST_HEAD(&new->pub.nontrans_list); | ||||||
|  | +		/* we'll set this later if it was non-NULL */ | ||||||
|  | +		new->pub.transmitted_bss = NULL; | ||||||
|  |   | ||||||
|  |  		if (rcu_access_pointer(tmp->pub.proberesp_ies)) { | ||||||
|  |  			hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN); | ||||||
|  | @@ -1983,10 +1979,15 @@ cfg80211_inform_single_bss_data(struct w | ||||||
|  |  		spin_lock_bh(&rdev->bss_lock); | ||||||
|  |  		if (cfg80211_add_nontrans_list(non_tx_data->tx_bss, | ||||||
|  |  					       &res->pub)) { | ||||||
|  | -			if (__cfg80211_unlink_bss(rdev, res)) | ||||||
|  | +			if (__cfg80211_unlink_bss(rdev, res)) { | ||||||
|  |  				rdev->bss_generation++; | ||||||
|  | +				res = NULL; | ||||||
|  | +			} | ||||||
|  |  		} | ||||||
|  |  		spin_unlock_bh(&rdev->bss_lock); | ||||||
|  | + | ||||||
|  | +		if (!res) | ||||||
|  | +			return NULL; | ||||||
|  |  	} | ||||||
|  |   | ||||||
|  |  	trace_cfg80211_return_bss(&res->pub); | ||||||
| @@ -0,0 +1,48 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Sat, 1 Oct 2022 00:01:44 +0200 | ||||||
|  | Subject: [PATCH] wifi: cfg80211: avoid nontransmitted BSS list | ||||||
|  |  corruption | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  |  | ||||||
|  | commit bcca852027e5878aec911a347407ecc88d6fff7f upstream. | ||||||
|  |  | ||||||
|  | If a non-transmitted BSS shares enough information (both | ||||||
|  | SSID and BSSID!) with another non-transmitted BSS of a | ||||||
|  | different AP, then we can find and update it, and then | ||||||
|  | try to add it to the non-transmitted BSS list. We do a | ||||||
|  | search for it on the transmitted BSS, but if it's not | ||||||
|  | there (but belongs to another transmitted BSS), the list | ||||||
|  | gets corrupted. | ||||||
|  |  | ||||||
|  | Since this is an erroneous situation, simply fail the | ||||||
|  | list insertion in this case and free the non-transmitted | ||||||
|  | BSS. | ||||||
|  |  | ||||||
|  | This fixes CVE-2022-42721. | ||||||
|  |  | ||||||
|  | Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/wireless/scan.c | ||||||
|  | +++ b/net/wireless/scan.c | ||||||
|  | @@ -425,6 +425,15 @@ cfg80211_add_nontrans_list(struct cfg802 | ||||||
|  |   | ||||||
|  |  	rcu_read_unlock(); | ||||||
|  |   | ||||||
|  | +	/* | ||||||
|  | +	 * This is a bit weird - it's not on the list, but already on another | ||||||
|  | +	 * one! The only way that could happen is if there's some BSSID/SSID | ||||||
|  | +	 * shared by multiple APs in their multi-BSSID profiles, potentially | ||||||
|  | +	 * with hidden SSID mixed in ... ignore it. | ||||||
|  | +	 */ | ||||||
|  | +	if (!list_empty(&nontrans_bss->nontrans_list)) | ||||||
|  | +		return -EINVAL; | ||||||
|  | + | ||||||
|  |  	/* add to the list */ | ||||||
|  |  	list_add_tail(&nontrans_bss->nontrans_list, &trans_bss->nontrans_list); | ||||||
|  |  	return 0; | ||||||
| @@ -0,0 +1,31 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Wed, 5 Oct 2022 15:10:09 +0200 | ||||||
|  | Subject: [PATCH] wifi: mac80211_hwsim: avoid mac80211 warning on bad | ||||||
|  |  rate | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  |  | ||||||
|  | commit 1833b6f46d7e2830251a063935ab464256defe22 upstream. | ||||||
|  |  | ||||||
|  | If the tool on the other side (e.g. wmediumd) gets confused | ||||||
|  | about the rate, we hit a warning in mac80211. Silence that | ||||||
|  | by effectively duplicating the check here and dropping the | ||||||
|  | frame silently (in mac80211 it's dropped with the warning). | ||||||
|  |  | ||||||
|  | Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/drivers/net/wireless/mac80211_hwsim.c | ||||||
|  | +++ b/drivers/net/wireless/mac80211_hwsim.c | ||||||
|  | @@ -3760,6 +3760,8 @@ static int hwsim_cloned_frame_received_n | ||||||
|  |   | ||||||
|  |  	rx_status.band = channel->band; | ||||||
|  |  	rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); | ||||||
|  | +	if (rx_status.rate_idx >= data2->hw->wiphy->bands[rx_status.band]->n_bitrates) | ||||||
|  | +		goto out; | ||||||
|  |  	rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); | ||||||
|  |   | ||||||
|  |  	hdr = (void *)skb->data; | ||||||
| @@ -0,0 +1,52 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Wed, 5 Oct 2022 21:24:10 +0200 | ||||||
|  | Subject: [PATCH] wifi: mac80211: fix crash in beacon protection for | ||||||
|  |  P2P-device | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  |  | ||||||
|  | commit b2d03cabe2b2e150ff5a381731ea0355459be09f upstream. | ||||||
|  |  | ||||||
|  | If beacon protection is active but the beacon cannot be | ||||||
|  | decrypted or is otherwise malformed, we call the cfg80211 | ||||||
|  | API to report this to userspace, but that uses a netdev | ||||||
|  | pointer, which isn't present for P2P-Device. Fix this to | ||||||
|  | call it only conditionally to ensure cfg80211 won't crash | ||||||
|  | in the case of P2P-Device. | ||||||
|  |  | ||||||
|  | This fixes CVE-2022-42722. | ||||||
|  |  | ||||||
|  | Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Fixes: 9eaf183af741 ("mac80211: Report beacon protection failures to user space") | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/mac80211/rx.c | ||||||
|  | +++ b/net/mac80211/rx.c | ||||||
|  | @@ -1986,10 +1986,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_ | ||||||
|  |   | ||||||
|  |  		if (mmie_keyidx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS || | ||||||
|  |  		    mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS + | ||||||
|  | -		    NUM_DEFAULT_BEACON_KEYS) { | ||||||
|  | -			cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, | ||||||
|  | -						     skb->data, | ||||||
|  | -						     skb->len); | ||||||
|  | +				   NUM_DEFAULT_BEACON_KEYS) { | ||||||
|  | +			if (rx->sdata->dev) | ||||||
|  | +				cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, | ||||||
|  | +							     skb->data, | ||||||
|  | +							     skb->len); | ||||||
|  |  			return RX_DROP_MONITOR; /* unexpected BIP keyidx */ | ||||||
|  |  		} | ||||||
|  |   | ||||||
|  | @@ -2137,7 +2138,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_ | ||||||
|  |  	/* either the frame has been decrypted or will be dropped */ | ||||||
|  |  	status->flag |= RX_FLAG_DECRYPTED; | ||||||
|  |   | ||||||
|  | -	if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE)) | ||||||
|  | +	if (unlikely(ieee80211_is_beacon(fc) && result == RX_DROP_UNUSABLE && | ||||||
|  | +		     rx->sdata->dev)) | ||||||
|  |  		cfg80211_rx_unprot_mlme_mgmt(rx->sdata->dev, | ||||||
|  |  					     skb->data, skb->len); | ||||||
|  |   | ||||||
| @@ -0,0 +1,85 @@ | |||||||
|  | From: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | Date: Wed, 5 Oct 2022 23:11:43 +0200 | ||||||
|  | Subject: [PATCH] wifi: cfg80211: update hidden BSSes to avoid WARN_ON | ||||||
|  | MIME-Version: 1.0 | ||||||
|  | Content-Type: text/plain; charset=UTF-8 | ||||||
|  | Content-Transfer-Encoding: 8bit | ||||||
|  |  | ||||||
|  | commit c90b93b5b782891ebfda49d4e5da36632fefd5d1 upstream. | ||||||
|  |  | ||||||
|  | When updating beacon elements in a non-transmitted BSS, | ||||||
|  | also update the hidden sub-entries to the same beacon | ||||||
|  | elements, so that a future update through other paths | ||||||
|  | won't trigger a WARN_ON(). | ||||||
|  |  | ||||||
|  | The warning is triggered because the beacon elements in | ||||||
|  | the hidden BSSes that are children of the BSS should | ||||||
|  | always be the same as in the parent. | ||||||
|  |  | ||||||
|  | Reported-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Tested-by: Sönke Huster <shuster@seemoo.tu-darmstadt.de> | ||||||
|  | Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") | ||||||
|  | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||||||
|  | --- | ||||||
|  |  | ||||||
|  | --- a/net/wireless/scan.c | ||||||
|  | +++ b/net/wireless/scan.c | ||||||
|  | @@ -1609,6 +1609,23 @@ struct cfg80211_non_tx_bss { | ||||||
|  |  	u8 bssid_index; | ||||||
|  |  }; | ||||||
|  |   | ||||||
|  | +static void cfg80211_update_hidden_bsses(struct cfg80211_internal_bss *known, | ||||||
|  | +					 const struct cfg80211_bss_ies *new_ies, | ||||||
|  | +					 const struct cfg80211_bss_ies *old_ies) | ||||||
|  | +{ | ||||||
|  | +	struct cfg80211_internal_bss *bss; | ||||||
|  | + | ||||||
|  | +	/* Assign beacon IEs to all sub entries */ | ||||||
|  | +	list_for_each_entry(bss, &known->hidden_list, hidden_list) { | ||||||
|  | +		const struct cfg80211_bss_ies *ies; | ||||||
|  | + | ||||||
|  | +		ies = rcu_access_pointer(bss->pub.beacon_ies); | ||||||
|  | +		WARN_ON(ies != old_ies); | ||||||
|  | + | ||||||
|  | +		rcu_assign_pointer(bss->pub.beacon_ies, new_ies); | ||||||
|  | +	} | ||||||
|  | +} | ||||||
|  | + | ||||||
|  |  static bool | ||||||
|  |  cfg80211_update_known_bss(struct cfg80211_registered_device *rdev, | ||||||
|  |  			  struct cfg80211_internal_bss *known, | ||||||
|  | @@ -1632,7 +1649,6 @@ cfg80211_update_known_bss(struct cfg8021 | ||||||
|  |  			kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); | ||||||
|  |  	} else if (rcu_access_pointer(new->pub.beacon_ies)) { | ||||||
|  |  		const struct cfg80211_bss_ies *old; | ||||||
|  | -		struct cfg80211_internal_bss *bss; | ||||||
|  |   | ||||||
|  |  		if (known->pub.hidden_beacon_bss && | ||||||
|  |  		    !list_empty(&known->hidden_list)) { | ||||||
|  | @@ -1660,16 +1676,7 @@ cfg80211_update_known_bss(struct cfg8021 | ||||||
|  |  		if (old == rcu_access_pointer(known->pub.ies)) | ||||||
|  |  			rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies); | ||||||
|  |   | ||||||
|  | -		/* Assign beacon IEs to all sub entries */ | ||||||
|  | -		list_for_each_entry(bss, &known->hidden_list, hidden_list) { | ||||||
|  | -			const struct cfg80211_bss_ies *ies; | ||||||
|  | - | ||||||
|  | -			ies = rcu_access_pointer(bss->pub.beacon_ies); | ||||||
|  | -			WARN_ON(ies != old); | ||||||
|  | - | ||||||
|  | -			rcu_assign_pointer(bss->pub.beacon_ies, | ||||||
|  | -					   new->pub.beacon_ies); | ||||||
|  | -		} | ||||||
|  | +		cfg80211_update_hidden_bsses(known, new->pub.beacon_ies, old); | ||||||
|  |   | ||||||
|  |  		if (old) | ||||||
|  |  			kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); | ||||||
|  | @@ -2319,6 +2326,8 @@ cfg80211_update_notlisted_nontrans(struc | ||||||
|  |  	} else { | ||||||
|  |  		old = rcu_access_pointer(nontrans_bss->beacon_ies); | ||||||
|  |  		rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies); | ||||||
|  | +		cfg80211_update_hidden_bsses(bss_from_pub(nontrans_bss), | ||||||
|  | +					     new_ies, old); | ||||||
|  |  		rcu_assign_pointer(nontrans_bss->ies, new_ies); | ||||||
|  |  		if (old) | ||||||
|  |  			kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); | ||||||
| @@ -29,7 +29,7 @@ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |||||||
|  |  | ||||||
| --- a/net/mac80211/scan.c | --- a/net/mac80211/scan.c | ||||||
| +++ b/net/mac80211/scan.c | +++ b/net/mac80211/scan.c | ||||||
| @@ -461,16 +461,19 @@ static void __ieee80211_scan_completed(s | @@ -465,16 +465,19 @@ static void __ieee80211_scan_completed(s | ||||||
|  	scan_req = rcu_dereference_protected(local->scan_req, |  	scan_req = rcu_dereference_protected(local->scan_req, | ||||||
|  					     lockdep_is_held(&local->mtx)); |  					     lockdep_is_held(&local->mtx)); | ||||||
|   |   | ||||||
|   | |||||||
| @@ -56,7 +56,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com> | |||||||
|   |   | ||||||
| --- a/net/mac80211/rx.c
 | --- a/net/mac80211/rx.c
 | ||||||
| +++ b/net/mac80211/rx.c
 | +++ b/net/mac80211/rx.c
 | ||||||
| @@ -3180,6 +3180,49 @@ static void ieee80211_process_sa_query_r
 | @@ -3182,6 +3182,49 @@ static void ieee80211_process_sa_query_r
 | ||||||
|  	ieee80211_tx_skb(sdata, skb); |  	ieee80211_tx_skb(sdata, skb); | ||||||
|  } |  } | ||||||
|   |   | ||||||
| @@ -106,7 +106,7 @@ Signed-off-by: Johannes Berg <johannes.berg@intel.com> | |||||||
|  static ieee80211_rx_result debug_noinline |  static ieee80211_rx_result debug_noinline | ||||||
|  ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) |  ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx) | ||||||
|  { |  { | ||||||
| @@ -3205,6 +3248,9 @@ ieee80211_rx_h_mgmt_check(struct ieee802
 | @@ -3207,6 +3250,9 @@ ieee80211_rx_h_mgmt_check(struct ieee802
 | ||||||
|  	    !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { |  	    !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) { | ||||||
|  		int sig = 0; |  		int sig = 0; | ||||||
|   |   | ||||||
		Reference in New Issue
	
	Block a user
	 Felix Fietkau
					Felix Fietkau