aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/process_keys.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:14 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:14 -0500
commit8bbf4976b59fc9fc2861e79cab7beb3f6d647640 (patch)
tree9bd621217cbdfcf94aca5b220de7363254d7fc23 /security/keys/process_keys.c
parente9e349b051d98799b743ebf248cc2d986fedf090 (diff)
KEYS: Alter use of key instantiation link-to-keyring argument
Alter the use of the key instantiation and negation functions' link-to-keyring arguments. Currently this specifies a keyring in the target process to link the key into, creating the keyring if it doesn't exist. This, however, can be a problem for copy-on-write credentials as it means that the instantiating process can alter the credentials of the requesting process. This patch alters the behaviour such that: (1) If keyctl_instantiate_key() or keyctl_negate_key() are given a specific keyring by ID (ringid >= 0), then that keyring will be used. (2) If keyctl_instantiate_key() or keyctl_negate_key() are given one of the special constants that refer to the requesting process's keyrings (KEY_SPEC_*_KEYRING, all <= 0), then: (a) If sys_request_key() was given a keyring to use (destringid) then the key will be attached to that keyring. (b) If sys_request_key() was given a NULL keyring, then the key being instantiated will be attached to the default keyring as set by keyctl_set_reqkey_keyring(). (3) No extra link will be made. Decision point (1) follows current behaviour, and allows those instantiators who've searched for a specifically named keyring in the requestor's keyring so as to partition the keys by type to still have their named keyrings. Decision point (2) allows the requestor to make sure that the key or keys that get produced by request_key() go where they want, whilst allowing the instantiator to request that the key is retained. This is mainly useful for situations where the instantiator makes a secondary request, the key for which should be retained by the initial requestor: +-----------+ +--------------+ +--------------+ | | | | | | | Requestor |------->| Instantiator |------->| Instantiator | | | | | | | +-----------+ +--------------+ +--------------+ request_key() request_key() This might be useful, for example, in Kerberos, where the requestor requests a ticket, and then the ticket instantiator requests the TGT, which someone else then has to go and fetch. The TGT, however, should be retained in the keyrings of the requestor, not the first instantiator. To make this explict an extra special keyring constant is also added. Signed-off-by: David Howells <dhowells@redhat.com> Reviewed-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys/process_keys.c')
-rw-r--r--security/keys/process_keys.c88
1 files changed, 54 insertions, 34 deletions
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 5be6d018759a..1c793b7090a7 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -40,9 +40,9 @@ struct key_user root_key_user = {
40/* 40/*
41 * install user and user session keyrings for a particular UID 41 * install user and user session keyrings for a particular UID
42 */ 42 */
43static int install_user_keyrings(struct task_struct *tsk) 43int install_user_keyrings(void)
44{ 44{
45 struct user_struct *user = tsk->user; 45 struct user_struct *user = current->user;
46 struct key *uid_keyring, *session_keyring; 46 struct key *uid_keyring, *session_keyring;
47 char buf[20]; 47 char buf[20];
48 int ret; 48 int ret;
@@ -67,7 +67,7 @@ static int install_user_keyrings(struct task_struct *tsk)
67 uid_keyring = find_keyring_by_name(buf, true); 67 uid_keyring = find_keyring_by_name(buf, true);
68 if (IS_ERR(uid_keyring)) { 68 if (IS_ERR(uid_keyring)) {
69 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 69 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
70 tsk, KEY_ALLOC_IN_QUOTA, 70 current, KEY_ALLOC_IN_QUOTA,
71 NULL); 71 NULL);
72 if (IS_ERR(uid_keyring)) { 72 if (IS_ERR(uid_keyring)) {
73 ret = PTR_ERR(uid_keyring); 73 ret = PTR_ERR(uid_keyring);
@@ -83,7 +83,8 @@ static int install_user_keyrings(struct task_struct *tsk)
83 if (IS_ERR(session_keyring)) { 83 if (IS_ERR(session_keyring)) {
84 session_keyring = 84 session_keyring =
85 keyring_alloc(buf, user->uid, (gid_t) -1, 85 keyring_alloc(buf, user->uid, (gid_t) -1,
86 tsk, KEY_ALLOC_IN_QUOTA, NULL); 86 current, KEY_ALLOC_IN_QUOTA,
87 NULL);
87 if (IS_ERR(session_keyring)) { 88 if (IS_ERR(session_keyring)) {
88 ret = PTR_ERR(session_keyring); 89 ret = PTR_ERR(session_keyring);
89 goto error_release; 90 goto error_release;
@@ -146,8 +147,9 @@ void switch_uid_keyring(struct user_struct *new_user)
146/* 147/*
147 * install a fresh thread keyring, discarding the old one 148 * install a fresh thread keyring, discarding the old one
148 */ 149 */
149int install_thread_keyring(struct task_struct *tsk) 150int install_thread_keyring(void)
150{ 151{
152 struct task_struct *tsk = current;
151 struct key *keyring, *old; 153 struct key *keyring, *old;
152 char buf[20]; 154 char buf[20];
153 int ret; 155 int ret;
@@ -178,8 +180,9 @@ error:
178/* 180/*
179 * make sure a process keyring is installed 181 * make sure a process keyring is installed
180 */ 182 */
181int install_process_keyring(struct task_struct *tsk) 183int install_process_keyring(void)
182{ 184{
185 struct task_struct *tsk = current;
183 struct key *keyring; 186 struct key *keyring;
184 char buf[20]; 187 char buf[20];
185 int ret; 188 int ret;
@@ -218,9 +221,9 @@ error:
218 * install a session keyring, discarding the old one 221 * install a session keyring, discarding the old one
219 * - if a keyring is not supplied, an empty one is invented 222 * - if a keyring is not supplied, an empty one is invented
220 */ 223 */
221static int install_session_keyring(struct task_struct *tsk, 224static int install_session_keyring(struct key *keyring)
222 struct key *keyring)
223{ 225{
226 struct task_struct *tsk = current;
224 unsigned long flags; 227 unsigned long flags;
225 struct key *old; 228 struct key *old;
226 char buf[20]; 229 char buf[20];
@@ -572,93 +575,91 @@ static int lookup_user_key_possessed(const struct key *key, const void *target)
572 * - don't create special keyrings unless so requested 575 * - don't create special keyrings unless so requested
573 * - partially constructed keys aren't found unless requested 576 * - partially constructed keys aren't found unless requested
574 */ 577 */
575key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, 578key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
576 int create, int partial, key_perm_t perm) 579 key_perm_t perm)
577{ 580{
581 struct request_key_auth *rka;
582 struct task_struct *t = current;
578 key_ref_t key_ref, skey_ref; 583 key_ref_t key_ref, skey_ref;
579 struct key *key; 584 struct key *key;
580 int ret; 585 int ret;
581 586
582 if (!context)
583 context = current;
584
585 key_ref = ERR_PTR(-ENOKEY); 587 key_ref = ERR_PTR(-ENOKEY);
586 588
587 switch (id) { 589 switch (id) {
588 case KEY_SPEC_THREAD_KEYRING: 590 case KEY_SPEC_THREAD_KEYRING:
589 if (!context->thread_keyring) { 591 if (!t->thread_keyring) {
590 if (!create) 592 if (!create)
591 goto error; 593 goto error;
592 594
593 ret = install_thread_keyring(context); 595 ret = install_thread_keyring();
594 if (ret < 0) { 596 if (ret < 0) {
595 key = ERR_PTR(ret); 597 key = ERR_PTR(ret);
596 goto error; 598 goto error;
597 } 599 }
598 } 600 }
599 601
600 key = context->thread_keyring; 602 key = t->thread_keyring;
601 atomic_inc(&key->usage); 603 atomic_inc(&key->usage);
602 key_ref = make_key_ref(key, 1); 604 key_ref = make_key_ref(key, 1);
603 break; 605 break;
604 606
605 case KEY_SPEC_PROCESS_KEYRING: 607 case KEY_SPEC_PROCESS_KEYRING:
606 if (!context->signal->process_keyring) { 608 if (!t->signal->process_keyring) {
607 if (!create) 609 if (!create)
608 goto error; 610 goto error;
609 611
610 ret = install_process_keyring(context); 612 ret = install_process_keyring();
611 if (ret < 0) { 613 if (ret < 0) {
612 key = ERR_PTR(ret); 614 key = ERR_PTR(ret);
613 goto error; 615 goto error;
614 } 616 }
615 } 617 }
616 618
617 key = context->signal->process_keyring; 619 key = t->signal->process_keyring;
618 atomic_inc(&key->usage); 620 atomic_inc(&key->usage);
619 key_ref = make_key_ref(key, 1); 621 key_ref = make_key_ref(key, 1);
620 break; 622 break;
621 623
622 case KEY_SPEC_SESSION_KEYRING: 624 case KEY_SPEC_SESSION_KEYRING:
623 if (!context->signal->session_keyring) { 625 if (!t->signal->session_keyring) {
624 /* always install a session keyring upon access if one 626 /* always install a session keyring upon access if one
625 * doesn't exist yet */ 627 * doesn't exist yet */
626 ret = install_user_keyrings(context); 628 ret = install_user_keyrings();
627 if (ret < 0) 629 if (ret < 0)
628 goto error; 630 goto error;
629 ret = install_session_keyring( 631 ret = install_session_keyring(t->user->session_keyring);
630 context, context->user->session_keyring);
631 if (ret < 0) 632 if (ret < 0)
632 goto error; 633 goto error;
633 } 634 }
634 635
635 rcu_read_lock(); 636 rcu_read_lock();
636 key = rcu_dereference(context->signal->session_keyring); 637 key = rcu_dereference(t->signal->session_keyring);
637 atomic_inc(&key->usage); 638 atomic_inc(&key->usage);
638 rcu_read_unlock(); 639 rcu_read_unlock();
639 key_ref = make_key_ref(key, 1); 640 key_ref = make_key_ref(key, 1);
640 break; 641 break;
641 642
642 case KEY_SPEC_USER_KEYRING: 643 case KEY_SPEC_USER_KEYRING:
643 if (!context->user->uid_keyring) { 644 if (!t->user->uid_keyring) {
644 ret = install_user_keyrings(context); 645 ret = install_user_keyrings();
645 if (ret < 0) 646 if (ret < 0)
646 goto error; 647 goto error;
647 } 648 }
648 649
649 key = context->user->uid_keyring; 650 key = t->user->uid_keyring;
650 atomic_inc(&key->usage); 651 atomic_inc(&key->usage);
651 key_ref = make_key_ref(key, 1); 652 key_ref = make_key_ref(key, 1);
652 break; 653 break;
653 654
654 case KEY_SPEC_USER_SESSION_KEYRING: 655 case KEY_SPEC_USER_SESSION_KEYRING:
655 if (!context->user->session_keyring) { 656 if (!t->user->session_keyring) {
656 ret = install_user_keyrings(context); 657 ret = install_user_keyrings();
657 if (ret < 0) 658 if (ret < 0)
658 goto error; 659 goto error;
659 } 660 }
660 661
661 key = context->user->session_keyring; 662 key = t->user->session_keyring;
662 atomic_inc(&key->usage); 663 atomic_inc(&key->usage);
663 key_ref = make_key_ref(key, 1); 664 key_ref = make_key_ref(key, 1);
664 break; 665 break;
@@ -669,7 +670,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
669 goto error; 670 goto error;
670 671
671 case KEY_SPEC_REQKEY_AUTH_KEY: 672 case KEY_SPEC_REQKEY_AUTH_KEY:
672 key = context->request_key_auth; 673 key = t->request_key_auth;
673 if (!key) 674 if (!key)
674 goto error; 675 goto error;
675 676
@@ -677,6 +678,25 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
677 key_ref = make_key_ref(key, 1); 678 key_ref = make_key_ref(key, 1);
678 break; 679 break;
679 680
681 case KEY_SPEC_REQUESTOR_KEYRING:
682 if (!t->request_key_auth)
683 goto error;
684
685 down_read(&t->request_key_auth->sem);
686 if (t->request_key_auth->flags & KEY_FLAG_REVOKED) {
687 key_ref = ERR_PTR(-EKEYREVOKED);
688 key = NULL;
689 } else {
690 rka = t->request_key_auth->payload.data;
691 key = rka->dest_keyring;
692 atomic_inc(&key->usage);
693 }
694 up_read(&t->request_key_auth->sem);
695 if (!key)
696 goto error;
697 key_ref = make_key_ref(key, 1);
698 break;
699
680 default: 700 default:
681 key_ref = ERR_PTR(-EINVAL); 701 key_ref = ERR_PTR(-EINVAL);
682 if (id < 1) 702 if (id < 1)
@@ -725,7 +745,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
725 goto invalid_key; 745 goto invalid_key;
726 746
727 /* check the permissions */ 747 /* check the permissions */
728 ret = key_task_permission(key_ref, context, perm); 748 ret = key_task_permission(key_ref, t, perm);
729 if (ret < 0) 749 if (ret < 0)
730 goto invalid_key; 750 goto invalid_key;
731 751
@@ -754,7 +774,7 @@ long join_session_keyring(const char *name)
754 774
755 /* if no name is provided, install an anonymous keyring */ 775 /* if no name is provided, install an anonymous keyring */
756 if (!name) { 776 if (!name) {
757 ret = install_session_keyring(tsk, NULL); 777 ret = install_session_keyring(NULL);
758 if (ret < 0) 778 if (ret < 0)
759 goto error; 779 goto error;
760 780
@@ -784,7 +804,7 @@ long join_session_keyring(const char *name)
784 } 804 }
785 805
786 /* we've got a keyring - now to install it */ 806 /* we've got a keyring - now to install it */
787 ret = install_session_keyring(tsk, keyring); 807 ret = install_session_keyring(keyring);
788 if (ret < 0) 808 if (ret < 0)
789 goto error2; 809 goto error2;
790 810