This is an automated email from the git hooks/post-receive script. It was generated because a ref change was pushed to the repository containing the project "IPFire 2.x development tree".
The branch, master has been updated via ee2e7db90bf12ab1c028f5f3b955afaf9cdf76f5 (commit) from a40977958b051de976b515b30be1fc3f17f19785 (commit)
Those revisions listed above that are new to this repository have not appeared on any other notification email; so we list those revisions in full, below.
- Log ----------------------------------------------------------------- commit ee2e7db90bf12ab1c028f5f3b955afaf9cdf76f5 Author: Peter Müller peter.mueller@ipfire.org Date: Mon Oct 17 16:26:19 2022 +0000
linux: Add upstream patches for CVE-2022-4{1674,2719-2722}
https://lists.ipfire.org/pipermail/development/2022-October/014562.html
Signed-off-by: Peter Müller peter.mueller@ipfire.org
-----------------------------------------------------------------------
Summary of changes: lfs/linux | 5 + .../linux/linux-5.15-wifi-security-patches-1.patch | 50 + .../linux-5.15-wifi-security-patches-10.patch | 98 ++ .../linux-5.15-wifi-security-patches-11.patch | 96 ++ .../linux-5.15-wifi-security-patches-12.patch | 1179 ++++++++++++++++++++ .../linux-5.15-wifi-security-patches-13.patch | 130 +++ .../linux-5.15-wifi-security-patches-14.patch | 107 ++ .../linux/linux-5.15-wifi-security-patches-2.patch | 59 + .../linux/linux-5.15-wifi-security-patches-3.patch | 49 + .../linux/linux-5.15-wifi-security-patches-4.patch | 96 ++ .../linux/linux-5.15-wifi-security-patches-5.patch | 56 + .../linux/linux-5.15-wifi-security-patches-6.patch | 39 + .../linux/linux-5.15-wifi-security-patches-7.patch | 60 + .../linux/linux-5.15-wifi-security-patches-8.patch | 94 ++ .../linux/linux-5.15-wifi-security-patches-9.patch | 126 +++ 15 files changed, 2244 insertions(+) create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-1.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-10.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-11.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-12.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-13.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-14.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-2.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-3.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-4.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-5.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-6.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-7.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-8.patch create mode 100644 src/patches/linux/linux-5.15-wifi-security-patches-9.patch
Difference in files: diff --git a/lfs/linux b/lfs/linux index ae9745d53..b628307fd 100644 --- a/lfs/linux +++ b/lfs/linux @@ -146,6 +146,11 @@ $(TARGET) : $(patsubst %,$(DIR_DL)/%,$(objects)) # https://bugzilla.ipfire.org/show_bug.cgi?id=12889 cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/devtmpfs-mount-with-noexec-and-nosuid.patch
+ # https://lists.ipfire.org/pipermail/development/2022-October/014562.html + for i in $$(seq 1 14); do \ + cd $(DIR_APP) && patch -Np1 < $(DIR_SRC)/src/patches/linux/linux-5.15-wifi-security-patches-$$i.patch || exit 1; \ + done + ifeq "$(BUILD_ARCH)" "armv6l" # Apply Arm-multiarch kernel patches. cd $(DIR_APP) && xzcat $(DIR_DL)/arm-multi-patches-$(ARM_PATCHES).patch.xz | patch -Np1 diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-1.patch b/src/patches/linux/linux-5.15-wifi-security-patches-1.patch new file mode 100644 index 000000000..b646eea49 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-1.patch @@ -0,0 +1,50 @@ +From 9a8ef2030510a9d6ce86fd535b8d10720230811f Mon Sep 17 00:00:00 2001 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 1a8b76c9dd56..d9ab37a798f4 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -2238,7 +2238,7 @@ cfg80211_update_notlisted_nontrans(struct wiphy *wiphy, + 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); + +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-10.patch b/src/patches/linux/linux-5.15-wifi-security-patches-10.patch new file mode 100644 index 000000000..51986afe7 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-10.patch @@ -0,0 +1,98 @@ +From 21df3a583e8e03d8f74fa2eedbcd7a2b3f5cabc1 Mon Sep 17 00:00:00 2001 +From: Johannes Berg johannes.berg@intel.com +Date: Thu, 13 Oct 2022 20:15:57 +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.If0d4ba75ee38998dc3eea... +Signed-off-by: Johannes Berg johannes.berg@intel.com +Cc: Felix Fietkau nbd@nbd.name +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/ieee80211_i.h | 9 +++++---- + net/mac80211/mlme.c | 9 +++++---- + net/mac80211/util.c | 10 +++++----- + 3 files changed, 15 insertions(+), 13 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 4bd55af184b2..5ea38ae65809 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1532,6 +1532,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; +@@ -2218,10 +2219,10 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, + 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, +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 1548f532dc1a..4414e82e71d1 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -4102,10 +4102,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + */ + 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)) { +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 00543ea9c6b5..ceb6894381e4 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1468,10 +1468,10 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, + 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; +@@ -1523,7 +1523,7 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, + + kfree(nontransmitted_profile); + +- return crc; ++ elems->crc = crc; + } + + void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-11.patch b/src/patches/linux/linux-5.15-wifi-security-patches-11.patch new file mode 100644 index 000000000..ae639c696 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-11.patch @@ -0,0 +1,96 @@ +From 630060f1175676b9cb3a032767f20dbce93616c9 Mon Sep 17 00:00:00 2001 +From: Johannes Berg johannes.berg@intel.com +Date: Thu, 13 Oct 2022 20:15:58 +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.Ice3159ffad03a007d6154... +Signed-off-by: Johannes Berg johannes.berg@intel.com +Cc: Felix Fietkau nbd@nbd.name +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/ieee80211_i.h | 2 -- + net/mac80211/mlme.c | 11 ++++++----- + net/mac80211/util.c | 4 ---- + 3 files changed, 6 insertions(+), 11 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 5ea38ae65809..c5f0ff805010 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1542,7 +1542,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; +@@ -1596,7 +1595,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; +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 4414e82e71d1..548cd14c5503 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -2889,17 +2889,17 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata, + { + 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(struct ieee80211_sub_if_data *sdata, + 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); +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index ceb6894381e4..664c32b6db19 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1117,10 +1117,6 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, + } 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) { +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-12.patch b/src/patches/linux/linux-5.15-wifi-security-patches-12.patch new file mode 100644 index 000000000..4dea89e4c --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-12.patch @@ -0,0 +1,1179 @@ +From fee48f3bdd7516bb63da507213916227cf147211 Mon Sep 17 00:00:00 2001 +From: Johannes Berg johannes.berg@intel.com +Date: Thu, 13 Oct 2022 20:15:59 +0200 +Subject: [PATCH] mac80211: always allocate struct ieee802_11_elems + +As the 802.11 spec evolves, we need to parse more and more +elements. This is causing the struct to grow, and we can no +longer get away with putting it on the stack. + +Change the API to always dynamically allocate and return an +allocated pointer that must be kfree()d later. + +As an alternative, I contemplated a scheme whereby we'd say +in the code which elements we needed, e.g. + + DECLARE_ELEMENT_PARSER(elems, + SUPPORTED_CHANNELS, + CHANNEL_SWITCH, + EXT(KEY_DELIVERY)); + + ieee802_11_parse_elems(..., &elems, ...); + +and while I think this is possible and will save us a lot +since most individual places only care about a small subset +of the elements, it ended up being a bit more work since a +lot of places do the parsing and then pass the struct to +other functions, sometimes with multiple levels. + +Link: https://lore.kernel.org/r/20210920154009.26caff6b5998.I05ae58768e990e611aee8... +Signed-off-by: Johannes Berg johannes.berg@intel.com +Cc: Felix Fietkau nbd@nbd.name +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/agg-rx.c | 11 +-- + net/mac80211/ibss.c | 25 +++--- + net/mac80211/ieee80211_i.h | 22 ++--- + net/mac80211/mesh.c | 85 ++++++++++-------- + net/mac80211/mesh_hwmp.c | 44 +++++----- + net/mac80211/mesh_plink.c | 11 +-- + net/mac80211/mlme.c | 176 +++++++++++++++++++++---------------- + net/mac80211/scan.c | 16 ++-- + net/mac80211/tdls.c | 63 +++++++------ + net/mac80211/util.c | 20 +++-- + 10 files changed, 272 insertions(+), 201 deletions(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index e43176794149..ffa4f31f6c2b 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -478,7 +478,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, + size_t len) + { + u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num; +- struct ieee802_11_elems elems = { }; ++ struct ieee802_11_elems *elems = NULL; + u8 dialog_token; + int ies_len; + +@@ -496,16 +496,17 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, + ies_len = len - offsetof(struct ieee80211_mgmt, + u.action.u.addba_req.variable); + if (ies_len) { +- ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable, +- ies_len, true, &elems, mgmt->bssid, NULL); +- if (elems.parse_error) ++ elems = ieee802_11_parse_elems(mgmt->u.action.u.addba_req.variable, ++ ies_len, true, mgmt->bssid, NULL); ++ if (!elems || elems->parse_error) + return; + } + + __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, + start_seq_num, ba_policy, tid, + buf_size, true, false, +- elems.addba_ext_ie); ++ elems ? elems->addba_ext_ie : NULL); ++ kfree(elems); + } + + void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index 1e133ca58e78..4b721b48f86a 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -9,7 +9,7 @@ + * Copyright 2009, Johannes Berg johannes@sipsolutions.net + * Copyright 2013-2014 Intel Mobile Communications GmbH + * Copyright(c) 2016 Intel Deutschland GmbH +- * Copyright(c) 2018-2020 Intel Corporation ++ * Copyright(c) 2018-2021 Intel Corporation + */ + + #include <linux/delay.h> +@@ -1593,7 +1593,7 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata, + struct ieee80211_rx_status *rx_status) + { + size_t baselen; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + + BUILD_BUG_ON(offsetof(typeof(mgmt->u.probe_resp), variable) != + offsetof(typeof(mgmt->u.beacon), variable)); +@@ -1606,10 +1606,14 @@ void ieee80211_rx_mgmt_probe_beacon(struct ieee80211_sub_if_data *sdata, + if (baselen > len) + return; + +- ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, +- false, &elems, mgmt->bssid, NULL); ++ elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable, ++ len - baselen, false, ++ mgmt->bssid, NULL); + +- ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems); ++ if (elems) { ++ ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, elems); ++ kfree(elems); ++ } + } + + void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, +@@ -1618,7 +1622,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + struct ieee80211_rx_status *rx_status; + struct ieee80211_mgmt *mgmt; + u16 fc; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + int ies_len; + + rx_status = IEEE80211_SKB_RXCB(skb); +@@ -1655,15 +1659,16 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + if (ies_len < 0) + break; + +- ieee802_11_parse_elems( ++ elems = ieee802_11_parse_elems( + mgmt->u.action.u.chan_switch.variable, +- ies_len, true, &elems, mgmt->bssid, NULL); ++ ies_len, true, mgmt->bssid, NULL); + +- if (elems.parse_error) ++ if (!elems || elems->parse_error) + break; + + ieee80211_rx_mgmt_spectrum_mgmt(sdata, mgmt, skb->len, +- rx_status, &elems); ++ rx_status, elems); ++ kfree(elems); + break; + } + } +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index c5f0ff805010..3633e49239c7 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -2217,18 +2217,18 @@ static inline void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, + ieee80211_tx_skb_tid(sdata, skb, 7); + } + +-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, +- u8 *transmitter_bssid, +- u8 *bss_bssid) ++struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len, ++ bool action, ++ u64 filter, u32 crc, ++ const u8 *transmitter_bssid, ++ const u8 *bss_bssid); ++static inline struct ieee802_11_elems * ++ieee802_11_parse_elems(const u8 *start, size_t len, bool action, ++ const u8 *transmitter_bssid, ++ const u8 *bss_bssid) + { +- ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0, +- transmitter_bssid, bss_bssid); ++ return ieee802_11_parse_elems_crc(start, len, action, 0, 0, ++ transmitter_bssid, bss_bssid); + } + + +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 9f6414a68d71..6847fdf93439 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -1247,7 +1247,7 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, + struct sk_buff *presp; + struct beacon_data *bcn; + struct ieee80211_mgmt *hdr; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + size_t baselen; + u8 *pos; + +@@ -1256,22 +1256,24 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, + if (baselen > len) + return; + +- ieee802_11_parse_elems(pos, len - baselen, false, &elems, mgmt->bssid, +- NULL); +- +- if (!elems.mesh_id) ++ elems = ieee802_11_parse_elems(pos, len - baselen, false, mgmt->bssid, ++ NULL); ++ if (!elems) + return; + ++ if (!elems->mesh_id) ++ goto free; ++ + /* 802.11-2012 10.1.4.3.2 */ + if ((!ether_addr_equal(mgmt->da, sdata->vif.addr) && + !is_broadcast_ether_addr(mgmt->da)) || +- elems.ssid_len != 0) +- return; ++ elems->ssid_len != 0) ++ goto free; + +- if (elems.mesh_id_len != 0 && +- (elems.mesh_id_len != ifmsh->mesh_id_len || +- memcmp(elems.mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len))) +- return; ++ if (elems->mesh_id_len != 0 && ++ (elems->mesh_id_len != ifmsh->mesh_id_len || ++ memcmp(elems->mesh_id, ifmsh->mesh_id, ifmsh->mesh_id_len))) ++ goto free; + + rcu_read_lock(); + bcn = rcu_dereference(ifmsh->beacon); +@@ -1295,6 +1297,8 @@ ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata, + ieee80211_tx_skb(sdata, presp); + out: + rcu_read_unlock(); ++free: ++ kfree(elems); + } + + static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, +@@ -1305,7 +1309,7 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + { + struct ieee80211_local *local = sdata->local; + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + struct ieee80211_channel *channel; + size_t baselen; + int freq; +@@ -1320,42 +1324,47 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + if (baselen > len) + return; + +- ieee802_11_parse_elems(mgmt->u.probe_resp.variable, len - baselen, +- false, &elems, mgmt->bssid, NULL); ++ elems = ieee802_11_parse_elems(mgmt->u.probe_resp.variable, ++ len - baselen, ++ false, mgmt->bssid, NULL); ++ if (!elems) ++ return; + + /* ignore non-mesh or secure / unsecure mismatch */ +- if ((!elems.mesh_id || !elems.mesh_config) || +- (elems.rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) || +- (!elems.rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)) +- return; ++ if ((!elems->mesh_id || !elems->mesh_config) || ++ (elems->rsn && sdata->u.mesh.security == IEEE80211_MESH_SEC_NONE) || ++ (!elems->rsn && sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)) ++ goto free; + +- if (elems.ds_params) +- freq = ieee80211_channel_to_frequency(elems.ds_params[0], band); ++ if (elems->ds_params) ++ freq = ieee80211_channel_to_frequency(elems->ds_params[0], band); + else + freq = rx_status->freq; + + channel = ieee80211_get_channel(local->hw.wiphy, freq); + + if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) +- return; ++ goto free; + +- if (mesh_matches_local(sdata, &elems)) { ++ if (mesh_matches_local(sdata, elems)) { + mpl_dbg(sdata, "rssi_threshold=%d,rx_status->signal=%d\n", + sdata->u.mesh.mshcfg.rssi_threshold, rx_status->signal); + if (!sdata->u.mesh.user_mpm || + sdata->u.mesh.mshcfg.rssi_threshold == 0 || + sdata->u.mesh.mshcfg.rssi_threshold < rx_status->signal) +- mesh_neighbour_update(sdata, mgmt->sa, &elems, ++ mesh_neighbour_update(sdata, mgmt->sa, elems, + rx_status); + + if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT && + !sdata->vif.csa_active) +- ieee80211_mesh_process_chnswitch(sdata, &elems, true); ++ ieee80211_mesh_process_chnswitch(sdata, elems, true); + } + + if (ifmsh->sync_ops) + ifmsh->sync_ops->rx_bcn_presp(sdata, stype, mgmt, len, +- elems.mesh_config, rx_status); ++ elems->mesh_config, rx_status); ++free: ++ kfree(elems); + } + + int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) +@@ -1447,7 +1456,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) + { + struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + u16 pre_value; + bool fwd_csa = true; + size_t baselen; +@@ -1460,33 +1469,37 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, + pos = mgmt->u.action.u.chan_switch.variable; + baselen = offsetof(struct ieee80211_mgmt, + u.action.u.chan_switch.variable); +- ieee802_11_parse_elems(pos, len - baselen, true, &elems, +- mgmt->bssid, NULL); +- +- if (!mesh_matches_local(sdata, &elems)) ++ elems = ieee802_11_parse_elems(pos, len - baselen, true, ++ mgmt->bssid, NULL); ++ if (!elems) + return; + +- ifmsh->chsw_ttl = elems.mesh_chansw_params_ie->mesh_ttl; ++ if (!mesh_matches_local(sdata, elems)) ++ goto free; ++ ++ ifmsh->chsw_ttl = elems->mesh_chansw_params_ie->mesh_ttl; + if (!--ifmsh->chsw_ttl) + fwd_csa = false; + +- pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value); ++ pre_value = le16_to_cpu(elems->mesh_chansw_params_ie->mesh_pre_value); + if (ifmsh->pre_value >= pre_value) +- return; ++ goto free; + + ifmsh->pre_value = pre_value; + + if (!sdata->vif.csa_active && +- !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { ++ !ieee80211_mesh_process_chnswitch(sdata, elems, false)) { + mcsa_dbg(sdata, "Failed to process CSA action frame"); +- return; ++ goto free; + } + + /* forward or re-broadcast the CSA frame */ + if (fwd_csa) { +- if (mesh_fwd_csa_frame(sdata, mgmt, len, &elems) < 0) ++ if (mesh_fwd_csa_frame(sdata, mgmt, len, elems) < 0) + mcsa_dbg(sdata, "Failed to forward the CSA frame"); + } ++free: ++ kfree(elems); + } + + static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata, +diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c +index a05b615deb51..44a6fdb6efbd 100644 +--- a/net/mac80211/mesh_hwmp.c ++++ b/net/mac80211/mesh_hwmp.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Copyright (c) 2008, 2009 open80211s Ltd. +- * Copyright (C) 2019 Intel Corporation ++ * Copyright (C) 2019, 2021 Intel Corporation + * Author: Luis Carlos Cobo luisca@cozybit.com + */ + +@@ -908,7 +908,7 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, + void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len) + { +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + size_t baselen; + u32 path_metric; + struct sta_info *sta; +@@ -926,37 +926,41 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata, + rcu_read_unlock(); + + baselen = (u8 *) mgmt->u.action.u.mesh_action.variable - (u8 *) mgmt; +- ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, +- len - baselen, false, &elems, mgmt->bssid, NULL); ++ elems = ieee802_11_parse_elems(mgmt->u.action.u.mesh_action.variable, ++ len - baselen, false, mgmt->bssid, NULL); ++ if (!elems) ++ return; + +- if (elems.preq) { +- if (elems.preq_len != 37) ++ if (elems->preq) { ++ if (elems->preq_len != 37) + /* Right now we support just 1 destination and no AE */ +- return; +- path_metric = hwmp_route_info_get(sdata, mgmt, elems.preq, ++ goto free; ++ path_metric = hwmp_route_info_get(sdata, mgmt, elems->preq, + MPATH_PREQ); + if (path_metric) +- hwmp_preq_frame_process(sdata, mgmt, elems.preq, ++ hwmp_preq_frame_process(sdata, mgmt, elems->preq, + path_metric); + } +- if (elems.prep) { +- if (elems.prep_len != 31) ++ if (elems->prep) { ++ if (elems->prep_len != 31) + /* Right now we support no AE */ +- return; +- path_metric = hwmp_route_info_get(sdata, mgmt, elems.prep, ++ goto free; ++ path_metric = hwmp_route_info_get(sdata, mgmt, elems->prep, + MPATH_PREP); + if (path_metric) +- hwmp_prep_frame_process(sdata, mgmt, elems.prep, ++ hwmp_prep_frame_process(sdata, mgmt, elems->prep, + path_metric); + } +- if (elems.perr) { +- if (elems.perr_len != 15) ++ if (elems->perr) { ++ if (elems->perr_len != 15) + /* Right now we support only one destination per PERR */ +- return; +- hwmp_perr_frame_process(sdata, mgmt, elems.perr); ++ goto free; ++ hwmp_perr_frame_process(sdata, mgmt, elems->perr); + } +- if (elems.rann) +- hwmp_rann_frame_process(sdata, mgmt, elems.rann); ++ if (elems->rann) ++ hwmp_rann_frame_process(sdata, mgmt, elems->rann); ++free: ++ kfree(elems); + } + + /** +diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c +index a6915847d78a..a829470dd59e 100644 +--- a/net/mac80211/mesh_plink.c ++++ b/net/mac80211/mesh_plink.c +@@ -1,7 +1,7 @@ + // SPDX-License-Identifier: GPL-2.0-only + /* + * Copyright (c) 2008, 2009 open80211s Ltd. +- * Copyright (C) 2019 Intel Corporation ++ * Copyright (C) 2019, 2021 Intel Corporation + * Author: Luis Carlos Cobo luisca@cozybit.com + */ + #include <linux/gfp.h> +@@ -1200,7 +1200,7 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, + struct ieee80211_mgmt *mgmt, size_t len, + struct ieee80211_rx_status *rx_status) + { +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + size_t baselen; + u8 *baseaddr; + +@@ -1228,7 +1228,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, + if (baselen > len) + return; + } +- ieee802_11_parse_elems(baseaddr, len - baselen, true, &elems, +- mgmt->bssid, NULL); +- mesh_process_plink_frame(sdata, mgmt, &elems, rx_status); ++ elems = ieee802_11_parse_elems(baseaddr, len - baselen, true, ++ mgmt->bssid, NULL); ++ mesh_process_plink_frame(sdata, mgmt, elems, rx_status); ++ kfree(elems); + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 548cd14c5503..45efa1d1c550 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3317,8 +3317,11 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + aid = 0; /* TODO */ + } + capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info); +- ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, elems, +- mgmt->bssid, assoc_data->bss->bssid); ++ elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, ++ mgmt->bssid, assoc_data->bss->bssid); ++ ++ if (!elems) ++ return false; + + if (elems->aid_resp) + aid = le16_to_cpu(elems->aid_resp->aid); +@@ -3340,7 +3343,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + + if (!is_s1g && !elems->supp_rates) { + sdata_info(sdata, "no SuppRates element in AssocResp\n"); +- return false; ++ ret = false; ++ goto out; + } + + sdata->vif.bss_conf.aid = aid; +@@ -3362,7 +3366,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT) && + (!elems->vht_cap_elem || !elems->vht_operation)))) { + const struct cfg80211_bss_ies *ies; +- struct ieee802_11_elems bss_elems; ++ struct ieee802_11_elems *bss_elems; + + rcu_read_lock(); + ies = rcu_dereference(cbss->ies); +@@ -3373,13 +3377,17 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + if (!bss_ies) + return false; + +- ieee802_11_parse_elems(bss_ies->data, bss_ies->len, +- false, &bss_elems, +- mgmt->bssid, +- assoc_data->bss->bssid); ++ bss_elems = ieee802_11_parse_elems(bss_ies->data, bss_ies->len, ++ false, mgmt->bssid, ++ assoc_data->bss->bssid); ++ if (!bss_elems) { ++ ret = false; ++ goto out; ++ } ++ + if (assoc_data->wmm && +- !elems->wmm_param && bss_elems.wmm_param) { +- elems->wmm_param = bss_elems.wmm_param; ++ !elems->wmm_param && bss_elems->wmm_param) { ++ elems->wmm_param = bss_elems->wmm_param; + sdata_info(sdata, + "AP bug: WMM param missing from AssocResp\n"); + } +@@ -3388,30 +3396,32 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + * Also check if we requested HT/VHT, otherwise the AP doesn't + * have to include the IEs in the (re)association response. + */ +- if (!elems->ht_cap_elem && bss_elems.ht_cap_elem && ++ if (!elems->ht_cap_elem && bss_elems->ht_cap_elem && + !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { +- elems->ht_cap_elem = bss_elems.ht_cap_elem; ++ elems->ht_cap_elem = bss_elems->ht_cap_elem; + sdata_info(sdata, + "AP bug: HT capability missing from AssocResp\n"); + } +- if (!elems->ht_operation && bss_elems.ht_operation && ++ if (!elems->ht_operation && bss_elems->ht_operation && + !(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { +- elems->ht_operation = bss_elems.ht_operation; ++ elems->ht_operation = bss_elems->ht_operation; + sdata_info(sdata, + "AP bug: HT operation missing from AssocResp\n"); + } +- if (!elems->vht_cap_elem && bss_elems.vht_cap_elem && ++ if (!elems->vht_cap_elem && bss_elems->vht_cap_elem && + !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { +- elems->vht_cap_elem = bss_elems.vht_cap_elem; ++ elems->vht_cap_elem = bss_elems->vht_cap_elem; + sdata_info(sdata, + "AP bug: VHT capa missing from AssocResp\n"); + } +- if (!elems->vht_operation && bss_elems.vht_operation && ++ if (!elems->vht_operation && bss_elems->vht_operation && + !(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) { +- elems->vht_operation = bss_elems.vht_operation; ++ elems->vht_operation = bss_elems->vht_operation; + sdata_info(sdata, + "AP bug: VHT operation missing from AssocResp\n"); + } ++ ++ kfree(bss_elems); + } + + /* +@@ -3662,6 +3672,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + + ret = true; + out: ++ kfree(elems); + kfree(bss_ies); + return ret; + } +@@ -3673,7 +3684,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data; + u16 capab_info, status_code, aid; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + int ac, uapsd_queues = -1; + u8 *pos; + bool reassoc; +@@ -3730,14 +3741,16 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + fils_decrypt_assoc_resp(sdata, (u8 *)mgmt, &len, assoc_data) < 0) + return; + +- ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, &elems, +- mgmt->bssid, assoc_data->bss->bssid); ++ elems = ieee802_11_parse_elems(pos, len - (pos - (u8 *)mgmt), false, ++ mgmt->bssid, assoc_data->bss->bssid); ++ if (!elems) ++ goto notify_driver; + + if (status_code == WLAN_STATUS_ASSOC_REJECTED_TEMPORARILY && +- elems.timeout_int && +- elems.timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) { ++ elems->timeout_int && ++ elems->timeout_int->type == WLAN_TIMEOUT_ASSOC_COMEBACK) { + u32 tu, ms; +- tu = le32_to_cpu(elems.timeout_int->value); ++ tu = le32_to_cpu(elems->timeout_int->value); + ms = tu * 1024 / 1000; + sdata_info(sdata, + "%pM rejected association temporarily; comeback duration %u TU (%u ms)\n", +@@ -3757,7 +3770,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + event.u.mlme.reason = status_code; + drv_event_callback(sdata->local, sdata, &event); + } else { +- if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, &elems)) { ++ if (!ieee80211_assoc_success(sdata, cbss, mgmt, len, elems)) { + /* oops -- internal error -- send timeout for now */ + ieee80211_destroy_assoc_data(sdata, false, false); + cfg80211_assoc_timeout(sdata->dev, cbss); +@@ -3787,6 +3800,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, + ifmgd->assoc_req_ies, ifmgd->assoc_req_ies_len); + notify_driver: + drv_mgd_complete_tx(sdata->local, sdata, &info); ++ kfree(elems); + } + + static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, +@@ -3991,7 +4005,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; + struct ieee80211_mgmt *mgmt = (void *) hdr; + size_t baselen; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + struct ieee80211_local *local = sdata->local; + struct ieee80211_chanctx_conf *chanctx_conf; + struct ieee80211_channel *chan; +@@ -4037,15 +4051,16 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + + if (ifmgd->assoc_data && ifmgd->assoc_data->need_beacon && + ieee80211_rx_our_beacon(bssid, ifmgd->assoc_data->bss)) { +- ieee802_11_parse_elems(variable, +- len - baselen, false, &elems, +- bssid, +- ifmgd->assoc_data->bss->bssid); ++ elems = ieee802_11_parse_elems(variable, len - baselen, false, ++ bssid, ++ ifmgd->assoc_data->bss->bssid); ++ if (!elems) ++ return; + + ieee80211_rx_bss_info(sdata, mgmt, len, rx_status); + +- if (elems.dtim_period) +- ifmgd->dtim_period = elems.dtim_period; ++ if (elems->dtim_period) ++ ifmgd->dtim_period = elems->dtim_period; + ifmgd->have_beacon = true; + ifmgd->assoc_data->need_beacon = false; + if (ieee80211_hw_check(&local->hw, TIMING_BEACON_ONLY)) { +@@ -4053,17 +4068,17 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + le64_to_cpu(mgmt->u.beacon.timestamp); + sdata->vif.bss_conf.sync_device_ts = + rx_status->device_timestamp; +- sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count; ++ sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count; + } + +- if (elems.mbssid_config_ie) ++ if (elems->mbssid_config_ie) + bss_conf->profile_periodicity = +- elems.mbssid_config_ie->profile_periodicity; ++ elems->mbssid_config_ie->profile_periodicity; + else + bss_conf->profile_periodicity = 0; + +- if (elems.ext_capab_len >= 11 && +- (elems.ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) ++ if (elems->ext_capab_len >= 11 && ++ (elems->ext_capab[10] & WLAN_EXT_CAPA11_EMA_SUPPORT)) + bss_conf->ema_ap = true; + else + bss_conf->ema_ap = false; +@@ -4072,6 +4087,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + ifmgd->assoc_data->timeout = jiffies; + ifmgd->assoc_data->timeout_started = true; + run_again(sdata, ifmgd->assoc_data->timeout); ++ kfree(elems); + return; + } + +@@ -4103,14 +4119,15 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + */ + if (!ieee80211_is_s1g_beacon(hdr->frame_control)) + ncrc = crc32_be(0, (void *)&mgmt->u.beacon.beacon_int, 4); +- ieee802_11_parse_elems_crc(variable, +- len - baselen, false, &elems, +- care_about_ies, ncrc, +- mgmt->bssid, bssid); +- ncrc = elems.crc; ++ elems = ieee802_11_parse_elems_crc(variable, len - baselen, ++ false, care_about_ies, ncrc, ++ mgmt->bssid, bssid); ++ if (!elems) ++ return; ++ ncrc = elems->crc; + + if (ieee80211_hw_check(&local->hw, PS_NULLFUNC_STACK) && +- ieee80211_check_tim(elems.tim, elems.tim_len, bss_conf->aid)) { ++ ieee80211_check_tim(elems->tim, elems->tim_len, bss_conf->aid)) { + if (local->hw.conf.dynamic_ps_timeout > 0) { + if (local->hw.conf.flags & IEEE80211_CONF_PS) { + local->hw.conf.flags &= ~IEEE80211_CONF_PS; +@@ -4180,12 +4197,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + le64_to_cpu(mgmt->u.beacon.timestamp); + sdata->vif.bss_conf.sync_device_ts = + rx_status->device_timestamp; +- sdata->vif.bss_conf.sync_dtim_count = elems.dtim_count; ++ sdata->vif.bss_conf.sync_dtim_count = elems->dtim_count; + } + + if ((ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid) || + ieee80211_is_s1g_short_beacon(mgmt->frame_control)) +- return; ++ goto free; + ifmgd->beacon_crc = ncrc; + ifmgd->beacon_crc_valid = true; + +@@ -4193,12 +4210,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + + ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, + rx_status->device_timestamp, +- &elems, true); ++ elems, true); + + if (!(ifmgd->flags & IEEE80211_STA_DISABLE_WMM) && +- ieee80211_sta_wmm_params(local, sdata, elems.wmm_param, +- elems.wmm_param_len, +- elems.mu_edca_param_set)) ++ ieee80211_sta_wmm_params(local, sdata, elems->wmm_param, ++ elems->wmm_param_len, ++ elems->mu_edca_param_set)) + changed |= BSS_CHANGED_QOS; + + /* +@@ -4207,7 +4224,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + */ + if (!ifmgd->have_beacon) { + /* a few bogus AP send dtim_period = 0 or no TIM IE */ +- bss_conf->dtim_period = elems.dtim_period ?: 1; ++ bss_conf->dtim_period = elems->dtim_period ?: 1; + + changed |= BSS_CHANGED_BEACON_INFO; + ifmgd->have_beacon = true; +@@ -4219,9 +4236,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + ieee80211_recalc_ps_vif(sdata); + } + +- if (elems.erp_info) { ++ if (elems->erp_info) { + erp_valid = true; +- erp_value = elems.erp_info[0]; ++ erp_value = elems->erp_info[0]; + } else { + erp_valid = false; + } +@@ -4234,12 +4251,12 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + mutex_lock(&local->sta_mtx); + sta = sta_info_get(sdata, bssid); + +- changed |= ieee80211_recalc_twt_req(sdata, sta, &elems); ++ changed |= ieee80211_recalc_twt_req(sdata, sta, elems); + +- if (ieee80211_config_bw(sdata, sta, elems.ht_cap_elem, +- elems.vht_cap_elem, elems.ht_operation, +- elems.vht_operation, elems.he_operation, +- elems.s1g_oper, bssid, &changed)) { ++ if (ieee80211_config_bw(sdata, sta, elems->ht_cap_elem, ++ elems->vht_cap_elem, elems->ht_operation, ++ elems->vht_operation, elems->he_operation, ++ elems->s1g_oper, bssid, &changed)) { + mutex_unlock(&local->sta_mtx); + sdata_info(sdata, + "failed to follow AP %pM bandwidth change, disconnect\n", +@@ -4251,21 +4268,23 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, + sizeof(deauth_buf), true, + WLAN_REASON_DEAUTH_LEAVING, + false); +- return; ++ goto free; + } + +- if (sta && elems.opmode_notif) +- ieee80211_vht_handle_opmode(sdata, sta, *elems.opmode_notif, ++ if (sta && elems->opmode_notif) ++ ieee80211_vht_handle_opmode(sdata, sta, *elems->opmode_notif, + rx_status->band); + mutex_unlock(&local->sta_mtx); + + changed |= ieee80211_handle_pwr_constr(sdata, chan, mgmt, +- elems.country_elem, +- elems.country_elem_len, +- elems.pwr_constr_elem, +- elems.cisco_dtpc_elem); ++ elems->country_elem, ++ elems->country_elem_len, ++ elems->pwr_constr_elem, ++ elems->cisco_dtpc_elem); + + ieee80211_bss_info_change_notify(sdata, changed); ++free: ++ kfree(elems); + } + + void ieee80211_sta_rx_queued_ext(struct ieee80211_sub_if_data *sdata, +@@ -4294,7 +4313,6 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + struct ieee80211_rx_status *rx_status; + struct ieee80211_mgmt *mgmt; + u16 fc; +- struct ieee802_11_elems elems; + int ies_len; + + rx_status = (struct ieee80211_rx_status *) skb->cb; +@@ -4326,6 +4344,8 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + break; + case IEEE80211_STYPE_ACTION: + if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) { ++ struct ieee802_11_elems *elems; ++ + ies_len = skb->len - + offsetof(struct ieee80211_mgmt, + u.action.u.chan_switch.variable); +@@ -4334,18 +4354,21 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + break; + + /* CSA IE cannot be overridden, no need for BSSID */ +- ieee802_11_parse_elems( +- mgmt->u.action.u.chan_switch.variable, +- ies_len, true, &elems, mgmt->bssid, NULL); ++ elems = ieee802_11_parse_elems( ++ mgmt->u.action.u.chan_switch.variable, ++ ies_len, true, mgmt->bssid, NULL); + +- if (elems.parse_error) ++ if (!elems || elems->parse_error) + break; + + ieee80211_sta_process_chanswitch(sdata, + rx_status->mactime, + rx_status->device_timestamp, +- &elems, false); ++ elems, false); ++ kfree(elems); + } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { ++ struct ieee802_11_elems *elems; ++ + ies_len = skb->len - + offsetof(struct ieee80211_mgmt, + u.action.u.ext_chan_switch.variable); +@@ -4357,21 +4380,22 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + * extended CSA IE can't be overridden, no need for + * BSSID + */ +- ieee802_11_parse_elems( +- mgmt->u.action.u.ext_chan_switch.variable, +- ies_len, true, &elems, mgmt->bssid, NULL); ++ elems = ieee802_11_parse_elems( ++ mgmt->u.action.u.ext_chan_switch.variable, ++ ies_len, true, mgmt->bssid, NULL); + +- if (elems.parse_error) ++ if (!elems || elems->parse_error) + break; + + /* for the handling code pretend this was also an IE */ +- elems.ext_chansw_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); ++ elems, false); ++ kfree(elems); + } + break; + } +diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c +index d6afaacaf7ef..e692a2487eb5 100644 +--- a/net/mac80211/scan.c ++++ b/net/mac80211/scan.c +@@ -9,7 +9,7 @@ + * Copyright 2007, Michael Wu flamingice@sourmilk.net + * Copyright 2013-2015 Intel Mobile Communications GmbH + * Copyright 2016-2017 Intel Deutschland GmbH +- * Copyright (C) 2018-2020 Intel Corporation ++ * Copyright (C) 2018-2021 Intel Corporation + */ + + #include <linux/if_arp.h> +@@ -155,7 +155,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local, + }; + bool signal_valid; + struct ieee80211_sub_if_data *scan_sdata; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + size_t baselen; + u8 *elements; + +@@ -209,8 +209,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local, + if (baselen > len) + return NULL; + +- ieee802_11_parse_elems(elements, len - baselen, false, &elems, +- mgmt->bssid, cbss->bssid); ++ elems = ieee802_11_parse_elems(elements, len - baselen, false, ++ mgmt->bssid, cbss->bssid); ++ if (!elems) ++ return NULL; + + /* In case the signal is invalid update the status */ + signal_valid = channel == cbss->channel; +@@ -218,15 +220,17 @@ ieee80211_bss_info_update(struct ieee80211_local *local, + rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL; + + bss = (void *)cbss->priv; +- ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon); ++ ieee80211_update_bss_from_elems(local, bss, elems, rx_status, beacon); + + list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) { + non_tx_bss = (void *)non_tx_cbss->priv; + +- ieee80211_update_bss_from_elems(local, non_tx_bss, &elems, ++ ieee80211_update_bss_from_elems(local, non_tx_bss, elems, + rx_status, beacon); + } + ++ kfree(elems); ++ + return bss; + } + +diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c +index 45e532ad1215..137be9ec94af 100644 +--- a/net/mac80211/tdls.c ++++ b/net/mac80211/tdls.c +@@ -6,7 +6,7 @@ + * Copyright 2014, Intel Corporation + * Copyright 2014 Intel Mobile Communications GmbH + * Copyright 2015 - 2016 Intel Deutschland GmbH +- * Copyright (C) 2019 Intel Corporation ++ * Copyright (C) 2019, 2021 Intel Corporation + */ + + #include <linux/ieee80211.h> +@@ -1684,7 +1684,7 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) + { + struct ieee80211_local *local = sdata->local; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems = NULL; + struct sta_info *sta; + struct ieee80211_tdls_data *tf = (void *)skb->data; + bool local_initiator; +@@ -1718,16 +1718,20 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata, + goto call_drv; + } + +- ieee802_11_parse_elems(tf->u.chan_switch_resp.variable, +- skb->len - baselen, false, &elems, +- NULL, NULL); +- if (elems.parse_error) { ++ elems = ieee802_11_parse_elems(tf->u.chan_switch_resp.variable, ++ skb->len - baselen, false, NULL, NULL); ++ if (!elems) { ++ ret = -ENOMEM; ++ goto out; ++ } ++ ++ if (elems->parse_error) { + tdls_dbg(sdata, "Invalid IEs in TDLS channel switch resp\n"); + ret = -EINVAL; + goto out; + } + +- if (!elems.ch_sw_timing || !elems.lnk_id) { ++ if (!elems->ch_sw_timing || !elems->lnk_id) { + tdls_dbg(sdata, "TDLS channel switch resp - missing IEs\n"); + ret = -EINVAL; + goto out; +@@ -1735,15 +1739,15 @@ ieee80211_process_tdls_channel_switch_resp(struct ieee80211_sub_if_data *sdata, + + /* validate the initiator is set correctly */ + local_initiator = +- !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); ++ !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); + if (local_initiator == sta->sta.tdls_initiator) { + tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n"); + ret = -EINVAL; + goto out; + } + +- params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time); +- params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout); ++ params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time); ++ params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout); + + params.tmpl_skb = + ieee80211_tdls_ch_sw_resp_tmpl_get(sta, ¶ms.ch_sw_tm_ie); +@@ -1763,6 +1767,7 @@ call_drv: + out: + mutex_unlock(&local->sta_mtx); + dev_kfree_skb_any(params.tmpl_skb); ++ kfree(elems); + return ret; + } + +@@ -1771,7 +1776,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, + struct sk_buff *skb) + { + struct ieee80211_local *local = sdata->local; +- struct ieee802_11_elems elems; ++ struct ieee802_11_elems *elems; + struct cfg80211_chan_def chandef; + struct ieee80211_channel *chan; + enum nl80211_channel_type chan_type; +@@ -1831,22 +1836,27 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, + return -EINVAL; + } + +- ieee802_11_parse_elems(tf->u.chan_switch_req.variable, +- skb->len - baselen, false, &elems, NULL, NULL); +- if (elems.parse_error) { ++ elems = ieee802_11_parse_elems(tf->u.chan_switch_req.variable, ++ skb->len - baselen, false, NULL, NULL); ++ if (!elems) ++ return -ENOMEM; ++ ++ if (elems->parse_error) { + tdls_dbg(sdata, "Invalid IEs in TDLS channel switch req\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto free; + } + +- if (!elems.ch_sw_timing || !elems.lnk_id) { ++ if (!elems->ch_sw_timing || !elems->lnk_id) { + tdls_dbg(sdata, "TDLS channel switch req - missing IEs\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto free; + } + +- if (!elems.sec_chan_offs) { ++ if (!elems->sec_chan_offs) { + chan_type = NL80211_CHAN_HT20; + } else { +- switch (elems.sec_chan_offs->sec_chan_offs) { ++ switch (elems->sec_chan_offs->sec_chan_offs) { + case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: + chan_type = NL80211_CHAN_HT40PLUS; + break; +@@ -1865,7 +1875,8 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, + if (!cfg80211_reg_can_beacon_relax(sdata->local->hw.wiphy, &chandef, + sdata->wdev.iftype)) { + tdls_dbg(sdata, "TDLS chan switch to forbidden channel\n"); +- return -EINVAL; ++ ret = -EINVAL; ++ goto free; + } + + mutex_lock(&local->sta_mtx); +@@ -1881,7 +1892,7 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, + + /* validate the initiator is set correctly */ + local_initiator = +- !memcmp(elems.lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); ++ !memcmp(elems->lnk_id->init_sta, sdata->vif.addr, ETH_ALEN); + if (local_initiator == sta->sta.tdls_initiator) { + tdls_dbg(sdata, "TDLS chan switch invalid lnk-id initiator\n"); + ret = -EINVAL; +@@ -1889,16 +1900,16 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, + } + + /* peer should have known better */ +- if (!sta->sta.ht_cap.ht_supported && elems.sec_chan_offs && +- elems.sec_chan_offs->sec_chan_offs) { ++ if (!sta->sta.ht_cap.ht_supported && elems->sec_chan_offs && ++ elems->sec_chan_offs->sec_chan_offs) { + tdls_dbg(sdata, "TDLS chan switch - wide chan unsupported\n"); + ret = -ENOTSUPP; + goto out; + } + + params.chandef = &chandef; +- params.switch_time = le16_to_cpu(elems.ch_sw_timing->switch_time); +- params.switch_timeout = le16_to_cpu(elems.ch_sw_timing->switch_timeout); ++ params.switch_time = le16_to_cpu(elems->ch_sw_timing->switch_time); ++ params.switch_timeout = le16_to_cpu(elems->ch_sw_timing->switch_timeout); + + params.tmpl_skb = + ieee80211_tdls_ch_sw_resp_tmpl_get(sta, +@@ -1917,6 +1928,8 @@ ieee80211_process_tdls_channel_switch_req(struct ieee80211_sub_if_data *sdata, + out: + mutex_unlock(&local->sta_mtx); + dev_kfree_skb_any(params.tmpl_skb); ++free: ++ kfree(elems); + return ret; + } + +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 664c32b6db19..2ac61e68b6b4 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1396,8 +1396,8 @@ _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, + + static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, + struct ieee802_11_elems *elems, +- u8 *transmitter_bssid, +- u8 *bss_bssid, ++ const u8 *transmitter_bssid, ++ const u8 *bss_bssid, + u8 *nontransmitted_profile) + { + const struct element *elem, *sub; +@@ -1464,16 +1464,20 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, + return found ? profile_len : 0; + } + +-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) ++struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len, ++ bool action, u64 filter, ++ u32 crc, ++ const u8 *transmitter_bssid, ++ const u8 *bss_bssid) + { ++ struct ieee802_11_elems *elems; + const struct element *non_inherit = NULL; + u8 *nontransmitted_profile; + int nontransmitted_profile_len = 0; + +- memset(elems, 0, sizeof(*elems)); ++ elems = kzalloc(sizeof(*elems), GFP_ATOMIC); ++ if (!elems) ++ return NULL; + elems->ie_start = start; + elems->total_len = len; + +@@ -1520,6 +1524,8 @@ void ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action, + kfree(nontransmitted_profile); + + elems->crc = crc; ++ ++ return elems; + } + + void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata, +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-13.patch b/src/patches/linux/linux-5.15-wifi-security-patches-13.patch new file mode 100644 index 000000000..1d167c19a --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-13.patch @@ -0,0 +1,130 @@ +From 7d998f6b7365d50a9905bf57fd28b41c7ebe8e9d Mon Sep 17 00:00:00 2001 +From: Johannes Berg johannes.berg@intel.com +Date: Thu, 13 Oct 2022 20:16:00 +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.Ib81ca187d3d3af7ed1bfe... +Signed-off-by: Johannes Berg johannes.berg@intel.com +Cc: Felix Fietkau nbd@nbd.name +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/agg-rx.c | 3 ++- + net/mac80211/ibss.c | 10 +++++----- + net/mac80211/mlme.c | 36 ++++++++++++++++++------------------ + 3 files changed, 25 insertions(+), 24 deletions(-) + +diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c +index ffa4f31f6c2b..0d2bab9d351c 100644 +--- a/net/mac80211/agg-rx.c ++++ b/net/mac80211/agg-rx.c +@@ -499,13 +499,14 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, + 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); + } + +diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c +index 4b721b48f86a..48e0260f3424 100644 +--- a/net/mac80211/ibss.c ++++ b/net/mac80211/ibss.c +@@ -1663,11 +1663,11 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, + 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; + } +diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c +index 45efa1d1c550..cc6d38a2e6d5 100644 +--- a/net/mac80211/mlme.c ++++ b/net/mac80211/mlme.c +@@ -3374,8 +3374,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata, + 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 ieee80211_sub_if_data *sdata, + 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 ieee80211_sub_if_data *sdata, + 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; + +- /* 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); ++ } + +- ieee80211_sta_process_chanswitch(sdata, +- rx_status->mactime, +- rx_status->device_timestamp, +- elems, false); + kfree(elems); + } + break; +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-14.patch b/src/patches/linux/linux-5.15-wifi-security-patches-14.patch new file mode 100644 index 000000000..f0ccc0b6a --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-14.patch @@ -0,0 +1,107 @@ +From de124365a7d2deed22cf706583930f28d537ff0f Mon Sep 17 00:00:00 2001 +From: Johannes Berg johannes.berg@intel.com +Date: Thu, 13 Oct 2022 20:16:01 +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 +Cc: Felix Fietkau nbd@nbd.name +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/ieee80211_i.h | 8 ++++++++ + net/mac80211/util.c | 29 ++++++++++++++--------------- + 2 files changed, 22 insertions(+), 15 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index 3633e49239c7..21549a440b38 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -1613,6 +1613,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( +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index 2ac61e68b6b4..354badd32793 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1475,24 +1475,25 @@ struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len, + 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); +@@ -1521,8 +1522,6 @@ struct ieee802_11_elems *ieee802_11_parse_elems_crc(const u8 *start, size_t len, + offsetofend(struct ieee80211_bssid_index, dtim_count)) + elems->dtim_count = elems->bssid_index->dtim_count; + +- kfree(nontransmitted_profile); +- + elems->crc = crc; + + return elems; +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-2.patch b/src/patches/linux/linux-5.15-wifi-security-patches-2.patch new file mode 100644 index 000000000..d2a04e717 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-2.patch @@ -0,0 +1,59 @@ +From 0a861bd25dad508e492c48169509d8c6b9246895 Mon Sep 17 00:00:00 2001 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/util.c | 2 ++ + net/wireless/scan.c | 2 ++ + 2 files changed, 4 insertions(+) + +diff --git a/net/mac80211/util.c b/net/mac80211/util.c +index be1911d8089f..00543ea9c6b5 100644 +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1414,6 +1414,8 @@ static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len, + 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]; +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index d9ab37a798f4..84c642eae4d8 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -2103,6 +2103,8 @@ static void cfg80211_parse_mbssid_data(struct wiphy *wiphy, + 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; + +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-3.patch b/src/patches/linux/linux-5.15-wifi-security-patches-3.patch new file mode 100644 index 000000000..60be08214 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-3.patch @@ -0,0 +1,49 @@ +From 9e99ca59ed3976921f8891c103d503b6da3e78af Mon Sep 17 00:00:00 2001 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/wireless/scan.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 84c642eae4d8..04c9b78b3fec 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -304,7 +304,8 @@ static size_t cfg80211_gen_new_ie(const u8 *ie, size_t ielen, + 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 u8 *ie, size_t ielen, + * 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); +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-4.patch b/src/patches/linux/linux-5.15-wifi-security-patches-4.patch new file mode 100644 index 000000000..bd2439041 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-4.patch @@ -0,0 +1,96 @@ +From bfe29873454f38eb1a511a76144ad1a4848ca176 Mon Sep 17 00:00:00 2001 +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=utf8 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/wireless/scan.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 04c9b78b3fec..2e576714e989 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -143,18 +143,12 @@ static inline void bss_ref_get(struct cfg80211_registered_device *rdev, + 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_registered_device *rdev, + 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 wiphy *wiphy, + 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); +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-5.patch b/src/patches/linux/linux-5.15-wifi-security-patches-5.patch new file mode 100644 index 000000000..c0c4dadd3 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-5.patch @@ -0,0 +1,56 @@ +From 0a8ee682e4f992eccce226b012bba600bb2251e2 Mon Sep 17 00:00:00 2001 +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=utf8 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/wireless/scan.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index 2e576714e989..a21baf7b3612 100644 +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -425,6 +425,15 @@ cfg80211_add_nontrans_list(struct cfg80211_bss *trans_bss, + + 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; +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-6.patch b/src/patches/linux/linux-5.15-wifi-security-patches-6.patch new file mode 100644 index 000000000..caa380de8 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-6.patch @@ -0,0 +1,39 @@ +From fff244e9171b2ca692469d41c68b36607bd73ab0 Mon Sep 17 00:00:00 2001 +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=utf8 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + drivers/net/wireless/mac80211_hwsim.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c +index 52a2574b7d13..b228567b2a73 100644 +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -3749,6 +3749,8 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, + + 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; +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-7.patch b/src/patches/linux/linux-5.15-wifi-security-patches-7.patch new file mode 100644 index 000000000..b5cb2ad12 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-7.patch @@ -0,0 +1,60 @@ +From 93a3a32554079432b49cf87f326607b2a2fab4f2 Mon Sep 17 00:00:00 2001 +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=utf8 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/rx.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c +index 743e97ba352c..175ead6b19cb 100644 +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -1982,10 +1982,11 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + + 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 */ + } + +@@ -2133,7 +2134,8 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) + /* 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); + +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-8.patch b/src/patches/linux/linux-5.15-wifi-security-patches-8.patch new file mode 100644 index 000000000..8099f3a72 --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-8.patch @@ -0,0 +1,94 @@ +From d15bb1f6dabe1d2a4155958111bea47db72b599c Mon Sep 17 00:00:00 2001 +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=utf8 +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 +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/wireless/scan.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +diff --git a/net/wireless/scan.c b/net/wireless/scan.c +index a21baf7b3612..f0de22a6caf7 100644 +--- 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 cfg80211_registered_device *rdev, + 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 cfg80211_registered_device *rdev, + 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(struct wiphy *wiphy, + } 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); +-- +2.30.2 + diff --git a/src/patches/linux/linux-5.15-wifi-security-patches-9.patch b/src/patches/linux/linux-5.15-wifi-security-patches-9.patch new file mode 100644 index 000000000..5781b077d --- /dev/null +++ b/src/patches/linux/linux-5.15-wifi-security-patches-9.patch @@ -0,0 +1,126 @@ +From 864f2d3482f4bd0c62b355e35ee8300be8ef488e Mon Sep 17 00:00:00 2001 +From: Johannes Berg johannes.berg@intel.com +Date: Thu, 13 Oct 2022 20:15:56 +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.I1824b773a0fbae4453e14... +Signed-off-by: Johannes Berg johannes.berg@intel.com +Cc: Felix Fietkau nbd@nbd.name +Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org +--- + net/mac80211/ieee80211_i.h | 7 +++---- + net/mac80211/mesh.c | 4 ++-- + net/mac80211/mesh_sync.c | 26 ++++++++++++-------------- + 3 files changed, 17 insertions(+), 20 deletions(-) + +diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h +index f7bea4af2ddb..4bd55af184b2 100644 +--- a/net/mac80211/ieee80211_i.h ++++ b/net/mac80211/ieee80211_i.h +@@ -631,10 +631,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 */ +diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c +index 42bd81a30310..9f6414a68d71 100644 +--- a/net/mac80211/mesh.c ++++ b/net/mac80211/mesh.c +@@ -1354,8 +1354,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, + } + + 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) +diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c +index fde93de2b80a..9e342cc2504c 100644 +--- 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 ieee80211_sub_if_data *sdata) + } + } + +-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_presp(struct ieee80211_sub_if_data *sdata, + */ + 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_presp(struct ieee80211_sub_if_data *sdata, + * 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; +-- +2.30.2 +
hooks/post-receive -- IPFire 2.x development tree