Skip to content

Commit

Permalink
mac80211: backport security fixes
Browse files Browse the repository at this point in the history
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 26f4002)
  • Loading branch information
nbd168 committed Oct 13, 2022
1 parent a077c6d commit f1de43d
Show file tree
Hide file tree
Showing 15 changed files with 2,057 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -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;
Original file line number Diff line number Diff line change
@@ -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,
Original file line number Diff line number Diff line change
@@ -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) {
Loading

1 comment on commit f1de43d

@Openwrtfunboy
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any POC for this? I would test it. Also any workarounds to avoid it if update is not possible?

Please sign in to comment.