From d4bbca7ec2959bdfb5866d985c8520e4d99d5cf9 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 29 May 2021 17:32:39 +0200 Subject: [PATCH] 4.19-stable patches added patches: ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch mac80211-do-not-accept-forward-invalid-eapol-frames.patch mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch --- ...of-a-msdu-before-processing-the-list.patch | 117 ++++++++++++++++++ ...rash-when-an-origin-has-no-snapshots.patch | 35 ++++++ ...-accept-forward-invalid-eapol-frames.patch | 103 +++++++++++++++ ...mixed-key-and-fragment-cache-attacks.patch | 76 ++++++++++++ queue-4.19/series | 4 + 5 files changed, 335 insertions(+) create mode 100644 queue-4.19/ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch create mode 100644 queue-4.19/dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch create mode 100644 queue-4.19/mac80211-do-not-accept-forward-invalid-eapol-frames.patch create mode 100644 queue-4.19/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch diff --git a/queue-4.19/ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch b/queue-4.19/ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch new file mode 100644 index 00000000000..0daca7d273d --- /dev/null +++ b/queue-4.19/ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch @@ -0,0 +1,117 @@ +From 62a8ff67eba52dae9b107e1fb8827054ed00a265 Mon Sep 17 00:00:00 2001 +From: Sriram R +Date: Tue, 11 May 2021 20:02:57 +0200 +Subject: ath10k: Validate first subframe of A-MSDU before processing the list + +From: Sriram R + +commit 62a8ff67eba52dae9b107e1fb8827054ed00a265 upstream. + +In certain scenarios a normal MSDU can be received as an A-MSDU when +the A-MSDU present bit of a QoS header gets flipped during reception. +Since this bit is unauthenticated, the hardware crypto engine can pass +the frame to the driver without any error indication. + +This could result in processing unintended subframes collected in the +A-MSDU list. Hence, validate A-MSDU list by checking if the first frame +has a valid subframe header. + +Comparing the non-aggregated MSDU and an A-MSDU, the fields of the first +subframe DA matches the LLC/SNAP header fields of a normal MSDU. +In order to avoid processing such frames, add a validation to +filter such A-MSDU frames where the first subframe header DA matches +with the LLC/SNAP header pattern. + +Tested-on: QCA9984 hw1.0 PCI 10.4-3.10-00047 + +Cc: stable@vger.kernel.org +Signed-off-by: Sriram R +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.e6f5eb7b9847.I38a77ae26096862527a5eab73caebd7346af8b66@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + drivers/net/wireless/ath/ath10k/htt_rx.c | 61 ++++++++++++++++++++++++++++--- + 1 file changed, 57 insertions(+), 4 deletions(-) + +--- a/drivers/net/wireless/ath/ath10k/htt_rx.c ++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c +@@ -1769,14 +1769,62 @@ static void ath10k_htt_rx_h_unchain(stru + ath10k_unchain_msdu(amsdu, unchain_cnt); + } + ++static bool ath10k_htt_rx_validate_amsdu(struct ath10k *ar, ++ struct sk_buff_head *amsdu) ++{ ++ u8 *subframe_hdr; ++ struct sk_buff *first; ++ bool is_first, is_last; ++ struct htt_rx_desc *rxd; ++ struct ieee80211_hdr *hdr; ++ size_t hdr_len, crypto_len; ++ enum htt_rx_mpdu_encrypt_type enctype; ++ int bytes_aligned = ar->hw_params.decap_align_bytes; ++ ++ first = skb_peek(amsdu); ++ ++ rxd = (void *)first->data - sizeof(*rxd); ++ hdr = (void *)rxd->rx_hdr_status; ++ ++ is_first = !!(rxd->msdu_end.common.info0 & ++ __cpu_to_le32(RX_MSDU_END_INFO0_FIRST_MSDU)); ++ is_last = !!(rxd->msdu_end.common.info0 & ++ __cpu_to_le32(RX_MSDU_END_INFO0_LAST_MSDU)); ++ ++ /* Return in case of non-aggregated msdu */ ++ if (is_first && is_last) ++ return true; ++ ++ /* First msdu flag is not set for the first msdu of the list */ ++ if (!is_first) ++ return false; ++ ++ enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0), ++ RX_MPDU_START_INFO0_ENCRYPT_TYPE); ++ ++ hdr_len = ieee80211_hdrlen(hdr->frame_control); ++ crypto_len = ath10k_htt_rx_crypto_param_len(ar, enctype); ++ ++ subframe_hdr = (u8 *)hdr + round_up(hdr_len, bytes_aligned) + ++ crypto_len; ++ ++ /* Validate if the amsdu has a proper first subframe. ++ * There are chances a single msdu can be received as amsdu when ++ * the unauthenticated amsdu flag of a QoS header ++ * gets flipped in non-SPP AMSDU's, in such cases the first ++ * subframe has llc/snap header in place of a valid da. ++ * return false if the da matches rfc1042 pattern ++ */ ++ if (ether_addr_equal(subframe_hdr, rfc1042_header)) ++ return false; ++ ++ return true; ++} ++ + static bool ath10k_htt_rx_amsdu_allowed(struct ath10k *ar, + struct sk_buff_head *amsdu, + struct ieee80211_rx_status *rx_status) + { +- /* FIXME: It might be a good idea to do some fuzzy-testing to drop +- * invalid/dangerous frames. +- */ +- + if (!rx_status->freq) { + ath10k_dbg(ar, ATH10K_DBG_HTT, "no channel configured; ignoring frame(s)!\n"); + return false; +@@ -1787,6 +1835,11 @@ static bool ath10k_htt_rx_amsdu_allowed( + return false; + } + ++ if (!ath10k_htt_rx_validate_amsdu(ar, amsdu)) { ++ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid amsdu received\n"); ++ return false; ++ } ++ + return true; + } + diff --git a/queue-4.19/dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch b/queue-4.19/dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch new file mode 100644 index 00000000000..d78e4f020a9 --- /dev/null +++ b/queue-4.19/dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch @@ -0,0 +1,35 @@ +From 7e768532b2396bcb7fbf6f82384b85c0f1d2f197 Mon Sep 17 00:00:00 2001 +From: Mikulas Patocka +Date: Tue, 25 May 2021 13:17:19 -0400 +Subject: dm snapshot: properly fix a crash when an origin has no snapshots + +From: Mikulas Patocka + +commit 7e768532b2396bcb7fbf6f82384b85c0f1d2f197 upstream. + +If an origin target has no snapshots, o->split_boundary is set to 0. +This causes BUG_ON(sectors <= 0) in block/bio.c:bio_split(). + +Fix this by initializing chunk_size, and in turn split_boundary, to +rounddown_pow_of_two(UINT_MAX) -- the largest power of two that fits +into "unsigned" type. + +Signed-off-by: Mikulas Patocka +Cc: stable@vger.kernel.org +Signed-off-by: Mike Snitzer +Signed-off-by: Greg Kroah-Hartman +--- + drivers/md/dm-snap.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/md/dm-snap.c ++++ b/drivers/md/dm-snap.c +@@ -794,7 +794,7 @@ static int dm_add_exception(void *contex + static uint32_t __minimum_chunk_size(struct origin *o) + { + struct dm_snapshot *snap; +- unsigned chunk_size = 0; ++ unsigned chunk_size = rounddown_pow_of_two(UINT_MAX); + + if (o) + list_for_each_entry(snap, &o->snapshots, list) diff --git a/queue-4.19/mac80211-do-not-accept-forward-invalid-eapol-frames.patch b/queue-4.19/mac80211-do-not-accept-forward-invalid-eapol-frames.patch new file mode 100644 index 00000000000..fad8e2b1841 --- /dev/null +++ b/queue-4.19/mac80211-do-not-accept-forward-invalid-eapol-frames.patch @@ -0,0 +1,103 @@ +From a8c4d76a8dd4fb9666fc8919a703d85fb8f44ed8 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:50 +0200 +Subject: mac80211: do not accept/forward invalid EAPOL frames + +From: Johannes Berg + +commit a8c4d76a8dd4fb9666fc8919a703d85fb8f44ed8 upstream. + +EAPOL frames are used for authentication and key management between the +AP and each individual STA associated in the BSS. Those frames are not +supposed to be sent by one associated STA to another associated STA +(either unicast for broadcast/multicast). + +Similarly, in 802.11 they're supposed to be sent to the authenticator +(AP) address. + +Since it is possible for unexpected EAPOL frames to result in misbehavior +in supplicant implementations, it is better for the AP to not allow such +cases to be forwarded to other clients either directly, or indirectly if +the AP interface is part of a bridge. + +Accept EAPOL (control port) frames only if they're transmitted to the +own address, or, due to interoperability concerns, to the PAE group +address. + +Disable forwarding of EAPOL (or well, the configured control port +protocol) frames back to wireless medium in all cases. Previously, these +frames were accepted from fully authenticated and authorized stations +and also from unauthenticated stations for one of the cases. + +Additionally, to avoid forwarding by the bridge, rewrite the PAE group +address case to the local MAC address. + +Cc: stable@vger.kernel.org +Co-developed-by: Jouni Malinen +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.cb327ed0cabe.Ib7dcffa2a31f0913d660de65ba3c8aca75b1d10f@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/rx.c | 33 +++++++++++++++++++++++++++------ + 1 file changed, 27 insertions(+), 6 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2408,13 +2408,13 @@ static bool ieee80211_frame_allowed(stru + struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data; + + /* +- * Allow EAPOL frames to us/the PAE group address regardless +- * of whether the frame was encrypted or not. ++ * Allow EAPOL frames to us/the PAE group address regardless of ++ * whether the frame was encrypted or not, and always disallow ++ * all other destination addresses for them. + */ +- if (ehdr->h_proto == rx->sdata->control_port_protocol && +- (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || +- ether_addr_equal(ehdr->h_dest, pae_group_addr))) +- return true; ++ if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol)) ++ return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) || ++ ether_addr_equal(ehdr->h_dest, pae_group_addr); + + if (ieee80211_802_1x_port_control(rx) || + ieee80211_drop_unencrypted(rx, fc)) +@@ -2438,8 +2438,28 @@ static void ieee80211_deliver_skb_to_loc + cfg80211_rx_control_port(dev, skb, noencrypt); + dev_kfree_skb(skb); + } else { ++ struct ethhdr *ehdr = (void *)skb_mac_header(skb); ++ + memset(skb->cb, 0, sizeof(skb->cb)); + ++ /* ++ * 802.1X over 802.11 requires that the authenticator address ++ * be used for EAPOL frames. However, 802.1X allows the use of ++ * the PAE group address instead. If the interface is part of ++ * a bridge and we pass the frame with the PAE group address, ++ * then the bridge will forward it to the network (even if the ++ * client was not associated yet), which isn't supposed to ++ * happen. ++ * To avoid that, rewrite the destination address to our own ++ * address, so that the authenticator (e.g. hostapd) will see ++ * the frame, but bridge won't forward it anywhere else. Note ++ * that due to earlier filtering, the only other address can ++ * be the PAE group address. ++ */ ++ if (unlikely(skb->protocol == sdata->control_port_protocol && ++ !ether_addr_equal(ehdr->h_dest, sdata->vif.addr))) ++ ether_addr_copy(ehdr->h_dest, sdata->vif.addr); ++ + /* deliver to local stack */ + if (rx->napi) + napi_gro_receive(rx->napi, skb); +@@ -2479,6 +2499,7 @@ ieee80211_deliver_skb(struct ieee80211_r + if ((sdata->vif.type == NL80211_IFTYPE_AP || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && + !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) && ++ ehdr->h_proto != rx->sdata->control_port_protocol && + (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) { + if (is_multicast_ether_addr(ehdr->h_dest) && + ieee80211_vif_get_num_mcast_if(sdata) != 0) { diff --git a/queue-4.19/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch b/queue-4.19/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch new file mode 100644 index 00000000000..8aed3f62811 --- /dev/null +++ b/queue-4.19/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch @@ -0,0 +1,76 @@ +From 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 Mon Sep 17 00:00:00 2001 +From: Wen Gong +Date: Tue, 11 May 2021 20:02:51 +0200 +Subject: mac80211: extend protection against mixed key and fragment cache attacks + +From: Wen Gong + +commit 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 upstream. + +For some chips/drivers, e.g., QCA6174 with ath10k, the decryption is +done by the hardware, and the Protected bit in the Frame Control field +is cleared in the lower level driver before the frame is passed to +mac80211. In such cases, the condition for ieee80211_has_protected() is +not met in ieee80211_rx_h_defragment() of mac80211 and the new security +validation steps are not executed. + +Extend mac80211 to cover the case where the Protected bit has been +cleared, but the frame is indicated as having been decrypted by the +hardware. This extends protection against mixed key and fragment cache +attack for additional drivers/chips. This fixes CVE-2020-24586 and +CVE-2020-24587 for such cases. + +Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1 + +Cc: stable@vger.kernel.org +Signed-off-by: Wen Gong +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.037aa5ca0390.I7bb888e2965a0db02a67075fcb5deb50eb7408aa@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/rx.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2113,6 +2113,7 @@ ieee80211_rx_h_defragment(struct ieee802 + unsigned int frag, seq; + struct ieee80211_fragment_entry *entry; + struct sk_buff *skb; ++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb); + + hdr = (struct ieee80211_hdr *)rx->skb->data; + fc = hdr->frame_control; +@@ -2171,7 +2172,9 @@ ieee80211_rx_h_defragment(struct ieee802 + sizeof(rx->key->u.gcmp.rx_pn[queue])); + BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN != + IEEE80211_GCMP_PN_LEN); +- } else if (rx->key && ieee80211_has_protected(fc)) { ++ } else if (rx->key && ++ (ieee80211_has_protected(fc) || ++ (status->flag & RX_FLAG_DECRYPTED))) { + entry->is_protected = true; + entry->key_color = rx->key->color; + } +@@ -2216,13 +2219,19 @@ ieee80211_rx_h_defragment(struct ieee802 + return RX_DROP_UNUSABLE; + memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); + } else if (entry->is_protected && +- (!rx->key || !ieee80211_has_protected(fc) || ++ (!rx->key || ++ (!ieee80211_has_protected(fc) && ++ !(status->flag & RX_FLAG_DECRYPTED)) || + rx->key->color != entry->key_color)) { + /* Drop this as a mixed key or fragment cache attack, even + * if for TKIP Michael MIC should protect us, and WEP is a + * lost cause anyway. + */ + return RX_DROP_UNUSABLE; ++ } else if (entry->is_protected && rx->key && ++ entry->key_color != rx->key->color && ++ (status->flag & RX_FLAG_DECRYPTED)) { ++ return RX_DROP_UNUSABLE; + } + + skb_pull(rx->skb, ieee80211_hdrlen(fc)); diff --git a/queue-4.19/series b/queue-4.19/series index fafe3d83ff2..3ff788e7e00 100644 --- a/queue-4.19/series +++ b/queue-4.19/series @@ -16,3 +16,7 @@ mac80211-drop-a-msdus-on-old-ciphers.patch mac80211-add-fragment-cache-to-sta_info.patch mac80211-check-defrag-pn-against-current-frame.patch mac80211-prevent-attacks-on-tkip-wep-as-well.patch +mac80211-do-not-accept-forward-invalid-eapol-frames.patch +mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch +ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch +dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch -- 2.47.3