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