aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/key.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/key.c')
-rw-r--r--net/mac80211/key.c304
1 files changed, 74 insertions, 230 deletions
diff --git a/net/mac80211/key.c b/net/mac80211/key.c
index 659a42d529e3..1b9d87ed143a 100644
--- a/net/mac80211/key.c
+++ b/net/mac80211/key.c
@@ -14,6 +14,7 @@
14#include <linux/list.h> 14#include <linux/list.h>
15#include <linux/rcupdate.h> 15#include <linux/rcupdate.h>
16#include <linux/rtnetlink.h> 16#include <linux/rtnetlink.h>
17#include <linux/slab.h>
17#include <net/mac80211.h> 18#include <net/mac80211.h>
18#include "ieee80211_i.h" 19#include "ieee80211_i.h"
19#include "driver-ops.h" 20#include "driver-ops.h"
@@ -35,80 +36,20 @@
35 * There is currently no way of knowing this except by looking into 36 * There is currently no way of knowing this except by looking into
36 * debugfs. 37 * debugfs.
37 * 38 *
38 * All key operations are protected internally so you can call them at 39 * All key operations are protected internally.
39 * any time.
40 * 40 *
41 * Within mac80211, key references are, just as STA structure references, 41 * Within mac80211, key references are, just as STA structure references,
42 * protected by RCU. Note, however, that some things are unprotected, 42 * protected by RCU. Note, however, that some things are unprotected,
43 * namely the key->sta dereferences within the hardware acceleration 43 * namely the key->sta dereferences within the hardware acceleration
44 * functions. This means that sta_info_destroy() must flush the key todo 44 * functions. This means that sta_info_destroy() must remove the key
45 * list. 45 * which waits for an RCU grace period.
46 *
47 * All the direct key list manipulation functions must not sleep because
48 * they can operate on STA info structs that are protected by RCU.
49 */ 46 */
50 47
51static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }; 48static const u8 bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
52 49
53/* key mutex: used to synchronise todo runners */ 50static void assert_key_lock(struct ieee80211_local *local)
54static DEFINE_MUTEX(key_mutex);
55static DEFINE_SPINLOCK(todo_lock);
56static LIST_HEAD(todo_list);
57
58static void key_todo(struct work_struct *work)
59{
60 ieee80211_key_todo();
61}
62
63static DECLARE_WORK(todo_work, key_todo);
64
65/**
66 * add_todo - add todo item for a key
67 *
68 * @key: key to add to do item for
69 * @flag: todo flag(s)
70 *
71 * Must be called with IRQs or softirqs disabled.
72 */
73static void add_todo(struct ieee80211_key *key, u32 flag)
74{
75 if (!key)
76 return;
77
78 spin_lock(&todo_lock);
79 key->flags |= flag;
80 /*
81 * Remove again if already on the list so that we move it to the end.
82 */
83 if (!list_empty(&key->todo))
84 list_del(&key->todo);
85 list_add_tail(&key->todo, &todo_list);
86 schedule_work(&todo_work);
87 spin_unlock(&todo_lock);
88}
89
90/**
91 * ieee80211_key_lock - lock the mac80211 key operation lock
92 *
93 * This locks the (global) mac80211 key operation lock, all
94 * key operations must be done under this lock.
95 */
96static void ieee80211_key_lock(void)
97{
98 mutex_lock(&key_mutex);
99}
100
101/**
102 * ieee80211_key_unlock - unlock the mac80211 key operation lock
103 */
104static void ieee80211_key_unlock(void)
105{
106 mutex_unlock(&key_mutex);
107}
108
109static void assert_key_lock(void)
110{ 51{
111 WARN_ON(!mutex_is_locked(&key_mutex)); 52 WARN_ON(!mutex_is_locked(&local->key_mtx));
112} 53}
113 54
114static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key) 55static struct ieee80211_sta *get_sta_for_key(struct ieee80211_key *key)
@@ -125,12 +66,13 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
125 struct ieee80211_sta *sta; 66 struct ieee80211_sta *sta;
126 int ret; 67 int ret;
127 68
128 assert_key_lock();
129 might_sleep(); 69 might_sleep();
130 70
131 if (!key->local->ops->set_key) 71 if (!key->local->ops->set_key)
132 return; 72 return;
133 73
74 assert_key_lock(key->local);
75
134 sta = get_sta_for_key(key); 76 sta = get_sta_for_key(key);
135 77
136 sdata = key->sdata; 78 sdata = key->sdata;
@@ -139,13 +81,10 @@ static void ieee80211_key_enable_hw_accel(struct ieee80211_key *key)
139 struct ieee80211_sub_if_data, 81 struct ieee80211_sub_if_data,
140 u.ap); 82 u.ap);
141 83
142 ret = drv_set_key(key->local, SET_KEY, &sdata->vif, sta, &key->conf); 84 ret = drv_set_key(key->local, SET_KEY, sdata, sta, &key->conf);
143 85
144 if (!ret) { 86 if (!ret)
145 spin_lock_bh(&todo_lock);
146 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE; 87 key->flags |= KEY_FLAG_UPLOADED_TO_HARDWARE;
147 spin_unlock_bh(&todo_lock);
148 }
149 88
150 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP) 89 if (ret && ret != -ENOSPC && ret != -EOPNOTSUPP)
151 printk(KERN_ERR "mac80211-%s: failed to set key " 90 printk(KERN_ERR "mac80211-%s: failed to set key "
@@ -160,18 +99,15 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
160 struct ieee80211_sta *sta; 99 struct ieee80211_sta *sta;
161 int ret; 100 int ret;
162 101
163 assert_key_lock();
164 might_sleep(); 102 might_sleep();
165 103
166 if (!key || !key->local->ops->set_key) 104 if (!key || !key->local->ops->set_key)
167 return; 105 return;
168 106
169 spin_lock_bh(&todo_lock); 107 assert_key_lock(key->local);
170 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE)) { 108
171 spin_unlock_bh(&todo_lock); 109 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
172 return; 110 return;
173 }
174 spin_unlock_bh(&todo_lock);
175 111
176 sta = get_sta_for_key(key); 112 sta = get_sta_for_key(key);
177 sdata = key->sdata; 113 sdata = key->sdata;
@@ -181,7 +117,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
181 struct ieee80211_sub_if_data, 117 struct ieee80211_sub_if_data,
182 u.ap); 118 u.ap);
183 119
184 ret = drv_set_key(key->local, DISABLE_KEY, &sdata->vif, 120 ret = drv_set_key(key->local, DISABLE_KEY, sdata,
185 sta, &key->conf); 121 sta, &key->conf);
186 122
187 if (ret) 123 if (ret)
@@ -190,9 +126,7 @@ static void ieee80211_key_disable_hw_accel(struct ieee80211_key *key)
190 wiphy_name(key->local->hw.wiphy), 126 wiphy_name(key->local->hw.wiphy),
191 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret); 127 key->conf.keyidx, sta ? sta->addr : bcast_addr, ret);
192 128
193 spin_lock_bh(&todo_lock);
194 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE; 129 key->flags &= ~KEY_FLAG_UPLOADED_TO_HARDWARE;
195 spin_unlock_bh(&todo_lock);
196} 130}
197 131
198static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, 132static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
@@ -200,22 +134,24 @@ static void __ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata,
200{ 134{
201 struct ieee80211_key *key = NULL; 135 struct ieee80211_key *key = NULL;
202 136
137 assert_key_lock(sdata->local);
138
203 if (idx >= 0 && idx < NUM_DEFAULT_KEYS) 139 if (idx >= 0 && idx < NUM_DEFAULT_KEYS)
204 key = sdata->keys[idx]; 140 key = sdata->keys[idx];
205 141
206 rcu_assign_pointer(sdata->default_key, key); 142 rcu_assign_pointer(sdata->default_key, key);
207 143
208 if (key) 144 if (key) {
209 add_todo(key, KEY_FLAG_TODO_DEFKEY); 145 ieee80211_debugfs_key_remove_default(key->sdata);
146 ieee80211_debugfs_key_add_default(key->sdata);
147 }
210} 148}
211 149
212void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx) 150void ieee80211_set_default_key(struct ieee80211_sub_if_data *sdata, int idx)
213{ 151{
214 unsigned long flags; 152 mutex_lock(&sdata->local->key_mtx);
215
216 spin_lock_irqsave(&sdata->local->key_lock, flags);
217 __ieee80211_set_default_key(sdata, idx); 153 __ieee80211_set_default_key(sdata, idx);
218 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 154 mutex_unlock(&sdata->local->key_mtx);
219} 155}
220 156
221static void 157static void
@@ -223,24 +159,26 @@ __ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, int idx)
223{ 159{
224 struct ieee80211_key *key = NULL; 160 struct ieee80211_key *key = NULL;
225 161
162 assert_key_lock(sdata->local);
163
226 if (idx >= NUM_DEFAULT_KEYS && 164 if (idx >= NUM_DEFAULT_KEYS &&
227 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS) 165 idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
228 key = sdata->keys[idx]; 166 key = sdata->keys[idx];
229 167
230 rcu_assign_pointer(sdata->default_mgmt_key, key); 168 rcu_assign_pointer(sdata->default_mgmt_key, key);
231 169
232 if (key) 170 if (key) {
233 add_todo(key, KEY_FLAG_TODO_DEFMGMTKEY); 171 ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
172 ieee80211_debugfs_key_add_mgmt_default(key->sdata);
173 }
234} 174}
235 175
236void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata, 176void ieee80211_set_default_mgmt_key(struct ieee80211_sub_if_data *sdata,
237 int idx) 177 int idx)
238{ 178{
239 unsigned long flags; 179 mutex_lock(&sdata->local->key_mtx);
240
241 spin_lock_irqsave(&sdata->local->key_lock, flags);
242 __ieee80211_set_default_mgmt_key(sdata, idx); 180 __ieee80211_set_default_mgmt_key(sdata, idx);
243 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 181 mutex_unlock(&sdata->local->key_mtx);
244} 182}
245 183
246 184
@@ -335,7 +273,7 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
335 key->conf.iv_len = CCMP_HDR_LEN; 273 key->conf.iv_len = CCMP_HDR_LEN;
336 key->conf.icv_len = CCMP_MIC_LEN; 274 key->conf.icv_len = CCMP_MIC_LEN;
337 if (seq) { 275 if (seq) {
338 for (i = 0; i < NUM_RX_DATA_QUEUES; i++) 276 for (i = 0; i < NUM_RX_DATA_QUEUES + 1; i++)
339 for (j = 0; j < CCMP_PN_LEN; j++) 277 for (j = 0; j < CCMP_PN_LEN; j++)
340 key->u.ccmp.rx_pn[i][j] = 278 key->u.ccmp.rx_pn[i][j] =
341 seq[CCMP_PN_LEN - j - 1]; 279 seq[CCMP_PN_LEN - j - 1];
@@ -351,7 +289,6 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
351 } 289 }
352 memcpy(key->conf.key, key_data, key_len); 290 memcpy(key->conf.key, key_data, key_len);
353 INIT_LIST_HEAD(&key->list); 291 INIT_LIST_HEAD(&key->list);
354 INIT_LIST_HEAD(&key->todo);
355 292
356 if (alg == ALG_CCMP) { 293 if (alg == ALG_CCMP) {
357 /* 294 /*
@@ -381,12 +318,29 @@ struct ieee80211_key *ieee80211_key_alloc(enum ieee80211_key_alg alg,
381 return key; 318 return key;
382} 319}
383 320
321static void __ieee80211_key_destroy(struct ieee80211_key *key)
322{
323 if (!key)
324 return;
325
326 if (key->local)
327 ieee80211_key_disable_hw_accel(key);
328
329 if (key->conf.alg == ALG_CCMP)
330 ieee80211_aes_key_free(key->u.ccmp.tfm);
331 if (key->conf.alg == ALG_AES_CMAC)
332 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
333 if (key->local)
334 ieee80211_debugfs_key_remove(key);
335
336 kfree(key);
337}
338
384void ieee80211_key_link(struct ieee80211_key *key, 339void ieee80211_key_link(struct ieee80211_key *key,
385 struct ieee80211_sub_if_data *sdata, 340 struct ieee80211_sub_if_data *sdata,
386 struct sta_info *sta) 341 struct sta_info *sta)
387{ 342{
388 struct ieee80211_key *old_key; 343 struct ieee80211_key *old_key;
389 unsigned long flags;
390 int idx; 344 int idx;
391 345
392 BUG_ON(!sdata); 346 BUG_ON(!sdata);
@@ -421,7 +375,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
421 */ 375 */
422 376
423 /* same here, the AP could be using QoS */ 377 /* same here, the AP could be using QoS */
424 ap = sta_info_get(key->local, key->sdata->u.mgd.bssid); 378 ap = sta_info_get(key->sdata, key->sdata->u.mgd.bssid);
425 if (ap) { 379 if (ap) {
426 if (test_sta_flags(ap, WLAN_STA_WME)) 380 if (test_sta_flags(ap, WLAN_STA_WME))
427 key->conf.flags |= 381 key->conf.flags |=
@@ -430,7 +384,7 @@ void ieee80211_key_link(struct ieee80211_key *key,
430 } 384 }
431 } 385 }
432 386
433 spin_lock_irqsave(&sdata->local->key_lock, flags); 387 mutex_lock(&sdata->local->key_mtx);
434 388
435 if (sta) 389 if (sta)
436 old_key = sta->key; 390 old_key = sta->key;
@@ -438,15 +392,13 @@ void ieee80211_key_link(struct ieee80211_key *key,
438 old_key = sdata->keys[idx]; 392 old_key = sdata->keys[idx];
439 393
440 __ieee80211_key_replace(sdata, sta, old_key, key); 394 __ieee80211_key_replace(sdata, sta, old_key, key);
395 __ieee80211_key_destroy(old_key);
441 396
442 /* free old key later */ 397 ieee80211_debugfs_key_add(key);
443 add_todo(old_key, KEY_FLAG_TODO_DELETE);
444 398
445 add_todo(key, KEY_FLAG_TODO_ADD_DEBUGFS); 399 ieee80211_key_enable_hw_accel(key);
446 if (netif_running(sdata->dev))
447 add_todo(key, KEY_FLAG_TODO_HWACCEL_ADD);
448 400
449 spin_unlock_irqrestore(&sdata->local->key_lock, flags); 401 mutex_unlock(&sdata->local->key_mtx);
450} 402}
451 403
452static void __ieee80211_key_free(struct ieee80211_key *key) 404static void __ieee80211_key_free(struct ieee80211_key *key)
@@ -457,170 +409,62 @@ static void __ieee80211_key_free(struct ieee80211_key *key)
457 if (key->sdata) 409 if (key->sdata)
458 __ieee80211_key_replace(key->sdata, key->sta, 410 __ieee80211_key_replace(key->sdata, key->sta,
459 key, NULL); 411 key, NULL);
460 412 __ieee80211_key_destroy(key);
461 add_todo(key, KEY_FLAG_TODO_DELETE);
462} 413}
463 414
464void ieee80211_key_free(struct ieee80211_key *key) 415void ieee80211_key_free(struct ieee80211_local *local,
416 struct ieee80211_key *key)
465{ 417{
466 unsigned long flags;
467
468 if (!key) 418 if (!key)
469 return; 419 return;
470 420
471 if (!key->sdata) { 421 mutex_lock(&local->key_mtx);
472 /* The key has not been linked yet, simply free it
473 * and don't Oops */
474 if (key->conf.alg == ALG_CCMP)
475 ieee80211_aes_key_free(key->u.ccmp.tfm);
476 kfree(key);
477 return;
478 }
479
480 spin_lock_irqsave(&key->sdata->local->key_lock, flags);
481 __ieee80211_key_free(key); 422 __ieee80211_key_free(key);
482 spin_unlock_irqrestore(&key->sdata->local->key_lock, flags); 423 mutex_unlock(&local->key_mtx);
483} 424}
484 425
485/* 426void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
486 * To be safe against concurrent manipulations of the list (which shouldn't
487 * actually happen) we need to hold the spinlock. But under the spinlock we
488 * can't actually do much, so we defer processing to the todo list. Then run
489 * the todo list to be sure the operation and possibly previously pending
490 * operations are completed.
491 */
492static void ieee80211_todo_for_each_key(struct ieee80211_sub_if_data *sdata,
493 u32 todo_flags)
494{ 427{
495 struct ieee80211_key *key; 428 struct ieee80211_key *key;
496 unsigned long flags;
497
498 might_sleep();
499
500 spin_lock_irqsave(&sdata->local->key_lock, flags);
501 list_for_each_entry(key, &sdata->key_list, list)
502 add_todo(key, todo_flags);
503 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
504 429
505 ieee80211_key_todo();
506}
507
508void ieee80211_enable_keys(struct ieee80211_sub_if_data *sdata)
509{
510 ASSERT_RTNL(); 430 ASSERT_RTNL();
511 431
512 if (WARN_ON(!netif_running(sdata->dev))) 432 if (WARN_ON(!ieee80211_sdata_running(sdata)))
513 return; 433 return;
514 434
515 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_ADD); 435 mutex_lock(&sdata->local->key_mtx);
516}
517 436
518void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata) 437 list_for_each_entry(key, &sdata->key_list, list)
519{ 438 ieee80211_key_enable_hw_accel(key);
520 ASSERT_RTNL();
521
522 ieee80211_todo_for_each_key(sdata, KEY_FLAG_TODO_HWACCEL_REMOVE);
523}
524
525static void __ieee80211_key_destroy(struct ieee80211_key *key)
526{
527 if (!key)
528 return;
529
530 ieee80211_key_disable_hw_accel(key);
531
532 if (key->conf.alg == ALG_CCMP)
533 ieee80211_aes_key_free(key->u.ccmp.tfm);
534 if (key->conf.alg == ALG_AES_CMAC)
535 ieee80211_aes_cmac_key_free(key->u.aes_cmac.tfm);
536 ieee80211_debugfs_key_remove(key);
537 439
538 kfree(key); 440 mutex_unlock(&sdata->local->key_mtx);
539} 441}
540 442
541static void __ieee80211_key_todo(void) 443void ieee80211_disable_keys(struct ieee80211_sub_if_data *sdata)
542{ 444{
543 struct ieee80211_key *key; 445 struct ieee80211_key *key;
544 bool work_done;
545 u32 todoflags;
546 446
547 /* 447 ASSERT_RTNL();
548 * NB: sta_info_destroy relies on this!
549 */
550 synchronize_rcu();
551
552 spin_lock_bh(&todo_lock);
553 while (!list_empty(&todo_list)) {
554 key = list_first_entry(&todo_list, struct ieee80211_key, todo);
555 list_del_init(&key->todo);
556 todoflags = key->flags & (KEY_FLAG_TODO_ADD_DEBUGFS |
557 KEY_FLAG_TODO_DEFKEY |
558 KEY_FLAG_TODO_DEFMGMTKEY |
559 KEY_FLAG_TODO_HWACCEL_ADD |
560 KEY_FLAG_TODO_HWACCEL_REMOVE |
561 KEY_FLAG_TODO_DELETE);
562 key->flags &= ~todoflags;
563 spin_unlock_bh(&todo_lock);
564
565 work_done = false;
566
567 if (todoflags & KEY_FLAG_TODO_ADD_DEBUGFS) {
568 ieee80211_debugfs_key_add(key);
569 work_done = true;
570 }
571 if (todoflags & KEY_FLAG_TODO_DEFKEY) {
572 ieee80211_debugfs_key_remove_default(key->sdata);
573 ieee80211_debugfs_key_add_default(key->sdata);
574 work_done = true;
575 }
576 if (todoflags & KEY_FLAG_TODO_DEFMGMTKEY) {
577 ieee80211_debugfs_key_remove_mgmt_default(key->sdata);
578 ieee80211_debugfs_key_add_mgmt_default(key->sdata);
579 work_done = true;
580 }
581 if (todoflags & KEY_FLAG_TODO_HWACCEL_ADD) {
582 ieee80211_key_enable_hw_accel(key);
583 work_done = true;
584 }
585 if (todoflags & KEY_FLAG_TODO_HWACCEL_REMOVE) {
586 ieee80211_key_disable_hw_accel(key);
587 work_done = true;
588 }
589 if (todoflags & KEY_FLAG_TODO_DELETE) {
590 __ieee80211_key_destroy(key);
591 work_done = true;
592 }
593 448
594 WARN_ON(!work_done); 449 mutex_lock(&sdata->local->key_mtx);
595 450
596 spin_lock_bh(&todo_lock); 451 list_for_each_entry(key, &sdata->key_list, list)
597 } 452 ieee80211_key_disable_hw_accel(key);
598 spin_unlock_bh(&todo_lock);
599}
600 453
601void ieee80211_key_todo(void) 454 mutex_unlock(&sdata->local->key_mtx);
602{
603 ieee80211_key_lock();
604 __ieee80211_key_todo();
605 ieee80211_key_unlock();
606} 455}
607 456
608void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata) 457void ieee80211_free_keys(struct ieee80211_sub_if_data *sdata)
609{ 458{
610 struct ieee80211_key *key, *tmp; 459 struct ieee80211_key *key, *tmp;
611 unsigned long flags;
612 460
613 ieee80211_key_lock(); 461 mutex_lock(&sdata->local->key_mtx);
614 462
615 ieee80211_debugfs_key_remove_default(sdata); 463 ieee80211_debugfs_key_remove_default(sdata);
616 ieee80211_debugfs_key_remove_mgmt_default(sdata); 464 ieee80211_debugfs_key_remove_mgmt_default(sdata);
617 465
618 spin_lock_irqsave(&sdata->local->key_lock, flags);
619 list_for_each_entry_safe(key, tmp, &sdata->key_list, list) 466 list_for_each_entry_safe(key, tmp, &sdata->key_list, list)
620 __ieee80211_key_free(key); 467 __ieee80211_key_free(key);
621 spin_unlock_irqrestore(&sdata->local->key_lock, flags);
622
623 __ieee80211_key_todo();
624 468
625 ieee80211_key_unlock(); 469 mutex_unlock(&sdata->local->key_mtx);
626} 470}