Takashi Iwai 60e80e
From 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 Mon Sep 17 00:00:00 2001
Takashi Iwai 60e80e
From: Wen Gong <wgong@codeaurora.org>
Takashi Iwai 60e80e
Date: Tue, 11 May 2021 20:02:51 +0200
Takashi Iwai 60e80e
Subject: [PATCH] mac80211: extend protection against mixed key and fragment cache attacks
Takashi Iwai 60e80e
Git-commit: 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1
Takashi Iwai 60e80e
Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next.git
Takashi Iwai 60e80e
Patch-mainline: Queued in subsystem maintainer repo
Takashi Iwai 60e80e
References: CVE-2020-24586 bsc#1185859
Takashi Iwai 60e80e
Takashi Iwai 60e80e
For some chips/drivers, e.g., QCA6174 with ath10k, the decryption is
Takashi Iwai 60e80e
done by the hardware, and the Protected bit in the Frame Control field
Takashi Iwai 60e80e
is cleared in the lower level driver before the frame is passed to
Takashi Iwai 60e80e
mac80211. In such cases, the condition for ieee80211_has_protected() is
Takashi Iwai 60e80e
not met in ieee80211_rx_h_defragment() of mac80211 and the new security
Takashi Iwai 60e80e
validation steps are not executed.
Takashi Iwai 60e80e
Takashi Iwai 60e80e
Extend mac80211 to cover the case where the Protected bit has been
Takashi Iwai 60e80e
cleared, but the frame is indicated as having been decrypted by the
Takashi Iwai 60e80e
hardware. This extends protection against mixed key and fragment cache
Takashi Iwai 60e80e
attack for additional drivers/chips. This fixes CVE-2020-24586 and
Takashi Iwai 60e80e
CVE-2020-24587 for such cases.
Takashi Iwai 60e80e
Takashi Iwai 60e80e
Tested-on: QCA6174 hw3.2 PCI WLAN.RM.4.4.1-00110-QCARMSWP-1
Takashi Iwai 60e80e
Takashi Iwai 60e80e
Cc: stable@vger.kernel.org
Takashi Iwai 60e80e
Signed-off-by: Wen Gong <wgong@codeaurora.org>
Takashi Iwai 60e80e
Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
Takashi Iwai 60e80e
Link: https://lore.kernel.org/r/20210511200110.037aa5ca0390.I7bb888e2965a0db02a67075fcb5deb50eb7408aa@changeid
Takashi Iwai 60e80e
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Takashi Iwai 60e80e
Acked-by: Takashi Iwai <tiwai@suse.de>
Takashi Iwai 60e80e
Takashi Iwai 60e80e
---
Takashi Iwai 60e80e
 net/mac80211/rx.c | 13 +++++++++++--
Takashi Iwai 60e80e
 1 file changed, 11 insertions(+), 2 deletions(-)
Takashi Iwai 60e80e
Takashi Iwai 60e80e
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
Takashi Iwai 60e80e
index 22a925899a9e..1bb43edd47b6 100644
Takashi Iwai 60e80e
--- a/net/mac80211/rx.c
Takashi Iwai 60e80e
+++ b/net/mac80211/rx.c
Takashi Iwai 60e80e
@@ -2229,6 +2229,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
Takashi Iwai 60e80e
 	unsigned int frag, seq;
Takashi Iwai 60e80e
 	struct ieee80211_fragment_entry *entry;
Takashi Iwai 60e80e
 	struct sk_buff *skb;
Takashi Iwai 60e80e
+	struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
Takashi Iwai 60e80e
 
Takashi Iwai 60e80e
 	hdr = (struct ieee80211_hdr *)rx->skb->data;
Takashi Iwai 60e80e
 	fc = hdr->frame_control;
Takashi Iwai 60e80e
@@ -2287,7 +2288,9 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
Takashi Iwai 60e80e
 				     sizeof(rx->key->u.gcmp.rx_pn[queue]));
Takashi Iwai 60e80e
 			BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
Takashi Iwai 60e80e
 				     IEEE80211_GCMP_PN_LEN);
Takashi Iwai 60e80e
-		} else if (rx->key && ieee80211_has_protected(fc)) {
Takashi Iwai 60e80e
+		} else if (rx->key &&
Takashi Iwai 60e80e
+			   (ieee80211_has_protected(fc) ||
Takashi Iwai 60e80e
+			    (status->flag & RX_FLAG_DECRYPTED))) {
Takashi Iwai 60e80e
 			entry->is_protected = true;
Takashi Iwai 60e80e
 			entry->key_color = rx->key->color;
Takashi Iwai 60e80e
 		}
Takashi Iwai 60e80e
@@ -2332,13 +2335,19 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
Takashi Iwai 60e80e
 			return RX_DROP_UNUSABLE;
Takashi Iwai 60e80e
 		memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
Takashi Iwai 60e80e
 	} else if (entry->is_protected &&
Takashi Iwai 60e80e
-		   (!rx->key || !ieee80211_has_protected(fc) ||
Takashi Iwai 60e80e
+		   (!rx->key ||
Takashi Iwai 60e80e
+		    (!ieee80211_has_protected(fc) &&
Takashi Iwai 60e80e
+		     !(status->flag & RX_FLAG_DECRYPTED)) ||
Takashi Iwai 60e80e
 		    rx->key->color != entry->key_color)) {
Takashi Iwai 60e80e
 		/* Drop this as a mixed key or fragment cache attack, even
Takashi Iwai 60e80e
 		 * if for TKIP Michael MIC should protect us, and WEP is a
Takashi Iwai 60e80e
 		 * lost cause anyway.
Takashi Iwai 60e80e
 		 */
Takashi Iwai 60e80e
 		return RX_DROP_UNUSABLE;
Takashi Iwai 60e80e
+	} else if (entry->is_protected && rx->key &&
Takashi Iwai 60e80e
+		   entry->key_color != rx->key->color &&
Takashi Iwai 60e80e
+		   (status->flag & RX_FLAG_DECRYPTED)) {
Takashi Iwai 60e80e
+		return RX_DROP_UNUSABLE;
Takashi Iwai 60e80e
 	}
Takashi Iwai 60e80e
 
Takashi Iwai 60e80e
 	skb_pull(rx->skb, ieee80211_hdrlen(fc));
Takashi Iwai 60e80e
-- 
Takashi Iwai 60e80e
2.26.2
Takashi Iwai 60e80e