--- /dev/null
+From 2b8a1fee3488c602aca8bea004a087e60806a5cf Mon Sep 17 00:00:00 2001
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:45 +0200
+Subject: cfg80211: mitigate A-MSDU aggregation attacks
+
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+
+commit 2b8a1fee3488c602aca8bea004a087e60806a5cf upstream.
+
+Mitigate A-MSDU injection attacks (CVE-2020-24588) by detecting if the
+destination address of a subframe equals an RFC1042 (i.e., LLC/SNAP)
+header, and if so dropping the complete A-MSDU frame. This mitigates
+known attacks, although new (unknown) aggregation-based attacks may
+remain possible.
+
+This defense works because in A-MSDU aggregation injection attacks, a
+normal encrypted Wi-Fi frame is turned into an A-MSDU frame. This means
+the first 6 bytes of the first A-MSDU subframe correspond to an RFC1042
+header. In other words, the destination MAC address of the first A-MSDU
+subframe contains the start of an RFC1042 header during an aggregation
+attack. We can detect this and thereby prevent this specific attack.
+For details, see Section 7.2 of "Fragment and Forge: Breaking Wi-Fi
+Through Frame Aggregation and Fragmentation".
+
+Note that for kernel 4.9 and above this patch depends on "mac80211:
+properly handle A-MSDUs that start with a rfc1042 header". Otherwise
+this patch has no impact and attacks will remain possible.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Link: https://lore.kernel.org/r/20210511200110.25d93176ddaf.I9e265b597f2cd23eb44573f35b625947b386a9de@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/wireless/util.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -771,6 +771,9 @@ void ieee80211_amsdu_to_8023s(struct sk_
+ remaining = skb->len - offset;
+ if (subframe_len > remaining)
+ goto purge;
++ /* mitigate A-MSDU aggregation injection attacks */
++ if (ether_addr_equal(eth.h_dest, rfc1042_header))
++ goto purge;
+
+ offset += sizeof(struct ethhdr);
+ last = remaining <= subframe_len + padding;
--- /dev/null
+From 3a11ce08c45b50d69c891d71760b7c5b92074709 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:47 +0200
+Subject: mac80211: add fragment cache to sta_info
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 3a11ce08c45b50d69c891d71760b7c5b92074709 upstream.
+
+Prior patches protected against fragmentation cache attacks
+by coloring keys, but this shows that it can lead to issues
+when multiple stations use the same sequence number. Add a
+fragment cache to struct sta_info (in addition to the one in
+the interface) to separate fragments for different stations
+properly.
+
+This then automatically clear most of the fragment cache when a
+station disconnects (or reassociates) from an AP, or when client
+interfaces disconnect from the network, etc.
+
+On the way, also fix the comment there since this brings us in line
+with the recommendation in 802.11-2016 ("An AP should support ...").
+Additionally, remove a useless condition (since there's no problem
+purging an already empty list).
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210511200110.fc35046b0d52.I1ef101e3784d13e8f6600d83de7ec9a3a45bcd52@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/ieee80211_i.h | 26 ++++----------------------
+ net/mac80211/iface.c | 11 +++--------
+ net/mac80211/rx.c | 41 ++++++++++++++++++++++++++++++-----------
+ net/mac80211/sta_info.c | 6 +++++-
+ net/mac80211/sta_info.h | 32 +++++++++++++++++++++++++++++++-
+ 5 files changed, 73 insertions(+), 43 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -50,12 +50,6 @@ struct ieee80211_local;
+ #define IEEE80211_ENCRYPT_HEADROOM 8
+ #define IEEE80211_ENCRYPT_TAILROOM 18
+
+-/* IEEE 802.11 (Ch. 9.5 Defragmentation) requires support for concurrent
+- * reception of at least three fragmented frames. This limit can be increased
+- * by changing this define, at the cost of slower frame reassembly and
+- * increased memory use (about 2 kB of RAM per entry). */
+-#define IEEE80211_FRAGMENT_MAX 4
+-
+ /* power level hasn't been configured (or set to automatic) */
+ #define IEEE80211_UNSET_POWER_LEVEL INT_MIN
+
+@@ -88,19 +82,6 @@ extern const u8 ieee80211_ac_to_qos_mask
+
+ #define IEEE80211_MAX_NAN_INSTANCE_ID 255
+
+-struct ieee80211_fragment_entry {
+- struct sk_buff_head skb_list;
+- unsigned long first_frag_time;
+- u16 seq;
+- u16 extra_len;
+- u16 last_frag;
+- u8 rx_queue;
+- bool check_sequential_pn; /* needed for CCMP/GCMP */
+- u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+- unsigned int key_color;
+-};
+-
+-
+ struct ieee80211_bss {
+ u32 device_ts_beacon, device_ts_presp;
+
+@@ -907,9 +888,7 @@ struct ieee80211_sub_if_data {
+
+ char name[IFNAMSIZ];
+
+- /* Fragment table for host-based reassembly */
+- struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
+- unsigned int fragment_next;
++ struct ieee80211_fragment_cache frags;
+
+ /* TID bitmap for NoAck policy */
+ u16 noack_map;
+@@ -2328,4 +2307,7 @@ u32 ieee80211_calc_expected_tx_airtime(s
+ #define debug_noinline
+ #endif
+
++void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache);
++void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache);
++
+ #endif /* IEEE80211_I_H */
+--- a/net/mac80211/iface.c
++++ b/net/mac80211/iface.c
+@@ -8,7 +8,7 @@
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (c) 2016 Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+ */
+ #include <linux/slab.h>
+ #include <linux/kernel.h>
+@@ -679,16 +679,12 @@ static void ieee80211_set_multicast_list
+ */
+ static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata)
+ {
+- int i;
+-
+ /* free extra data */
+ ieee80211_free_keys(sdata, false);
+
+ ieee80211_debugfs_remove_netdev(sdata);
+
+- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+- __skb_queue_purge(&sdata->fragments[i].skb_list);
+- sdata->fragment_next = 0;
++ ieee80211_destroy_frag_cache(&sdata->frags);
+
+ if (ieee80211_vif_is_mesh(&sdata->vif))
+ ieee80211_mesh_teardown_sdata(sdata);
+@@ -1950,8 +1946,7 @@ int ieee80211_if_add(struct ieee80211_lo
+ sdata->wdev.wiphy = local->hw.wiphy;
+ sdata->local = local;
+
+- for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+- skb_queue_head_init(&sdata->fragments[i].skb_list);
++ ieee80211_init_frag_cache(&sdata->frags);
+
+ INIT_LIST_HEAD(&sdata->key_list);
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2133,19 +2133,34 @@ ieee80211_rx_h_decrypt(struct ieee80211_
+ return result;
+ }
+
++void ieee80211_init_frag_cache(struct ieee80211_fragment_cache *cache)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(cache->entries); i++)
++ skb_queue_head_init(&cache->entries[i].skb_list);
++}
++
++void ieee80211_destroy_frag_cache(struct ieee80211_fragment_cache *cache)
++{
++ int i;
++
++ for (i = 0; i < ARRAY_SIZE(cache->entries); i++)
++ __skb_queue_purge(&cache->entries[i].skb_list);
++}
++
+ static inline struct ieee80211_fragment_entry *
+-ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
++ieee80211_reassemble_add(struct ieee80211_fragment_cache *cache,
+ unsigned int frag, unsigned int seq, int rx_queue,
+ struct sk_buff **skb)
+ {
+ struct ieee80211_fragment_entry *entry;
+
+- entry = &sdata->fragments[sdata->fragment_next++];
+- if (sdata->fragment_next >= IEEE80211_FRAGMENT_MAX)
+- sdata->fragment_next = 0;
++ entry = &cache->entries[cache->next++];
++ if (cache->next >= IEEE80211_FRAGMENT_MAX)
++ cache->next = 0;
+
+- if (!skb_queue_empty(&entry->skb_list))
+- __skb_queue_purge(&entry->skb_list);
++ __skb_queue_purge(&entry->skb_list);
+
+ __skb_queue_tail(&entry->skb_list, *skb); /* no need for locking */
+ *skb = NULL;
+@@ -2160,14 +2175,14 @@ ieee80211_reassemble_add(struct ieee8021
+ }
+
+ static inline struct ieee80211_fragment_entry *
+-ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
++ieee80211_reassemble_find(struct ieee80211_fragment_cache *cache,
+ unsigned int frag, unsigned int seq,
+ int rx_queue, struct ieee80211_hdr *hdr)
+ {
+ struct ieee80211_fragment_entry *entry;
+ int i, idx;
+
+- idx = sdata->fragment_next;
++ idx = cache->next;
+ for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
+ struct ieee80211_hdr *f_hdr;
+ struct sk_buff *f_skb;
+@@ -2176,7 +2191,7 @@ ieee80211_reassemble_find(struct ieee802
+ if (idx < 0)
+ idx = IEEE80211_FRAGMENT_MAX - 1;
+
+- entry = &sdata->fragments[idx];
++ entry = &cache->entries[idx];
+ if (skb_queue_empty(&entry->skb_list) || entry->seq != seq ||
+ entry->rx_queue != rx_queue ||
+ entry->last_frag + 1 != frag)
+@@ -2217,6 +2232,7 @@ static bool requires_sequential_pn(struc
+ static ieee80211_rx_result debug_noinline
+ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
+ {
++ struct ieee80211_fragment_cache *cache = &rx->sdata->frags;
+ struct ieee80211_hdr *hdr;
+ u16 sc;
+ __le16 fc;
+@@ -2238,6 +2254,9 @@ ieee80211_rx_h_defragment(struct ieee802
+ goto out_no_led;
+ }
+
++ if (rx->sta)
++ cache = &rx->sta->frags;
++
+ if (likely(!ieee80211_has_morefrags(fc) && frag == 0))
+ goto out;
+
+@@ -2256,7 +2275,7 @@ ieee80211_rx_h_defragment(struct ieee802
+
+ if (frag == 0) {
+ /* This is the first fragment of a new frame. */
+- entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
++ entry = ieee80211_reassemble_add(cache, frag, seq,
+ rx->seqno_idx, &(rx->skb));
+ if (requires_sequential_pn(rx, fc)) {
+ int queue = rx->security_idx;
+@@ -2284,7 +2303,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ /* This is a fragment for a frame that should already be pending in
+ * fragment cache. Add this fragment to the end of the pending entry.
+ */
+- entry = ieee80211_reassemble_find(rx->sdata, frag, seq,
++ entry = ieee80211_reassemble_find(cache, frag, seq,
+ rx->seqno_idx, hdr);
+ if (!entry) {
+ I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
+--- a/net/mac80211/sta_info.c
++++ b/net/mac80211/sta_info.c
+@@ -4,7 +4,7 @@
+ * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright (C) 2015 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+ */
+
+ #include <linux/module.h>
+@@ -392,6 +392,8 @@ struct sta_info *sta_info_alloc(struct i
+
+ u64_stats_init(&sta->rx_stats.syncp);
+
++ ieee80211_init_frag_cache(&sta->frags);
++
+ sta->sta_state = IEEE80211_STA_NONE;
+
+ /* Mark TID as unreserved */
+@@ -1102,6 +1104,8 @@ static void __sta_info_destroy_part2(str
+
+ ieee80211_sta_debugfs_remove(sta);
+
++ ieee80211_destroy_frag_cache(&sta->frags);
++
+ cleanup_single_sta(sta);
+ }
+
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -3,7 +3,7 @@
+ * Copyright 2002-2005, Devicescape Software, Inc.
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015-2017 Intel Deutschland GmbH
+- * Copyright(c) 2020 Intel Corporation
++ * Copyright(c) 2020-2021 Intel Corporation
+ */
+
+ #ifndef STA_INFO_H
+@@ -437,6 +437,33 @@ struct ieee80211_sta_rx_stats {
+ };
+
+ /*
++ * IEEE 802.11-2016 (10.6 "Defragmentation") recommends support for "concurrent
++ * reception of at least one MSDU per access category per associated STA"
++ * on APs, or "at least one MSDU per access category" on other interface types.
++ *
++ * This limit can be increased by changing this define, at the cost of slower
++ * frame reassembly and increased memory use while fragments are pending.
++ */
++#define IEEE80211_FRAGMENT_MAX 4
++
++struct ieee80211_fragment_entry {
++ struct sk_buff_head skb_list;
++ unsigned long first_frag_time;
++ u16 seq;
++ u16 extra_len;
++ u16 last_frag;
++ u8 rx_queue;
++ bool check_sequential_pn; /* needed for CCMP/GCMP */
++ u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
++ unsigned int key_color;
++};
++
++struct ieee80211_fragment_cache {
++ struct ieee80211_fragment_entry entries[IEEE80211_FRAGMENT_MAX];
++ unsigned int next;
++};
++
++/*
+ * The bandwidth threshold below which the per-station CoDel parameters will be
+ * scaled to be more lenient (to prevent starvation of slow stations). This
+ * value will be scaled by the number of active stations when it is being
+@@ -529,6 +556,7 @@ struct ieee80211_sta_rx_stats {
+ * @status_stats.last_ack_signal: last ACK signal
+ * @status_stats.ack_signal_filled: last ACK signal validity
+ * @status_stats.avg_ack_signal: average ACK signal
++ * @frags: fragment cache
+ */
+ struct sta_info {
+ /* General information, mostly static */
+@@ -637,6 +665,8 @@ struct sta_info {
+
+ struct cfg80211_chan_def tdls_chandef;
+
++ struct ieee80211_fragment_cache frags;
++
+ /* keep last! */
+ struct ieee80211_sta sta;
+ };
--- /dev/null
+From bf30ca922a0c0176007e074b0acc77ed345e9990 Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:48 +0200
+Subject: mac80211: check defrag PN against current frame
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit bf30ca922a0c0176007e074b0acc77ed345e9990 upstream.
+
+As pointed out by Mathy Vanhoef, we implement the RX PN check
+on fragmented frames incorrectly - we check against the last
+received PN prior to the new frame, rather than to the one in
+this frame itself.
+
+Prior patches addressed the security issue here, but in order
+to be able to reason better about the code, fix it to really
+compare against the current frame's PN, not the last stored
+one.
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210511200110.bfbc340ff071.Id0b690e581da7d03d76df90bb0e3fd55930bc8a0@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/ieee80211_i.h | 11 +++++++++--
+ net/mac80211/rx.c | 5 ++---
+ net/mac80211/wpa.c | 13 +++++++++----
+ 3 files changed, 20 insertions(+), 9 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -223,8 +223,15 @@ struct ieee80211_rx_data {
+ */
+ int security_idx;
+
+- u32 tkip_iv32;
+- u16 tkip_iv16;
++ union {
++ struct {
++ u32 iv32;
++ u16 iv16;
++ } tkip;
++ struct {
++ u8 pn[IEEE80211_CCMP_PN_LEN];
++ } ccm_gcm;
++ };
+ };
+
+ struct ieee80211_csa_settings {
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2318,7 +2318,6 @@ ieee80211_rx_h_defragment(struct ieee802
+ if (entry->check_sequential_pn) {
+ int i;
+ u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
+- int queue;
+
+ if (!requires_sequential_pn(rx, fc))
+ return RX_DROP_UNUSABLE;
+@@ -2333,8 +2332,8 @@ ieee80211_rx_h_defragment(struct ieee802
+ if (pn[i])
+ break;
+ }
+- queue = rx->security_idx;
+- rpn = rx->key->u.ccmp.rx_pn[queue];
++
++ rpn = rx->ccm_gcm.pn;
+ if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
+ return RX_DROP_UNUSABLE;
+ memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
+--- a/net/mac80211/wpa.c
++++ b/net/mac80211/wpa.c
+@@ -3,6 +3,7 @@
+ * Copyright 2002-2004, Instant802 Networks, Inc.
+ * Copyright 2008, Jouni Malinen <j@w1.fi>
+ * Copyright (C) 2016-2017 Intel Deutschland GmbH
++ * Copyright (C) 2020-2021 Intel Corporation
+ */
+
+ #include <linux/netdevice.h>
+@@ -167,8 +168,8 @@ ieee80211_rx_h_michael_mic_verify(struct
+
+ update_iv:
+ /* update IV in key information to be able to detect replays */
+- rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip_iv32;
+- rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip_iv16;
++ rx->key->u.tkip.rx[rx->security_idx].iv32 = rx->tkip.iv32;
++ rx->key->u.tkip.rx[rx->security_idx].iv16 = rx->tkip.iv16;
+
+ return RX_CONTINUE;
+
+@@ -294,8 +295,8 @@ ieee80211_crypto_tkip_decrypt(struct iee
+ key, skb->data + hdrlen,
+ skb->len - hdrlen, rx->sta->sta.addr,
+ hdr->addr1, hwaccel, rx->security_idx,
+- &rx->tkip_iv32,
+- &rx->tkip_iv16);
++ &rx->tkip.iv32,
++ &rx->tkip.iv16);
+ if (res != TKIP_DECRYPT_OK)
+ return RX_DROP_UNUSABLE;
+
+@@ -553,6 +554,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee
+ }
+
+ memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN);
++ if (unlikely(ieee80211_is_frag(hdr)))
++ memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN);
+ }
+
+ /* Remove CCMP header and MIC */
+@@ -781,6 +784,8 @@ ieee80211_crypto_gcmp_decrypt(struct iee
+ }
+
+ memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN);
++ if (unlikely(ieee80211_is_frag(hdr)))
++ memcpy(rx->ccm_gcm.pn, pn, IEEE80211_CCMP_PN_LEN);
+ }
+
+ /* Remove GCMP header and MIC */
--- /dev/null
+From 270032a2a9c4535799736142e1e7c413ca7b836e Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:46 +0200
+Subject: mac80211: drop A-MSDUs on old ciphers
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 270032a2a9c4535799736142e1e7c413ca7b836e upstream.
+
+With old ciphers (WEP and TKIP) we shouldn't be using A-MSDUs
+since A-MSDUs are only supported if we know that they are, and
+the only practical way for that is HT support which doesn't
+support old ciphers.
+
+However, we would normally accept them anyway. Since we check
+the MMIC before deaggregating A-MSDUs, and the A-MSDU bit in
+the QoS header is not protected in TKIP (or WEP), this enables
+attacks similar to CVE-2020-24588. To prevent that, drop A-MSDUs
+completely with old ciphers.
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210511200110.076543300172.I548e6e71f1ee9cad4b9a37bf212ae7db723587aa@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -6,7 +6,7 @@
+ * Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
+ * Copyright 2013-2014 Intel Mobile Communications GmbH
+ * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
+- * Copyright (C) 2018-2020 Intel Corporation
++ * Copyright (C) 2018-2021 Intel Corporation
+ */
+
+ #include <linux/jiffies.h>
+@@ -2749,6 +2749,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
+ if (is_multicast_ether_addr(hdr->addr1))
+ return RX_DROP_UNUSABLE;
+
++ if (rx->key) {
++ /*
++ * We should not receive A-MSDUs on pre-HT connections,
++ * and HT connections cannot use old ciphers. Thus drop
++ * them, as in those cases we couldn't even have SPP
++ * A-MSDUs or such.
++ */
++ switch (rx->key->conf.cipher) {
++ case WLAN_CIPHER_SUITE_WEP40:
++ case WLAN_CIPHER_SUITE_WEP104:
++ case WLAN_CIPHER_SUITE_TKIP:
++ return RX_DROP_UNUSABLE;
++ default:
++ break;
++ }
++ }
++
+ return __ieee80211_rx_h_amsdu(rx, 0);
+ }
+
--- /dev/null
+From 7e44a0b597f04e67eee8cdcbe7ee706c6f5de38b Mon Sep 17 00:00:00 2001
+From: Johannes Berg <johannes.berg@intel.com>
+Date: Tue, 11 May 2021 20:02:49 +0200
+Subject: mac80211: prevent attacks on TKIP/WEP as well
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit 7e44a0b597f04e67eee8cdcbe7ee706c6f5de38b upstream.
+
+Similar to the issues fixed in previous patches, TKIP and WEP
+should be protected even if for TKIP we have the Michael MIC
+protecting it, and WEP is broken anyway.
+
+However, this also somewhat protects potential other algorithms
+that drivers might implement.
+
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20210511200110.430e8c202313.Ia37e4e5b6b3eaab1a5ae050e015f6c92859dbe27@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 12 ++++++++++++
+ net/mac80211/sta_info.h | 3 ++-
+ 2 files changed, 14 insertions(+), 1 deletion(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2284,6 +2284,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ * next fragment has a sequential PN value.
+ */
+ entry->check_sequential_pn = true;
++ entry->is_protected = true;
+ entry->key_color = rx->key->color;
+ memcpy(entry->last_pn,
+ rx->key->u.ccmp.rx_pn[queue],
+@@ -2296,6 +2297,9 @@ ieee80211_rx_h_defragment(struct ieee802
+ sizeof(rx->key->u.gcmp.rx_pn[queue]));
+ BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
+ IEEE80211_GCMP_PN_LEN);
++ } else if (rx->key && ieee80211_has_protected(fc)) {
++ entry->is_protected = true;
++ entry->key_color = rx->key->color;
+ }
+ return RX_QUEUED;
+ }
+@@ -2337,6 +2341,14 @@ ieee80211_rx_h_defragment(struct ieee802
+ if (memcmp(pn, rpn, IEEE80211_CCMP_PN_LEN))
+ return RX_DROP_UNUSABLE;
+ memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN);
++ } else if (entry->is_protected &&
++ (!rx->key || !ieee80211_has_protected(fc) ||
++ rx->key->color != entry->key_color)) {
++ /* Drop this as a mixed key or fragment cache attack, even
++ * if for TKIP Michael MIC should protect us, and WEP is a
++ * lost cause anyway.
++ */
++ return RX_DROP_UNUSABLE;
+ }
+
+ skb_pull(rx->skb, ieee80211_hdrlen(fc));
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -453,7 +453,8 @@ struct ieee80211_fragment_entry {
+ u16 extra_len;
+ u16 last_frag;
+ u8 rx_queue;
+- bool check_sequential_pn; /* needed for CCMP/GCMP */
++ u8 check_sequential_pn:1, /* needed for CCMP/GCMP */
++ is_protected:1;
+ u8 last_pn[6]; /* PN of the last fragment if CCMP was used */
+ unsigned int key_color;
+ };
--- /dev/null
+From a1d5ff5651ea592c67054233b14b30bf4452999c Mon Sep 17 00:00:00 2001
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Date: Tue, 11 May 2021 20:02:44 +0200
+Subject: mac80211: properly handle A-MSDUs that start with an RFC 1042 header
+
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+
+commit a1d5ff5651ea592c67054233b14b30bf4452999c upstream.
+
+Properly parse A-MSDUs whose first 6 bytes happen to equal a rfc1042
+header. This can occur in practice when the destination MAC address
+equals AA:AA:03:00:00:00. More importantly, this simplifies the next
+patch to mitigate A-MSDU injection attacks.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Link: https://lore.kernel.org/r/20210511200110.0b2b886492f0.I23dd5d685fe16d3b0ec8106e8f01b59f499dffed@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/net/cfg80211.h | 4 ++--
+ net/mac80211/rx.c | 2 +-
+ net/wireless/util.c | 4 ++--
+ 3 files changed, 5 insertions(+), 5 deletions(-)
+
+--- a/include/net/cfg80211.h
++++ b/include/net/cfg80211.h
+@@ -5624,7 +5624,7 @@ unsigned int ieee80211_get_mesh_hdrlen(s
+ */
+ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype,
+- u8 data_offset);
++ u8 data_offset, bool is_amsdu);
+
+ /**
+ * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3
+@@ -5636,7 +5636,7 @@ int ieee80211_data_to_8023_exthdr(struct
+ static inline int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+ enum nl80211_iftype iftype)
+ {
+- return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0);
++ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, 0, false);
+ }
+
+ /**
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2692,7 +2692,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
+ if (ieee80211_data_to_8023_exthdr(skb, ðhdr,
+ rx->sdata->vif.addr,
+ rx->sdata->vif.type,
+- data_offset))
++ data_offset, true))
+ return RX_DROP_UNUSABLE;
+
+ ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -541,7 +541,7 @@ EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen)
+
+ int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr,
+ const u8 *addr, enum nl80211_iftype iftype,
+- u8 data_offset)
++ u8 data_offset, bool is_amsdu)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ struct {
+@@ -629,7 +629,7 @@ int ieee80211_data_to_8023_exthdr(struct
+ skb_copy_bits(skb, hdrlen, &payload, sizeof(payload));
+ tmp.h_proto = payload.proto;
+
+- if (likely((ether_addr_equal(payload.hdr, rfc1042_header) &&
++ if (likely((!is_amsdu && ether_addr_equal(payload.hdr, rfc1042_header) &&
+ tmp.h_proto != htons(ETH_P_AARP) &&
+ tmp.h_proto != htons(ETH_P_IPX)) ||
+ ether_addr_equal(payload.hdr, bridge_tunnel_header)))
netfilter-nft_set_pipapo_avx2-add-irq_fpu_usable-check-fallback-to-non-avx2-version.patch
mac80211-assure-all-fragments-are-encrypted.patch
mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch
+mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch
+cfg80211-mitigate-a-msdu-aggregation-attacks.patch
+mac80211-drop-a-msdus-on-old-ciphers.patch
+mac80211-add-fragment-cache-to-sta_info.patch
+mac80211-check-defrag-pn-against-current-frame.patch
+mac80211-prevent-attacks-on-tkip-wep-as-well.patch
selftests-gpio-use-test_gen_progs_extended.patch
selftests-gpio-move-include-of-lib.mk-up.patch
selftests-gpio-fix-build-when-source-tree-is-read-on.patch