54e09af3b3a17f1ab42248ca73ab8a31e1c827b4
[openwrt/staging/svanheule.git] /
1 From a0761a301746ec2d92d7fcb82af69c0a6a4339aa Mon Sep 17 00:00:00 2001
2 From: Johannes Berg <johannes.berg@intel.com>
3 Date: Thu, 26 Mar 2020 15:09:42 +0200
4 Subject: mac80211: drop data frames without key on encrypted links
5
6 If we know that we have an encrypted link (based on having had
7 a key configured for TX in the past) then drop all data frames
8 in the key selection handler if there's no key anymore.
9
10 This fixes an issue with mac80211 internal TXQs - there we can
11 buffer frames for an encrypted link, but then if the key is no
12 longer there when they're dequeued, the frames are sent without
13 encryption. This happens if a station is disconnected while the
14 frames are still on the TXQ.
15
16 Detecting that a link should be encrypted based on a first key
17 having been configured for TX is fine as there are no use cases
18 for a connection going from with encryption to no encryption.
19 With extended key IDs, however, there is a case of having a key
20 configured for only decryption, so we can't just trigger this
21 behaviour on a key being configured.
22
23 Cc: stable@vger.kernel.org
24 Reported-by: Jouni Malinen <j@w1.fi>
25 Signed-off-by: Johannes Berg <johannes.berg@intel.com>
26 Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
27 ---
28 net/mac80211/debugfs_sta.c | 3 ++-
29 net/mac80211/key.c | 20 ++++++++++++--------
30 net/mac80211/sta_info.h | 1 +
31 net/mac80211/tx.c | 12 +++++++++---
32 4 files changed, 24 insertions(+), 12 deletions(-)
33
34 --- a/net/mac80211/debugfs_sta.c
35 +++ b/net/mac80211/debugfs_sta.c
36 @@ -5,7 +5,7 @@
37 * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
38 * Copyright 2013-2014 Intel Mobile Communications GmbH
39 * Copyright(c) 2016 Intel Deutschland GmbH
40 - * Copyright (C) 2018 - 2019 Intel Corporation
41 + * Copyright (C) 2018 - 2020 Intel Corporation
42 */
43
44 #include <linux/debugfs.h>
45 @@ -78,6 +78,7 @@ static const char * const sta_flag_names
46 FLAG(MPSP_OWNER),
47 FLAG(MPSP_RECIPIENT),
48 FLAG(PS_DELIVER),
49 + FLAG(USES_ENCRYPTION),
50 #undef FLAG
51 };
52
53 --- a/net/mac80211/key.c
54 +++ b/net/mac80211/key.c
55 @@ -6,7 +6,7 @@
56 * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
57 * Copyright 2013-2014 Intel Mobile Communications GmbH
58 * Copyright 2015-2017 Intel Deutschland GmbH
59 - * Copyright 2018-2019 Intel Corporation
60 + * Copyright 2018-2020 Intel Corporation
61 */
62
63 #include <linux/if_ether.h>
64 @@ -262,22 +262,29 @@ static void ieee80211_key_disable_hw_acc
65 sta ? sta->sta.addr : bcast_addr, ret);
66 }
67
68 -int ieee80211_set_tx_key(struct ieee80211_key *key)
69 +static int _ieee80211_set_tx_key(struct ieee80211_key *key, bool force)
70 {
71 struct sta_info *sta = key->sta;
72 struct ieee80211_local *local = key->local;
73
74 assert_key_lock(local);
75
76 + set_sta_flag(sta, WLAN_STA_USES_ENCRYPTION);
77 +
78 sta->ptk_idx = key->conf.keyidx;
79
80 - if (!ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT))
81 + if (force || !ieee80211_hw_check(&local->hw, AMPDU_KEYBORDER_SUPPORT))
82 clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
83 ieee80211_check_fast_xmit(sta);
84
85 return 0;
86 }
87
88 +int ieee80211_set_tx_key(struct ieee80211_key *key)
89 +{
90 + return _ieee80211_set_tx_key(key, false);
91 +}
92 +
93 static void ieee80211_pairwise_rekey(struct ieee80211_key *old,
94 struct ieee80211_key *new)
95 {
96 @@ -441,11 +448,8 @@ static int ieee80211_key_replace(struct
97 if (pairwise) {
98 rcu_assign_pointer(sta->ptk[idx], new);
99 if (new &&
100 - !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)) {
101 - sta->ptk_idx = idx;
102 - clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
103 - ieee80211_check_fast_xmit(sta);
104 - }
105 + !(new->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX))
106 + _ieee80211_set_tx_key(new, true);
107 } else {
108 rcu_assign_pointer(sta->gtk[idx], new);
109 }
110 --- a/net/mac80211/sta_info.h
111 +++ b/net/mac80211/sta_info.h
112 @@ -98,6 +98,7 @@ enum ieee80211_sta_info_flags {
113 WLAN_STA_MPSP_OWNER,
114 WLAN_STA_MPSP_RECIPIENT,
115 WLAN_STA_PS_DELIVER,
116 + WLAN_STA_USES_ENCRYPTION,
117
118 NUM_WLAN_STA_FLAGS,
119 };
120 --- a/net/mac80211/tx.c
121 +++ b/net/mac80211/tx.c
122 @@ -590,10 +590,13 @@ ieee80211_tx_h_select_key(struct ieee802
123 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
124 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
125
126 - if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT))
127 + if (unlikely(info->flags & IEEE80211_TX_INTFL_DONT_ENCRYPT)) {
128 tx->key = NULL;
129 - else if (tx->sta &&
130 - (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
131 + return TX_CONTINUE;
132 + }
133 +
134 + if (tx->sta &&
135 + (key = rcu_dereference(tx->sta->ptk[tx->sta->ptk_idx])))
136 tx->key = key;
137 else if (ieee80211_is_group_privacy_action(tx->skb) &&
138 (key = rcu_dereference(tx->sdata->default_multicast_key)))
139 @@ -654,6 +657,9 @@ ieee80211_tx_h_select_key(struct ieee802
140 if (!skip_hw && tx->key &&
141 tx->key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)
142 info->control.hw_key = &tx->key->conf;
143 + } else if (!ieee80211_is_mgmt(hdr->frame_control) && tx->sta &&
144 + test_sta_flag(tx->sta, WLAN_STA_USES_ENCRYPTION)) {
145 + return TX_DROP;
146 }
147
148 return TX_CONTINUE;