aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2005-09-28 12:03:15 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-28 12:10:47 -0400
commit664cceb0093b755739e56572b836a99104ee8a75 (patch)
treedbaa3ab802803879f29532db4d8a91a54294cf88 /security
parent5134fc15b643dc36eb9aa77e4318b886844a9ac5 (diff)
[PATCH] Keys: Add possessor permissions to keys [try #3]
The attached patch adds extra permission grants to keys for the possessor of a key in addition to the owner, group and other permissions bits. This makes SUID binaries easier to support without going as far as labelling keys and key targets using the LSM facilities. This patch adds a second "pointer type" to key structures (struct key_ref *) that can have the bottom bit of the address set to indicate the possession of a key. This is propagated through searches from the keyring to the discovered key. It has been made a separate type so that the compiler can spot attempts to dereference a potentially incorrect pointer. The "possession" attribute can't be attached to a key structure directly as it's not an intrinsic property of a key. Pointers to keys have been replaced with struct key_ref *'s wherever possession information needs to be passed through. This does assume that the bottom bit of the pointer will always be zero on return from kmem_cache_alloc(). The key reference type has been made into a typedef so that at least it can be located in the sources, even though it's basically a pointer to an undefined type. I've also renamed the accessor functions to be more useful, and all reference variables should now end in "_ref". Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security')
-rw-r--r--security/keys/internal.h26
-rw-r--r--security/keys/key.c81
-rw-r--r--security/keys/keyctl.c301
-rw-r--r--security/keys/keyring.c86
-rw-r--r--security/keys/proc.c2
-rw-r--r--security/keys/process_keys.c164
-rw-r--r--security/keys/request_key.c36
-rw-r--r--security/keys/request_key_auth.c2
8 files changed, 391 insertions, 307 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h
index 46c8602661c9..db99ed434f3a 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -71,26 +71,26 @@ extern void keyring_publish_name(struct key *keyring);
71 71
72extern int __key_link(struct key *keyring, struct key *key); 72extern int __key_link(struct key *keyring, struct key *key);
73 73
74extern struct key *__keyring_search_one(struct key *keyring, 74extern key_ref_t __keyring_search_one(key_ref_t keyring_ref,
75 const struct key_type *type, 75 const struct key_type *type,
76 const char *description, 76 const char *description,
77 key_perm_t perm); 77 key_perm_t perm);
78 78
79extern struct key *keyring_search_instkey(struct key *keyring, 79extern struct key *keyring_search_instkey(struct key *keyring,
80 key_serial_t target_id); 80 key_serial_t target_id);
81 81
82typedef int (*key_match_func_t)(const struct key *, const void *); 82typedef int (*key_match_func_t)(const struct key *, const void *);
83 83
84extern struct key *keyring_search_aux(struct key *keyring, 84extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
85 struct task_struct *tsk, 85 struct task_struct *tsk,
86 struct key_type *type, 86 struct key_type *type,
87 const void *description, 87 const void *description,
88 key_match_func_t match); 88 key_match_func_t match);
89 89
90extern struct key *search_process_keyrings(struct key_type *type, 90extern key_ref_t search_process_keyrings(struct key_type *type,
91 const void *description, 91 const void *description,
92 key_match_func_t match, 92 key_match_func_t match,
93 struct task_struct *tsk); 93 struct task_struct *tsk);
94 94
95extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); 95extern struct key *find_keyring_by_name(const char *name, key_serial_t bound);
96 96
diff --git a/security/keys/key.c b/security/keys/key.c
index fb89f9844465..2182be9e9309 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -693,14 +693,15 @@ void key_type_put(struct key_type *ktype)
693 * - the key has an incremented refcount 693 * - the key has an incremented refcount
694 * - we need to put the key if we get an error 694 * - we need to put the key if we get an error
695 */ 695 */
696static inline struct key *__key_update(struct key *key, const void *payload, 696static inline key_ref_t __key_update(key_ref_t key_ref,
697 size_t plen) 697 const void *payload, size_t plen)
698{ 698{
699 struct key *key = key_ref_to_ptr(key_ref);
699 int ret; 700 int ret;
700 701
701 /* need write permission on the key to update it */ 702 /* need write permission on the key to update it */
702 ret = -EACCES; 703 ret = -EACCES;
703 if (!key_permission(key, KEY_WRITE)) 704 if (!key_permission(key_ref, KEY_WRITE))
704 goto error; 705 goto error;
705 706
706 ret = -EEXIST; 707 ret = -EEXIST;
@@ -719,12 +720,12 @@ static inline struct key *__key_update(struct key *key, const void *payload,
719 720
720 if (ret < 0) 721 if (ret < 0)
721 goto error; 722 goto error;
722 out: 723out:
723 return key; 724 return key_ref;
724 725
725 error: 726error:
726 key_put(key); 727 key_put(key);
727 key = ERR_PTR(ret); 728 key_ref = ERR_PTR(ret);
728 goto out; 729 goto out;
729 730
730} /* end __key_update() */ 731} /* end __key_update() */
@@ -734,52 +735,56 @@ static inline struct key *__key_update(struct key *key, const void *payload,
734 * search the specified keyring for a key of the same description; if one is 735 * search the specified keyring for a key of the same description; if one is
735 * found, update it, otherwise add a new one 736 * found, update it, otherwise add a new one
736 */ 737 */
737struct key *key_create_or_update(struct key *keyring, 738key_ref_t key_create_or_update(key_ref_t keyring_ref,
738 const char *type, 739 const char *type,
739 const char *description, 740 const char *description,
740 const void *payload, 741 const void *payload,
741 size_t plen, 742 size_t plen,
742 int not_in_quota) 743 int not_in_quota)
743{ 744{
744 struct key_type *ktype; 745 struct key_type *ktype;
745 struct key *key = NULL; 746 struct key *keyring, *key = NULL;
746 key_perm_t perm; 747 key_perm_t perm;
748 key_ref_t key_ref;
747 int ret; 749 int ret;
748 750
749 key_check(keyring);
750
751 /* look up the key type to see if it's one of the registered kernel 751 /* look up the key type to see if it's one of the registered kernel
752 * types */ 752 * types */
753 ktype = key_type_lookup(type); 753 ktype = key_type_lookup(type);
754 if (IS_ERR(ktype)) { 754 if (IS_ERR(ktype)) {
755 key = ERR_PTR(-ENODEV); 755 key_ref = ERR_PTR(-ENODEV);
756 goto error; 756 goto error;
757 } 757 }
758 758
759 ret = -EINVAL; 759 key_ref = ERR_PTR(-EINVAL);
760 if (!ktype->match || !ktype->instantiate) 760 if (!ktype->match || !ktype->instantiate)
761 goto error_2; 761 goto error_2;
762 762
763 keyring = key_ref_to_ptr(keyring_ref);
764
765 key_check(keyring);
766
767 down_write(&keyring->sem);
768
769 /* if we're going to allocate a new key, we're going to have
770 * to modify the keyring */
771 key_ref = ERR_PTR(-EACCES);
772 if (!key_permission(keyring_ref, KEY_WRITE))
773 goto error_3;
774
763 /* search for an existing key of the same type and description in the 775 /* search for an existing key of the same type and description in the
764 * destination keyring 776 * destination keyring
765 */ 777 */
766 down_write(&keyring->sem); 778 key_ref = __keyring_search_one(keyring_ref, ktype, description, 0);
767 779 if (!IS_ERR(key_ref))
768 key = __keyring_search_one(keyring, ktype, description, 0);
769 if (!IS_ERR(key))
770 goto found_matching_key; 780 goto found_matching_key;
771 781
772 /* if we're going to allocate a new key, we're going to have to modify
773 * the keyring */
774 ret = -EACCES;
775 if (!key_permission(keyring, KEY_WRITE))
776 goto error_3;
777
778 /* decide on the permissions we want */ 782 /* decide on the permissions we want */
779 perm = KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; 783 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK;
784 perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK;
780 785
781 if (ktype->read) 786 if (ktype->read)
782 perm |= KEY_USR_READ; 787 perm |= KEY_POS_READ | KEY_USR_READ;
783 788
784 if (ktype == &key_type_keyring || ktype->update) 789 if (ktype == &key_type_keyring || ktype->update)
785 perm |= KEY_USR_WRITE; 790 perm |= KEY_USR_WRITE;