301-ath10k-drop-fragments-with-multicast-DA-for-PCIe.patch 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. From: Wen Gong <[email protected]>
  2. Date: Tue, 11 May 2021 20:02:53 +0200
  3. Subject: [PATCH] ath10k: drop fragments with multicast DA for PCIe
  4. Fragmentation is not used with multicast frames. Discard unexpected
  5. fragments with multicast DA. This fixes CVE-2020-26145.
  6. Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
  7. Cc: [email protected]
  8. Signed-off-by: Wen Gong <[email protected]>
  9. Signed-off-by: Jouni Malinen <[email protected]>
  10. Signed-off-by: Johannes Berg <[email protected]>
  11. ---
  12. --- a/drivers/net/wireless/ath/ath10k/htt_rx.c
  13. +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
  14. @@ -1768,6 +1768,16 @@ static u64 ath10k_htt_rx_h_get_pn(struct
  15. return pn;
  16. }
  17. +static bool ath10k_htt_rx_h_frag_multicast_check(struct ath10k *ar,
  18. + struct sk_buff *skb,
  19. + u16 offset)
  20. +{
  21. + struct ieee80211_hdr *hdr;
  22. +
  23. + hdr = (struct ieee80211_hdr *)(skb->data + offset);
  24. + return !is_multicast_ether_addr(hdr->addr1);
  25. +}
  26. +
  27. static bool ath10k_htt_rx_h_frag_pn_check(struct ath10k *ar,
  28. struct sk_buff *skb,
  29. u16 peer_id,
  30. @@ -1839,7 +1849,7 @@ static void ath10k_htt_rx_h_mpdu(struct
  31. bool is_decrypted;
  32. bool is_mgmt;
  33. u32 attention;
  34. - bool frag_pn_check = true;
  35. + bool frag_pn_check = true, multicast_check = true;
  36. if (skb_queue_empty(amsdu))
  37. return;
  38. @@ -1946,13 +1956,20 @@ static void ath10k_htt_rx_h_mpdu(struct
  39. 0,
  40. enctype);
  41. - if (!frag_pn_check) {
  42. - /* Discard the fragment with invalid PN */
  43. + if (frag)
  44. + multicast_check = ath10k_htt_rx_h_frag_multicast_check(ar,
  45. + msdu,
  46. + 0);
  47. +
  48. + if (!frag_pn_check || !multicast_check) {
  49. + /* Discard the fragment with invalid PN or multicast DA
  50. + */
  51. temp = msdu->prev;
  52. __skb_unlink(msdu, amsdu);
  53. dev_kfree_skb_any(msdu);
  54. msdu = temp;
  55. frag_pn_check = true;
  56. + multicast_check = true;
  57. continue;
  58. }