mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-24 15:56:49 +00:00
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>
(cherry-picked from commit 26f400210d
)
This commit is contained in:
parent
a077c6da98
commit
f1de43d0a0
@ -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));
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user