Commit 65c415a1 authored by Wen Gong's avatar Wen Gong Committed by Johannes Berg
Browse files

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: stable@vger.kernel.org
Signed-off-by: default avatarWen Gong <wgong@codeaurora.org>
Signed-off-by: default avatarJouni Malinen <jouni@codeaurora.org>
Link: https://lore.kernel.org/r/20210511200110.5a0bd289bda8.Idd6ebea20038fb1cfee6de924aa595e5647c9eae@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent a1166b26
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -1768,6 +1768,16 @@ static u64 ath10k_htt_rx_h_get_pn(struct ath10k *ar, struct sk_buff *skb,
	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,
@@ -1839,7 +1849,7 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
	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;
@@ -1946,13 +1956,20 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
								      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;
		}