From 4795504cb1cad2d15545448b542d9e7923cf94e6 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Thu, 13 Oct 2022 18:56:54 +0200 Subject: [PATCH] 5.4-stable patches added patches: wifi-cfg80211-avoid-nontransmitted-bss-list-corruption.patch wifi-cfg80211-ensure-length-byte-is-present-before-access.patch wifi-cfg80211-fix-bss-refcounting-bugs.patch wifi-cfg80211-fix-u8-overflow-in-cfg80211_update_notlisted_nontrans.patch wifi-cfg80211-mac80211-reject-bad-mbssid-elements.patch wifi-cfg80211-update-hidden-bsses-to-avoid-warn_on.patch wifi-mac80211_hwsim-avoid-mac80211-warning-on-bad-rate.patch --- queue-5.4/series | 7 ++ ...d-nontransmitted-bss-list-corruption.patch | 53 +++++++++++ ...length-byte-is-present-before-access.patch | 46 +++++++++ ...fi-cfg80211-fix-bss-refcounting-bugs.patch | 93 +++++++++++++++++++ ...n-cfg80211_update_notlisted_nontrans.patch | 46 +++++++++ ...-mac80211-reject-bad-mbssid-elements.patch | 54 +++++++++++ ...update-hidden-bsses-to-avoid-warn_on.patch | 91 ++++++++++++++++++ ...m-avoid-mac80211-warning-on-bad-rate.patch | 36 +++++++ 8 files changed, 426 insertions(+) create mode 100644 queue-5.4/wifi-cfg80211-avoid-nontransmitted-bss-list-corruption.patch create mode 100644 queue-5.4/wifi-cfg80211-ensure-length-byte-is-present-before-access.patch create mode 100644 queue-5.4/wifi-cfg80211-fix-bss-refcounting-bugs.patch create mode 100644 queue-5.4/wifi-cfg80211-fix-u8-overflow-in-cfg80211_update_notlisted_nontrans.patch create mode 100644 queue-5.4/wifi-cfg80211-mac80211-reject-bad-mbssid-elements.patch create mode 100644 queue-5.4/wifi-cfg80211-update-hidden-bsses-to-avoid-warn_on.patch create mode 100644 queue-5.4/wifi-mac80211_hwsim-avoid-mac80211-warning-on-bad-rate.patch diff --git a/queue-5.4/series b/queue-5.4/series index b11e475d432..de301473b54 100644 --- a/queue-5.4/series +++ b/queue-5.4/series @@ -27,3 +27,10 @@ usb-serial-qcserial-add-new-usb-id-for-dell-branded-em7455.patch random-restore-o_nonblock-support.patch random-avoid-reading-two-cache-lines-on-irq-randomness.patch random-use-expired-timer-rather-than-wq-for-mixing-fast-pool.patch +wifi-cfg80211-fix-u8-overflow-in-cfg80211_update_notlisted_nontrans.patch +wifi-cfg80211-mac80211-reject-bad-mbssid-elements.patch +wifi-cfg80211-ensure-length-byte-is-present-before-access.patch +wifi-cfg80211-fix-bss-refcounting-bugs.patch +wifi-cfg80211-avoid-nontransmitted-bss-list-corruption.patch +wifi-mac80211_hwsim-avoid-mac80211-warning-on-bad-rate.patch +wifi-cfg80211-update-hidden-bsses-to-avoid-warn_on.patch diff --git a/queue-5.4/wifi-cfg80211-avoid-nontransmitted-bss-list-corruption.patch b/queue-5.4/wifi-cfg80211-avoid-nontransmitted-bss-list-corruption.patch new file mode 100644 index 00000000000..b915c01486a --- /dev/null +++ b/queue-5.4/wifi-cfg80211-avoid-nontransmitted-bss-list-corruption.patch @@ -0,0 +1,53 @@ +From bcca852027e5878aec911a347407ecc88d6fff7f Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Sat, 1 Oct 2022 00:01:44 +0200 +Subject: wifi: cfg80211: avoid nontransmitted BSS list corruption +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Johannes Berg + +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 +Tested-by: Sönke Huster +Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/scan.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -386,6 +386,15 @@ cfg80211_add_nontrans_list(struct cfg802 + + rcu_read_unlock(); + ++ /* ++ * This is a bit weird - it's not on the list, but already on another ++ * one! The only way that could happen is if there's some BSSID/SSID ++ * shared by multiple APs in their multi-BSSID profiles, potentially ++ * with hidden SSID mixed in ... ignore it. ++ */ ++ if (!list_empty(&nontrans_bss->nontrans_list)) ++ return -EINVAL; ++ + /* add to the list */ + list_add_tail(&nontrans_bss->nontrans_list, &trans_bss->nontrans_list); + return 0; diff --git a/queue-5.4/wifi-cfg80211-ensure-length-byte-is-present-before-access.patch b/queue-5.4/wifi-cfg80211-ensure-length-byte-is-present-before-access.patch new file mode 100644 index 00000000000..eae36a850b7 --- /dev/null +++ b/queue-5.4/wifi-cfg80211-ensure-length-byte-is-present-before-access.patch @@ -0,0 +1,46 @@ +From 567e14e39e8f8c6997a1378bc3be615afca86063 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Thu, 29 Sep 2022 21:50:44 +0200 +Subject: wifi: cfg80211: ensure length byte is present before access + +From: Johannes Berg + +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 +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/scan.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -265,7 +265,8 @@ static size_t cfg80211_gen_new_ie(const + tmp_old = cfg80211_find_ie(WLAN_EID_SSID, ie, ielen); + tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + 2 : ie; + +- while (tmp_old + tmp_old[1] + 2 - ie <= ielen) { ++ while (tmp_old + 2 - ie <= ielen && ++ tmp_old + tmp_old[1] + 2 - ie <= ielen) { + if (tmp_old[0] == 0) { + tmp_old++; + continue; +@@ -325,7 +326,8 @@ static size_t cfg80211_gen_new_ie(const + * copied to new ie, skip ssid, capability, bssid-index ie + */ + tmp_new = sub_copy; +- while (tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) { ++ while (tmp_new + 2 - sub_copy <= subie_len && ++ tmp_new + tmp_new[1] + 2 - sub_copy <= subie_len) { + if (!(tmp_new[0] == WLAN_EID_NON_TX_BSSID_CAP || + tmp_new[0] == WLAN_EID_SSID)) { + memcpy(pos, tmp_new, tmp_new[1] + 2); diff --git a/queue-5.4/wifi-cfg80211-fix-bss-refcounting-bugs.patch b/queue-5.4/wifi-cfg80211-fix-bss-refcounting-bugs.patch new file mode 100644 index 00000000000..d10efbe1e47 --- /dev/null +++ b/queue-5.4/wifi-cfg80211-fix-bss-refcounting-bugs.patch @@ -0,0 +1,93 @@ +From 0b7808818cb9df6680f98996b8e9a439fa7bcc2f Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Fri, 30 Sep 2022 23:44:23 +0200 +Subject: wifi: cfg80211: fix BSS refcounting bugs +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Johannes Berg + +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 +Tested-by: Sönke Huster +Fixes: a3584f56de1c ("cfg80211: Properly track transmitting and non-transmitting BSS") +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/scan.c | 27 ++++++++++++++------------- + 1 file changed, 14 insertions(+), 13 deletions(-) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -104,18 +104,12 @@ static inline void bss_ref_get(struct cf + lockdep_assert_held(&rdev->bss_lock); + + bss->refcount++; +- if (bss->pub.hidden_beacon_bss) { +- bss = container_of(bss->pub.hidden_beacon_bss, +- struct cfg80211_internal_bss, +- pub); +- bss->refcount++; +- } +- if (bss->pub.transmitted_bss) { +- bss = container_of(bss->pub.transmitted_bss, +- struct cfg80211_internal_bss, +- pub); +- bss->refcount++; +- } ++ ++ if (bss->pub.hidden_beacon_bss) ++ bss_from_pub(bss->pub.hidden_beacon_bss)->refcount++; ++ ++ if (bss->pub.transmitted_bss) ++ bss_from_pub(bss->pub.transmitted_bss)->refcount++; + } + + static inline void bss_ref_put(struct cfg80211_registered_device *rdev, +@@ -1233,6 +1227,8 @@ cfg80211_bss_update(struct cfg80211_regi + new->refcount = 1; + INIT_LIST_HEAD(&new->hidden_list); + INIT_LIST_HEAD(&new->pub.nontrans_list); ++ /* we'll set this later if it was non-NULL */ ++ new->pub.transmitted_bss = NULL; + + if (rcu_access_pointer(tmp->pub.proberesp_ies)) { + hidden = rb_find_bss(rdev, tmp, BSS_CMP_HIDE_ZLEN); +@@ -1462,10 +1458,15 @@ cfg80211_inform_single_bss_data(struct w + spin_lock_bh(&rdev->bss_lock); + if (cfg80211_add_nontrans_list(non_tx_data->tx_bss, + &res->pub)) { +- if (__cfg80211_unlink_bss(rdev, res)) ++ if (__cfg80211_unlink_bss(rdev, res)) { + rdev->bss_generation++; ++ res = NULL; ++ } + } + spin_unlock_bh(&rdev->bss_lock); ++ ++ if (!res) ++ return NULL; + } + + trace_cfg80211_return_bss(&res->pub); diff --git a/queue-5.4/wifi-cfg80211-fix-u8-overflow-in-cfg80211_update_notlisted_nontrans.patch b/queue-5.4/wifi-cfg80211-fix-u8-overflow-in-cfg80211_update_notlisted_nontrans.patch new file mode 100644 index 00000000000..bb89c0b4bee --- /dev/null +++ b/queue-5.4/wifi-cfg80211-fix-u8-overflow-in-cfg80211_update_notlisted_nontrans.patch @@ -0,0 +1,46 @@ +From aebe9f4639b13a1f4e9a6b42cdd2e38c617b442d Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 28 Sep 2022 21:56:15 +0200 +Subject: wifi: cfg80211: fix u8 overflow in cfg80211_update_notlisted_nontrans() + +From: Johannes Berg + +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 +Tested-by: Soenke Huster +Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") +Reviewed-by: Kees Cook +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/scan.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -1717,7 +1717,7 @@ cfg80211_update_notlisted_nontrans(struc + size_t new_ie_len; + struct cfg80211_bss_ies *new_ies; + const struct cfg80211_bss_ies *old; +- u8 cpy_len; ++ size_t cpy_len; + + lockdep_assert_held(&wiphy_to_rdev(wiphy)->bss_lock); + diff --git a/queue-5.4/wifi-cfg80211-mac80211-reject-bad-mbssid-elements.patch b/queue-5.4/wifi-cfg80211-mac80211-reject-bad-mbssid-elements.patch new file mode 100644 index 00000000000..e958e244899 --- /dev/null +++ b/queue-5.4/wifi-cfg80211-mac80211-reject-bad-mbssid-elements.patch @@ -0,0 +1,54 @@ +From 8f033d2becc24aa6bfd2a5c104407963560caabc Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 28 Sep 2022 22:01:37 +0200 +Subject: wifi: cfg80211/mac80211: reject bad MBSSID elements + +From: Johannes Berg + +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 +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/util.c | 2 ++ + net/wireless/scan.c | 2 ++ + 2 files changed, 4 insertions(+) + +--- a/net/mac80211/util.c ++++ b/net/mac80211/util.c +@@ -1289,6 +1289,8 @@ static size_t ieee802_11_find_bssid_prof + for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) { + if (elem->datalen < 2) + continue; ++ if (elem->data[0] < 1 || elem->data[0] > 8) ++ continue; + + for_each_element(sub, elem->data + 1, elem->datalen - 1) { + u8 new_bssid[ETH_ALEN]; +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -1582,6 +1582,8 @@ static void cfg80211_parse_mbssid_data(s + for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ie, ielen) { + if (elem->datalen < 4) + continue; ++ if (elem->data[0] < 1 || (int)elem->data[0] > 8) ++ continue; + for_each_element(sub, elem->data + 1, elem->datalen - 1) { + u8 profile_len; + diff --git a/queue-5.4/wifi-cfg80211-update-hidden-bsses-to-avoid-warn_on.patch b/queue-5.4/wifi-cfg80211-update-hidden-bsses-to-avoid-warn_on.patch new file mode 100644 index 00000000000..43c817a7256 --- /dev/null +++ b/queue-5.4/wifi-cfg80211-update-hidden-bsses-to-avoid-warn_on.patch @@ -0,0 +1,91 @@ +From c90b93b5b782891ebfda49d4e5da36632fefd5d1 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 5 Oct 2022 23:11:43 +0200 +Subject: wifi: cfg80211: update hidden BSSes to avoid WARN_ON +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Johannes Berg + +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 +Tested-by: Sönke Huster +Fixes: 0b8fb8235be8 ("cfg80211: Parsing of Multiple BSSID information in scanning") +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/wireless/scan.c | 31 ++++++++++++++++++++----------- + 1 file changed, 20 insertions(+), 11 deletions(-) + +--- a/net/wireless/scan.c ++++ b/net/wireless/scan.c +@@ -1099,6 +1099,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, +@@ -1122,7 +1139,6 @@ cfg80211_update_known_bss(struct cfg8021 + kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); + } else if (rcu_access_pointer(new->pub.beacon_ies)) { + const struct cfg80211_bss_ies *old; +- struct cfg80211_internal_bss *bss; + + if (known->pub.hidden_beacon_bss && + !list_empty(&known->hidden_list)) { +@@ -1150,16 +1166,7 @@ cfg80211_update_known_bss(struct cfg8021 + if (old == rcu_access_pointer(known->pub.ies)) + rcu_assign_pointer(known->pub.ies, new->pub.beacon_ies); + +- /* Assign beacon IEs to all sub entries */ +- list_for_each_entry(bss, &known->hidden_list, hidden_list) { +- const struct cfg80211_bss_ies *ies; +- +- ies = rcu_access_pointer(bss->pub.beacon_ies); +- WARN_ON(ies != old); +- +- rcu_assign_pointer(bss->pub.beacon_ies, +- new->pub.beacon_ies); +- } ++ cfg80211_update_hidden_bsses(known, new->pub.beacon_ies, old); + + if (old) + kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); +@@ -1798,6 +1805,8 @@ cfg80211_update_notlisted_nontrans(struc + } else { + old = rcu_access_pointer(nontrans_bss->beacon_ies); + rcu_assign_pointer(nontrans_bss->beacon_ies, new_ies); ++ cfg80211_update_hidden_bsses(bss_from_pub(nontrans_bss), ++ new_ies, old); + rcu_assign_pointer(nontrans_bss->ies, new_ies); + if (old) + kfree_rcu((struct cfg80211_bss_ies *)old, rcu_head); diff --git a/queue-5.4/wifi-mac80211_hwsim-avoid-mac80211-warning-on-bad-rate.patch b/queue-5.4/wifi-mac80211_hwsim-avoid-mac80211-warning-on-bad-rate.patch new file mode 100644 index 00000000000..507297f1aa1 --- /dev/null +++ b/queue-5.4/wifi-mac80211_hwsim-avoid-mac80211-warning-on-bad-rate.patch @@ -0,0 +1,36 @@ +From 1833b6f46d7e2830251a063935ab464256defe22 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Wed, 5 Oct 2022 15:10:09 +0200 +Subject: wifi: mac80211_hwsim: avoid mac80211 warning on bad rate +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Johannes Berg + +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 +Tested-by: Sönke Huster +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/mac80211_hwsim.c | 2 ++ + 1 file changed, 2 insertions(+) + +--- a/drivers/net/wireless/mac80211_hwsim.c ++++ b/drivers/net/wireless/mac80211_hwsim.c +@@ -3411,6 +3411,8 @@ static int hwsim_cloned_frame_received_n + + rx_status.band = data2->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.47.3