mac80211: Update to backports-5.10.42
[openwrt/staging/ynezz.git] / package / kernel / mac80211 / patches / ath / 300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
diff --git a/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch b/package/kernel/mac80211/patches/ath/300-ath10k-add-CCMP-PN-replay-protection-for-fragmented-.patch
deleted file mode 100644 (file)
index 0ce49b2..0000000
+++ /dev/null
@@ -1,180 +0,0 @@
-From: Wen Gong <wgong@codeaurora.org>
-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: stable@vger.kernel.org
-Signed-off-by: Wen Gong <wgong@codeaurora.org>
-Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
-Signed-off-by: Johannes Berg <johannes.berg@intel.com>
----
-
---- a/drivers/net/wireless/ath/ath10k/htt.h
-+++ b/drivers/net/wireless/ath/ath10k/htt.h
-@@ -846,6 +846,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
-@@ -1746,16 +1746,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;
-@@ -1768,6 +1839,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;
-@@ -1866,6 +1938,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);
-@@ -2071,7 +2161,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);
-@@ -3027,7 +3118,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: