--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:28 +0200
+Subject: cfg80211: mitigate A-MSDU aggregation attacks
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Message-ID: <20210531202834.179810-5-johannes@sipsolutions.net>
+
+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
+@@ -689,6 +689,9 @@ void ieee80211_amsdu_to_8023s(struct sk_
+ /* the last MSDU has no padding */
+ if (subframe_len > remaining)
+ goto purge;
++ /* mitigate A-MSDU aggregation injection attacks */
++ if (ether_addr_equal(eth->h_dest, rfc1042_header))
++ goto purge;
+
+ skb_pull(skb, sizeof(struct ethhdr));
+ /* reuse skb for the last subframe */
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:30 +0200
+Subject: mac80211: add fragment cache to sta_info
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Johannes Berg <johannes.berg@intel.com>
+Message-ID: <20210531202834.179810-7-johannes@sipsolutions.net>
+
+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 | 9 ++-------
+ net/mac80211/rx.c | 41 ++++++++++++++++++++++++++++++-----------
+ net/mac80211/sta_info.c | 4 ++++
+ net/mac80211/sta_info.h | 30 ++++++++++++++++++++++++++++++
+ 5 files changed, 70 insertions(+), 40 deletions(-)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -51,12 +51,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
+
+@@ -85,19 +79,6 @@ struct ieee80211_local;
+
+ #define IEEE80211_DEAUTH_FRAME_LEN (24 /* hdr */ + 2 /* reason */)
+
+-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;
+
+@@ -835,9 +816,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;
+@@ -2077,4 +2056,7 @@ extern const struct ethtool_ops ieee8021
+ #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
+@@ -1082,16 +1082,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))
+ mesh_rmc_free(sdata);
+@@ -1787,8 +1783,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
+@@ -1738,19 +1738,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;
+@@ -1765,14 +1780,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;
+
+@@ -1780,7 +1795,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)
+@@ -1820,6 +1835,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;
+@@ -1842,6 +1858,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;
+
+@@ -1860,7 +1879,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;
+@@ -1888,7 +1907,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
+@@ -355,6 +355,8 @@ struct sta_info *sta_info_alloc(struct i
+ sta->sdata = sdata;
+ sta->rx_stats.last_rx = jiffies;
+
++ ieee80211_init_frag_cache(&sta->frags);
++
+ sta->sta_state = IEEE80211_STA_NONE;
+
+ /* Mark TID as unreserved */
+@@ -974,6 +976,8 @@ static void __sta_info_destroy_part2(str
+ ieee80211_sta_debugfs_remove(sta);
+ ieee80211_recalc_min_chandef(sdata);
+
++ ieee80211_destroy_frag_cache(&sta->frags);
++
+ cleanup_single_sta(sta);
+ }
+
+--- a/net/mac80211/sta_info.h
++++ b/net/mac80211/sta_info.h
+@@ -324,6 +324,33 @@ struct mesh_sta {
+
+ DECLARE_EWMA(signal, 1024, 8)
+
++/*
++ * 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;
++};
++
+ /**
+ * struct sta_info - STA information
+ *
+@@ -384,6 +411,7 @@ DECLARE_EWMA(signal, 1024, 8)
+ * @tx_stats: TX statistics
+ * @rx_stats: RX statistics
+ * @status_stats: TX status statistics
++ * @frags: fragment cache
+ */
+ struct sta_info {
+ /* General information, mostly static */
+@@ -493,6 +521,8 @@ struct sta_info {
+
+ struct cfg80211_chan_def tdls_chandef;
+
++ struct ieee80211_fragment_cache frags;
++
+ /* keep last! */
+ struct ieee80211_sta sta;
+ };
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:25 +0200
+Subject: mac80211: assure all fragments are encrypted
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Message-ID: <20210531202834.179810-2-johannes@sipsolutions.net>
+
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+
+commit 965a7d72e798eb7af0aa67210e37cf7ecd1c9cad upstream.
+
+Do not mix plaintext and encrypted fragments in protected Wi-Fi
+networks. This fixes CVE-2020-26147.
+
+Previously, an attacker was able to first forward a legitimate encrypted
+fragment towards a victim, followed by a plaintext fragment. The
+encrypted and plaintext fragment would then be reassembled. For further
+details see Section 6.3 and Appendix D in the paper "Fragment and Forge:
+Breaking Wi-Fi Through Frame Aggregation and Fragmentation".
+
+Because of this change there are now two equivalent conditions in the
+code to determine if a received fragment requires sequential PNs, so we
+also move this test to a separate function to make the code easier to
+maintain.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Link: https://lore.kernel.org/r/20210511200110.30c4394bb835.I5acfdb552cc1d20c339c262315950b3eac491397@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 23 ++++++++++++-----------
+ 1 file changed, 12 insertions(+), 11 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1807,6 +1807,16 @@ ieee80211_reassemble_find(struct ieee802
+ return NULL;
+ }
+
++static bool requires_sequential_pn(struct ieee80211_rx_data *rx, __le16 fc)
++{
++ return rx->key &&
++ (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
++ rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
++ ieee80211_has_protected(fc);
++}
++
+ static ieee80211_rx_result debug_noinline
+ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
+ {
+@@ -1852,12 +1862,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ /* This is the first fragment of a new frame. */
+ entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
+ rx->seqno_idx, &(rx->skb));
+- if (rx->key &&
+- (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
+- rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
+- rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
+- rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
+- ieee80211_has_protected(fc)) {
++ if (requires_sequential_pn(rx, fc)) {
+ int queue = rx->security_idx;
+
+ /* Store CCMP/GCMP PN so that we can verify that the
+@@ -1899,11 +1904,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
+ int queue;
+
+- if (!rx->key ||
+- (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
+- rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
+- rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
+- rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
++ if (!requires_sequential_pn(rx, fc))
+ return RX_DROP_UNUSABLE;
+ memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+ for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:31 +0200
+Subject: mac80211: check defrag PN against current frame
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Johannes Berg <johannes.berg@intel.com>
+Message-ID: <20210531202834.179810-8-johannes@sipsolutions.net>
+
+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>
+---
+ include/linux/ieee80211.h | 10 ++++++++++
+ net/mac80211/ieee80211_i.h | 11 +++++++++--
+ net/mac80211/rx.c | 5 ++---
+ net/mac80211/wpa.c | 12 ++++++++----
+ 4 files changed, 29 insertions(+), 9 deletions(-)
+
+--- a/include/linux/ieee80211.h
++++ b/include/linux/ieee80211.h
+@@ -638,6 +638,16 @@ static inline bool ieee80211_is_first_fr
+ return (seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0;
+ }
+
++/**
++ * ieee80211_is_frag - check if a frame is a fragment
++ * @hdr: 802.11 header of the frame
++ */
++static inline bool ieee80211_is_frag(struct ieee80211_hdr *hdr)
++{
++ return ieee80211_has_morefrags(hdr->frame_control) ||
++ hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG);
++}
++
+ struct ieee80211s_hdr {
+ u8 flags;
+ u8 ttl;
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -218,8 +218,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
+@@ -1922,7 +1922,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;
+@@ -1937,8 +1936,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
+@@ -161,8 +161,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;
+
+@@ -292,8 +292,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 +553,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 */
+@@ -784,6 +786,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 foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:33 +0200
+Subject: mac80211: do not accept/forward invalid EAPOL frames
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Johannes Berg <johannes.berg@intel.com>, Jouni Malinen <jouni@codeaurora.org>
+Message-ID: <20210531202834.179810-10-johannes@sipsolutions.net>
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+commit a8c4d76a8dd4fb9666fc8919a703d85fb8f44ed8 upstream.
+
+EAPOL frames are used for authentication and key management between the
+AP and each individual STA associated in the BSS. Those frames are not
+supposed to be sent by one associated STA to another associated STA
+(either unicast for broadcast/multicast).
+
+Similarly, in 802.11 they're supposed to be sent to the authenticator
+(AP) address.
+
+Since it is possible for unexpected EAPOL frames to result in misbehavior
+in supplicant implementations, it is better for the AP to not allow such
+cases to be forwarded to other clients either directly, or indirectly if
+the AP interface is part of a bridge.
+
+Accept EAPOL (control port) frames only if they're transmitted to the
+own address, or, due to interoperability concerns, to the PAE group
+address.
+
+Disable forwarding of EAPOL (or well, the configured control port
+protocol) frames back to wireless medium in all cases. Previously, these
+frames were accepted from fully authenticated and authorized stations
+and also from unauthenticated stations for one of the cases.
+
+Additionally, to avoid forwarding by the bridge, rewrite the PAE group
+address case to the local MAC address.
+
+Cc: stable@vger.kernel.org
+Co-developed-by: Jouni Malinen <jouni@codeaurora.org>
+Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
+Link: https://lore.kernel.org/r/20210511200110.cb327ed0cabe.Ib7dcffa2a31f0913d660de65ba3c8aca75b1d10f@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 34 ++++++++++++++++++++++++++++------
+ 1 file changed, 28 insertions(+), 6 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2141,13 +2141,13 @@ static bool ieee80211_frame_allowed(stru
+ struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
+
+ /*
+- * Allow EAPOL frames to us/the PAE group address regardless
+- * of whether the frame was encrypted or not.
++ * Allow EAPOL frames to us/the PAE group address regardless of
++ * whether the frame was encrypted or not, and always disallow
++ * all other destination addresses for them.
+ */
+- if (ehdr->h_proto == rx->sdata->control_port_protocol &&
+- (ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
+- ether_addr_equal(ehdr->h_dest, pae_group_addr)))
+- return true;
++ if (unlikely(ehdr->h_proto == rx->sdata->control_port_protocol))
++ return ether_addr_equal(ehdr->h_dest, rx->sdata->vif.addr) ||
++ ether_addr_equal(ehdr->h_dest, pae_group_addr);
+
+ if (ieee80211_802_1x_port_control(rx) ||
+ ieee80211_drop_unencrypted(rx, fc))
+@@ -2176,6 +2176,7 @@ ieee80211_deliver_skb(struct ieee80211_r
+ if ((sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+ !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
++ ehdr->h_proto != rx->sdata->control_port_protocol &&
+ (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
+ if (is_multicast_ether_addr(ehdr->h_dest)) {
+ /*
+@@ -2228,9 +2229,30 @@ ieee80211_deliver_skb(struct ieee80211_r
+ #endif
+
+ if (skb) {
++ struct ethhdr *ehdr = (void *)skb_mac_header(skb);
++
+ /* deliver to local stack */
+ skb->protocol = eth_type_trans(skb, dev);
+ memset(skb->cb, 0, sizeof(skb->cb));
++
++ /*
++ * 802.1X over 802.11 requires that the authenticator address
++ * be used for EAPOL frames. However, 802.1X allows the use of
++ * the PAE group address instead. If the interface is part of
++ * a bridge and we pass the frame with the PAE group address,
++ * then the bridge will forward it to the network (even if the
++ * client was not associated yet), which isn't supposed to
++ * happen.
++ * To avoid that, rewrite the destination address to our own
++ * address, so that the authenticator (e.g. hostapd) will see
++ * the frame, but bridge won't forward it anywhere else. Note
++ * that due to earlier filtering, the only other address can
++ * be the PAE group address.
++ */
++ if (unlikely(skb->protocol == sdata->control_port_protocol &&
++ !ether_addr_equal(ehdr->h_dest, sdata->vif.addr)))
++ ether_addr_copy(ehdr->h_dest, sdata->vif.addr);
++
+ if (rx->napi)
+ napi_gro_receive(rx->napi, skb);
+ else
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:29 +0200
+Subject: mac80211: drop A-MSDUs on old ciphers
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Johannes Berg <johannes.berg@intel.com>
+Message-ID: <20210531202834.179810-6-johannes@sipsolutions.net>
+
+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 | 17 +++++++++++++++++
+ 1 file changed, 17 insertions(+)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -2264,6 +2264,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx
+ if (skb_linearize(skb))
+ 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;
++ }
++ }
++
+ ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
+ rx->sdata->vif.type,
+ rx->local->hw.extra_tx_headroom, true);
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:34 +0200
+Subject: mac80211: extend protection against mixed key and fragment cache attacks
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Wen Gong <wgong@codeaurora.org>
+Message-ID: <20210531202834.179810-11-johannes@sipsolutions.net>
+
+From: Wen Gong <wgong@codeaurora.org>
+
+commit 3edc6b0d6c061a70d8ca3c3c72eb1f58ce29bfb1 upstream.
+
+For some chips/drivers, e.g., QCA6174 with ath10k, the decryption is
+done by the hardware, and the Protected bit in the Frame Control field
+is cleared in the lower level driver before the frame is passed to
+mac80211. In such cases, the condition for ieee80211_has_protected() is
+not met in ieee80211_rx_h_defragment() of mac80211 and the new security
+validation steps are not executed.
+
+Extend mac80211 to cover the case where the Protected bit has been
+cleared, but the frame is indicated as having been decrypted by the
+hardware. This extends protection against mixed key and fragment cache
+attack for additional drivers/chips. This fixes CVE-2020-24586 and
+CVE-2020-24587 for such cases.
+
+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>
+Link: https://lore.kernel.org/r/20210511200110.037aa5ca0390.I7bb888e2965a0db02a67075fcb5deb50eb7408aa@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/rx.c | 14 +++++++++++---
+ 1 file changed, 11 insertions(+), 3 deletions(-)
+
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1842,7 +1842,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ unsigned int frag, seq;
+ struct ieee80211_fragment_entry *entry;
+ struct sk_buff *skb;
+- struct ieee80211_rx_status *status;
++ struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
+
+ hdr = (struct ieee80211_hdr *)rx->skb->data;
+ fc = hdr->frame_control;
+@@ -1901,7 +1901,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)) {
++ } else if (rx->key &&
++ (ieee80211_has_protected(fc) ||
++ (status->flag & RX_FLAG_DECRYPTED))) {
+ entry->is_protected = true;
+ entry->key_color = rx->key->color;
+ }
+@@ -1946,13 +1948,19 @@ ieee80211_rx_h_defragment(struct ieee802
+ 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 ||
++ (!ieee80211_has_protected(fc) &&
++ !(status->flag & RX_FLAG_DECRYPTED)) ||
+ 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;
++ } else if (entry->is_protected && rx->key &&
++ entry->key_color != rx->key->color &&
++ (status->flag & RX_FLAG_DECRYPTED)) {
++ return RX_DROP_UNUSABLE;
+ }
+
+ skb_pull(rx->skb, ieee80211_hdrlen(fc));
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:32 +0200
+Subject: mac80211: prevent attacks on TKIP/WEP as well
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Johannes Berg <johannes.berg@intel.com>
+Message-ID: <20210531202834.179810-9-johannes@sipsolutions.net>
+
+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
+@@ -1888,6 +1888,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],
+@@ -1900,6 +1901,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;
+ }
+@@ -1941,6 +1945,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
+@@ -341,7 +341,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 foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:26 +0200
+Subject: mac80211: prevent mixed key and fragment cache attacks
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Message-ID: <20210531202834.179810-3-johannes@sipsolutions.net>
+
+From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+
+commit 94034c40ab4a3fcf581fbc7f8fdf4e29943c4a24 upstream.
+
+Simultaneously prevent mixed key attacks (CVE-2020-24587) and fragment
+cache attacks (CVE-2020-24586). This is accomplished by assigning a
+unique color to every key (per interface) and using this to track which
+key was used to decrypt a fragment. When reassembling frames, it is
+now checked whether all fragments were decrypted using the same key.
+
+To assure that fragment cache attacks are also prevented, the ID that is
+assigned to keys is unique even over (re)associations and (re)connects.
+This means fragments separated by a (re)association or (re)connect will
+not be reassembled. Because mac80211 now also prevents the reassembly of
+mixed encrypted and plaintext fragments, all cache attacks are prevented.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Link: https://lore.kernel.org/r/20210511200110.3f8290e59823.I622a67769ed39257327a362cfc09c812320eb979@changeid
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/mac80211/ieee80211_i.h | 1 +
+ net/mac80211/key.c | 7 +++++++
+ net/mac80211/key.h | 2 ++
+ net/mac80211/rx.c | 6 ++++++
+ 4 files changed, 16 insertions(+)
+
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -94,6 +94,7 @@ struct ieee80211_fragment_entry {
+ 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;
+ };
+
+
+--- a/net/mac80211/key.c
++++ b/net/mac80211/key.c
+@@ -646,6 +646,7 @@ int ieee80211_key_link(struct ieee80211_
+ struct sta_info *sta)
+ {
+ struct ieee80211_local *local = sdata->local;
++ static atomic_t key_color = ATOMIC_INIT(0);
+ struct ieee80211_key *old_key;
+ int idx = key->conf.keyidx;
+ bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE;
+@@ -680,6 +681,12 @@ int ieee80211_key_link(struct ieee80211_
+ key->sdata = sdata;
+ key->sta = sta;
+
++ /*
++ * Assign a unique ID to every key so we can easily prevent mixed
++ * key and fragment cache attacks.
++ */
++ key->color = atomic_inc_return(&key_color);
++
+ increment_tailroom_need_count(sdata);
+
+ ieee80211_key_replace(sdata, sta, pairwise, old_key, key);
+--- a/net/mac80211/key.h
++++ b/net/mac80211/key.h
+@@ -123,6 +123,8 @@ struct ieee80211_key {
+ } debugfs;
+ #endif
+
++ unsigned int color;
++
+ /*
+ * key config, must be last because it contains key
+ * material as variable length member
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -1869,6 +1869,7 @@ ieee80211_rx_h_defragment(struct ieee802
+ * next fragment has a sequential PN value.
+ */
+ entry->check_sequential_pn = true;
++ entry->key_color = rx->key->color;
+ memcpy(entry->last_pn,
+ rx->key->u.ccmp.rx_pn[queue],
+ IEEE80211_CCMP_PN_LEN);
+@@ -1906,6 +1907,11 @@ ieee80211_rx_h_defragment(struct ieee802
+
+ if (!requires_sequential_pn(rx, fc))
+ return RX_DROP_UNUSABLE;
++
++ /* Prevent mixed key and fragment cache attacks */
++ if (entry->key_color != rx->key->color)
++ return RX_DROP_UNUSABLE;
++
+ memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
+ for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
+ pn[i]++;
--- /dev/null
+From foo@baz Tue Jun 1 10:12:37 AM CEST 2021
+From: Johannes Berg <johannes@sipsolutions.net>
+Date: Mon, 31 May 2021 22:28:27 +0200
+Subject: mac80211: properly handle A-MSDUs that start with an RFC 1042 header
+To: linux-wireless@vger.kernel.org
+Cc: stable@vger.kernel.org, Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
+Message-ID: <20210531202834.179810-4-johannes@sipsolutions.net>
+
+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>
+---
+ net/wireless/util.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+--- a/net/wireless/util.c
++++ b/net/wireless/util.c
+@@ -409,8 +409,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s
+ }
+ EXPORT_SYMBOL(ieee80211_get_mesh_hdrlen);
+
+-int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
+- enum nl80211_iftype iftype)
++static int __ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
++ enum nl80211_iftype iftype, bool is_amsdu)
+ {
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
+ u16 hdrlen, ethertype;
+@@ -504,7 +504,7 @@ int ieee80211_data_to_8023(struct sk_buf
+ payload = skb->data + hdrlen;
+ ethertype = (payload[6] << 8) | payload[7];
+
+- if (likely((ether_addr_equal(payload, rfc1042_header) &&
++ if (likely((!is_amsdu && ether_addr_equal(payload, rfc1042_header) &&
+ ethertype != ETH_P_AARP && ethertype != ETH_P_IPX) ||
+ ether_addr_equal(payload, bridge_tunnel_header))) {
+ /* remove RFC1042 or Bridge-Tunnel encapsulation and
+@@ -525,6 +525,12 @@ int ieee80211_data_to_8023(struct sk_buf
+ }
+ return 0;
+ }
++
++int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
++ enum nl80211_iftype iftype)
++{
++ return __ieee80211_data_to_8023(skb, addr, iftype, false);
++}
+ EXPORT_SYMBOL(ieee80211_data_to_8023);
+
+ int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
nfc-nci-fix-memory-leak-in-nci_allocate_device.patch
proc-check-proc-pid-attr-writes-against-file-opener.patch
net-hso-fix-control-request-directions.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
+mac80211-do-not-accept-forward-invalid-eapol-frames.patch
+mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch
dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch
kgdb-fix-gcc-11-warnings-harder.patch
misc-uss720-fix-memory-leak-in-uss720_probe.patch