--- /dev/null
+From a1166b2653db2f3de7338b9fb8a0f6e924b904ee Mon Sep 17 00:00:00 2001
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:52 +0200
+Subject: ath10k: add CCMP PN replay protection for fragmented frames for PCIe
+
+From: Wen Gong <wgong@codeaurora.org>
+
+commit a1166b2653db2f3de7338b9fb8a0f6e924b904ee upstream.
+
+PN replay check for not fragmented frames is finished in the firmware,
+but this was not done for fragmented frames when ath10k is used with
+QCA6174/QCA6377 PCIe. mac80211 has the function
+ieee80211_rx_h_defragment() for PN replay check for fragmented frames,
+but this does not get checked with QCA6174 due to the
+ieee80211_has_protected() condition not matching the cleared Protected
+bit case.
+
+Validate the PN of received fragmented frames within ath10k when CCMP is
+used and drop the fragment if the PN is not correct (incremented by
+exactly one from the previous fragment). This applies only for
+QCA6174/QCA6377 PCIe.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.9ba2664866a4.I756e47b67e210dba69966d989c4711ffc02dc6bc@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath10k/htt.h | 1
+ drivers/net/wireless/ath/ath10k/htt_rx.c | 99 +++++++++++++++++++++++++++++--
+ 2 files changed, 96 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath10k/htt.h
++++ b/drivers/net/wireless/ath/ath10k/htt.h
+@@ -835,6 +835,7 @@ enum htt_security_types {
+
+ #define ATH10K_HTT_TXRX_PEER_SECURITY_MAX 2
+ #define ATH10K_TXRX_NUM_EXT_TIDS 19
++#define ATH10K_TXRX_NON_QOS_TID 16
+
+ enum htt_security_flags {
+ #define HTT_SECURITY_TYPE_MASK 0x7F
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -1739,16 +1739,87 @@ static void ath10k_htt_rx_h_csum_offload
+ msdu->ip_summed = ath10k_htt_rx_get_csum_state(msdu);
+ }
+
++static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb,
++ u16 offset,
++ enum htt_rx_mpdu_encrypt_type enctype)
++{
++ struct ieee80211_hdr *hdr;
++ u64 pn = 0;
++ u8 *ehdr;
++
++ hdr = (struct ieee80211_hdr *)(skb->data + offset);
++ ehdr = skb->data + offset + ieee80211_hdrlen(hdr->frame_control);
++
++ if (enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) {
++ pn = ehdr[0];
++ pn |= (u64)ehdr[1] << 8;
++ pn |= (u64)ehdr[4] << 16;
++ pn |= (u64)ehdr[5] << 24;
++ pn |= (u64)ehdr[6] << 32;
++ pn |= (u64)ehdr[7] << 40;
++ }
++ return pn;
++}
++
++static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
++ struct sk_buff *skb,
++ u16 peer_id,
++ u16 offset,
++ enum htt_rx_mpdu_encrypt_type enctype)
++{
++ struct ath10k_peer *peer;
++ union htt_rx_pn_t *last_pn, new_pn = {0};
++ struct ieee80211_hdr *hdr;
++ bool more_frags;
++ u8 tid, frag_number;
++ u32 seq;
++
++ peer = ath10k_peer_find_by_id(ar, peer_id);
++ if (!peer) {
++ ath10k_dbg(ar, ATH10K_DBG_HTT, "invalid peer for frag pn check\n");
++ return false;
++ }
++
++ hdr = (struct ieee80211_hdr *)(skb->data + offset);
++ if (ieee80211_is_data_qos(hdr->frame_control))
++ tid = ieee80211_get_tid(hdr);
++ else
++ tid = ATH10K_TXRX_NON_QOS_TID;
++
++ last_pn = &peer->frag_tids_last_pn[tid];
++ new_pn.pn48 = ath10k_htt_rx_h_get_pn(ar, skb, offset, enctype);
++ more_frags = ieee80211_has_morefrags(hdr->frame_control);
++ frag_number = le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG;
++ seq = (__le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
++
++ if (frag_number == 0) {
++ last_pn->pn48 = new_pn.pn48;
++ peer->frag_tids_seq[tid] = seq;
++ } else {
++ if (seq != peer->frag_tids_seq[tid])
++ return false;
++
++ if (new_pn.pn48 != last_pn->pn48 + 1)
++ return false;
++
++ last_pn->pn48 = new_pn.pn48;
++ }
++
++ return true;
++}
++
+ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
+ struct sk_buff_head *amsdu,
+ struct ieee80211_rx_status *status,
+ bool fill_crypt_header,
+ u8 *rx_hdr,
+- enum ath10k_pkt_rx_err *err)
++ enum ath10k_pkt_rx_err *err,
++ u16 peer_id,
++ bool frag)
+ {
+ struct sk_buff *first;
+ struct sk_buff *last;
+- struct sk_buff *msdu;
++ struct sk_buff *msdu, *temp;
+ struct htt_rx_desc *rxd;
+ struct ieee80211_hdr *hdr;
+ enum htt_rx_mpdu_encrypt_type enctype;
+@@ -1761,6 +1832,7 @@ static void ath10k_htt_rx_h_mpdu(struct
+ bool is_decrypted;
+ bool is_mgmt;
+ u32 attention;
++ bool frag_pn_check = true;
+
+ if (skb_queue_empty(amsdu))
+ return;
+@@ -1859,6 +1931,24 @@ static void ath10k_htt_rx_h_mpdu(struct
+ }
+
+ skb_queue_walk(amsdu, msdu) {
++ if (frag && !fill_crypt_header && is_decrypted &&
++ enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
++ frag_pn_check = ath10k_htt_rx_h_frag_pn_check(ar,
++ msdu,
++ peer_id,
++ 0,
++ enctype);
++
++ if (!frag_pn_check) {
++ /* Discard the fragment with invalid PN */
++ temp = msdu->prev;
++ __skb_unlink(msdu, amsdu);
++ dev_kfree_skb_any(msdu);
++ msdu = temp;
++ frag_pn_check = true;
++ continue;
++ }
++
+ ath10k_htt_rx_h_csum_offload(msdu);
+ ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
+ is_decrypted);
+@@ -2064,7 +2154,8 @@ static int ath10k_htt_rx_handle_amsdu(st
+ ath10k_htt_rx_h_unchain(ar, &amsdu, &drop_cnt, &unchain_cnt);
+
+ ath10k_htt_rx_h_filter(ar, &amsdu, rx_status, &drop_cnt_filter);
+- ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err);
++ ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true, first_hdr, &err, 0,
++ false);
+ msdus_to_queue = skb_queue_len(&amsdu);
+ ath10k_htt_rx_h_enqueue(ar, &amsdu, rx_status);
+
+@@ -3014,7 +3105,7 @@ static int ath10k_htt_rx_in_ord_ind(stru
+ ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
+ ath10k_htt_rx_h_filter(ar, &amsdu, status, NULL);
+ ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false, NULL,
+- NULL);
++ NULL, peer_id, frag);
+ ath10k_htt_rx_h_enqueue(ar, &amsdu, status);
+ break;
+ case -EAGAIN:
--- /dev/null
+From 65c415a144ad8132b6a6d97d4a1919ffc728e2d1 Mon Sep 17 00:00:00 2001
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:53 +0200
+Subject: ath10k: drop fragments with multicast DA for PCIe
+
+From: Wen Gong <wgong@codeaurora.org>
+
+commit 65c415a144ad8132b6a6d97d4a1919ffc728e2d1 upstream.
+
+Fragmentation is not used with multicast frames. Discard unexpected
+fragments with multicast DA. This fixes CVE-2020-26145.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.5a0bd289bda8.Idd6ebea20038fb1cfee6de924aa595e5647c9eae@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath10k/htt_rx.c | 23 ++++++++++++++++++++---
+ 1 file changed, 20 insertions(+), 3 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -1761,6 +1761,16 @@ static u64 ath10k_htt_rx_h_get_pn(struct
+ return pn;
+ }
+
++static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar,
++ struct sk_buff *skb,
++ u16 offset)
++{
++ struct ieee80211_hdr *hdr;
++
++ hdr = (struct ieee80211_hdr *)(skb->data + offset);
++ return !is_multicast_ether_addr(hdr->addr1);
++}
++
+ static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
+ struct sk_buff *skb,
+ u16 peer_id,
+@@ -1832,7 +1842,7 @@ static void ath10k_htt_rx_h_mpdu(struct
+ bool is_decrypted;
+ bool is_mgmt;
+ u32 attention;
+- bool frag_pn_check = true;
++ bool frag_pn_check = true, multicast_check = true;
+
+ if (skb_queue_empty(amsdu))
+ return;
+@@ -1939,13 +1949,20 @@ static void ath10k_htt_rx_h_mpdu(struct
+ 0,
+ enctype);
+
+- if (!frag_pn_check) {
+- /* Discard the fragment with invalid PN */
++ if (frag)
++ multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar,
++ msdu,
++ 0);
++
++ if (!frag_pn_check || !multicast_check) {
++ /* Discard the fragment with invalid PN or multicast DA
++ */
+ temp = msdu->prev;
+ __skb_unlink(msdu, amsdu);
+ dev_kfree_skb_any(msdu);
+ msdu = temp;
+ frag_pn_check = true;
++ multicast_check = true;
+ continue;
+ }
+
--- /dev/null
+From 40e7462dad6f3d06efdb17d26539e61ab6e34db1 Mon Sep 17 00:00:00 2001
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:54 +0200
+Subject: ath10k: drop fragments with multicast DA for SDIO
+
+From: Wen Gong <wgong@codeaurora.org>
+
+commit 40e7462dad6f3d06efdb17d26539e61ab6e34db1 upstream.
+
+Fragmentation is not used with multicast frames. Discard unexpected
+fragments with multicast DA. This fixes CVE-2020-26145.
+
+Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.9ca6ca7945a9.I1e18b514590af17c155bda86699bc3a971a8dcf4@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath10k/htt_rx.c | 9 +++++++--
+ 1 file changed, 7 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -2605,6 +2605,13 @@ static bool ath10k_htt_rx_proc_rx_frag_i
+ rx_desc = (struct htt_hl_rx_desc *)(skb->data + tot_hdr_len);
+ rx_desc_info = __le32_to_cpu(rx_desc->info);
+
++ hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
++
++ if (is_multicast_ether_addr(hdr->addr1)) {
++ /* Discard the fragment with multicast DA */
++ goto err;
++ }
++
+ if (!MS(rx_desc_info, HTT_RX_DESC_HL_INFO_ENCRYPTED)) {
+ spin_unlock_bh(&ar->data_lock);
+ return ath10k_htt_rx_proc_rx_ind_hl(htt, &resp->rx_ind_hl, skb,
+@@ -2612,8 +2619,6 @@ static bool ath10k_htt_rx_proc_rx_frag_i
+ HTT_RX_NON_TKIP_MIC);
+ }
+
+- hdr = (struct ieee80211_hdr *)((u8 *)rx_desc + rx_hl->fw_desc.len);
+-
+ if (ieee80211_has_retry(hdr->frame_control))
+ goto err;
+
--- /dev/null
+From 079a108feba474b4b32bd3471db03e11f2f83b81 Mon Sep 17 00:00:00 2001
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:55 +0200
+Subject: ath10k: drop MPDU which has discard flag set by firmware for SDIO
+
+From: Wen Gong <wgong@codeaurora.org>
+
+commit 079a108feba474b4b32bd3471db03e11f2f83b81 upstream.
+
+When the discard flag is set by the firmware for an MPDU, it should be
+dropped. This allows a mitigation for CVE-2020-24588 to be implemented
+in the firmware.
+
+Tested-on: QCA6174 hw3.2 SDIO WLAN.RMH.4.4.1-00049
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.11968c725b5c.Idd166365ebea2771c0c0a38c78b5060750f90e17@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath10k/htt_rx.c | 5 +++++
+ drivers/net/wireless/ath/ath10k/rx_desc.h | 14 +++++++++++++-
+ 2 files changed, 18 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -2305,6 +2305,11 @@ static bool ath10k_htt_rx_proc_rx_ind_hl
+ fw_desc = &rx->fw_desc;
+ rx_desc_len = fw_desc->len;
+
++ if (fw_desc->u.bits.discard) {
++ ath10k_dbg(ar, ATH10K_DBG_HTT, "htt discard mpdu\n");
++ goto err;
++ }
++
+ /* I have not yet seen any case where num_mpdu_ranges > 1.
+ * qcacld does not seem handle that case either, so we introduce the
+ * same limitiation here as well.
+--- a/drivers/net/wireless/ath/ath10k/rx_desc.h
++++ b/drivers/net/wireless/ath/ath10k/rx_desc.h
+@@ -1282,7 +1282,19 @@ struct fw_rx_desc_base {
+ #define FW_RX_DESC_UDP (1 << 6)
+
+ struct fw_rx_desc_hl {
+- u8 info0;
++ union {
++ struct {
++ u8 discard:1,
++ forward:1,
++ any_err:1,
++ dup_err:1,
++ reserved:1,
++ inspect:1,
++ extension:2;
++ } bits;
++ u8 info0;
++ } u;
++
+ u8 version;
+ u8 len;
+ u8 flags;
--- /dev/null
+From 0dc267b13f3a7e8424a898815dd357211b737330 Mon Sep 17 00:00:00 2001
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:56 +0200
+Subject: ath10k: Fix TKIP Michael MIC verification for PCIe
+
+From: Wen Gong <wgong@codeaurora.org>
+
+commit 0dc267b13f3a7e8424a898815dd357211b737330 upstream.
+
+TKIP Michael MIC was not verified properly for PCIe cases since the
+validation steps in ieee80211_rx_h_michael_mic_verify() in mac80211 did
+not get fully executed due to unexpected flag values in
+ieee80211_rx_status.
+
+Fix this by setting the flags property to meet mac80211 expectations for
+performing Michael MIC validation there. This fixes CVE-2020-26141. It
+does the same as ath10k_htt_rx_proc_rx_ind_hl() for SDIO which passed
+MIC verification case. This applies only to QCA6174/QCA9377 PCIe.
+
+Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Wen Gong <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.c3f1d42c6746.I795593fcaae941c471425b8c7d5f7bb185d29142@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/net/wireless/ath/ath10k/htt_rx.c | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
++++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
+@@ -1967,6 +1967,11 @@ static void ath10k_htt_rx_h_mpdu(struct
+ }
+
+ ath10k_htt_rx_h_csum_offload(msdu);
++
++ if (frag && !fill_crypt_header &&
++ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
++ status->flag &= ~RX_FLAG_MMIC_STRIPPED;
++
+ ath10k_htt_rx_h_undecap(ar, msdu, status, first_hdr, enctype,
+ is_decrypted);
+
+@@ -1984,6 +1989,11 @@ static void ath10k_htt_rx_h_mpdu(struct
+
+ hdr = (void *)msdu->data;
+ hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
++
++ if (frag && !fill_crypt_header &&
++ enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA)
++ status->flag &= ~RX_FLAG_IV_STRIPPED &
++ ~RX_FLAG_MMIC_STRIPPED;
+ }
+ }
+
--- /dev/null
+From 62a8ff67eba52dae9b107e1fb8827054ed00a265 Mon Sep 17 00:00:00 2001
+From: Sriram R <srirrama@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:57 +0200
+Subject: ath10k: Validate first subframe of A-MSDU before processing the list
+
+From: Sriram R <srirrama@codeaurora.org>
+
+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 <srirrama@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.e6f5eb7b9847.I38a77ae26096862527a5eab73caebd7346af8b66@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -2101,14 +2101,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;
+@@ -2119,6 +2167,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;
+ }
+
--- /dev/null
+From 7e768532b2396bcb7fbf6f82384b85c0f1d2f197 Mon Sep 17 00:00:00 2001
+From: Mikulas Patocka <mpatocka@redhat.com>
+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 <mpatocka@redhat.com>
+
+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 <mpatocka@redhat.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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
+@@ -854,7 +854,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)
--- /dev/null
+From b95f045ea35673572ef46d6483ad8bd6d353d63c Mon Sep 17 00:00:00 2001
+From: James Zhu <James.Zhu@amd.com>
+Date: Tue, 18 May 2021 10:58:22 -0400
+Subject: drm/amdgpu/vcn1: add cancel_delayed_work_sync before power gate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: James Zhu <James.Zhu@amd.com>
+
+commit b95f045ea35673572ef46d6483ad8bd6d353d63c upstream.
+
+Add cancel_delayed_work_sync before set power gating state
+to avoid race condition issue when power gating.
+
+Signed-off-by: James Zhu <James.Zhu@amd.com>
+Reviewed-by: Leo Liu <leo.liu@amd.com>
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v1_0.c
+@@ -233,9 +233,13 @@ static int vcn_v1_0_hw_fini(void *handle
+ struct amdgpu_device *adev = (struct amdgpu_device *)handle;
+ struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
+
++ cancel_delayed_work_sync(&adev->vcn.idle_work);
++
+ if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
+- RREG32_SOC15(VCN, 0, mmUVD_STATUS))
++ (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
++ RREG32_SOC15(VCN, 0, mmUVD_STATUS))) {
+ vcn_v1_0_set_powergating_state(adev, AMD_PG_STATE_GATE);
++ }
+
+ ring->sched.ready = false;
+
--- /dev/null
+From 0c6013377b4027e69d8f3e63b6bf556b6cb87802 Mon Sep 17 00:00:00 2001
+From: James Zhu <James.Zhu@amd.com>
+Date: Wed, 19 May 2021 11:26:32 -0400
+Subject: drm/amdgpu/vcn2.0: add cancel_delayed_work_sync before power gate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: James Zhu <James.Zhu@amd.com>
+
+commit 0c6013377b4027e69d8f3e63b6bf556b6cb87802 upstream.
+
+Add cancel_delayed_work_sync before set power gating state
+to avoid race condition issue when power gating.
+
+Signed-off-by: James Zhu <James.Zhu@amd.com>
+Reviewed-by: Leo Liu <leo.liu@amd.com>
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+@@ -293,6 +293,8 @@ static int vcn_v2_0_hw_fini(void *handle
+ struct amdgpu_ring *ring = &adev->vcn.inst->ring_dec;
+ int i;
+
++ cancel_delayed_work_sync(&adev->vcn.idle_work);
++
+ if ((adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG) ||
+ (adev->vcn.cur_state != AMD_PG_STATE_GATE &&
+ RREG32_SOC15(VCN, 0, mmUVD_STATUS)))
--- /dev/null
+From 2fb536ea42d557f39f70c755f68e1aa1ad466c55 Mon Sep 17 00:00:00 2001
+From: James Zhu <James.Zhu@amd.com>
+Date: Wed, 19 May 2021 11:40:39 -0400
+Subject: drm/amdgpu/vcn2.5: add cancel_delayed_work_sync before power gate
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: James Zhu <James.Zhu@amd.com>
+
+commit 2fb536ea42d557f39f70c755f68e1aa1ad466c55 upstream.
+
+Add cancel_delayed_work_sync before set power gating state
+to avoid race condition issue when power gating.
+
+Signed-off-by: James Zhu <James.Zhu@amd.com>
+Reviewed-by: Leo Liu <leo.liu@amd.com>
+Acked-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
++++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+@@ -302,6 +302,8 @@ static int vcn_v2_5_hw_fini(void *handle
+ struct amdgpu_ring *ring;
+ int i;
+
++ cancel_delayed_work_sync(&adev->vcn.idle_work);
++
+ for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ if (adev->vcn.harvest_config & (1 << i))
+ continue;
--- /dev/null
+From a8c4d76a8dd4fb9666fc8919a703d85fb8f44ed8 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:50 +0200
+Subject: mac80211: do not accept/forward invalid EAPOL frames
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+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 <jouni@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.cb327ed0cabe.Ib7dcffa2a31f0913d660de65ba3c8aca75b1d10f@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 33 +++++++++++++++++++++++++++------
+ 1 file changed, 27 insertions(+), 6 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2484,13 +2484,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))
+@@ -2514,8 +2514,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);
+@@ -2555,6 +2575,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) {
--- /dev/null
+From 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 Mon Sep 17 00:00:00 2001
+From: Wen Gong <wgong@codeaurora.org>
+Date: Tue, 11 May 2021 20:02:51 +0200
+Subject: mac80211: extend protection against mixed key and fragment cache attacks
+
+From: Wen Gong <wgong@codeaurora.org>
+
+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 <wgong@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.037aa5ca0390.I7bb888e2965a0db02a67075fcb5deb50eb7408aa@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 13 +++++++++++--
+ 1 file changed, 11 insertions(+), 2 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2189,6 +2189,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;
+@@ -2247,7 +2248,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;
+ }
+@@ -2292,13 +2295,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));
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-add-ccmp-pn-replay-protection-for-fragmented-frames-for-pcie.patch
+ath10k-drop-fragments-with-multicast-da-for-pcie.patch
+ath10k-drop-fragments-with-multicast-da-for-sdio.patch
+ath10k-drop-mpdu-which-has-discard-flag-set-by-firmware-for-sdio.patch
+ath10k-fix-tkip-michael-mic-verification-for-pcie.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
+drm-amdgpu-vcn1-add-cancel_delayed_work_sync-before-power-gate.patch
+drm-amdgpu-vcn2.0-add-cancel_delayed_work_sync-before-power-gate.patch
+drm-amdgpu-vcn2.5-add-cancel_delayed_work_sync-before-power-gate.patch
selftests-gpio-use-test_gen_progs_extended.patch
selftests-gpio-move-include-of-lib.mk-up.patch
selftests-gpio-fix-build-when-source-tree-is-read-on.patch