This applies the FragAttack patches also to ath10k-ct.

Signed-off-by: Hauke Mehrtens <[email protected]>
---

I do not have a ath10k device close here at the moment, it would be nice 
if someone could check if this works fine.

 package/kernel/ath10k-ct/Makefile             |   2 +-
 ...PN-replay-protection-for-fragmented-.patch | 180 ++++++++++++++++++
 ...fragments-with-multicast-DA-for-PCIe.patch |  66 +++++++
 ...fragments-with-multicast-DA-for-SDIO.patch |  40 ++++
 ...-which-has-discard-flag-set-by-firmw.patch |  54 ++++++
 ...IP-Michael-MIC-verification-for-PCIe.patch |  48 +++++
 ...first-subframe-of-A-MSDU-before-proc.patch | 109 +++++++++++
 7 files changed, 498 insertions(+), 1 deletion(-)
 create mode 100644 
package/kernel/ath10k-ct/patches/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
 create mode 100644 
package/kernel/ath10k-ct/patches/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch
 create mode 100644 
package/kernel/ath10k-ct/patches/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch
 create mode 100644 
package/kernel/ath10k-ct/patches/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch
 create mode 100644 
package/kernel/ath10k-ct/patches/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch
 create mode 100644 
package/kernel/ath10k-ct/patches/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch

diff --git a/package/kernel/ath10k-ct/Makefile 
b/package/kernel/ath10k-ct/Makefile
index a225bd8b191f..d6ad53fb5871 100644
--- a/package/kernel/ath10k-ct/Makefile
+++ b/package/kernel/ath10k-ct/Makefile
@@ -1,7 +1,7 @@
 include $(TOPDIR)/rules.mk
 
 PKG_NAME:=ath10k-ct
-PKG_RELEASE=2
+PKG_RELEASE=3
 
 PKG_LICENSE:=GPLv2
 PKG_LICENSE_FILES:=
diff --git 
a/package/kernel/ath10k-ct/patches/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
 
b/package/kernel/ath10k-ct/patches/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
new file mode 100644
index 000000000000..89d4237d3409
--- /dev/null
+++ 
b/package/kernel/ath10k-ct/patches/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
@@ -0,0 +1,180 @@
+From: Wen Gong <[email protected]>
+Date: Tue, 11 May 2021 20:02:52 +0200
+Subject: [PATCH] ath10k: add CCMP PN replay protection for fragmented
+ frames for PCIe
+
+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: [email protected]
+Signed-off-by: Wen Gong <[email protected]>
+Signed-off-by: Jouni Malinen <[email protected]>
+Signed-off-by: Johannes Berg <[email protected]>
+---
+
+--- a/ath10k-5.10/htt.h
++++ b/ath10k-5.10/htt.h
+@@ -853,6 +853,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 0x3F
+--- a/ath10k-5.10/htt_rx.c
++++ b/ath10k-5.10/htt_rx.c
+@@ -1841,16 +1841,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;
+@@ -1863,6 +1934,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;
+@@ -1970,6 +2042,24 @@ static void ath10k_htt_rx_h_mpdu(struct
+ #ifdef CONFIG_ATH10K_DEBUGFS
+               ar->debug.rx_bytes += msdu->len;
+ #endif
++              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);
+@@ -2186,7 +2276,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);
+ 
+@@ -3291,7 +3382,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:
diff --git 
a/package/kernel/ath10k-ct/patches/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch
 
b/package/kernel/ath10k-ct/patches/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch
new file mode 100644
index 000000000000..129cd894c072
--- /dev/null
+++ 
b/package/kernel/ath10k-ct/patches/301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch
@@ -0,0 +1,66 @@
+From: Wen Gong <[email protected]>
+Date: Tue, 11 May 2021 20:02:53 +0200
+Subject: [PATCH] ath10k: drop fragments with multicast DA for PCIe
+
+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: [email protected]
+Signed-off-by: Wen Gong <[email protected]>
+Signed-off-by: Jouni Malinen <[email protected]>
+Signed-off-by: Johannes Berg <[email protected]>
+---
+
+--- a/ath10k-5.10/htt_rx.c
++++ b/ath10k-5.10/htt_rx.c
+@@ -1863,6 +1863,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,
+@@ -1934,7 +1944,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;
+@@ -2050,13 +2060,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;
+               }
+ 
diff --git 
a/package/kernel/ath10k-ct/patches/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch
 
b/package/kernel/ath10k-ct/patches/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch
new file mode 100644
index 000000000000..cfd7365f1a43
--- /dev/null
+++ 
b/package/kernel/ath10k-ct/patches/302-ath10k-drop-fragments-with-multicast-DA-for-SDIO.patch
@@ -0,0 +1,40 @@
+From: Wen Gong <[email protected]>
+Date: Tue, 11 May 2021 20:02:54 +0200
+Subject: [PATCH] ath10k: drop fragments with multicast DA for SDIO
+
+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: [email protected]
+Signed-off-by: Wen Gong <[email protected]>
+Signed-off-by: Jouni Malinen <[email protected]>
+Signed-off-by: Johannes Berg <[email protected]>
+---
+
+--- a/ath10k-5.10/htt_rx.c
++++ b/ath10k-5.10/htt_rx.c
+@@ -2732,6 +2732,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,
+@@ -2739,8 +2746,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;
+ 
diff --git 
a/package/kernel/ath10k-ct/patches/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch
 
b/package/kernel/ath10k-ct/patches/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch
new file mode 100644
index 000000000000..311b57a12e54
--- /dev/null
+++ 
b/package/kernel/ath10k-ct/patches/303-ath10k-drop-MPDU-which-has-discard-flag-set-by-firmw.patch
@@ -0,0 +1,54 @@
+From: Wen Gong <[email protected]>
+Date: Tue, 11 May 2021 20:02:55 +0200
+Subject: [PATCH] ath10k: drop MPDU which has discard flag set by firmware
+ for SDIO
+
+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: [email protected]
+Signed-off-by: Wen Gong <[email protected]>
+Signed-off-by: Jouni Malinen <[email protected]>
+Signed-off-by: Johannes Berg <[email protected]>
+---
+
+--- a/ath10k-5.10/htt_rx.c
++++ b/ath10k-5.10/htt_rx.c
+@@ -2427,6 +2427,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/ath10k-5.10/rx_desc.h
++++ b/ath10k-5.10/rx_desc.h
+@@ -1283,7 +1283,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;
diff --git 
a/package/kernel/ath10k-ct/patches/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch
 
b/package/kernel/ath10k-ct/patches/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch
new file mode 100644
index 000000000000..f556e58eb198
--- /dev/null
+++ 
b/package/kernel/ath10k-ct/patches/304-ath10k-Fix-TKIP-Michael-MIC-verification-for-PCIe.patch
@@ -0,0 +1,48 @@
+From: Wen Gong <[email protected]>
+Date: Tue, 11 May 2021 20:02:56 +0200
+Subject: [PATCH] ath10k: Fix TKIP Michael MIC verification for PCIe
+
+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: [email protected]
+Signed-off-by: Wen Gong <[email protected]>
+Signed-off-by: Jouni Malinen <[email protected]>
+Signed-off-by: Johannes Berg <[email protected]>
+---
+
+--- a/ath10k-5.10/htt_rx.c
++++ b/ath10k-5.10/htt_rx.c
+@@ -2078,6 +2078,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);
+ 
+@@ -2095,6 +2100,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;
+       }
+ }
+ 
diff --git 
a/package/kernel/ath10k-ct/patches/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch
 
b/package/kernel/ath10k-ct/patches/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch
new file mode 100644
index 000000000000..ae1a5c9df95d
--- /dev/null
+++ 
b/package/kernel/ath10k-ct/patches/305-ath10k-Validate-first-subframe-of-A-MSDU-before-proc.patch
@@ -0,0 +1,109 @@
+From: Sriram R <[email protected]>
+Date: Tue, 11 May 2021 20:02:57 +0200
+Subject: [PATCH] ath10k: Validate first subframe of A-MSDU before
+ processing the list
+
+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: [email protected]
+Signed-off-by: Sriram R <[email protected]>
+Signed-off-by: Jouni Malinen <[email protected]>
+Signed-off-by: Johannes Berg <[email protected]>
+---
+
+--- a/ath10k-5.10/htt_rx.c
++++ b/ath10k-5.10/htt_rx.c
+@@ -2217,14 +2217,62 @@ static void ath10k_htt_rx_h_unchain(stru
+       ath10k_unchain_msdu(ar, 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");
+ #ifdef CONFIG_ATH10K_DEBUGFS
+@@ -2241,6 +2289,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;
+ }
+ 
-- 
2.30.2


_______________________________________________
openwrt-devel mailing list
[email protected]
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to