From: Greg Kroah-Hartman Date: Tue, 1 Jun 2021 07:27:03 +0000 (+0200) Subject: 4.14-stable patches X-Git-Tag: v4.4.271~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f4ee47d2a555365d2d792b694db11879d5127981;p=thirdparty%2Fkernel%2Fstable-queue.git 4.14-stable patches added patches: mac80211-add-fragment-cache-to-sta_info.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-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch --- diff --git a/queue-4.14/cfg80211-mitigate-a-msdu-aggregation-attacks.patch b/queue-4.14/cfg80211-mitigate-a-msdu-aggregation-attacks.patch index 0687a89031f..684718e46af 100644 --- a/queue-4.14/cfg80211-mitigate-a-msdu-aggregation-attacks.patch +++ b/queue-4.14/cfg80211-mitigate-a-msdu-aggregation-attacks.patch @@ -1,7 +1,10 @@ -From 2b8a1fee3488c602aca8bea004a087e60806a5cf Mon Sep 17 00:00:00 2001 -From: Mathy Vanhoef -Date: Tue, 11 May 2021 20:02:45 +0200 +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:29 +0200 Subject: cfg80211: mitigate A-MSDU aggregation attacks +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Mathy Vanhoef +Message-ID: <20210531203135.180427-5-johannes@sipsolutions.net> From: Mathy Vanhoef @@ -37,7 +40,7 @@ Signed-off-by: Greg Kroah-Hartman --- a/net/wireless/util.c +++ b/net/wireless/util.c -@@ -767,6 +767,9 @@ void ieee80211_amsdu_to_8023s(struct sk_ +@@ -768,6 +768,9 @@ void ieee80211_amsdu_to_8023s(struct sk_ remaining = skb->len - offset; if (subframe_len > remaining) goto purge; diff --git a/queue-4.14/mac80211-add-fragment-cache-to-sta_info.patch b/queue-4.14/mac80211-add-fragment-cache-to-sta_info.patch new file mode 100644 index 00000000000..b36fc567b92 --- /dev/null +++ b/queue-4.14/mac80211-add-fragment-cache-to-sta_info.patch @@ -0,0 +1,302 @@ +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:31 +0200 +Subject: mac80211: add fragment cache to sta_info +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Johannes Berg +Message-ID: <20210531203135.180427-7-johannes@sipsolutions.net> + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -52,12 +52,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 + +@@ -90,19 +84,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; + +@@ -882,9 +863,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; +@@ -2164,4 +2143,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 +@@ -1127,16 +1127,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); +@@ -1846,8 +1842,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 +@@ -1899,19 +1899,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; +@@ -1926,14 +1941,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; + +@@ -1941,7 +1956,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) +@@ -1981,6 +1996,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; +@@ -2002,6 +2018,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; + +@@ -2020,7 +2039,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; +@@ -2048,7 +2067,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 +@@ -367,6 +367,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 */ +@@ -1005,6 +1007,8 @@ static void __sta_info_destroy_part2(str + rate_control_remove_sta_debugfs(sta); + 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 +@@ -398,6 +398,33 @@ struct ieee80211_sta_rx_stats { + u64 msdu[IEEE80211_NUM_TIDS + 1]; + }; + ++/* ++ * 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 +@@ -470,6 +497,7 @@ struct ieee80211_sta_rx_stats { + * @pcpu_rx_stats: per-CPU RX statistics, assigned only if the driver needs + * this (by advertising the USES_RSS hw flag) + * @status_stats: TX status statistics ++ * @frags: fragment cache + */ + struct sta_info { + /* General information, mostly static */ +@@ -569,6 +597,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.14/mac80211-assure-all-fragments-are-encrypted.patch b/queue-4.14/mac80211-assure-all-fragments-are-encrypted.patch index 55df58c1730..61f7e0af606 100644 --- a/queue-4.14/mac80211-assure-all-fragments-are-encrypted.patch +++ b/queue-4.14/mac80211-assure-all-fragments-are-encrypted.patch @@ -1,7 +1,10 @@ -From 965a7d72e798eb7af0aa67210e37cf7ecd1c9cad Mon Sep 17 00:00:00 2001 -From: Mathy Vanhoef -Date: Tue, 11 May 2021 20:02:42 +0200 +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:26 +0200 Subject: mac80211: assure all fragments are encrypted +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Mathy Vanhoef +Message-ID: <20210531203135.180427-2-johannes@sipsolutions.net> From: Mathy Vanhoef diff --git a/queue-4.14/mac80211-check-defrag-pn-against-current-frame.patch b/queue-4.14/mac80211-check-defrag-pn-against-current-frame.patch index 81f2fabec3b..da36aee09d8 100644 --- a/queue-4.14/mac80211-check-defrag-pn-against-current-frame.patch +++ b/queue-4.14/mac80211-check-defrag-pn-against-current-frame.patch @@ -1,7 +1,10 @@ -From bf30ca922a0c0176007e074b0acc77ed345e9990 Mon Sep 17 00:00:00 2001 -From: Johannes Berg -Date: Tue, 11 May 2021 20:02:48 +0200 +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:32 +0200 Subject: mac80211: check defrag PN against current frame +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Johannes Berg +Message-ID: <20210531203135.180427-8-johannes@sipsolutions.net> From: Johannes Berg @@ -24,12 +27,12 @@ Signed-off-by: Greg Kroah-Hartman --- net/mac80211/ieee80211_i.h | 11 +++++++++-- net/mac80211/rx.c | 5 ++--- - net/mac80211/wpa.c | 13 +++++++++---- - 3 files changed, 20 insertions(+), 9 deletions(-) + net/mac80211/wpa.c | 12 ++++++++---- + 3 files changed, 19 insertions(+), 9 deletions(-) --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h -@@ -242,8 +242,15 @@ struct ieee80211_rx_data { +@@ -223,8 +223,15 @@ struct ieee80211_rx_data { */ int security_idx; @@ -49,7 +52,7 @@ Signed-off-by: Greg Kroah-Hartman struct ieee80211_csa_settings { --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c -@@ -2063,7 +2063,6 @@ ieee80211_rx_h_defragment(struct ieee802 +@@ -2082,7 +2082,6 @@ ieee80211_rx_h_defragment(struct ieee802 if (entry->check_sequential_pn) { int i; u8 pn[IEEE80211_CCMP_PN_LEN], *rpn; @@ -57,7 +60,7 @@ Signed-off-by: Greg Kroah-Hartman if (!requires_sequential_pn(rx, fc)) return RX_DROP_UNUSABLE; -@@ -2078,8 +2077,8 @@ ieee80211_rx_h_defragment(struct ieee802 +@@ -2097,8 +2096,8 @@ ieee80211_rx_h_defragment(struct ieee802 if (pn[i]) break; } @@ -70,15 +73,7 @@ Signed-off-by: Greg Kroah-Hartman memcpy(entry->last_pn, pn, IEEE80211_CCMP_PN_LEN); --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c -@@ -2,6 +2,7 @@ - * Copyright 2002-2004, Instant802 Networks, Inc. - * Copyright 2008, Jouni Malinen - * Copyright (C) 2016 Intel Deutschland GmbH -+ * Copyright (C) 2020-2021 Intel Corporation - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License version 2 as -@@ -162,8 +163,8 @@ ieee80211_rx_h_michael_mic_verify(struct +@@ -162,8 +162,8 @@ ieee80211_rx_h_michael_mic_verify(struct update_iv: /* update IV in key information to be able to detect replays */ @@ -89,7 +84,7 @@ Signed-off-by: Greg Kroah-Hartman return RX_CONTINUE; -@@ -289,8 +290,8 @@ ieee80211_crypto_tkip_decrypt(struct iee +@@ -289,8 +289,8 @@ ieee80211_crypto_tkip_decrypt(struct iee key, skb->data + hdrlen, skb->len - hdrlen, rx->sta->sta.addr, hdr->addr1, hwaccel, rx->security_idx, @@ -100,7 +95,7 @@ Signed-off-by: Greg Kroah-Hartman if (res != TKIP_DECRYPT_OK) return RX_DROP_UNUSABLE; -@@ -548,6 +549,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee +@@ -548,6 +548,8 @@ ieee80211_crypto_ccmp_decrypt(struct iee } memcpy(key->u.ccmp.rx_pn[queue], pn, IEEE80211_CCMP_PN_LEN); @@ -109,7 +104,7 @@ Signed-off-by: Greg Kroah-Hartman } /* Remove CCMP header and MIC */ -@@ -777,6 +780,8 @@ ieee80211_crypto_gcmp_decrypt(struct iee +@@ -777,6 +779,8 @@ ieee80211_crypto_gcmp_decrypt(struct iee } memcpy(key->u.gcmp.rx_pn[queue], pn, IEEE80211_GCMP_PN_LEN); diff --git a/queue-4.14/mac80211-do-not-accept-forward-invalid-eapol-frames.patch b/queue-4.14/mac80211-do-not-accept-forward-invalid-eapol-frames.patch new file mode 100644 index 00000000000..2631bb5c4ef --- /dev/null +++ b/queue-4.14/mac80211-do-not-accept-forward-invalid-eapol-frames.patch @@ -0,0 +1,108 @@ +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:34 +0200 +Subject: mac80211: do not accept/forward invalid EAPOL frames +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Johannes Berg , Jouni Malinen +Message-ID: <20210531203135.180427-10-johannes@sipsolutions.net> + +From: Johannes Berg + +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 +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.cb327ed0cabe.Ib7dcffa2a31f0913d660de65ba3c8aca75b1d10f@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/rx.c | 34 ++++++++++++++++++++++++++++------ + 1 file changed, 28 insertions(+), 6 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2298,13 +2298,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)) +@@ -2344,6 +2344,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) && + ieee80211_vif_get_num_mcast_if(sdata) != 0) { +@@ -2397,9 +2398,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.14/mac80211-drop-a-msdus-on-old-ciphers.patch b/queue-4.14/mac80211-drop-a-msdus-on-old-ciphers.patch new file mode 100644 index 00000000000..a18538c5760 --- /dev/null +++ b/queue-4.14/mac80211-drop-a-msdus-on-old-ciphers.patch @@ -0,0 +1,57 @@ +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:30 +0200 +Subject: mac80211: drop A-MSDUs on old ciphers +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Johannes Berg +Message-ID: <20210531203135.180427-6-johannes@sipsolutions.net> + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/rx.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2455,6 +2455,23 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + true)) + 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, diff --git a/queue-4.14/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch b/queue-4.14/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch new file mode 100644 index 00000000000..3dd645bf1d2 --- /dev/null +++ b/queue-4.14/mac80211-extend-protection-against-mixed-key-and-fragment-cache-attacks.patch @@ -0,0 +1,79 @@ +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:35 +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 +Message-ID: <20210531203135.180427-11-johannes@sipsolutions.net> + +From: Wen Gong + +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 +Signed-off-by: Jouni Malinen +Link: https://lore.kernel.org/r/20210511200110.037aa5ca0390.I7bb888e2965a0db02a67075fcb5deb50eb7408aa@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + net/mac80211/rx.c | 13 +++++++++++-- + 1 file changed, 11 insertions(+), 2 deletions(-) + +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2003,6 +2003,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 = IEEE80211_SKB_RXCB(rx->skb); + + hdr = (struct ieee80211_hdr *)rx->skb->data; + fc = hdr->frame_control; +@@ -2061,7 +2062,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; + } +@@ -2106,13 +2109,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.14/mac80211-prevent-attacks-on-tkip-wep-as-well.patch b/queue-4.14/mac80211-prevent-attacks-on-tkip-wep-as-well.patch new file mode 100644 index 00000000000..10d8ae832c9 --- /dev/null +++ b/queue-4.14/mac80211-prevent-attacks-on-tkip-wep-as-well.patch @@ -0,0 +1,75 @@ +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:33 +0200 +Subject: mac80211: prevent attacks on TKIP/WEP as well +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Johannes Berg +Message-ID: <20210531203135.180427-9-johannes@sipsolutions.net> + +From: Johannes Berg + +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 +@@ -2048,6 +2048,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], +@@ -2060,6 +2061,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; + } +@@ -2101,6 +2105,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 +@@ -415,7 +415,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.14/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch b/queue-4.14/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch index d2be0cfb44a..74d5bd4133c 100644 --- a/queue-4.14/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch +++ b/queue-4.14/mac80211-prevent-mixed-key-and-fragment-cache-attacks.patch @@ -1,7 +1,10 @@ -From 94034c40ab4a3fcf581fbc7f8fdf4e29943c4a24 Mon Sep 17 00:00:00 2001 -From: Mathy Vanhoef -Date: Tue, 11 May 2021 20:02:43 +0200 +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:27 +0200 Subject: mac80211: prevent mixed key and fragment cache attacks +To: linux-wireless@vger.kernel.org +Cc: stable@vger.kernel.org, Mathy Vanhoef +Message-ID: <20210531203135.180427-3-johannes@sipsolutions.net> From: Mathy Vanhoef @@ -43,17 +46,17 @@ Signed-off-by: Greg Kroah-Hartman --- a/net/mac80211/key.c +++ b/net/mac80211/key.c -@@ -647,6 +647,7 @@ int ieee80211_key_link(struct ieee80211_ - struct ieee80211_sub_if_data *sdata, +@@ -648,6 +648,7 @@ int ieee80211_key_link(struct ieee80211_ struct sta_info *sta) { -+ static atomic_t key_color = ATOMIC_INIT(0); struct ieee80211_local *local = sdata->local; ++ static atomic_t key_color = ATOMIC_INIT(0); struct ieee80211_key *old_key; int idx = key->conf.keyidx; -@@ -682,6 +683,12 @@ int ieee80211_key_link(struct ieee80211_ - key->sdata = sdata; - key->sta = sta; + bool pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; +@@ -659,6 +660,12 @@ int ieee80211_key_link(struct ieee80211_ + bool delay_tailroom = sdata->vif.type == NL80211_IFTYPE_STATION; + int ret; + /* + * Assign a unique ID to every key so we can easily prevent mixed @@ -61,9 +64,9 @@ Signed-off-by: Greg Kroah-Hartman + */ + key->color = atomic_inc_return(&key_color); + - increment_tailroom_need_count(sdata); + mutex_lock(&sdata->local->key_mtx); - ieee80211_key_replace(sdata, sta, pairwise, old_key, key); + if (sta && pairwise) --- a/net/mac80211/key.h +++ b/net/mac80211/key.h @@ -127,6 +127,8 @@ struct ieee80211_key { diff --git a/queue-4.14/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch b/queue-4.14/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch new file mode 100644 index 00000000000..585f58815c6 --- /dev/null +++ b/queue-4.14/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch @@ -0,0 +1,82 @@ +From foo@baz Tue Jun 1 09:24:27 AM CEST 2021 +From: Johannes Berg +Date: Mon, 31 May 2021 22:31:28 +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 +Message-ID: <20210531203135.180427-4-johannes@sipsolutions.net> + +From: Mathy Vanhoef + +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 +Link: https://lore.kernel.org/r/20210511200110.0b2b886492f0.I23dd5d685fe16d3b0ec8106e8f01b59f499dffed@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + include/net/cfg80211.h | 5 +++-- + net/mac80211/rx.c | 3 ++- + net/wireless/util.c | 5 +++-- + 3 files changed, 8 insertions(+), 5 deletions(-) + +--- a/include/net/cfg80211.h ++++ b/include/net/cfg80211.h +@@ -4338,7 +4338,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s + * Return: 0 on success. Non-zero on error. + */ + int ieee80211_data_to_8023_exthdr(struct sk_buff *skb, struct ethhdr *ehdr, +- const u8 *addr, enum nl80211_iftype iftype); ++ const u8 *addr, enum nl80211_iftype iftype, ++ bool is_amsdu); + + /** + * ieee80211_data_to_8023 - convert an 802.11 data frame to 802.3 +@@ -4350,7 +4351,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); ++ return ieee80211_data_to_8023_exthdr(skb, NULL, addr, iftype, false); + } + + /** +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -2451,7 +2451,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx + + if (ieee80211_data_to_8023_exthdr(skb, ðhdr, + rx->sdata->vif.addr, +- rx->sdata->vif.type)) ++ rx->sdata->vif.type, ++ 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 +@@ -422,7 +422,8 @@ unsigned int ieee80211_get_mesh_hdrlen(s + 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) ++ const u8 *addr, enum nl80211_iftype iftype, ++ bool is_amsdu) + { + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; + struct { +@@ -510,7 +511,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))) diff --git a/queue-4.14/series b/queue-4.14/series index 7d7f0ec42bb..3171d99bd29 100644 --- a/queue-4.14/series +++ b/queue-4.14/series @@ -12,8 +12,14 @@ 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 ath10k-validate-first-subframe-of-a-msdu-before-processing-the-list.patch dm-snapshot-properly-fix-a-crash-when-an-origin-has-no-snapshots.patch kgdb-fix-gcc-11-warnings-harder.patch