mac80211/ath11k: backport krak2 mitigation

Signed-off-by: John Crispin <john@phrozen.org>
This commit is contained in:
John Crispin
2021-06-14 10:55:14 +02:00
committed by Rick Sommerville
parent e8418c0c54
commit bebf6d322d
2 changed files with 326 additions and 0 deletions

View File

@@ -0,0 +1,84 @@
From 0e23a88c63d6abbeaef8ec90bd29584b7c5068bd Mon Sep 17 00:00:00 2001
From: Sriram R <srirrama@codeaurora.org>
Date: Thu, 10 Dec 2020 14:20:50 +0530
Subject: [PATCH] ath11k: Clear the fragment cache during key install
Currently the fragment cache setup during peer assoc is
cleared during peer delete. In case a key reinstallation
happens with the same peer, possibilitites are same fragment cache
where some fragments were added before key installation could be clubbed
with fragments received after. In ideal cases where
this could result in wrong PN since we expect all fragments to
have incrementing PN, this behavior could be explioted
to mix fragments of different data resulting in a proper
unintended reassembled packet to be passed up the stack.
Signed-off-by: Sriram R <srirrama@codeaurora.org>
---
drivers/net/wireless/ath/ath11k/dp_rx.c | 19 +++++++++++++++++++
drivers/net/wireless/ath/ath11k/dp_rx.h | 1 +
drivers/net/wireless/ath/ath11k/mac.c | 6 ++++++
3 files changed, 26 insertions(+)
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 0fa25c1..06bbd6e 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -844,6 +844,25 @@ static void ath11k_dp_rx_frags_cleanup(struct dp_rx_tid *rx_tid, bool rel_link_d
__skb_queue_purge(&rx_tid->rx_frags);
}
+void ath11k_peer_frags_flush(struct ath11k *ar, struct ath11k_peer *peer)
+{
+ struct dp_rx_tid *rx_tid;
+ int i;
+
+ lockdep_assert_held(&ar->ab->base_lock);
+
+ for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
+ rx_tid = &peer->rx_tid[i];
+
+ spin_unlock_bh(&ar->ab->base_lock);
+ del_timer_sync(&rx_tid->frag_timer);
+ spin_lock_bh(&ar->ab->base_lock);
+
+ ath11k_dp_rx_frags_cleanup(rx_tid, true);
+
+ }
+}
+
void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer)
{
struct dp_rx_tid *rx_tid;
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.h b/drivers/net/wireless/ath/ath11k/dp_rx.h
index f005ded..732f9a7 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.h
@@ -68,6 +68,7 @@ int ath11k_dp_peer_rx_pn_replay_config(struct ath11k_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
struct ieee80211_key_conf *key);
+void ath11k_peer_frags_flush(struct ath11k *ar, struct ath11k_peer *peer);
void ath11k_peer_rx_tid_cleanup(struct ath11k *ar, struct ath11k_peer *peer);
void ath11k_peer_rx_tid_delete(struct ath11k *ar,
struct ath11k_peer *peer, u8 tid);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 4c88eab..91d645e 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -3707,6 +3707,12 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
*/
spin_lock_bh(&ab->base_lock);
peer = ath11k_peer_find(ab, arvif->vdev_id, peer_addr);
+
+ /* flush the fragments cache during key (re)install to
+ * ensure all frags in the new frag list belong to the same key.
+ */
+ if (peer && cmd == SET_KEY)
+ ath11k_peer_frags_flush(ar, peer);
spin_unlock_bh(&ab->base_lock);
if (!peer) {
--
2.7.4

View File

@@ -0,0 +1,242 @@
From patchwork Tue May 11 18:02:44 2021
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
X-Patchwork-Submitter: Johannes Berg <johannes@sipsolutions.net>
X-Patchwork-Id: 12251641
X-Patchwork-Delegate: johannes@sipsolutions.net
Return-Path: <linux-wireless-owner@kernel.org>
X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on
aws-us-west-2-korg-lkml-1.web.codeaurora.org
X-Spam-Level:
X-Spam-Status: No, score=-16.8 required=3.0 tests=BAYES_00,
HEADER_FROM_DIFFERENT_DOMAINS,INCLUDES_CR_TRAILER,INCLUDES_PATCH,
MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT
autolearn=unavailable autolearn_force=no version=3.4.0
Received: from mail.kernel.org (mail.kernel.org [198.145.29.99])
by smtp.lore.kernel.org (Postfix) with ESMTP id 5E0C4C43617
for <linux-wireless@archiver.kernel.org>;
Tue, 11 May 2021 18:03:20 +0000 (UTC)
Received: from vger.kernel.org (vger.kernel.org [23.128.96.18])
by mail.kernel.org (Postfix) with ESMTP id 2E1D461625
for <linux-wireless@archiver.kernel.org>;
Tue, 11 May 2021 18:03:20 +0000 (UTC)
Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand
id S231693AbhEKSEZ (ORCPT
<rfc822;linux-wireless@archiver.kernel.org>);
Tue, 11 May 2021 14:04:25 -0400
Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41156 "EHLO
lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org
with ESMTP id S231561AbhEKSEV (ORCPT
<rfc822;linux-wireless@vger.kernel.org>);
Tue, 11 May 2021 14:04:21 -0400
Received: from sipsolutions.net (s3.sipsolutions.net
[IPv6:2a01:4f8:191:4433::2])
by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D055CC06175F;
Tue, 11 May 2021 11:03:10 -0700 (PDT)
Received: by sipsolutions.net with esmtpsa
(TLS1.3:ECDHE_X25519__RSA_PSS_RSAE_SHA256__AES_256_GCM:256)
(Exim 4.94.2)
(envelope-from <johannes@sipsolutions.net>)
id 1lgWir-007aAS-9o; Tue, 11 May 2021 20:03:09 +0200
From: Johannes Berg <johannes@sipsolutions.net>
To: linux-wireless@vger.kernel.org
Cc: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>, stable@vger.kernel.org
Subject: [PATCH 03/18] mac80211: properly handle A-MSDUs that start with an
RFC 1042 header
Date: Tue, 11 May 2021 20:02:44 +0200
Message-Id:
<20210511200110.0b2b886492f0.I23dd5d685fe16d3b0ec8106e8f01b59f499dffed@changeid>
X-Mailer: git-send-email 2.30.2
In-Reply-To: <20210511180259.159598-1-johannes@sipsolutions.net>
References: <20210511180259.159598-1-johannes@sipsolutions.net>
MIME-Version: 1.0
Precedence: bulk
List-ID: <linux-wireless.vger.kernel.org>
X-Mailing-List: linux-wireless@vger.kernel.org
From: Mathy Vanhoef <Mathy.Vanhoef@kuleuven.be>
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>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/cfg80211.h | 4 ++--
net/mac80211/rx.c | 2 +-
net/wireless/util.c | 4 ++--
3 files changed, 5 insertions(+), 5 deletions(-)
Index: backports-20200902_001-4.4.60-931c337125/include/net/cfg80211.h
===================================================================
--- backports-20200902_001-4.4.60-931c337125.orig/include/net/cfg80211.h
+++ backports-20200902_001-4.4.60-931c337125/include/net/cfg80211.h
@@ -5631,7 +5631,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
@@ -5643,7 +5643,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);
}
/**
Index: backports-20200902_001-4.4.60-931c337125/net/mac80211/rx.c
===================================================================
--- backports-20200902_001-4.4.60-931c337125.orig/net/mac80211/rx.c
+++ backports-20200902_001-4.4.60-931c337125/net/mac80211/rx.c
@@ -6,7 +6,7 @@
* Copyright 2007-2010 Johannes Berg <johannes@sipsolutions.net>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright(c) 2015 - 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2020 Intel Corporation
+ * Copyright (C) 2018-2021 Intel Corporation
*/
#include <linux/jiffies.h>
@@ -2555,13 +2555,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.
- */
- 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;
+ * 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 (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))
@@ -2632,7 +2632,26 @@ static void ieee80211_deliver_skb_to_loc
cfg80211_rx_control_port(dev, skb, noencrypt);
dev_kfree_skb(skb);
} else {
+ struct ethhdr *ehdr = (void *)skb_mac_header(skb);
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);
+
netif_rx_nss(rx, skb);
}
}
@@ -2672,6 +2691,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) {
@@ -2781,7 +2801,7 @@ __ieee80211_rx_h_amsdu(struct ieee80211_
if (ieee80211_data_to_8023_exthdr(skb, &ethhdr,
rx->sdata->vif.addr,
rx->sdata->vif.type,
- data_offset))
+ data_offset, true))
return RX_DROP_UNUSABLE;
ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
@@ -2838,6 +2858,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);
}
Index: backports-20200902_001-4.4.60-931c337125/net/wireless/util.c
===================================================================
--- backports-20200902_001-4.4.60-931c337125.orig/net/wireless/util.c
+++ backports-20200902_001-4.4.60-931c337125/net/wireless/util.c
@@ -474,7 +474,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 {
@@ -562,7 +562,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)))
@@ -708,6 +708,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;
Index: backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/nss.c
===================================================================
--- backports-20200902_001-4.4.60-931c337125.orig/drivers/net/wireless/ath/ath11k/nss.c
+++ backports-20200902_001-4.4.60-931c337125/drivers/net/wireless/ath/ath11k/nss.c
@@ -477,7 +477,7 @@ static int ath11k_nss_deliver_rx(struct
}
if (ieee80211_data_to_8023_exthdr(skb, NULL, vif->addr, vif->type,
- data_offs - hdr_len)) {
+ data_offs - hdr_len, false)) {
dev_kfree_skb_any(skb);
return -EINVAL;
}