]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
4.4-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Jun 2021 08:15:06 +0000 (10:15 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 1 Jun 2021 08:15:06 +0000 (10:15 +0200)
added patches:
cfg80211-mitigate-a-msdu-aggregation-attacks.patch
mac80211-add-fragment-cache-to-sta_info.patch
mac80211-assure-all-fragments-are-encrypted.patch
mac80211-check-defrag-pn-against-current-frame.patch
mac80211-do-not-accept-forward-invalid-eapol-frames.patch
mac80211-drop-a-msdus-on-old-ciphers.patch
mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch
mac80211-prevent-attacks-on-tkip-wep-as-well.patch
mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch
mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch

queue-4.4/cfg80211-mitigate-a-msdu-aggregation-attacks.patch [new file with mode: 0644]
queue-4.4/mac80211-add-fragment-cache-to-sta_info.patch [new file with mode: 0644]
queue-4.4/mac80211-assure-all-fragments-are-encrypted.patch [new file with mode: 0644]
queue-4.4/mac80211-check-defrag-pn-against-current-frame.patch [new file with mode: 0644]
queue-4.4/mac80211-do-not-accept-forward-invalid-eapol-frames.patch [new file with mode: 0644]
queue-4.4/mac80211-drop-a-msdus-on-old-ciphers.patch [new file with mode: 0644]
queue-4.4/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch [new file with mode: 0644]
queue-4.4/mac80211-prevent-attacks-on-tkip-wep-as-well.patch [new file with mode: 0644]
queue-4.4/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch [new file with mode: 0644]
queue-4.4/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch [new file with mode: 0644]
queue-4.4/series

diff --git a/queue-4.4/cfg80211-mitigate-a-msdu-aggregation-attacks.patch b/queue-4.4/cfg80211-mitigate-a-msdu-aggregation-attacks.patch
new file mode 100644 (file)
index 0000000..494eb4e
--- /dev/null
@@ -0,0 +1,52 @@
+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 */
diff --git a/queue-4.4/mac80211-add-fragment-cache-to-sta_info.patch b/queue-4.4/mac80211-add-fragment-cache-to-sta_info.patch
new file mode 100644 (file)
index 0000000..df43154
--- /dev/null
@@ -0,0 +1,302 @@
+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;
+ };
diff --git a/queue-4.4/mac80211-assure-all-fragments-are-encrypted.patch b/queue-4.4/mac80211-assure-all-fragments-are-encrypted.patch
new file mode 100644 (file)
index 0000000..8ccdd7d
--- /dev/null
@@ -0,0 +1,81 @@
+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--) {
diff --git a/queue-4.4/mac80211-check-defrag-pn-against-current-frame.patch b/queue-4.4/mac80211-check-defrag-pn-against-current-frame.patch
new file mode 100644 (file)
index 0000000..563dc6b
--- /dev/null
@@ -0,0 +1,135 @@
+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 */
diff --git a/queue-4.4/mac80211-do-not-accept-forward-invalid-eapol-frames.patch b/queue-4.4/mac80211-do-not-accept-forward-invalid-eapol-frames.patch
new file mode 100644 (file)
index 0000000..209b6f3
--- /dev/null
@@ -0,0 +1,108 @@
+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
diff --git a/queue-4.4/mac80211-drop-a-msdus-on-old-ciphers.patch b/queue-4.4/mac80211-drop-a-msdus-on-old-ciphers.patch
new file mode 100644 (file)
index 0000000..cc14b77
--- /dev/null
@@ -0,0 +1,57 @@
+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);
diff --git a/queue-4.4/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch b/queue-4.4/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch
new file mode 100644 (file)
index 0000000..b74620e
--- /dev/null
@@ -0,0 +1,80 @@
+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));
diff --git a/queue-4.4/mac80211-prevent-attacks-on-tkip-wep-as-well.patch b/queue-4.4/mac80211-prevent-attacks-on-tkip-wep-as-well.patch
new file mode 100644 (file)
index 0000000..7131176
--- /dev/null
@@ -0,0 +1,75 @@
+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;
+ };
diff --git a/queue-4.4/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch b/queue-4.4/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch
new file mode 100644 (file)
index 0000000..e7817d1
--- /dev/null
@@ -0,0 +1,102 @@
+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]++;
diff --git a/queue-4.4/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch b/queue-4.4/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch
new file mode 100644 (file)
index 0000000..efa9c19
--- /dev/null
@@ -0,0 +1,61 @@
+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,
index 2d4183905f302ca7c2daa1e6a62c60159c467a93..b1b5d37a581a5fc717ce3537d55cc17b86f5b080 100644 (file)
@@ -3,6 +3,16 @@ netfilter-x_tables-use-correct-memory-barriers.patch
 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