kernel: backport the I2C bus recovery for uDPU
[oweals/openwrt.git] / package / kernel / mac80211 / patches / subsys / 314-mac80211-drop-data-frames-without-key-on-encrypted-l.patch
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;