diff options
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r-- | security/keys/keyring.c | 312 |
1 files changed, 207 insertions, 105 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index e2ab4f8e7481..90a551e4da66 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* keyring.c: keyring handling | 1 | /* keyring.c: keyring handling |
2 | * | 2 | * |
3 | * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. | 3 | * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. |
4 | * Written by David Howells (dhowells@redhat.com) | 4 | * Written by David Howells (dhowells@redhat.com) |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or | 6 | * This program is free software; you can redistribute it and/or |
@@ -132,10 +132,17 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); | 132 | (PAGE_SIZE - sizeof(*klist)) / sizeof(struct key); |
133 | 133 | ||
134 | ret = 0; | 134 | ret = 0; |
135 | sklist = source->payload.subscriptions; | ||
136 | 135 | ||
137 | if (sklist && sklist->nkeys > 0) { | 136 | /* find out how many keys are currently linked */ |
137 | rcu_read_lock(); | ||
138 | sklist = rcu_dereference(source->payload.subscriptions); | ||
139 | max = 0; | ||
140 | if (sklist) | ||
138 | max = sklist->nkeys; | 141 | max = sklist->nkeys; |
142 | rcu_read_unlock(); | ||
143 | |||
144 | /* allocate a new payload and stuff load with key links */ | ||
145 | if (max > 0) { | ||
139 | BUG_ON(max > limit); | 146 | BUG_ON(max > limit); |
140 | 147 | ||
141 | max = (max + 3) & ~3; | 148 | max = (max + 3) & ~3; |
@@ -148,6 +155,10 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
148 | if (!klist) | 155 | if (!klist) |
149 | goto error; | 156 | goto error; |
150 | 157 | ||
158 | /* set links */ | ||
159 | rcu_read_lock(); | ||
160 | sklist = rcu_dereference(source->payload.subscriptions); | ||
161 | |||
151 | klist->maxkeys = max; | 162 | klist->maxkeys = max; |
152 | klist->nkeys = sklist->nkeys; | 163 | klist->nkeys = sklist->nkeys; |
153 | memcpy(klist->keys, | 164 | memcpy(klist->keys, |
@@ -157,7 +168,9 @@ static int keyring_duplicate(struct key *keyring, const struct key *source) | |||
157 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 168 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
158 | atomic_inc(&klist->keys[loop]->usage); | 169 | atomic_inc(&klist->keys[loop]->usage); |
159 | 170 | ||
160 | keyring->payload.subscriptions = klist; | 171 | rcu_read_unlock(); |
172 | |||
173 | rcu_assign_pointer(keyring->payload.subscriptions, klist); | ||
161 | ret = 0; | 174 | ret = 0; |
162 | } | 175 | } |
163 | 176 | ||
@@ -192,7 +205,7 @@ static void keyring_destroy(struct key *keyring) | |||
192 | write_unlock(&keyring_name_lock); | 205 | write_unlock(&keyring_name_lock); |
193 | } | 206 | } |
194 | 207 | ||
195 | klist = keyring->payload.subscriptions; | 208 | klist = rcu_dereference(keyring->payload.subscriptions); |
196 | if (klist) { | 209 | if (klist) { |
197 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 210 | for (loop = klist->nkeys - 1; loop >= 0; loop--) |
198 | key_put(klist->keys[loop]); | 211 | key_put(klist->keys[loop]); |
@@ -216,17 +229,20 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) | |||
216 | seq_puts(m, "[anon]"); | 229 | seq_puts(m, "[anon]"); |
217 | } | 230 | } |
218 | 231 | ||
219 | klist = keyring->payload.subscriptions; | 232 | rcu_read_lock(); |
233 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
220 | if (klist) | 234 | if (klist) |
221 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); | 235 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); |
222 | else | 236 | else |
223 | seq_puts(m, ": empty"); | 237 | seq_puts(m, ": empty"); |
238 | rcu_read_unlock(); | ||
224 | 239 | ||
225 | } /* end keyring_describe() */ | 240 | } /* end keyring_describe() */ |
226 | 241 | ||
227 | /*****************************************************************************/ | 242 | /*****************************************************************************/ |
228 | /* | 243 | /* |
229 | * read a list of key IDs from the keyring's contents | 244 | * read a list of key IDs from the keyring's contents |
245 | * - the keyring's semaphore is read-locked | ||
230 | */ | 246 | */ |
231 | static long keyring_read(const struct key *keyring, | 247 | static long keyring_read(const struct key *keyring, |
232 | char __user *buffer, size_t buflen) | 248 | char __user *buffer, size_t buflen) |
@@ -237,7 +253,7 @@ static long keyring_read(const struct key *keyring, | |||
237 | int loop, ret; | 253 | int loop, ret; |
238 | 254 | ||
239 | ret = 0; | 255 | ret = 0; |
240 | klist = keyring->payload.subscriptions; | 256 | klist = rcu_dereference(keyring->payload.subscriptions); |
241 | 257 | ||
242 | if (klist) { | 258 | if (klist) { |
243 | /* calculate how much data we could return */ | 259 | /* calculate how much data we could return */ |
@@ -292,7 +308,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
292 | uid, gid, KEY_USR_ALL, not_in_quota); | 308 | uid, gid, KEY_USR_ALL, not_in_quota); |
293 | 309 | ||
294 | if (!IS_ERR(keyring)) { | 310 | if (!IS_ERR(keyring)) { |
295 | ret = key_instantiate_and_link(keyring, NULL, 0, dest); | 311 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
296 | if (ret < 0) { | 312 | if (ret < 0) { |
297 | key_put(keyring); | 313 | key_put(keyring); |
298 | keyring = ERR_PTR(ret); | 314 | keyring = ERR_PTR(ret); |
@@ -310,17 +326,18 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
310 | * - we only find keys on which we have search permission | 326 | * - we only find keys on which we have search permission |
311 | * - we use the supplied match function to see if the description (or other | 327 | * - we use the supplied match function to see if the description (or other |
312 | * feature of interest) matches | 328 | * feature of interest) matches |
313 | * - we readlock the keyrings as we search down the tree | 329 | * - we rely on RCU to prevent the keyring lists from disappearing on us |
314 | * - we return -EAGAIN if we didn't find any matching key | 330 | * - we return -EAGAIN if we didn't find any matching key |
315 | * - we return -ENOKEY if we only found negative matching keys | 331 | * - we return -ENOKEY if we only found negative matching keys |
316 | */ | 332 | */ |
317 | struct key *keyring_search_aux(struct key *keyring, | 333 | struct key *keyring_search_aux(struct key *keyring, |
334 | struct task_struct *context, | ||
318 | struct key_type *type, | 335 | struct key_type *type, |
319 | const void *description, | 336 | const void *description, |
320 | key_match_func_t match) | 337 | key_match_func_t match) |
321 | { | 338 | { |
322 | struct { | 339 | struct { |
323 | struct key *keyring; | 340 | struct keyring_list *keylist; |
324 | int kix; | 341 | int kix; |
325 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | 342 | } stack[KEYRING_SEARCH_MAX_DEPTH]; |
326 | 343 | ||
@@ -328,13 +345,15 @@ struct key *keyring_search_aux(struct key *keyring, | |||
328 | struct timespec now; | 345 | struct timespec now; |
329 | struct key *key; | 346 | struct key *key; |
330 | long err; | 347 | long err; |
331 | int sp, psp, kix; | 348 | int sp, kix; |
332 | 349 | ||
333 | key_check(keyring); | 350 | key_check(keyring); |
334 | 351 | ||
352 | rcu_read_lock(); | ||
353 | |||
335 | /* top keyring must have search permission to begin the search */ | 354 | /* top keyring must have search permission to begin the search */ |
336 | key = ERR_PTR(-EACCES); | 355 | key = ERR_PTR(-EACCES); |
337 | if (!key_permission(keyring, KEY_SEARCH)) | 356 | if (!key_task_permission(keyring, context, KEY_SEARCH)) |
338 | goto error; | 357 | goto error; |
339 | 358 | ||
340 | key = ERR_PTR(-ENOTDIR); | 359 | key = ERR_PTR(-ENOTDIR); |
@@ -347,11 +366,10 @@ struct key *keyring_search_aux(struct key *keyring, | |||
347 | 366 | ||
348 | /* start processing a new keyring */ | 367 | /* start processing a new keyring */ |
349 | descend: | 368 | descend: |
350 | read_lock(&keyring->lock); | 369 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
351 | if (keyring->flags & KEY_FLAG_REVOKED) | ||
352 | goto not_this_keyring; | 370 | goto not_this_keyring; |
353 | 371 | ||
354 | keylist = keyring->payload.subscriptions; | 372 | keylist = rcu_dereference(keyring->payload.subscriptions); |
355 | if (!keylist) | 373 | if (!keylist) |
356 | goto not_this_keyring; | 374 | goto not_this_keyring; |
357 | 375 | ||
@@ -364,7 +382,7 @@ struct key *keyring_search_aux(struct key *keyring, | |||
364 | continue; | 382 | continue; |
365 | 383 | ||
366 | /* skip revoked keys and expired keys */ | 384 | /* skip revoked keys and expired keys */ |
367 | if (key->flags & KEY_FLAG_REVOKED) | 385 | if (test_bit(KEY_FLAG_REVOKED, &key->flags)) |
368 | continue; | 386 | continue; |
369 | 387 | ||
370 | if (key->expiry && now.tv_sec >= key->expiry) | 388 | if (key->expiry && now.tv_sec >= key->expiry) |
@@ -375,11 +393,11 @@ struct key *keyring_search_aux(struct key *keyring, | |||
375 | continue; | 393 | continue; |
376 | 394 | ||
377 | /* key must have search permissions */ | 395 | /* key must have search permissions */ |
378 | if (!key_permission(key, KEY_SEARCH)) | 396 | if (!key_task_permission(key, context, KEY_SEARCH)) |
379 | continue; | 397 | continue; |
380 | 398 | ||
381 | /* we set a different error code if we find a negative key */ | 399 | /* we set a different error code if we find a negative key */ |
382 | if (key->flags & KEY_FLAG_NEGATIVE) { | 400 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { |
383 | err = -ENOKEY; | 401 | err = -ENOKEY; |
384 | continue; | 402 | continue; |
385 | } | 403 | } |
@@ -390,48 +408,37 @@ struct key *keyring_search_aux(struct key *keyring, | |||
390 | /* search through the keyrings nested in this one */ | 408 | /* search through the keyrings nested in this one */ |
391 | kix = 0; | 409 | kix = 0; |
392 | ascend: | 410 | ascend: |
393 | while (kix < keylist->nkeys) { | 411 | for (; kix < keylist->nkeys; kix++) { |
394 | key = keylist->keys[kix]; | 412 | key = keylist->keys[kix]; |
395 | if (key->type != &key_type_keyring) | 413 | if (key->type != &key_type_keyring) |
396 | goto next; | 414 | continue; |
397 | 415 | ||
398 | /* recursively search nested keyrings | 416 | /* recursively search nested keyrings |
399 | * - only search keyrings for which we have search permission | 417 | * - only search keyrings for which we have search permission |
400 | */ | 418 | */ |
401 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) | 419 | if (sp >= KEYRING_SEARCH_MAX_DEPTH) |
402 | goto next; | 420 | continue; |
403 | |||
404 | if (!key_permission(key, KEY_SEARCH)) | ||
405 | goto next; | ||
406 | 421 | ||
407 | /* evade loops in the keyring tree */ | 422 | if (!key_task_permission(key, context, KEY_SEARCH)) |
408 | for (psp = 0; psp < sp; psp++) | 423 | continue; |
409 | if (stack[psp].keyring == keyring) | ||
410 | goto next; | ||
411 | 424 | ||
412 | /* stack the current position */ | 425 | /* stack the current position */ |
413 | stack[sp].keyring = keyring; | 426 | stack[sp].keylist = keylist; |
414 | stack[sp].kix = kix; | 427 | stack[sp].kix = kix; |
415 | sp++; | 428 | sp++; |
416 | 429 | ||
417 | /* begin again with the new keyring */ | 430 | /* begin again with the new keyring */ |
418 | keyring = key; | 431 | keyring = key; |
419 | goto descend; | 432 | goto descend; |
420 | |||
421 | next: | ||
422 | kix++; | ||
423 | } | 433 | } |
424 | 434 | ||
425 | /* the keyring we're looking at was disqualified or didn't contain a | 435 | /* the keyring we're looking at was disqualified or didn't contain a |
426 | * matching key */ | 436 | * matching key */ |
427 | not_this_keyring: | 437 | not_this_keyring: |
428 | read_unlock(&keyring->lock); | ||
429 | |||
430 | if (sp > 0) { | 438 | if (sp > 0) { |
431 | /* resume the processing of a keyring higher up in the tree */ | 439 | /* resume the processing of a keyring higher up in the tree */ |
432 | sp--; | 440 | sp--; |
433 | keyring = stack[sp].keyring; | 441 | keylist = stack[sp].keylist; |
434 | keylist = keyring->payload.subscriptions; | ||
435 | kix = stack[sp].kix + 1; | 442 | kix = stack[sp].kix + 1; |
436 | goto ascend; | 443 | goto ascend; |
437 | } | 444 | } |
@@ -442,16 +449,9 @@ struct key *keyring_search_aux(struct key *keyring, | |||
442 | /* we found a viable match */ | 449 | /* we found a viable match */ |
443 | found: | 450 | found: |
444 | atomic_inc(&key->usage); | 451 | atomic_inc(&key->usage); |
445 | read_unlock(&keyring->lock); | ||
446 | |||
447 | /* unwind the keyring stack */ | ||
448 | while (sp > 0) { | ||
449 | sp--; | ||
450 | read_unlock(&stack[sp].keyring->lock); | ||
451 | } | ||
452 | |||
453 | key_check(key); | 452 | key_check(key); |
454 | error: | 453 | error: |
454 | rcu_read_unlock(); | ||
455 | return key; | 455 | return key; |
456 | 456 | ||
457 | } /* end keyring_search_aux() */ | 457 | } /* end keyring_search_aux() */ |
@@ -469,7 +469,11 @@ struct key *keyring_search(struct key *keyring, | |||
469 | struct key_type *type, | 469 | struct key_type *type, |
470 | const char *description) | 470 | const char *description) |
471 | { | 471 | { |
472 | return keyring_search_aux(keyring, type, description, type->match); | 472 | if (!type->match) |
473 | return ERR_PTR(-ENOKEY); | ||
474 | |||
475 | return keyring_search_aux(keyring, current, | ||
476 | type, description, type->match); | ||
473 | 477 | ||
474 | } /* end keyring_search() */ | 478 | } /* end keyring_search() */ |
475 | 479 | ||
@@ -489,15 +493,18 @@ struct key *__keyring_search_one(struct key *keyring, | |||
489 | struct key *key; | 493 | struct key *key; |
490 | int loop; | 494 | int loop; |
491 | 495 | ||
492 | klist = keyring->payload.subscriptions; | 496 | rcu_read_lock(); |
497 | |||
498 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
493 | if (klist) { | 499 | if (klist) { |
494 | for (loop = 0; loop < klist->nkeys; loop++) { | 500 | for (loop = 0; loop < klist->nkeys; loop++) { |
495 | key = klist->keys[loop]; | 501 | key = klist->keys[loop]; |
496 | 502 | ||
497 | if (key->type == ktype && | 503 | if (key->type == ktype && |
498 | key->type->match(key, description) && | 504 | (!key->type->match || |
505 | key->type->match(key, description)) && | ||
499 | key_permission(key, perm) && | 506 | key_permission(key, perm) && |
500 | !(key->flags & KEY_FLAG_REVOKED) | 507 | !test_bit(KEY_FLAG_REVOKED, &key->flags) |
501 | ) | 508 | ) |
502 | goto found; | 509 | goto found; |
503 | } | 510 | } |
@@ -509,12 +516,58 @@ struct key *__keyring_search_one(struct key *keyring, | |||
509 | found: | 516 | found: |
510 | atomic_inc(&key->usage); | 517 | atomic_inc(&key->usage); |
511 | error: | 518 | error: |
519 | rcu_read_unlock(); | ||
512 | return key; | 520 | return key; |
513 | 521 | ||
514 | } /* end __keyring_search_one() */ | 522 | } /* end __keyring_search_one() */ |
515 | 523 | ||
516 | /*****************************************************************************/ | 524 | /*****************************************************************************/ |
517 | /* | 525 | /* |
526 | * search for an instantiation authorisation key matching a target key | ||
527 | * - the RCU read lock must be held by the caller | ||
528 | * - a target_id of zero specifies any valid token | ||
529 | */ | ||
530 | struct key *keyring_search_instkey(struct key *keyring, | ||
531 | key_serial_t target_id) | ||
532 | { | ||
533 | struct request_key_auth *rka; | ||
534 | struct keyring_list *klist; | ||
535 | struct key *instkey; | ||
536 | int loop; | ||
537 | |||
538 | klist = rcu_dereference(keyring->payload.subscriptions); | ||
539 | if (klist) { | ||
540 | for (loop = 0; loop < klist->nkeys; loop++) { | ||
541 | instkey = klist->keys[loop]; | ||
542 | |||
543 | if (instkey->type != &key_type_request_key_auth) | ||
544 | continue; | ||
545 | |||
546 | rka = instkey->payload.data; | ||
547 | if (target_id && rka->target_key->serial != target_id) | ||
548 | continue; | ||
549 | |||
550 | /* the auth key is revoked during instantiation */ | ||
551 | if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags)) | ||
552 | goto found; | ||
553 | |||
554 | instkey = ERR_PTR(-EKEYREVOKED); | ||
555 | goto error; | ||
556 | } | ||
557 | } | ||
558 | |||
559 | instkey = ERR_PTR(-EACCES); | ||
560 | goto error; | ||
561 | |||
562 | found: | ||
563 | atomic_inc(&instkey->usage); | ||
564 | error: | ||
565 | return instkey; | ||
566 | |||
567 | } /* end keyring_search_instkey() */ | ||
568 | |||
569 | /*****************************************************************************/ | ||
570 | /* | ||
518 | * find a keyring with the specified name | 571 | * find a keyring with the specified name |
519 | * - all named keyrings are searched | 572 | * - all named keyrings are searched |
520 | * - only find keyrings with search permission for the process | 573 | * - only find keyrings with search permission for the process |
@@ -540,7 +593,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
540 | &keyring_name_hash[bucket], | 593 | &keyring_name_hash[bucket], |
541 | type_data.link | 594 | type_data.link |
542 | ) { | 595 | ) { |
543 | if (keyring->flags & KEY_FLAG_REVOKED) | 596 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
544 | continue; | 597 | continue; |
545 | 598 | ||
546 | if (strcmp(keyring->description, name) != 0) | 599 | if (strcmp(keyring->description, name) != 0) |
@@ -579,7 +632,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound) | |||
579 | static int keyring_detect_cycle(struct key *A, struct key *B) | 632 | static int keyring_detect_cycle(struct key *A, struct key *B) |
580 | { | 633 | { |
581 | struct { | 634 | struct { |
582 | struct key *subtree; | 635 | struct keyring_list *keylist; |
583 | int kix; | 636 | int kix; |
584 | } stack[KEYRING_SEARCH_MAX_DEPTH]; | 637 | } stack[KEYRING_SEARCH_MAX_DEPTH]; |
585 | 638 | ||
@@ -587,20 +640,21 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
587 | struct key *subtree, *key; | 640 | struct key *subtree, *key; |
588 | int sp, kix, ret; | 641 | int sp, kix, ret; |
589 | 642 | ||
643 | rcu_read_lock(); | ||
644 | |||
590 | ret = -EDEADLK; | 645 | ret = -EDEADLK; |
591 | if (A == B) | 646 | if (A == B) |
592 | goto error; | 647 | goto cycle_detected; |
593 | 648 | ||
594 | subtree = B; | 649 | subtree = B; |
595 | sp = 0; | 650 | sp = 0; |
596 | 651 | ||
597 | /* start processing a new keyring */ | 652 | /* start processing a new keyring */ |
598 | descend: | 653 | descend: |
599 | read_lock(&subtree->lock); | 654 | if (test_bit(KEY_FLAG_REVOKED, &subtree->flags)) |
600 | if (subtree->flags & KEY_FLAG_REVOKED) | ||
601 | goto not_this_keyring; | 655 | goto not_this_keyring; |
602 | 656 | ||
603 | keylist = subtree->payload.subscriptions; | 657 | keylist = rcu_dereference(subtree->payload.subscriptions); |
604 | if (!keylist) | 658 | if (!keylist) |
605 | goto not_this_keyring; | 659 | goto not_this_keyring; |
606 | kix = 0; | 660 | kix = 0; |
@@ -619,7 +673,7 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
619 | goto too_deep; | 673 | goto too_deep; |
620 | 674 | ||
621 | /* stack the current position */ | 675 | /* stack the current position */ |
622 | stack[sp].subtree = subtree; | 676 | stack[sp].keylist = keylist; |
623 | stack[sp].kix = kix; | 677 | stack[sp].kix = kix; |
624 | sp++; | 678 | sp++; |
625 | 679 | ||
@@ -632,13 +686,10 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
632 | /* the keyring we're looking at was disqualified or didn't contain a | 686 | /* the keyring we're looking at was disqualified or didn't contain a |
633 | * matching key */ | 687 | * matching key */ |
634 | not_this_keyring: | 688 | not_this_keyring: |
635 | read_unlock(&subtree->lock); | ||
636 | |||
637 | if (sp > 0) { | 689 | if (sp > 0) { |
638 | /* resume the checking of a keyring higher up in the tree */ | 690 | /* resume the checking of a keyring higher up in the tree */ |
639 | sp--; | 691 | sp--; |
640 | subtree = stack[sp].subtree; | 692 | keylist = stack[sp].keylist; |
641 | keylist = subtree->payload.subscriptions; | ||
642 | kix = stack[sp].kix + 1; | 693 | kix = stack[sp].kix + 1; |
643 | goto ascend; | 694 | goto ascend; |
644 | } | 695 | } |
@@ -646,30 +697,36 @@ static int keyring_detect_cycle(struct key *A, struct key *B) | |||
646 | ret = 0; /* no cycles detected */ | 697 | ret = 0; /* no cycles detected */ |
647 | 698 | ||
648 | error: | 699 | error: |
700 | rcu_read_unlock(); | ||
649 | return ret; | 701 | return ret; |
650 | 702 | ||
651 | too_deep: | 703 | too_deep: |
652 | ret = -ELOOP; | 704 | ret = -ELOOP; |
653 | goto error_unwind; | 705 | goto error; |
706 | |||
654 | cycle_detected: | 707 | cycle_detected: |
655 | ret = -EDEADLK; | 708 | ret = -EDEADLK; |
656 | error_unwind: | ||
657 | read_unlock(&subtree->lock); | ||
658 | |||
659 | /* unwind the keyring stack */ | ||
660 | while (sp > 0) { | ||
661 | sp--; | ||
662 | read_unlock(&stack[sp].subtree->lock); | ||
663 | } | ||
664 | |||
665 | goto error; | 709 | goto error; |
666 | 710 | ||
667 | } /* end keyring_detect_cycle() */ | 711 | } /* end keyring_detect_cycle() */ |
668 | 712 | ||
669 | /*****************************************************************************/ | 713 | /*****************************************************************************/ |
670 | /* | 714 | /* |
715 | * dispose of a keyring list after the RCU grace period | ||
716 | */ | ||
717 | static void keyring_link_rcu_disposal(struct rcu_head *rcu) | ||
718 | { | ||
719 | struct keyring_list *klist = | ||
720 | container_of(rcu, struct keyring_list, rcu); | ||
721 | |||
722 | kfree(klist); | ||
723 | |||
724 | } /* end keyring_link_rcu_disposal() */ | ||
725 | |||
726 | /*****************************************************************************/ | ||
727 | /* | ||
671 | * link a key into to a keyring | 728 | * link a key into to a keyring |
672 | * - must be called with the keyring's semaphore held | 729 | * - must be called with the keyring's semaphore write-locked |
673 | */ | 730 | */ |
674 | int __key_link(struct key *keyring, struct key *key) | 731 | int __key_link(struct key *keyring, struct key *key) |
675 | { | 732 | { |
@@ -679,7 +736,7 @@ int __key_link(struct key *keyring, struct key *key) | |||
679 | int ret; | 736 | int ret; |
680 | 737 | ||
681 | ret = -EKEYREVOKED; | 738 | ret = -EKEYREVOKED; |
682 | if (keyring->flags & KEY_FLAG_REVOKED) | 739 | if (test_bit(KEY_FLAG_REVOKED, &keyring->flags)) |
683 | goto error; | 740 | goto error; |
684 | 741 | ||
685 | ret = -ENOTDIR; | 742 | ret = -ENOTDIR; |
@@ -710,9 +767,10 @@ int __key_link(struct key *keyring, struct key *key) | |||
710 | /* there's sufficient slack space to add directly */ | 767 | /* there's sufficient slack space to add directly */ |
711 | atomic_inc(&key->usage); | 768 | atomic_inc(&key->usage); |
712 | 769 | ||
713 | write_lock(&keyring->lock); | 770 | klist->keys[klist->nkeys] = key; |
714 | klist->keys[klist->nkeys++] = key; | 771 | smp_wmb(); |
715 | write_unlock(&keyring->lock); | 772 | klist->nkeys++; |
773 | smp_wmb(); | ||
716 | 774 | ||
717 | ret = 0; | 775 | ret = 0; |
718 | } | 776 | } |
@@ -723,6 +781,8 @@ int __key_link(struct key *keyring, struct key *key) | |||
723 | max += klist->maxkeys; | 781 | max += klist->maxkeys; |
724 | 782 | ||
725 | ret = -ENFILE; | 783 | ret = -ENFILE; |
784 | if (max > 65535) | ||
785 | goto error3; | ||
726 | size = sizeof(*klist) + sizeof(*key) * max; | 786 | size = sizeof(*klist) + sizeof(*key) * max; |
727 | if (size > PAGE_SIZE) | 787 | if (size > PAGE_SIZE) |
728 | goto error3; | 788 | goto error3; |
@@ -743,14 +803,13 @@ int __key_link(struct key *keyring, struct key *key) | |||
743 | 803 | ||
744 | /* add the key into the new space */ | 804 | /* add the key into the new space */ |
745 | atomic_inc(&key->usage); | 805 | atomic_inc(&key->usage); |
746 | |||
747 | write_lock(&keyring->lock); | ||
748 | keyring->payload.subscriptions = nklist; | ||
749 | nklist->keys[nklist->nkeys++] = key; | 806 | nklist->keys[nklist->nkeys++] = key; |
750 | write_unlock(&keyring->lock); | 807 | |
808 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); | ||
751 | 809 | ||
752 | /* dispose of the old keyring list */ | 810 | /* dispose of the old keyring list */ |
753 | kfree(klist); | 811 | if (klist) |
812 | call_rcu(&klist->rcu, keyring_link_rcu_disposal); | ||
754 | 813 | ||
755 | ret = 0; | 814 | ret = 0; |
756 | } | 815 | } |
@@ -791,11 +850,26 @@ EXPORT_SYMBOL(key_link); | |||
791 | 850 | ||
792 | /*****************************************************************************/ | 851 | /*****************************************************************************/ |
793 | /* | 852 | /* |
853 | * dispose of a keyring list after the RCU grace period, freeing the unlinked | ||
854 | * key | ||
855 | */ | ||
856 | static void keyring_unlink_rcu_disposal(struct rcu_head *rcu) | ||
857 | { | ||
858 | struct keyring_list *klist = | ||
859 | container_of(rcu, struct keyring_list, rcu); | ||
860 | |||
861 | key_put(klist->keys[klist->delkey]); | ||
862 | kfree(klist); | ||
863 | |||
864 | } /* end keyring_unlink_rcu_disposal() */ | ||
865 | |||
866 | /*****************************************************************************/ | ||
867 | /* | ||
794 | * unlink the first link to a key from a keyring | 868 | * unlink the first link to a key from a keyring |
795 | */ | 869 | */ |
796 | int key_unlink(struct key *keyring, struct key *key) | 870 | int key_unlink(struct key *keyring, struct key *key) |
797 | { | 871 | { |
798 | struct keyring_list *klist; | 872 | struct keyring_list *klist, *nklist; |
799 | int loop, ret; | 873 | int loop, ret; |
800 | 874 | ||
801 | key_check(keyring); | 875 | key_check(keyring); |
@@ -819,31 +893,45 @@ int key_unlink(struct key *keyring, struct key *key) | |||
819 | ret = -ENOENT; | 893 | ret = -ENOENT; |
820 | goto error; | 894 | goto error; |
821 | 895 | ||
822 | key_is_present: | 896 | key_is_present: |
897 | /* we need to copy the key list for RCU purposes */ | ||
898 | nklist = kmalloc(sizeof(*klist) + sizeof(*key) * klist->maxkeys, | ||
899 | GFP_KERNEL); | ||
900 | if (!nklist) | ||
901 | goto nomem; | ||
902 | nklist->maxkeys = klist->maxkeys; | ||
903 | nklist->nkeys = klist->nkeys - 1; | ||
904 | |||
905 | if (loop > 0) | ||
906 | memcpy(&nklist->keys[0], | ||
907 | &klist->keys[0], | ||
908 | loop * sizeof(klist->keys[0])); | ||
909 | |||
910 | if (loop < nklist->nkeys) | ||
911 | memcpy(&nklist->keys[loop], | ||
912 | &klist->keys[loop + 1], | ||
913 | (nklist->nkeys - loop) * sizeof(klist->keys[0])); | ||
914 | |||
823 | /* adjust the user's quota */ | 915 | /* adjust the user's quota */ |
824 | key_payload_reserve(keyring, | 916 | key_payload_reserve(keyring, |
825 | keyring->datalen - KEYQUOTA_LINK_BYTES); | 917 | keyring->datalen - KEYQUOTA_LINK_BYTES); |
826 | 918 | ||
827 | /* shuffle down the key pointers | 919 | rcu_assign_pointer(keyring->payload.subscriptions, nklist); |
828 | * - it might be worth shrinking the allocated memory, but that runs | ||
829 | * the risk of ENOMEM as we would have to copy | ||
830 | */ | ||
831 | write_lock(&keyring->lock); | ||
832 | 920 | ||
833 | klist->nkeys--; | 921 | up_write(&keyring->sem); |
834 | if (loop < klist->nkeys) | ||
835 | memcpy(&klist->keys[loop], | ||
836 | &klist->keys[loop + 1], | ||
837 | (klist->nkeys - loop) * sizeof(struct key *)); | ||
838 | 922 | ||
839 | write_unlock(&keyring->lock); | 923 | /* schedule for later cleanup */ |
924 | klist->delkey = loop; | ||
925 | call_rcu(&klist->rcu, keyring_unlink_rcu_disposal); | ||
840 | 926 | ||
841 | up_write(&keyring->sem); | ||
842 | key_put(key); | ||
843 | ret = 0; | 927 | ret = 0; |
844 | 928 | ||
845 | error: | 929 | error: |
846 | return ret; | 930 | return ret; |
931 | nomem: | ||
932 | ret = -ENOMEM; | ||
933 | up_write(&keyring->sem); | ||
934 | goto error; | ||
847 | 935 | ||
848 | } /* end key_unlink() */ | 936 | } /* end key_unlink() */ |
849 | 937 | ||
@@ -851,13 +939,32 @@ EXPORT_SYMBOL(key_unlink); | |||
851 | 939 | ||
852 | /*****************************************************************************/ | 940 | /*****************************************************************************/ |
853 | /* | 941 | /* |
942 | * dispose of a keyring list after the RCU grace period, releasing the keys it | ||
943 | * links to | ||
944 | */ | ||
945 | static void keyring_clear_rcu_disposal(struct rcu_head *rcu) | ||
946 | { | ||
947 | struct keyring_list *klist; | ||
948 | int loop; | ||
949 | |||
950 | klist = container_of(rcu, struct keyring_list, rcu); | ||
951 | |||
952 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | ||
953 | key_put(klist->keys[loop]); | ||
954 | |||
955 | kfree(klist); | ||
956 | |||
957 | } /* end keyring_clear_rcu_disposal() */ | ||
958 | |||
959 | /*****************************************************************************/ | ||
960 | /* | ||
854 | * clear the specified process keyring | 961 | * clear the specified process keyring |
855 | * - implements keyctl(KEYCTL_CLEAR) | 962 | * - implements keyctl(KEYCTL_CLEAR) |
856 | */ | 963 | */ |
857 | int keyring_clear(struct key *keyring) | 964 | int keyring_clear(struct key *keyring) |
858 | { | 965 | { |
859 | struct keyring_list *klist; | 966 | struct keyring_list *klist; |
860 | int loop, ret; | 967 | int ret; |
861 | 968 | ||
862 | ret = -ENOTDIR; | 969 | ret = -ENOTDIR; |
863 | if (keyring->type == &key_type_keyring) { | 970 | if (keyring->type == &key_type_keyring) { |
@@ -870,20 +977,15 @@ int keyring_clear(struct key *keyring) | |||
870 | key_payload_reserve(keyring, | 977 | key_payload_reserve(keyring, |
871 | sizeof(struct keyring_list)); | 978 | sizeof(struct keyring_list)); |
872 | 979 | ||
873 | write_lock(&keyring->lock); | 980 | rcu_assign_pointer(keyring->payload.subscriptions, |
874 | keyring->payload.subscriptions = NULL; | 981 | NULL); |
875 | write_unlock(&keyring->lock); | ||
876 | } | 982 | } |
877 | 983 | ||
878 | up_write(&keyring->sem); | 984 | up_write(&keyring->sem); |
879 | 985 | ||
880 | /* free the keys after the locks have been dropped */ | 986 | /* free the keys after the locks have been dropped */ |
881 | if (klist) { | 987 | if (klist) |
882 | for (loop = klist->nkeys - 1; loop >= 0; loop--) | 988 | call_rcu(&klist->rcu, keyring_clear_rcu_disposal); |
883 | key_put(klist->keys[loop]); | ||
884 | |||
885 | kfree(klist); | ||
886 | } | ||
887 | 989 | ||
888 | ret = 0; | 990 | ret = 0; |
889 | } | 991 | } |