aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2005-06-24 01:00:56 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:05:19 -0400
commit3e30148c3d524a9c1c63ca28261bc24c457eb07a (patch)
treea2fcc46cc11fe871ad976c07476d934a07313576 /security/keys/process_keys.c
parent8589b4e00e352f983259140f25a262d973be6bc5 (diff)
[PATCH] Keys: Make request-key create an authorisation key
The attached patch makes the following changes: (1) There's a new special key type called ".request_key_auth". This is an authorisation key for when one process requests a key and another process is started to construct it. This type of key cannot be created by the user; nor can it be requested by kernel services. Authorisation keys hold two references: (a) Each refers to a key being constructed. When the key being constructed is instantiated the authorisation key is revoked, rendering it of no further use. (b) The "authorising process". This is either: (i) the process that called request_key(), or: (ii) if the process that called request_key() itself had an authorisation key in its session keyring, then the authorising process referred to by that authorisation key will also be referred to by the new authorisation key. This means that the process that initiated a chain of key requests will authorise the lot of them, and will, by default, wind up with the keys obtained from them in its keyrings. (2) request_key() creates an authorisation key which is then passed to /sbin/request-key in as part of a new session keyring. (3) When request_key() is searching for a key to hand back to the caller, if it comes across an authorisation key in the session keyring of the calling process, it will also search the keyrings of the process specified therein and it will use the specified process's credentials (fsuid, fsgid, groups) to do that rather than the calling process's credentials. This allows a process started by /sbin/request-key to find keys belonging to the authorising process. (4) A key can be read, even if the process executing KEYCTL_READ doesn't have direct read or search permission if that key is contained within the keyrings of a process specified by an authorisation key found within the calling process's session keyring, and is searchable using the credentials of the authorising process. This allows a process started by /sbin/request-key to read keys belonging to the authorising process. (5) The magic KEY_SPEC_*_KEYRING key IDs when passed to KEYCTL_INSTANTIATE or KEYCTL_NEGATE will specify a keyring of the authorising process, rather than the process doing the instantiation. (6) One of the process keyrings can be nominated as the default to which request_key() should attach new keys if not otherwise specified. This is done with KEYCTL_SET_REQKEY_KEYRING and one of the KEY_REQKEY_DEFL_* constants. The current setting can also be read using this call. (7) request_key() is partially interruptible. If it is waiting for another process to finish constructing a key, it can be interrupted. This permits a request-key cycle to be broken without recourse to rebooting. Signed-Off-By: David Howells <dhowells@redhat.com> Signed-Off-By: Benoit Boissinot <benoit.boissinot@ens-lyon.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c179
1 files changed, 111 insertions, 68 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 972e30172687..34db087bbcc7 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -165,7 +165,7 @@ int install_thread_keyring(struct task_struct *tsk)
165/* 165/*
166 * make sure a process keyring is installed 166 * make sure a process keyring is installed
167 */ 167 */
168static int install_process_keyring(struct task_struct *tsk) 168int install_process_keyring(struct task_struct *tsk)
169{ 169{
170 unsigned long flags; 170 unsigned long flags;
171 struct key *keyring; 171 struct key *keyring;
@@ -376,12 +376,13 @@ void key_fsgid_changed(struct task_struct *tsk)
376 * - we return -EAGAIN if we didn't find any matching key 376 * - we return -EAGAIN if we didn't find any matching key
377 * - we return -ENOKEY if we found only negative matching keys 377 * - we return -ENOKEY if we found only negative matching keys
378 */ 378 */
379struct key *search_process_keyrings_aux(struct key_type *type, 379struct key *search_process_keyrings(struct key_type *type,
380 const void *description, 380 const void *description,
381 key_match_func_t match) 381 key_match_func_t match,
382 struct task_struct *context)
382{ 383{
383 struct task_struct *tsk = current; 384 struct request_key_auth *rka;
384 struct key *key, *ret, *err; 385 struct key *key, *ret, *err, *instkey;
385 386
386 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 387 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
387 * searchable, but we failed to find a key or we found a negative key; 388 * searchable, but we failed to find a key or we found a negative key;
@@ -395,9 +396,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
395 err = ERR_PTR(-EAGAIN); 396 err = ERR_PTR(-EAGAIN);
396 397
397 /* search the thread keyring first */ 398 /* search the thread keyring first */
398 if (tsk->thread_keyring) { 399 if (context->thread_keyring) {
399 key = keyring_search_aux(tsk->thread_keyring, type, 400 key = keyring_search_aux(context->thread_keyring,
400 description, match); 401 context, type, description, match);
401 if (!IS_ERR(key)) 402 if (!IS_ERR(key))
402 goto found; 403 goto found;
403 404
@@ -415,9 +416,9 @@ struct key *search_process_keyrings_aux(struct key_type *type,
415 } 416 }
416 417
417 /* search the process keyring second */ 418 /* search the process keyring second */
418 if (tsk->signal->process_keyring) { 419 if (context->signal->process_keyring) {
419 key = keyring_search_aux(tsk->signal->process_keyring, 420 key = keyring_search_aux(context->signal->process_keyring,
420 type, description, match); 421 context, type, description, match);
421 if (!IS_ERR(key)) 422 if (!IS_ERR(key))
422 goto found; 423 goto found;
423 424
@@ -434,53 +435,93 @@ struct key *search_process_keyrings_aux(struct key_type *type,
434 } 435 }
435 } 436 }
436 437
437 /* search the session keyring last */ 438 /* search the session keyring */
438 if (tsk->signal->session_keyring) { 439 if (context->signal->session_keyring) {
439 rcu_read_lock(); 440 rcu_read_lock();
440 key = keyring_search_aux( 441 key = keyring_search_aux(
441 rcu_dereference(tsk->signal->session_keyring), 442 rcu_dereference(context->signal->session_keyring),
442 type, description, match); 443 context, type, description, match);
443 rcu_read_unlock(); 444 rcu_read_unlock();
445
446 if (!IS_ERR(key))
447 goto found;
448
449 switch (PTR_ERR(key)) {
450 case -EAGAIN: /* no key */
451 if (ret)
452 break;
453 case -ENOKEY: /* negative key */
454 ret = key;
455 break;
456 default:
457 err = key;
458 break;
459 }
460
461 /* if this process has a session keyring and that has an
462 * instantiation authorisation key in the bottom level, then we
463 * also search the keyrings of the process mentioned there */
464 if (context != current)
465 goto no_key;
466
467 rcu_read_lock();
468 instkey = __keyring_search_one(
469 rcu_dereference(context->signal->session_keyring),
470 &key_type_request_key_auth, NULL, 0);
471 rcu_read_unlock();
472
473 if (IS_ERR(instkey))
474 goto no_key;
475
476 rka = instkey->payload.data;
477
478 key = search_process_keyrings(type, description, match,
479 rka->context);
480 key_put(instkey);
481
482 if (!IS_ERR(key))
483 goto found;
484
485 switch (PTR_ERR(key)) {
486 case -EAGAIN: /* no key */
487 if (ret)
488 break;
489 case -ENOKEY: /* negative key */
490 ret = key;
491 break;
492 default:
493 err = key;
494 break;
495 }
444 } 496 }
497 /* or search the user-session keyring */
445 else { 498 else {
446 key = keyring_search_aux(tsk->user->session_keyring, 499 key = keyring_search_aux(context->user->session_keyring,
447 type, description, match); 500 context, type, description, match);
448 } 501 if (!IS_ERR(key))
449 502 goto found;
450 if (!IS_ERR(key))
451 goto found;
452 503
453 switch (PTR_ERR(key)) { 504 switch (PTR_ERR(key)) {
454 case -EAGAIN: /* no key */ 505 case -EAGAIN: /* no key */
455 if (ret) 506 if (ret)
507 break;
508 case -ENOKEY: /* negative key */
509 ret = key;
456 break; 510 break;
457 case -ENOKEY: /* negative key */ 511 default:
458 ret = key; 512 err = key;
459 break; 513 break;
460 default: 514 }
461 err = key;
462 break;
463 } 515 }
464 516
517
518no_key:
465 /* no key - decide on the error we're going to go for */ 519 /* no key - decide on the error we're going to go for */
466 key = ret ? ret : err; 520 key = ret ? ret : err;
467 521
468 found: 522found:
469 return key; 523 return key;
470 524
471} /* end search_process_keyrings_aux() */
472
473/*****************************************************************************/
474/*
475 * search the process keyrings for the first matching key
476 * - we return -EAGAIN if we didn't find any matching key
477 * - we return -ENOKEY if we found only negative matching keys
478 */
479struct key *search_process_keyrings(struct key_type *type,
480 const char *description)
481{
482 return search_process_keyrings_aux(type, description, type->match);
483
484} /* end search_process_keyrings() */ 525} /* end search_process_keyrings() */
485 526
486/*****************************************************************************/ 527/*****************************************************************************/
@@ -489,72 +530,73 @@ struct key *search_process_keyrings(struct key_type *type,
489 * - don't create special keyrings unless so requested 530 * - don't create special keyrings unless so requested
490 * - partially constructed keys aren't found unless requested 531 * - partially constructed keys aren't found unless requested
491 */ 532 */
492struct key *lookup_user_key(key_serial_t id, int create, int partial, 533struct key *lookup_user_key(struct task_struct *context, key_serial_t id,
493 key_perm_t perm) 534 int create, int partial, key_perm_t perm)
494{ 535{
495 struct task_struct *tsk = current;
496 unsigned long flags;
497 struct key *key; 536 struct key *key;
498 int ret; 537 int ret;
499 538
539 if (!context)
540 context = current;
541
500 key = ERR_PTR(-ENOKEY); 542 key = ERR_PTR(-ENOKEY);
501 543
502 switch (id) { 544 switch (id) {
503 case KEY_SPEC_THREAD_KEYRING: 545 case KEY_SPEC_THREAD_KEYRING:
504 if (!tsk->thread_keyring) { 546 if (!context->thread_keyring) {
505 if (!create) 547 if (!create)
506 goto error; 548 goto error;
507 549
508 ret = install_thread_keyring(tsk); 550 ret = install_thread_keyring(context);
509 if (ret < 0) { 551 if (ret < 0) {
510 key = ERR_PTR(ret); 552 key = ERR_PTR(ret);
511 goto error; 553 goto error;
512 } 554 }
513 } 555 }
514 556
515 key = tsk->thread_keyring; 557 key = context->thread_keyring;
516 atomic_inc(&key->usage); 558 atomic_inc(&key->usage);
517 break; 559 break;
518 560
519 case KEY_SPEC_PROCESS_KEYRING: 561 case KEY_SPEC_PROCESS_KEYRING:
520 if (!tsk->signal->process_keyring) { 562 if (!context->signal->process_keyring) {
521 if (!create) 563 if (!create)
522 goto error; 564 goto error;
523 565
524 ret = install_process_keyring(tsk); 566 ret = install_process_keyring(context);
525 if (ret < 0) { 567 if (ret < 0) {
526 key = ERR_PTR(ret); 568 key = ERR_PTR(ret);
527 goto error; 569 goto error;
528 } 570 }
529 } 571 }
530 572
531 key = tsk->signal->process_keyring; 573 key = context->signal->process_keyring;
532 atomic_inc(&key->usage); 574 atomic_inc(&key->usage);
533 break; 575 break;
534 576
535 case KEY_SPEC_SESSION_KEYRING: 577 case KEY_SPEC_SESSION_KEYRING:
536 if (!tsk->signal->session_keyring) { 578 if (!context->signal->session_keyring) {
537 /* always install a session keyring upon access if one 579 /* always install a session keyring upon access if one
538 * doesn't exist yet */ 580 * doesn't exist yet */
539 ret = install_session_keyring( 581 ret = install_session_keyring(
540 tsk, tsk->user->session_keyring); 582 context, context->user->session_keyring);
541 if (ret < 0) 583 if (ret < 0)
542 goto error; 584 goto error;
543 } 585 }
544 586
545 spin_lock_irqsave(&tsk->sighand->siglock, flags); 587 rcu_read_lock();
546 key = tsk->signal->session_keyring; 588 key = rcu_dereference(context->signal->session_keyring);
547 atomic_inc(&key->usage); 589 atomic_inc(&key->usage);
548 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 590 rcu_read_unlock();
549 break; 591 break;
550 592
551 case KEY_SPEC_USER_KEYRING: 593 case KEY_SPEC_USER_KEYRING:
552 key = tsk->user->uid_keyring; 594 key = context->user->uid_keyring;
553 atomic_inc(&key->usage); 595 atomic_inc(&key->usage);
554 break; 596 break;
555 597
556 case KEY_SPEC_USER_SESSION_KEYRING: 598 case KEY_SPEC_USER_SESSION_KEYRING:
557 key = tsk->user->session_keyring; 599 key = context->user->session_keyring;
558 atomic_inc(&key->usage); 600 atomic_inc(&key->usage);
559 break; 601 break;
560 602
@@ -574,7 +616,7 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
574 break; 616 break;
575 } 617 }
576 618
577 /* check the status and permissions */ 619 /* check the status */
578 if (perm) { 620 if (perm) {
579 ret = key_validate(key); 621 ret = key_validate(key);
580 if (ret < 0) 622 if (ret < 0)
@@ -585,8 +627,10 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
585 if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 627 if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags))
586 goto invalid_key; 628 goto invalid_key;
587 629
630 /* check the permissions */
588 ret = -EACCES; 631 ret = -EACCES;
589 if (!key_permission(key, perm)) 632
633 if (!key_task_permission(key, context, perm))
590 goto invalid_key; 634 goto invalid_key;
591 635
592 error: 636 error:
@@ -609,7 +653,6 @@ struct key *lookup_user_key(key_serial_t id, int create, int partial,
609long join_session_keyring(const char *name) 653long join_session_keyring(const char *name)
610{ 654{
611 struct task_struct *tsk = current; 655 struct task_struct *tsk = current;
612 unsigned long flags;
613 struct key *keyring; 656 struct key *keyring;
614 long ret; 657 long ret;
615 658
@@ -619,9 +662,9 @@ long join_session_keyring(const char *name)
619 if (ret < 0) 662 if (ret < 0)
620 goto error; 663 goto error;
621 664
622 spin_lock_irqsave(&tsk->sighand->siglock, flags); 665 rcu_read_lock();
623 ret = tsk->signal->session_keyring->serial; 666 ret = rcu_dereference(tsk->signal->session_keyring)->serial;
624 spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 667 rcu_read_unlock();
625 goto error; 668 goto error;
626 } 669 }
627 670