From bbb1b57a26f3b8de369b169dcbd1dfa80a0b3102 Mon Sep 17 00:00:00 2001 From: Greg Kroah-Hartman Date: Sat, 29 May 2021 17:07:30 +0200 Subject: [PATCH] 5.12-stable patches 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 --- ...-mitigate-a-msdu-aggregation-attacks.patch | 49 +++ ...80211-add-fragment-cache-to-sta_info.patch | 326 ++++++++++++++++++ ...heck-defrag-pn-against-current-frame.patch | 120 +++++++ ...mac80211-drop-a-msdus-on-old-ciphers.patch | 63 ++++ ...-prevent-attacks-on-tkip-wep-as-well.patch | 72 ++++ ...s-that-start-with-an-rfc-1042-header.patch | 76 ++++ queue-5.12/series | 6 + 7 files changed, 712 insertions(+) create mode 100644 queue-5.12/cfg80211-mitigate-a-msdu-aggregation-attacks.patch create mode 100644 queue-5.12/mac80211-add-fragment-cache-to-sta_info.patch create mode 100644 queue-5.12/mac80211-check-defrag-pn-against-current-frame.patch create mode 100644 queue-5.12/mac80211-drop-a-msdus-on-old-ciphers.patch create mode 100644 queue-5.12/mac80211-prevent-attacks-on-tkip-wep-as-well.patch create mode 100644 queue-5.12/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch diff --git a/queue-5.12/cfg80211-mitigate-a-msdu-aggregation-attacks.patch b/queue-5.12/cfg80211-mitigate-a-msdu-aggregation-attacks.patch new file mode 100644 index 00000000000..65a1a466d04 --- /dev/null +++ b/queue-5.12/cfg80211-mitigate-a-msdu-aggregation-attacks.patch @@ -0,0 +1,49 @@ +From 2b8a1fee3488c602aca8bea004a087e60806a5cf Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef +Date: Tue, 11 May 2021 20:02:45 +0200 +Subject: cfg80211: mitigate A-MSDU aggregation attacks + +From: Mathy Vanhoef + +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 +Link: https://lore.kernel.org/r/20210511200110.25d93176ddaf.I9e265b597f2cd23eb44573f35b625947b386a9de@changeid +Signed-off-by: Johannes Berg +Signed-off-by: Greg Kroah-Hartman +--- + 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.12/mac80211-add-fragment-cache-to-sta_info.patch b/queue-5.12/mac80211-add-fragment-cache-to-sta_info.patch new file mode 100644 index 00000000000..5a37dccac90 --- /dev/null +++ b/queue-5.12/mac80211-add-fragment-cache-to-sta_info.patch @@ -0,0 +1,326 @@ +From 3a11ce08c45b50d69c891d71760b7c5b92074709 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:47 +0200 +Subject: mac80211: add fragment cache to sta_info + +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 | 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; + +@@ -903,9 +884,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; +@@ -2319,4 +2298,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 + * 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 + #include +@@ -676,16 +676,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); +@@ -1928,8 +1924,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 +@@ -2122,19 +2122,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; +@@ -2149,14 +2164,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; +@@ -2165,7 +2180,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) +@@ -2206,6 +2221,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; +@@ -2227,6 +2243,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; + +@@ -2245,7 +2264,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; +@@ -2273,7 +2292,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 + * 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 +@@ -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 +@@ -439,6 +439,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 +@@ -531,6 +558,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 */ +@@ -639,6 +667,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.12/mac80211-check-defrag-pn-against-current-frame.patch b/queue-5.12/mac80211-check-defrag-pn-against-current-frame.patch new file mode 100644 index 00000000000..734f2ba1b05 --- /dev/null +++ b/queue-5.12/mac80211-check-defrag-pn-against-current-frame.patch @@ -0,0 +1,120 @@ +From bf30ca922a0c0176007e074b0acc77ed345e9990 Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:48 +0200 +Subject: mac80211: check defrag PN against current frame + +From: Johannes Berg + +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 +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(-) + +--- 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 +@@ -2307,7 +2307,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; +@@ -2322,8 +2321,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 + * Copyright (C) 2016-2017 Intel Deutschland GmbH ++ * Copyright (C) 2020-2021 Intel Corporation + */ + + #include +@@ -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.12/mac80211-drop-a-msdus-on-old-ciphers.patch b/queue-5.12/mac80211-drop-a-msdus-on-old-ciphers.patch new file mode 100644 index 00000000000..8a01983ec02 --- /dev/null +++ b/queue-5.12/mac80211-drop-a-msdus-on-old-ciphers.patch @@ -0,0 +1,63 @@ +From 270032a2a9c4535799736142e1e7c413ca7b836e Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:46 +0200 +Subject: mac80211: drop A-MSDUs on old ciphers + +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 | 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 + * 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 +@@ -2738,6 +2738,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.12/mac80211-prevent-attacks-on-tkip-wep-as-well.patch b/queue-5.12/mac80211-prevent-attacks-on-tkip-wep-as-well.patch new file mode 100644 index 00000000000..4fefab9e6e3 --- /dev/null +++ b/queue-5.12/mac80211-prevent-attacks-on-tkip-wep-as-well.patch @@ -0,0 +1,72 @@ +From 7e44a0b597f04e67eee8cdcbe7ee706c6f5de38b Mon Sep 17 00:00:00 2001 +From: Johannes Berg +Date: Tue, 11 May 2021 20:02:49 +0200 +Subject: mac80211: prevent attacks on TKIP/WEP as well + +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 +@@ -2273,6 +2273,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], +@@ -2285,6 +2286,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; + } +@@ -2326,6 +2330,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 +@@ -455,7 +455,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.12/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch b/queue-5.12/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch new file mode 100644 index 00000000000..ea846cd28a2 --- /dev/null +++ b/queue-5.12/mac80211-properly-handle-a-msdus-that-start-with-an-rfc-1042-header.patch @@ -0,0 +1,76 @@ +From a1d5ff5651ea592c67054233b14b30bf4452999c Mon Sep 17 00:00:00 2001 +From: Mathy Vanhoef +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 + +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 | 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 +@@ -5756,7 +5756,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 +@@ -5768,7 +5768,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 +@@ -2681,7 +2681,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_ + if (ieee80211_data_to_8023_exthdr(skb, ðhdr, + rx->sdata->vif.addr, + rx->sdata->vif.type, +- data_offset)) ++ data_offset, true)) + return RX_DROP_UNUSABLE; + + ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr, +--- a/net/wireless/util.c ++++ b/net/wireless/util.c +@@ -542,7 +542,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))) diff --git a/queue-5.12/series b/queue-5.12/series index 6d7b389eb41..8f0f3c36a15 100644 --- a/queue-5.12/series +++ b/queue-5.12/series @@ -34,3 +34,9 @@ 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 -- 2.47.3