]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.10-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 29 May 2021 15:07:15 +0000 (17:07 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sat, 29 May 2021 15:07:15 +0000 (17:07 +0200)
added patches:
cfg80211-mitigate-a-msdu-aggregation-attacks.patch
mac80211-add-fragment-cache-to-sta_info.patch
mac80211-check-defrag-pn-against-current-frame.patch
mac80211-drop-a-msdus-on-old-ciphers.patch
mac80211-prevent-attacks-on-tkip-wep-as-well.patch
mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch

queue-5.10/cfg80211-mitigate-a-msdu-aggregation-attacks.patch [new file with mode: 0644]
queue-5.10/mac80211-add-fragment-cache-to-sta_info.patch [new file with mode: 0644]
queue-5.10/mac80211-check-defrag-pn-against-current-frame.patch [new file with mode: 0644]
queue-5.10/mac80211-drop-a-msdus-on-old-ciphers.patch [new file with mode: 0644]
queue-5.10/mac80211-prevent-attacks-on-tkip-wep-as-well.patch [new file with mode: 0644]
queue-5.10/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch [new file with mode: 0644]
queue-5.10/series

diff --git a/queue-5.10/cfg80211-mitigate-a-msdu-aggregation-attacks.patch b/queue-5.10/cfg80211-mitigate-a-msdu-aggregation-attacks.patch
new file mode 100644 (file)
index 0000000..65a1a46
--- /dev/null
@@ -0,0 +1,49 @@
+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;
diff --git a/queue-5.10/mac80211-add-fragment-cache-to-sta_info.patch b/queue-5.10/mac80211-add-fragment-cache-to-sta_info.patch
new file mode 100644 (file)
index 0000000..39e4d1d
--- /dev/null
@@ -0,0 +1,326 @@
+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;
+ };
diff --git a/queue-5.10/mac80211-check-defrag-pn-against-current-frame.patch b/queue-5.10/mac80211-check-defrag-pn-against-current-frame.patch
new file mode 100644 (file)
index 0000000..718ac15
--- /dev/null
@@ -0,0 +1,120 @@
+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 */
diff --git a/queue-5.10/mac80211-drop-a-msdus-on-old-ciphers.patch b/queue-5.10/mac80211-drop-a-msdus-on-old-ciphers.patch
new file mode 100644 (file)
index 0000000..86a9728
--- /dev/null
@@ -0,0 +1,63 @@
+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);
+ }
diff --git a/queue-5.10/mac80211-prevent-attacks-on-tkip-wep-as-well.patch b/queue-5.10/mac80211-prevent-attacks-on-tkip-wep-as-well.patch
new file mode 100644 (file)
index 0000000..6c9829b
--- /dev/null
@@ -0,0 +1,72 @@
+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;
+ };
diff --git a/queue-5.10/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch b/queue-5.10/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch
new file mode 100644 (file)
index 0000000..298cc04
--- /dev/null
@@ -0,0 +1,76 @@
+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, &ethhdr,
+                                         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)))
index 871b42aa1a5641562dd7fb6e1be7bc5746726edc..f5fdb06863d5353f4af95ee114ce4b6bc55ccd18 100644 (file)
@@ -22,6 +22,12 @@ net-sched-fq_pie-fix-oob-access-in-the-traffic-path.patch
 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