Commit 3b96766f0e643f52ae19e134664df6730c737e87

Authored by Johannes Berg
Committed by John W. Linville
1 parent 7d1559f173

mac80211: fix key vs. sta locking problems

Up to now, key manipulation is supposed to run under RTNL to
avoid concurrent manipulations and also allow the set_key()
hardware callback to sleep. This is not feasible because STA
structs are rcu-protected and thus a lot of operations there
cannot take the RTNL. Also, key references are rcu-protected
so we cannot do things atomically.

This patch changes key locking completely:
 * key operations are now atomic
 * hardware crypto offload is enabled and disabled from
   a workqueue, due to that key freeing is also delayed
 * debugfs code is also run from a workqueue
 * keys reference STAs (and vice versa!) so during STA
   unlink the STAs key reference is removed but not the
   keys STA reference, to avoid races key todo work is
   run before STA destruction.
 * fewer STA operations now need the RTNL which was
   required due to key operations

This fixes the locking problems lockdep pointed out and also
makes things more light-weight because the rtnl isn't required
as much.

Note that the key todo lock/key mutex are global locks, this
is not required, of course, they could be per-hardware instead.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>

Showing 11 changed files with 385 additions and 229 deletions Side-by-side Diff

... ... @@ -135,6 +135,7 @@
135 135 struct sta_info *sta = NULL;
136 136 enum ieee80211_key_alg alg;
137 137 struct ieee80211_key *key;
  138 + int err;
138 139  
139 140 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
140 141  
141 142  
142 143  
... ... @@ -157,17 +158,24 @@
157 158 if (!key)
158 159 return -ENOMEM;
159 160  
  161 + rcu_read_lock();
  162 +
160 163 if (mac_addr) {
161 164 sta = sta_info_get(sdata->local, mac_addr);
162 165 if (!sta) {
163 166 ieee80211_key_free(key);
164   - return -ENOENT;
  167 + err = -ENOENT;
  168 + goto out_unlock;
165 169 }
166 170 }
167 171  
168 172 ieee80211_key_link(key, sdata, sta);
169 173  
170   - return 0;
  174 + err = 0;
  175 + out_unlock:
  176 + rcu_read_unlock();
  177 +
  178 + return err;
171 179 }
172 180  
173 181 static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
174 182  
175 183  
176 184  
177 185  
178 186  
179 187  
180 188  
... ... @@ -179,28 +187,37 @@
179 187  
180 188 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
181 189  
  190 + rcu_read_lock();
  191 +
182 192 if (mac_addr) {
  193 + ret = -ENOENT;
  194 +
183 195 sta = sta_info_get(sdata->local, mac_addr);
184 196 if (!sta)
185   - return -ENOENT;
  197 + goto out_unlock;
186 198  
187   - ret = 0;
188 199 if (sta->key) {
189 200 ieee80211_key_free(sta->key);
190 201 WARN_ON(sta->key);
191   - } else
192   - ret = -ENOENT;
  202 + ret = 0;
  203 + }
193 204  
194   - return ret;
  205 + goto out_unlock;
195 206 }
196 207  
197   - if (!sdata->keys[key_idx])
198   - return -ENOENT;
  208 + if (!sdata->keys[key_idx]) {
  209 + ret = -ENOENT;
  210 + goto out_unlock;
  211 + }
199 212  
200 213 ieee80211_key_free(sdata->keys[key_idx]);
201 214 WARN_ON(sdata->keys[key_idx]);
202 215  
203   - return 0;
  216 + ret = 0;
  217 + out_unlock:
  218 + rcu_read_unlock();
  219 +
  220 + return ret;
204 221 }
205 222  
206 223 static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
... ... @@ -217,6 +234,8 @@
217 234 u16 iv16;
218 235 int err = -ENOENT;
219 236  
  237 + rcu_read_lock();
  238 +
220 239 if (mac_addr) {
221 240 sta = sta_info_get(sdata->local, mac_addr);
222 241 if (!sta)
... ... @@ -280,6 +299,7 @@
280 299 err = 0;
281 300  
282 301 out:
  302 + rcu_read_unlock();
283 303 return err;
284 304 }
285 305  
286 306  
... ... @@ -289,8 +309,12 @@
289 309 {
290 310 struct ieee80211_sub_if_data *sdata;
291 311  
  312 + rcu_read_lock();
  313 +
292 314 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
293 315 ieee80211_set_default_key(sdata, key_idx);
  316 +
  317 + rcu_read_unlock();
294 318  
295 319 return 0;
296 320 }
net/mac80211/debugfs_key.c
... ... @@ -184,23 +184,35 @@
184 184 key->debugfs.name = debugfs_create_file(#name, 0400,\
185 185 key->debugfs.dir, key, &key_##name##_ops);
186 186  
187   -void ieee80211_debugfs_key_add(struct ieee80211_local *local,
188   - struct ieee80211_key *key)
189   -{
  187 +void ieee80211_debugfs_key_add(struct ieee80211_key *key)
  188 + {
190 189 static int keycount;
191   - char buf[20];
  190 + char buf[50];
  191 + DECLARE_MAC_BUF(mac);
  192 + struct sta_info *sta;
192 193  
193   - if (!local->debugfs.keys)
  194 + if (!key->local->debugfs.keys)
194 195 return;
195 196  
196 197 sprintf(buf, "%d", keycount);
197 198 keycount++;
198 199 key->debugfs.dir = debugfs_create_dir(buf,
199   - local->debugfs.keys);
  200 + key->local->debugfs.keys);
200 201  
201 202 if (!key->debugfs.dir)
202 203 return;
203 204  
  205 + rcu_read_lock();
  206 + sta = rcu_dereference(key->sta);
  207 + if (sta)
  208 + sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
  209 + rcu_read_unlock();
  210 +
  211 + /* using sta as a boolean is fine outside RCU lock */
  212 + if (sta)
  213 + key->debugfs.stalink =
  214 + debugfs_create_symlink("station", key->debugfs.dir, buf);
  215 +
204 216 DEBUGFS_ADD(keylen);
205 217 DEBUGFS_ADD(flags);
206 218 DEBUGFS_ADD(keyidx);
... ... @@ -257,19 +269,6 @@
257 269  
258 270 debugfs_remove(sdata->debugfs.default_key);
259 271 sdata->debugfs.default_key = NULL;
260   -}
261   -void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
262   - struct sta_info *sta)
263   -{
264   - char buf[50];
265   - DECLARE_MAC_BUF(mac);
266   -
267   - if (!key->debugfs.dir)
268   - return;
269   -
270   - sprintf(buf, "../../stations/%s", print_mac(mac, sta->addr));
271   - key->debugfs.stalink =
272   - debugfs_create_symlink("station", key->debugfs.dir, buf);
273 272 }
274 273  
275 274 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
net/mac80211/debugfs_key.h
... ... @@ -2,18 +2,14 @@
2 2 #define __MAC80211_DEBUGFS_KEY_H
3 3  
4 4 #ifdef CONFIG_MAC80211_DEBUGFS
5   -void ieee80211_debugfs_key_add(struct ieee80211_local *local,
6   - struct ieee80211_key *key);
  5 +void ieee80211_debugfs_key_add(struct ieee80211_key *key);
7 6 void ieee80211_debugfs_key_remove(struct ieee80211_key *key);
8 7 void ieee80211_debugfs_key_add_default(struct ieee80211_sub_if_data *sdata);
9 8 void ieee80211_debugfs_key_remove_default(struct ieee80211_sub_if_data *sdata);
10   -void ieee80211_debugfs_key_sta_link(struct ieee80211_key *key,
11   - struct sta_info *sta);
12 9 void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
13 10 struct sta_info *sta);
14 11 #else
15   -static inline void ieee80211_debugfs_key_add(struct ieee80211_local *local,
16   - struct ieee80211_key *key)
  12 +static inline void ieee80211_debugfs_key_add(struct ieee80211_key *key)
17 13 {}
18 14 static inline void ieee80211_debugfs_key_remove(struct ieee80211_key *key)
19 15 {}
... ... @@ -22,9 +18,6 @@
22 18 {}
23 19 static inline void ieee80211_debugfs_key_remove_default(
24 20 struct ieee80211_sub_if_data *sdata)
25   -{}
26   -static inline void ieee80211_debugfs_key_sta_link(
27   - struct ieee80211_key *key, struct sta_info *sta)
28 21 {}
29 22 static inline void ieee80211_debugfs_key_sta_del(struct ieee80211_key *key,
30 23 struct sta_info *sta)
net/mac80211/ieee80211.c
... ... @@ -1868,6 +1868,12 @@
1868 1868 {
1869 1869 rc80211_pid_exit();
1870 1870  
  1871 + /*
  1872 + * For key todo, it'll be empty by now but the work
  1873 + * might still be scheduled.
  1874 + */
  1875 + flush_scheduled_work();
  1876 +
1871 1877 if (mesh_allocated)
1872 1878 ieee80211s_stop();
1873 1879  
net/mac80211/ieee80211_i.h
... ... @@ -600,8 +600,8 @@
600 600 /*
601 601 * The lock only protects the list, hash, timer and counter
602 602 * against manipulation, reads are done in RCU. Additionally,
603   - * the lock protects each BSS's TIM bitmap and a few items
604   - * in a STA info structure.
  603 + * the lock protects each BSS's TIM bitmap, a few items in
  604 + * STA info structures and various key pointers.
605 605 */
606 606 spinlock_t sta_lock;
607 607 unsigned long num_sta;
net/mac80211/ieee80211_ioctl.c
... ... @@ -36,6 +36,7 @@
36 36 struct sta_info *sta;
37 37 struct ieee80211_key *key;
38 38 struct ieee80211_sub_if_data *sdata;
  39 + int err;
39 40  
40 41 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
41 42  
42 43  
43 44  
44 45  
45 46  
... ... @@ -46,24 +47,32 @@
46 47 }
47 48  
48 49 if (remove) {
  50 + rcu_read_lock();
  51 +
  52 + err = 0;
  53 +
49 54 if (is_broadcast_ether_addr(sta_addr)) {
50 55 key = sdata->keys[idx];
51 56 } else {
52 57 sta = sta_info_get(local, sta_addr);
53   - if (!sta)
54   - return -ENOENT;
  58 + if (!sta) {
  59 + err = -ENOENT;
  60 + goto out_unlock;
  61 + }
55 62 key = sta->key;
56 63 }
57 64  
58 65 ieee80211_key_free(key);
59   - return 0;
60 66 } else {
61 67 key = ieee80211_key_alloc(alg, idx, key_len, _key);
62 68 if (!key)
63 69 return -ENOMEM;
64 70  
65 71 sta = NULL;
  72 + err = 0;
66 73  
  74 + rcu_read_lock();
  75 +
67 76 if (!is_broadcast_ether_addr(sta_addr)) {
68 77 set_tx_key = 0;
69 78 /*
70 79  
... ... @@ -74,13 +83,15 @@
74 83 */
75 84 if (idx != 0 && alg != ALG_WEP) {
76 85 ieee80211_key_free(key);
77   - return -EINVAL;
  86 + err = -EINVAL;
  87 + goto out_unlock;
78 88 }
79 89  
80 90 sta = sta_info_get(local, sta_addr);
81 91 if (!sta) {
82 92 ieee80211_key_free(key);
83   - return -ENOENT;
  93 + err = -ENOENT;
  94 + goto out_unlock;
84 95 }
85 96 }
86 97  
... ... @@ -90,7 +101,10 @@
90 101 ieee80211_set_default_key(sdata, idx);
91 102 }
92 103  
93   - return 0;
  104 + out_unlock:
  105 + rcu_read_unlock();
  106 +
  107 + return err;
94 108 }
95 109  
96 110 static int ieee80211_ioctl_siwgenie(struct net_device *dev,
net/mac80211/ieee80211_key.h
... ... @@ -51,13 +51,19 @@
51 51 *
52 52 * @KEY_FLAG_UPLOADED_TO_HARDWARE: Indicates that this key is present
53 53 * in the hardware for TX crypto hardware acceleration.
54   - * @KEY_FLAG_REMOVE_FROM_HARDWARE: Indicates to the key code that this
55   - * key is present in the hardware (but it cannot be used for
56   - * hardware acceleration any more!)
  54 + * @KEY_FLAG_TODO_DELETE: Key is marked for deletion and will, after an
  55 + * RCU grace period, no longer be reachable other than from the
  56 + * todo list.
  57 + * @KEY_FLAG_TODO_HWACCEL: Key needs to be added to hardware acceleration.
  58 + * @KEY_FLAG_TODO_DEFKEY: Key is default key and debugfs needs to be updated.
  59 + * @KEY_FLAG_TODO_ADD_DEBUGFS: Key needs to be added to debugfs.
57 60 */
58 61 enum ieee80211_internal_key_flags {
59 62 KEY_FLAG_UPLOADED_TO_HARDWARE = BIT(0),
60   - KEY_FLAG_REMOVE_FROM_HARDWARE = BIT(1),
  63 + KEY_FLAG_TODO_DELETE = BIT(1),
  64 + KEY_FLAG_TODO_HWACCEL = BIT(2),
  65 + KEY_FLAG_TODO_DEFKEY = BIT(3),
  66 + KEY_FLAG_TODO_ADD_DEBUGFS = BIT(4),
61 67 };
62 68  
63 69 struct ieee80211_key {
64 70  
65 71  
... ... @@ -65,8 +71,12 @@
65 71 struct ieee80211_sub_if_data *sdata;
66 72 struct sta_info *sta;
67 73  
  74 + /* for sdata list */
68 75 struct list_head list;
  76 + /* for todo list */
  77 + struct list_head todo;
69 78  
  79 + /* protected by todo lock! */
70 80 unsigned int flags;
71 81  
72 82 union {
... ... @@ -141,6 +151,8 @@
141 151 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata);
142 152 void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata);
143 153 void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata);
  154 +
  155 +void ieee80211_key_todo(void);
144 156  
145 157 #endif /* IEEE80211_KEY_H */
net/mac80211/ieee80211_sta.c
... ... @@ -952,11 +952,8 @@
952 952  
953 953 rcu_read_unlock();
954 954  
955   - if (disassoc && sta) {
956   - rtnl_lock();
  955 + if (disassoc && sta)
957 956 sta_info_destroy(sta);
958   - rtnl_unlock();
959   - }
960 957  
961 958 if (disassoc) {
962 959 ifsta->state = IEEE80211_DISABLED;
963 960  
... ... @@ -3104,12 +3101,8 @@
3104 3101 }
3105 3102 spin_unlock_irqrestore(&local->sta_lock, flags);
3106 3103  
3107   - synchronize_rcu();
3108   -
3109   - rtnl_lock();
3110 3104 list_for_each_entry_safe(sta, tmp, &tmp_list, list)
3111 3105 sta_info_destroy(sta);
3112   - rtnl_unlock();
3113 3106 }
3114 3107  
3115 3108  
... ... @@ -2,7 +2,7 @@
2 2 * Copyright 2002-2005, Instant802 Networks, Inc.
3 3 * Copyright 2005-2006, Devicescape Software, Inc.
4 4 * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
5   - * Copyright 2007 Johannes Berg <johannes@sipsolutions.net>
  5 + * Copyright 2007-2008 Johannes Berg <johannes@sipsolutions.net>
6 6 *
7 7 * This program is free software; you can redistribute it and/or modify
8 8 * it under the terms of the GNU General Public License version 2 as
9 9  
10 10  
... ... @@ -33,17 +33,78 @@
33 33 * There is currently no way of knowing this except by looking into
34 34 * debugfs.
35 35 *
36   - * All operations here are called under RTNL so no extra locking is
37   - * required.
  36 + * All key operations are protected internally so you can call them at
  37 + * any time.
38 38 *
39   - * NOTE: This code requires that sta info *destruction* is done under
40   - * RTNL, otherwise it can try to access already freed STA structs
41   - * when a STA key is being freed.
  39 + * Within mac80211, key references are, just as STA structure references,
  40 + * protected by RCU. Note, however, that some things are unprotected,
  41 + * namely the key->sta dereferences within the hardware acceleration
  42 + * functions. This means that sta_info_destroy() must flush the key todo
  43 + * list.
  44 + *
  45 + * All the direct key list manipulation functions must not sleep because
  46 + * they can operate on STA info structs that are protected by RCU.
42 47 */
43 48  
44 49 static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
45 50 static const u8 zero_addr[ETH_ALEN];
46 51  
  52 +/* key mutex: used to synchronise todo runners */
  53 +static DEFINE_MUTEX(key_mutex);
  54 +static DEFINE_SPINLOCK(todo_lock);
  55 +static LIST_HEAD(todo_list);
  56 +
  57 +static void key_todo(struct work_struct *work)
  58 +{
  59 + ieee80211_key_todo();
  60 +}
  61 +
  62 +static DECLARE_WORK(todo_work, key_todo);
  63 +
  64 +/**
  65 + * add_todo - add todo item for a key
  66 + *
  67 + * @key: key to add to do item for
  68 + * @flag: todo flag(s)
  69 + */
  70 +static void add_todo(struct ieee80211_key *key, u32 flag)
  71 +{
  72 + if (!key)
  73 + return;
  74 +
  75 + spin_lock(&todo_lock);
  76 + key->flags |= flag;
  77 + /* only add if not already added */
  78 + if (list_empty(&key->todo))
  79 + list_add(&key->todo, &todo_list);
  80 + schedule_work(&todo_work);
  81 + spin_unlock(&todo_lock);
  82 +}
  83 +
  84 +/**
  85 + * ieee80211_key_lock - lock the mac80211 key operation lock
  86 + *
  87 + * This locks the (global) mac80211 key operation lock, all
  88 + * key operations must be done under this lock.
  89 + */
  90 +static void ieee80211_key_lock(void)
  91 +{
  92 + mutex_lock(&key_mutex);
  93 +}
  94 +
  95 +/**
  96 + * ieee80211_key_unlock - unlock the mac80211 key operation lock
  97 + */
  98 +static void ieee80211_key_unlock(void)
  99 +{
  100 + mutex_unlock(&key_mutex);
  101 +}
  102 +
  103 +static void assert_key_lock(void)
  104 +{
  105 + WARN_ON(!mutex_is_locked(&key_mutex));
  106 +}
  107 +
47 108 static const u8 *get_mac_for_key(struct ieee80211_key *key)
48 109 {
49 110 const u8 *addr = bcast_addr;
50 111  
51 112  
52 113  
... ... @@ -70,26 +131,23 @@
70 131 int ret;
71 132 DECLARE_MAC_BUF(mac);
72 133  
  134 + assert_key_lock();
  135 + might_sleep();
  136 +
73 137 if (!key->local->ops->set_key)
74 138 return;
75 139  
76   - /*
77   - * This makes sure that all pending flushes have
78   - * actually completed prior to uploading new key
79   - * material to the hardware. That is necessary to
80   - * avoid races between flushing STAs and adding
81   - * new keys for them.
82   - */
83   - __ieee80211_run_pending_flush(key->local);
84   -
85 140 addr = get_mac_for_key(key);
86 141  
87 142 ret = key->local->ops->set_key(local_to_hw(key->local), SET_KEY,
88 143 key->sdata->dev->dev_addr, addr,
89 144 &key->conf);
90 145  
91   - if (!ret)
  146 + if (!ret) {
  147 + spin_lock(&todo_lock);
92 148 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
  149 + spin_unlock(&todo_lock);
  150 + }
93 151  
94 152 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
95 153 printk(KERN_ERR "mac80211-%s: failed to set key "
96 154  
97 155  
98 156  
... ... @@ -98,26 +156,24 @@
98 156 key->conf.keyidx, print_mac(mac, addr), ret);
99 157 }
100 158  
101   -static void ieee80211_key_mark_hw_accel_off(struct ieee80211_key *key)
102   -{
103   - if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) {
104   - key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
105   - key->flags |= KEY_FLAG_REMOVE_FROM_HARDWARE;
106   - }
107   -}
108   -
109 159 static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
110 160 {
111 161 const u8 *addr;
112 162 int ret;
113 163 DECLARE_MAC_BUF(mac);
114 164  
  165 + assert_key_lock();
  166 + might_sleep();
  167 +
115 168 if (!key || !key->local->ops->set_key)
116 169 return;
117 170  
118   - if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE) &&
119   - !(key->flags & KEY_FLAG_REMOVE_FROM_HARDWARE))
  171 + spin_lock(&todo_lock);
  172 + if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) {
  173 + spin_unlock(&todo_lock);
120 174 return;
  175 + }
  176 + spin_unlock(&todo_lock);
121 177  
122 178 addr = get_mac_for_key(key);
123 179  
124 180  
... ... @@ -131,10 +187,74 @@
131 187 wiphy_name(key->local->hw.wiphy),
132 188 key->conf.keyidx, print_mac(mac, addr), ret);
133 189  
134   - key->flags &= ~(KEY_FLAG_UPLOADED_TO_HARDWARE |
135   - KEY_FLAG_REMOVE_FROM_HARDWARE);
  190 + spin_lock(&todo_lock);
  191 + key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
  192 + spin_unlock(&todo_lock);
136 193 }
137 194  
  195 +static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
  196 + int idx)
  197 +{
  198 + struct ieee80211_key *key = NULL;
  199 +
  200 + if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
  201 + key = sdata->keys[idx];
  202 +
  203 + rcu_assign_pointer(sdata->default_key, key);
  204 +
  205 + if (key)
  206 + add_todo(key, KEY_FLAG_TODO_DEFKEY);
  207 +}
  208 +
  209 +void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
  210 +{
  211 + unsigned long flags;
  212 +
  213 + spin_lock_irqsave(&sdata->local->sta_lock, flags);
  214 + __ieee80211_set_default_key(sdata, idx);
  215 + spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
  216 +}
  217 +
  218 +
  219 +static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
  220 + struct sta_info *sta,
  221 + struct ieee80211_key *old,
  222 + struct ieee80211_key *new)
  223 +{
  224 + int idx, defkey;
  225 +
  226 + if (new)
  227 + list_add(&new->list, &sdata->key_list);
  228 +
  229 + if (sta) {
  230 + rcu_assign_pointer(sta->key, new);
  231 + } else {
  232 + WARN_ON(new && old && new->conf.keyidx != old->conf.keyidx);
  233 +
  234 + if (old)
  235 + idx = old->conf.keyidx;
  236 + else
  237 + idx = new->conf.keyidx;
  238 +
  239 + defkey = old && sdata->default_key == old;
  240 +
  241 + if (defkey && !new)
  242 + __ieee80211_set_default_key(sdata, -1);
  243 +
  244 + rcu_assign_pointer(sdata->keys[idx], new);
  245 + if (defkey && new)
  246 + __ieee80211_set_default_key(sdata, new->conf.keyidx);
  247 + }
  248 +
  249 + if (old) {
  250 + /*
  251 + * We'll use an empty list to indicate that the key
  252 + * has already been removed.
  253 + */
  254 + list_del_init(&old->list);
  255 + }
  256 +}
  257 +
138 258 struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
139 259 int idx,
140 260 size_t key_len,
... ... @@ -160,6 +280,7 @@
160 280 key->conf.keylen = key_len;
161 281 memcpy(key->conf.key, key_data, key_len);
162 282 INIT_LIST_HEAD(&key->list);
  283 + INIT_LIST_HEAD(&key->todo);
163 284  
164 285 if (alg == ALG_CCMP) {
165 286 /*
... ... @@ -168,7 +289,7 @@
168 289 */
169 290 key->u.ccmp.tfm = ieee80211_aes_key_setup_encrypt(key_data);
170 291 if (!key->u.ccmp.tfm) {
171   - ieee80211_key_free(key);
  292 + kfree(key);
172 293 return NULL;
173 294 }
174 295 }
175 296  
176 297  
... ... @@ -176,56 +297,14 @@
176 297 return key;
177 298 }
178 299  
179   -static void __ieee80211_key_replace(struct ieee80211_sub_if_data *sdata,
180   - struct sta_info *sta,
181   - struct ieee80211_key *key,
182   - struct ieee80211_key *new)
183   -{
184   - int idx, defkey;
185   -
186   - if (new)
187   - list_add(&new->list, &sdata->key_list);
188   -
189   - if (sta) {
190   - rcu_assign_pointer(sta->key, new);
191   - } else {
192   - WARN_ON(new && key && new->conf.keyidx != key->conf.keyidx);
193   -
194   - if (key)
195   - idx = key->conf.keyidx;
196   - else
197   - idx = new->conf.keyidx;
198   -
199   - defkey = key && sdata->default_key == key;
200   -
201   - if (defkey && !new)
202   - ieee80211_set_default_key(sdata, -1);
203   -
204   - rcu_assign_pointer(sdata->keys[idx], new);
205   - if (defkey && new)
206   - ieee80211_set_default_key(sdata, new->conf.keyidx);
207   - }
208   -
209   - if (key) {
210   - ieee80211_key_mark_hw_accel_off(key);
211   - /*
212   - * We'll use an empty list to indicate that the key
213   - * has already been removed.
214   - */
215   - list_del_init(&key->list);
216   - }
217   -}
218   -
219 300 void ieee80211_key_link(struct ieee80211_key *key,
220 301 struct ieee80211_sub_if_data *sdata,
221 302 struct sta_info *sta)
222 303 {
223 304 struct ieee80211_key *old_key;
  305 + unsigned long flags;
224 306 int idx;
225 307  
226   - ASSERT_RTNL();
227   - might_sleep();
228   -
229 308 BUG_ON(!sdata);
230 309 BUG_ON(!key);
231 310  
232 311  
... ... @@ -234,11 +313,7 @@
234 313 key->sdata = sdata;
235 314 key->sta = sta;
236 315  
237   - ieee80211_debugfs_key_add(key->local, key);
238   -
239 316 if (sta) {
240   - ieee80211_debugfs_key_sta_link(key, sta);
241   -
242 317 /*
243 318 * some hardware cannot handle TKIP with QoS, so
244 319 * we indicate whether QoS could be in use.
... ... @@ -249,7 +324,10 @@
249 324 if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
250 325 struct sta_info *ap;
251 326  
252   - rcu_read_lock();
  327 + /*
  328 + * We're getting a sta pointer in,
  329 + * so must be under RCU read lock.
  330 + */
253 331  
254 332 /* same here, the AP could be using QoS */
255 333 ap = sta_info_get(key->local, key->sdata->u.sta.bssid);
256 334  
... ... @@ -258,11 +336,11 @@
258 336 key->conf.flags |=
259 337 IEEE80211_KEY_FLAG_WMM_STA;
260 338 }
261   -
262   - rcu_read_unlock();
263 339 }
264 340 }
265 341  
  342 + spin_lock_irqsave(&sdata->local->sta_lock, flags);
  343 +
266 344 if (sta)
267 345 old_key = sta->key;
268 346 else
269 347  
270 348  
271 349  
272 350  
273 351  
274 352  
275 353  
276 354  
277 355  
... ... @@ -270,51 +348,74 @@
270 348  
271 349 __ieee80211_key_replace(sdata, sta, old_key, key);
272 350  
273   - if (old_key) {
274   - synchronize_rcu();
275   - ieee80211_key_free(old_key);
276   - }
  351 + spin_unlock_irqrestore(&sdata->local->sta_lock, flags);
277 352  
  353 + /* free old key later */
  354 + add_todo(old_key, KEY_FLAG_TODO_DELETE);
  355 +
  356 + add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS);
278 357 if (netif_running(sdata->dev))
279   - ieee80211_key_enable_hw_accel(key);
  358 + add_todo(key, KEY_FLAG_TODO_HWACCEL);
280 359 }
281 360  
282 361 void ieee80211_key_free(struct ieee80211_key *key)
283 362 {
284   - ASSERT_RTNL();
285   - might_sleep();
  363 + unsigned long flags;
286 364  
287 365 if (!key)
288 366 return;
289 367  
  368 + /*
  369 + * Replace key with nothingness if it was ever used.
  370 + */
290 371 if (key->sdata) {
291   - /*
292   - * Replace key with nothingness.
293   - *
294   - * Because other code may have key reference (RCU protected)
295   - * right now, we then wait for a grace period before freeing
296   - * it.
297   - * An empty list indicates it was never added to the key list
298   - * or has been removed already. It may, however, still be in
299   - * hardware for acceleration.
300   - */
301   - if (!list_empty(&key->list))
302   - __ieee80211_key_replace(key->sdata, key->sta,
303   - key, NULL);
  372 + spin_lock_irqsave(&key->sdata->local->sta_lock, flags);
  373 + __ieee80211_key_replace(key->sdata, key->sta,
  374 + key, NULL);
  375 + spin_unlock_irqrestore(&key->sdata->local->sta_lock, flags);
  376 + }
304 377  
305   - /*
306   - * Do NOT remove this without looking at sta_info_destroy()
307   - */
308   - synchronize_rcu();
  378 + add_todo(key, KEY_FLAG_TODO_DELETE);
  379 +}
309 380  
310   - /*
311   - * Remove from hwaccel if appropriate, this will
312   - * only happen when the key is actually unlinked,
313   - * it will already be done when the key was replaced.
314   - */
  381 +void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
  382 +{
  383 + struct ieee80211_key *key;
  384 +
  385 + might_sleep();
  386 +
  387 + if (WARN_ON(!netif_running(sdata->dev)))
  388 + return;
  389 +
  390 + ieee80211_key_lock();
  391 +
  392 + list_for_each_entry(key, &sdata->key_list, list)
  393 + ieee80211_key_enable_hw_accel(key);
  394 +
  395 + ieee80211_key_unlock();
  396 +}
  397 +
  398 +void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
  399 +{
  400 + struct ieee80211_key *key;
  401 +
  402 + might_sleep();
  403 +
  404 + ieee80211_key_lock();
  405 +
  406 + list_for_each_entry(key, &sdata->key_list, list)
315 407 ieee80211_key_disable_hw_accel(key);
316   - }
317 408  
  409 + ieee80211_key_unlock();
  410 +}
  411 +
  412 +static void __ieee80211_key_free(struct ieee80211_key *key)
  413 +{
  414 + if (!key)
  415 + return;
  416 +
  417 + ieee80211_key_disable_hw_accel(key);
  418 +
318 419 if (key->conf.alg == ALG_CCMP)
319 420 ieee80211_aes_key_free(key->u.ccmp.tfm);
320 421 ieee80211_debugfs_key_remove(key);
321 422  
322 423  
323 424  
324 425  
325 426  
326 427  
327 428  
328 429  
329 430  
330 431  
331 432  
332 433  
... ... @@ -322,57 +423,76 @@
322 423 kfree(key);
323 424 }
324 425  
325   -void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
  426 +static void __ieee80211_key_todo(void)
326 427 {
327   - struct ieee80211_key *key = NULL;
  428 + struct ieee80211_key *key;
  429 + bool work_done;
  430 + u32 todoflags;
328 431  
329   - if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
330   - key = sdata->keys[idx];
  432 + /*
  433 + * NB: sta_info_destroy relies on this!
  434 + */
  435 + synchronize_rcu();
331 436  
332   - if (sdata->default_key != key) {
333   - ieee80211_debugfs_key_remove_default(sdata);
  437 + spin_lock(&todo_lock);
  438 + while (!list_empty(&todo_list)) {
  439 + key = list_first_entry(&todo_list, struct ieee80211_key, todo);
  440 + list_del_init(&key->todo);
  441 + todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
  442 + KEY_FLAG_TODO_DEFKEY |
  443 + KEY_FLAG_TODO_HWACCEL |
  444 + KEY_FLAG_TODO_DELETE);
  445 + key->flags &= ~todoflags;
  446 + spin_unlock(&todo_lock);
334 447  
335   - rcu_assign_pointer(sdata->default_key, key);
  448 + work_done = false;
336 449  
337   - if (sdata->default_key)
338   - ieee80211_debugfs_key_add_default(sdata);
  450 + if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
  451 + ieee80211_debugfs_key_add(key);
  452 + work_done = true;
  453 + }
  454 + if (todoflags & KEY_FLAG_TODO_DEFKEY) {
  455 + ieee80211_debugfs_key_remove_default(key->sdata);
  456 + ieee80211_debugfs_key_add_default(key->sdata);
  457 + work_done = true;
  458 + }
  459 + if (todoflags & KEY_FLAG_TODO_HWACCEL) {
  460 + ieee80211_key_enable_hw_accel(key);
  461 + work_done = true;
  462 + }
  463 + if (todoflags & KEY_FLAG_TODO_DELETE) {
  464 + __ieee80211_key_free(key);
  465 + work_done = true;
  466 + }
  467 +
  468 + WARN_ON(!work_done);
  469 +
  470 + spin_lock(&todo_lock);
339 471 }
  472 + spin_unlock(&todo_lock);
340 473 }
341 474  
  475 +void ieee80211_key_todo(void)
  476 +{
  477 + ieee80211_key_lock();
  478 + __ieee80211_key_todo();
  479 + ieee80211_key_unlock();
  480 +}
  481 +
342 482 void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
343 483 {
344 484 struct ieee80211_key *key, *tmp;
345 485 LIST_HEAD(tmp_list);
346 486  
347   - ASSERT_RTNL();
348   - might_sleep();
  487 + ieee80211_key_lock();
349 488  
  489 + ieee80211_debugfs_key_remove_default(sdata);
  490 +
350 491 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
351 492 ieee80211_key_free(key);
352   -}
353 493  
354   -void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
355   -{
356   - struct ieee80211_key *key;
  494 + __ieee80211_key_todo();
357 495  
358   - ASSERT_RTNL();
359   - might_sleep();
360   -
361   - if (WARN_ON(!netif_running(sdata->dev)))
362   - return;
363   -
364   - list_for_each_entry(key, &sdata->key_list, list)
365   - ieee80211_key_enable_hw_accel(key);
366   -}
367   -
368   -void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
369   -{
370   - struct ieee80211_key *key;
371   -
372   - ASSERT_RTNL();
373   - might_sleep();
374   -
375   - list_for_each_entry(key, &sdata->key_list, list)
376   - ieee80211_key_disable_hw_accel(key);
  496 + ieee80211_key_unlock();
377 497 }
net/mac80211/sta_info.c
... ... @@ -51,17 +51,15 @@
51 51 *
52 52 * In order to remove a STA info structure, the caller needs to first
53 53 * unlink it (sta_info_unlink()) from the list and hash tables and
54   - * then destroy it while holding the RTNL; sta_info_destroy() will wait
55   - * for an RCU grace period to elapse before actually freeing it. Due to
56   - * the pinning and the possibility of multiple callers trying to remove
57   - * the same STA info at the same time, sta_info_unlink() can clear the
58   - * STA info pointer it is passed to indicate that the STA info is owned
59   - * by somebody else now.
  54 + * then destroy it; sta_info_destroy() will wait for an RCU grace period
  55 + * to elapse before actually freeing it. Due to the pinning and the
  56 + * possibility of multiple callers trying to remove the same STA info at
  57 + * the same time, sta_info_unlink() can clear the STA info pointer it is
  58 + * passed to indicate that the STA info is owned by somebody else now.
60 59 *
61 60 * If sta_info_unlink() did not clear the pointer then the caller owns
62 61 * the STA info structure now and is responsible of destroying it with
63   - * a call to sta_info_destroy(), not before RCU synchronisation, of
64   - * course. Note that sta_info_destroy() must be protected by the RTNL.
  62 + * a call to sta_info_destroy().
65 63 *
66 64 * In all other cases, there is no concept of ownership on a STA entry,
67 65 * each structure is owned by the global hash table/list until it is
... ... @@ -164,7 +162,6 @@
164 162 struct sk_buff *skb;
165 163 int i;
166 164  
167   - ASSERT_RTNL();
168 165 might_sleep();
169 166  
170 167 if (!sta)
... ... @@ -180,22 +177,16 @@
180 177 mesh_plink_deactivate(sta);
181 178 #endif
182 179  
183   - if (sta->key) {
184   - /*
185   - * NOTE: This will call synchronize_rcu() internally to
186   - * make sure no key references can be in use. We rely on
187   - * that when we take this branch to make sure nobody can
188   - * reference this STA struct any longer!
189   - */
190   - ieee80211_key_free(sta->key);
191   - WARN_ON(sta->key);
192   - } else {
193   - /*
194   - * Make sure that nobody can reference this STA struct
195   - * any longer.
196   - */
197   - synchronize_rcu();
198   - }
  180 + /*
  181 + * We have only unlinked the key, and actually destroying it
  182 + * may mean it is removed from hardware which requires that
  183 + * the key->sta pointer is still valid, so flush the key todo
  184 + * list here.
  185 + *
  186 + * ieee80211_key_todo() will synchronize_rcu() so after this
  187 + * nothing can reference this sta struct any more.
  188 + */
  189 + ieee80211_key_todo();
199 190  
200 191 #ifdef CONFIG_MAC80211_MESH
201 192 if (ieee80211_vif_is_mesh(&sta->sdata->vif))
... ... @@ -439,6 +430,11 @@
439 430 return;
440 431 }
441 432  
  433 + if ((*sta)->key) {
  434 + ieee80211_key_free((*sta)->key);
  435 + WARN_ON((*sta)->key);
  436 + }
  437 +
442 438 list_del(&(*sta)->list);
443 439  
444 440 if ((*sta)->flags & WLAN_STA_PS) {
... ... @@ -652,7 +648,7 @@
652 648 }
653 649 #endif
654 650  
655   -void __ieee80211_run_pending_flush(struct ieee80211_local *local)
  651 +static void __ieee80211_run_pending_flush(struct ieee80211_local *local)
656 652 {
657 653 struct sta_info *sta;
658 654 unsigned long flags;
net/mac80211/sta_info.h
... ... @@ -359,7 +359,6 @@
359 359 int sta_info_flush(struct ieee80211_local *local,
360 360 struct ieee80211_sub_if_data *sdata);
361 361 void sta_info_flush_delayed(struct ieee80211_sub_if_data *sdata);
362   -void __ieee80211_run_pending_flush(struct ieee80211_local *local);
363 362  
364 363 #endif /* STA_INFO_H */