aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2008-11-13 18:39:23 -0500
committerJames Morris <jmorris@namei.org>2008-11-13 18:39:23 -0500
commitd84f4f992cbd76e8f39c488cf0c5d123843923b1 (patch)
treefc4a0349c42995715b93d0f7a3c78e9ea9b3f36e /security/keys
parent745ca2475a6ac596e3d8d37c2759c0fbe2586227 (diff)
CRED: Inaugurate COW credentials
Inaugurate copy-on-write credentials management. This uses RCU to manage the credentials pointer in the task_struct with respect to accesses by other tasks. A process may only modify its own credentials, and so does not need locking to access or modify its own credentials. A mutex (cred_replace_mutex) is added to the task_struct to control the effect of PTRACE_ATTACHED on credential calculations, particularly with respect to execve(). With this patch, the contents of an active credentials struct may not be changed directly; rather a new set of credentials must be prepared, modified and committed using something like the following sequence of events: struct cred *new = prepare_creds(); int ret = blah(new); if (ret < 0) { abort_creds(new); return ret; } return commit_creds(new); There are some exceptions to this rule: the keyrings pointed to by the active credentials may be instantiated - keyrings violate the COW rule as managing COW keyrings is tricky, given that it is possible for a task to directly alter the keys in a keyring in use by another task. To help enforce this, various pointers to sets of credentials, such as those in the task_struct, are declared const. The purpose of this is compile-time discouragement of altering credentials through those pointers. Once a set of credentials has been made public through one of these pointers, it may not be modified, except under special circumstances: (1) Its reference count may incremented and decremented. (2) The keyrings to which it points may be modified, but not replaced. The only safe way to modify anything else is to create a replacement and commit using the functions described in Documentation/credentials.txt (which will be added by a later patch). This patch and the preceding patches have been tested with the LTP SELinux testsuite. This patch makes several logical sets of alteration: (1) execve(). This now prepares and commits credentials in various places in the security code rather than altering the current creds directly. (2) Temporary credential overrides. do_coredump() and sys_faccessat() now prepare their own credentials and temporarily override the ones currently on the acting thread, whilst preventing interference from other threads by holding cred_replace_mutex on the thread being dumped. This will be replaced in a future patch by something that hands down the credentials directly to the functions being called, rather than altering the task's objective credentials. (3) LSM interface. A number of functions have been changed, added or removed: (*) security_capset_check(), ->capset_check() (*) security_capset_set(), ->capset_set() Removed in favour of security_capset(). (*) security_capset(), ->capset() New. This is passed a pointer to the new creds, a pointer to the old creds and the proposed capability sets. It should fill in the new creds or return an error. All pointers, barring the pointer to the new creds, are now const. (*) security_bprm_apply_creds(), ->bprm_apply_creds() Changed; now returns a value, which will cause the process to be killed if it's an error. (*) security_task_alloc(), ->task_alloc_security() Removed in favour of security_prepare_creds(). (*) security_cred_free(), ->cred_free() New. Free security data attached to cred->security. (*) security_prepare_creds(), ->cred_prepare() New. Duplicate any security data attached to cred->security. (*) security_commit_creds(), ->cred_commit() New. Apply any security effects for the upcoming installation of new security by commit_creds(). (*) security_task_post_setuid(), ->task_post_setuid() Removed in favour of security_task_fix_setuid(). (*) security_task_fix_setuid(), ->task_fix_setuid() Fix up the proposed new credentials for setuid(). This is used by cap_set_fix_setuid() to implicitly adjust capabilities in line with setuid() changes. Changes are made to the new credentials, rather than the task itself as in security_task_post_setuid(). (*) security_task_reparent_to_init(), ->task_reparent_to_init() Removed. Instead the task being reparented to init is referred directly to init's credentials. NOTE! This results in the loss of some state: SELinux's osid no longer records the sid of the thread that forked it. (*) security_key_alloc(), ->key_alloc() (*) security_key_permission(), ->key_permission() Changed. These now take cred pointers rather than task pointers to refer to the security context. (4) sys_capset(). This has been simplified and uses less locking. The LSM functions it calls have been merged. (5) reparent_to_kthreadd(). This gives the current thread the same credentials as init by simply using commit_thread() to point that way. (6) __sigqueue_alloc() and switch_uid() __sigqueue_alloc() can't stop the target task from changing its creds beneath it, so this function gets a reference to the currently applicable user_struct which it then passes into the sigqueue struct it returns if successful. switch_uid() is now called from commit_creds(), and possibly should be folded into that. commit_creds() should take care of protecting __sigqueue_alloc(). (7) [sg]et[ug]id() and co and [sg]et_current_groups. The set functions now all use prepare_creds(), commit_creds() and abort_creds() to build and check a new set of credentials before applying it. security_task_set[ug]id() is called inside the prepared section. This guarantees that nothing else will affect the creds until we've finished. The calling of set_dumpable() has been moved into commit_creds(). Much of the functionality of set_user() has been moved into commit_creds(). The get functions all simply access the data directly. (8) security_task_prctl() and cap_task_prctl(). security_task_prctl() has been modified to return -ENOSYS if it doesn't want to handle a function, or otherwise return the return value directly rather than through an argument. Additionally, cap_task_prctl() now prepares a new set of credentials, even if it doesn't end up using it. (9) Keyrings. A number of changes have been made to the keyrings code: (a) switch_uid_keyring(), copy_keys(), exit_keys() and suid_keys() have all been dropped and built in to the credentials functions directly. They may want separating out again later. (b) key_alloc() and search_process_keyrings() now take a cred pointer rather than a task pointer to specify the security context. (c) copy_creds() gives a new thread within the same thread group a new thread keyring if its parent had one, otherwise it discards the thread keyring. (d) The authorisation key now points directly to the credentials to extend the search into rather pointing to the task that carries them. (e) Installing thread, process or session keyrings causes a new set of credentials to be created, even though it's not strictly necessary for process or session keyrings (they're shared). (10) Usermode helper. The usermode helper code now carries a cred struct pointer in its subprocess_info struct instead of a new session keyring pointer. This set of credentials is derived from init_cred and installed on the new process after it has been cloned. call_usermodehelper_setup() allocates the new credentials and call_usermodehelper_freeinfo() discards them if they haven't been used. A special cred function (prepare_usermodeinfo_creds()) is provided specifically for call_usermodehelper_setup() to call. call_usermodehelper_setkeys() adjusts the credentials to sport the supplied keyring as the new session keyring. (11) SELinux. SELinux has a number of changes, in addition to those to support the LSM interface changes mentioned above: (a) selinux_setprocattr() no longer does its check for whether the current ptracer can access processes with the new SID inside the lock that covers getting the ptracer's SID. Whilst this lock ensures that the check is done with the ptracer pinned, the result is only valid until the lock is released, so there's no point doing it inside the lock. (12) is_single_threaded(). This function has been extracted from selinux_setprocattr() and put into a file of its own in the lib/ directory as join_session_keyring() now wants to use it too. The code in SELinux just checked to see whether a task shared mm_structs with other tasks (CLONE_VM), but that isn't good enough. We really want to know if they're part of the same thread group (CLONE_THREAD). (13) nfsd. The NFS server daemon now has to use the COW credentials to set the credentials it is going to use. It really needs to pass the credentials down to the functions it calls, but it can't do that until other patches in this series have been applied. Signed-off-by: David Howells <dhowells@redhat.com> Acked-by: James Morris <jmorris@namei.org> Signed-off-by: James Morris <jmorris@namei.org>
Diffstat (limited to 'security/keys')
-rw-r--r--security/keys/internal.h17
-rw-r--r--security/keys/key.c25
-rw-r--r--security/keys/keyctl.c95
-rw-r--r--security/keys/keyring.c14
-rw-r--r--security/keys/permission.c24
-rw-r--r--security/keys/proc.c8
-rw-r--r--security/keys/process_keys.c333
-rw-r--r--security/keys/request_key.c29
-rw-r--r--security/keys/request_key_auth.c41
9 files changed, 317 insertions, 269 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h
index d1586c629788..81932abefe7b 100644
--- a/security/keys/internal.h
+++ b/security/keys/internal.h
@@ -12,6 +12,7 @@
12#ifndef _INTERNAL_H 12#ifndef _INTERNAL_H
13#define _INTERNAL_H 13#define _INTERNAL_H
14 14
15#include <linux/sched.h>
15#include <linux/key-type.h> 16#include <linux/key-type.h>
16 17
17static inline __attribute__((format(printf, 1, 2))) 18static inline __attribute__((format(printf, 1, 2)))
@@ -25,7 +26,7 @@ void no_printk(const char *fmt, ...)
25#define kleave(FMT, ...) \ 26#define kleave(FMT, ...) \
26 printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) 27 printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__)
27#define kdebug(FMT, ...) \ 28#define kdebug(FMT, ...) \
28 printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__) 29 printk(KERN_DEBUG " "FMT"\n", ##__VA_ARGS__)
29#else 30#else
30#define kenter(FMT, ...) \ 31#define kenter(FMT, ...) \
31 no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) 32 no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__)
@@ -97,7 +98,7 @@ extern struct key *keyring_search_instkey(struct key *keyring,
97typedef int (*key_match_func_t)(const struct key *, const void *); 98typedef int (*key_match_func_t)(const struct key *, const void *);
98 99
99extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, 100extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
100 struct task_struct *tsk, 101 const struct cred *cred,
101 struct key_type *type, 102 struct key_type *type,
102 const void *description, 103 const void *description,
103 key_match_func_t match); 104 key_match_func_t match);
@@ -105,13 +106,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref,
105extern key_ref_t search_process_keyrings(struct key_type *type, 106extern key_ref_t search_process_keyrings(struct key_type *type,
106 const void *description, 107 const void *description,
107 key_match_func_t match, 108 key_match_func_t match,
108 struct task_struct *tsk); 109 const struct cred *cred);
109 110
110extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); 111extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check);
111 112
112extern int install_user_keyrings(void); 113extern int install_user_keyrings(void);
113extern int install_thread_keyring(void); 114extern int install_thread_keyring_to_cred(struct cred *);
114extern int install_process_keyring(void); 115extern int install_process_keyring_to_cred(struct cred *);
115 116
116extern struct key *request_key_and_link(struct key_type *type, 117extern struct key *request_key_and_link(struct key_type *type,
117 const char *description, 118 const char *description,
@@ -130,12 +131,12 @@ extern long join_session_keyring(const char *name);
130 * check to see whether permission is granted to use a key in the desired way 131 * check to see whether permission is granted to use a key in the desired way
131 */ 132 */
132extern int key_task_permission(const key_ref_t key_ref, 133extern int key_task_permission(const key_ref_t key_ref,
133 struct task_struct *context, 134 const struct cred *cred,
134 key_perm_t perm); 135 key_perm_t perm);
135 136
136static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) 137static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
137{ 138{
138 return key_task_permission(key_ref, current, perm); 139 return key_task_permission(key_ref, current_cred(), perm);
139} 140}
140 141
141/* required permissions */ 142/* required permissions */
@@ -153,7 +154,7 @@ static inline int key_permission(const key_ref_t key_ref, key_perm_t perm)
153struct request_key_auth { 154struct request_key_auth {
154 struct key *target_key; 155 struct key *target_key;
155 struct key *dest_keyring; 156 struct key *dest_keyring;
156 struct task_struct *context; 157 const struct cred *cred;
157 void *callout_info; 158 void *callout_info;
158 size_t callout_len; 159 size_t callout_len;
159 pid_t pid; 160 pid_t pid;
diff --git a/security/keys/key.c b/security/keys/key.c
index a6ca39ed3b0e..f76c8a546fd3 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -218,7 +218,7 @@ serial_exists:
218 * instantiate the key or discard it before returning 218 * instantiate the key or discard it before returning
219 */ 219 */
220struct key *key_alloc(struct key_type *type, const char *desc, 220struct key *key_alloc(struct key_type *type, const char *desc,
221 uid_t uid, gid_t gid, struct task_struct *ctx, 221 uid_t uid, gid_t gid, const struct cred *cred,
222 key_perm_t perm, unsigned long flags) 222 key_perm_t perm, unsigned long flags)
223{ 223{
224 struct key_user *user = NULL; 224 struct key_user *user = NULL;
@@ -294,7 +294,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
294#endif 294#endif
295 295
296 /* let the security module know about the key */ 296 /* let the security module know about the key */
297 ret = security_key_alloc(key, ctx, flags); 297 ret = security_key_alloc(key, cred, flags);
298 if (ret < 0) 298 if (ret < 0)
299 goto security_error; 299 goto security_error;
300 300
@@ -391,7 +391,7 @@ static int __key_instantiate_and_link(struct key *key,
391 const void *data, 391 const void *data,
392 size_t datalen, 392 size_t datalen,
393 struct key *keyring, 393 struct key *keyring,
394 struct key *instkey) 394 struct key *authkey)
395{ 395{
396 int ret, awaken; 396 int ret, awaken;
397 397
@@ -421,8 +421,8 @@ static int __key_instantiate_and_link(struct key *key,
421 ret = __key_link(keyring, key); 421 ret = __key_link(keyring, key);
422 422
423 /* disable the authorisation key */ 423 /* disable the authorisation key */
424 if (instkey) 424 if (authkey)
425 key_revoke(instkey); 425 key_revoke(authkey);
426 } 426 }
427 } 427 }
428 428
@@ -444,14 +444,14 @@ int key_instantiate_and_link(struct key *key,
444 const void *data, 444 const void *data,
445 size_t datalen, 445 size_t datalen,
446 struct key *keyring, 446 struct key *keyring,
447 struct key *instkey) 447 struct key *authkey)
448{ 448{
449 int ret; 449 int ret;
450 450
451 if (keyring) 451 if (keyring)
452 down_write(&keyring->sem); 452 down_write(&keyring->sem);
453 453
454 ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey); 454 ret = __key_instantiate_and_link(key, data, datalen, keyring, authkey);
455 455
456 if (keyring) 456 if (keyring)
457 up_write(&keyring->sem); 457 up_write(&keyring->sem);
@@ -469,7 +469,7 @@ EXPORT_SYMBOL(key_instantiate_and_link);
469int key_negate_and_link(struct key *key, 469int key_negate_and_link(struct key *key,
470 unsigned timeout, 470 unsigned timeout,
471 struct key *keyring, 471 struct key *keyring,
472 struct key *instkey) 472 struct key *authkey)
473{ 473{
474 struct timespec now; 474 struct timespec now;
475 int ret, awaken; 475 int ret, awaken;
@@ -504,8 +504,8 @@ int key_negate_and_link(struct key *key,
504 ret = __key_link(keyring, key); 504 ret = __key_link(keyring, key);
505 505
506 /* disable the authorisation key */ 506 /* disable the authorisation key */
507 if (instkey) 507 if (authkey)
508 key_revoke(instkey); 508 key_revoke(authkey);
509 } 509 }
510 510
511 mutex_unlock(&key_construction_mutex); 511 mutex_unlock(&key_construction_mutex);
@@ -743,6 +743,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
743 key_perm_t perm, 743 key_perm_t perm,
744 unsigned long flags) 744 unsigned long flags)
745{ 745{
746 const struct cred *cred = current_cred();
746 struct key_type *ktype; 747 struct key_type *ktype;
747 struct key *keyring, *key = NULL; 748 struct key *keyring, *key = NULL;
748 key_ref_t key_ref; 749 key_ref_t key_ref;
@@ -802,8 +803,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
802 } 803 }
803 804
804 /* allocate a new key */ 805 /* allocate a new key */
805 key = key_alloc(ktype, description, current_fsuid(), current_fsgid(), 806 key = key_alloc(ktype, description, cred->fsuid, cred->fsgid, cred,
806 current, perm, flags); 807 perm, flags);
807 if (IS_ERR(key)) { 808 if (IS_ERR(key)) {
808 key_ref = ERR_CAST(key); 809 key_ref = ERR_CAST(key);
809 goto error_3; 810 goto error_3;
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 8833b447adef..7c72baa02f2e 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -866,6 +866,23 @@ static long get_instantiation_keyring(key_serial_t ringid,
866 return -ENOKEY; 866 return -ENOKEY;
867} 867}
868 868
869/*
870 * change the request_key authorisation key on the current process
871 */
872static int keyctl_change_reqkey_auth(struct key *key)
873{
874 struct cred *new;
875
876 new = prepare_creds();
877 if (!new)
878 return -ENOMEM;
879
880 key_put(new->request_key_auth);
881 new->request_key_auth = key_get(key);
882
883 return commit_creds(new);
884}
885
869/*****************************************************************************/ 886/*****************************************************************************/
870/* 887/*
871 * instantiate the key with the specified payload, and, if one is given, link 888 * instantiate the key with the specified payload, and, if one is given, link
@@ -876,12 +893,15 @@ long keyctl_instantiate_key(key_serial_t id,
876 size_t plen, 893 size_t plen,
877 key_serial_t ringid) 894 key_serial_t ringid)
878{ 895{
896 const struct cred *cred = current_cred();
879 struct request_key_auth *rka; 897 struct request_key_auth *rka;
880 struct key *instkey, *dest_keyring; 898 struct key *instkey, *dest_keyring;
881 void *payload; 899 void *payload;
882 long ret; 900 long ret;
883 bool vm = false; 901 bool vm = false;
884 902
903 kenter("%d,,%zu,%d", id, plen, ringid);
904
885 ret = -EINVAL; 905 ret = -EINVAL;
886 if (plen > 1024 * 1024 - 1) 906 if (plen > 1024 * 1024 - 1)
887 goto error; 907 goto error;
@@ -889,7 +909,7 @@ long keyctl_instantiate_key(key_serial_t id,
889 /* the appropriate instantiation authorisation key must have been 909 /* the appropriate instantiation authorisation key must have been
890 * assumed before calling this */ 910 * assumed before calling this */
891 ret = -EPERM; 911 ret = -EPERM;
892 instkey = current->cred->request_key_auth; 912 instkey = cred->request_key_auth;
893 if (!instkey) 913 if (!instkey)
894 goto error; 914 goto error;
895 915
@@ -931,10 +951,8 @@ long keyctl_instantiate_key(key_serial_t id,
931 951
932 /* discard the assumed authority if it's just been disabled by 952 /* discard the assumed authority if it's just been disabled by
933 * instantiation of the key */ 953 * instantiation of the key */
934 if (ret == 0) { 954 if (ret == 0)
935 key_put(current->cred->request_key_auth); 955 keyctl_change_reqkey_auth(NULL);
936 current->cred->request_key_auth = NULL;
937 }
938 956
939error2: 957error2:
940 if (!vm) 958 if (!vm)
@@ -953,14 +971,17 @@ error:
953 */ 971 */
954long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) 972long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
955{ 973{
974 const struct cred *cred = current_cred();
956 struct request_key_auth *rka; 975 struct request_key_auth *rka;
957 struct key *instkey, *dest_keyring; 976 struct key *instkey, *dest_keyring;
958 long ret; 977 long ret;
959 978
979 kenter("%d,%u,%d", id, timeout, ringid);
980
960 /* the appropriate instantiation authorisation key must have been 981 /* the appropriate instantiation authorisation key must have been
961 * assumed before calling this */ 982 * assumed before calling this */
962 ret = -EPERM; 983 ret = -EPERM;
963 instkey = current->cred->request_key_auth; 984 instkey = cred->request_key_auth;
964 if (!instkey) 985 if (!instkey)
965 goto error; 986 goto error;
966 987
@@ -982,10 +1003,8 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid)
982 1003
983 /* discard the assumed authority if it's just been disabled by 1004 /* discard the assumed authority if it's just been disabled by
984 * instantiation of the key */ 1005 * instantiation of the key */
985 if (ret == 0) { 1006 if (ret == 0)
986 key_put(current->cred->request_key_auth); 1007 keyctl_change_reqkey_auth(NULL);
987 current->cred->request_key_auth = NULL;
988 }
989 1008
990error: 1009error:
991 return ret; 1010 return ret;
@@ -999,36 +1018,56 @@ error:
999 */ 1018 */
1000long keyctl_set_reqkey_keyring(int reqkey_defl) 1019long keyctl_set_reqkey_keyring(int reqkey_defl)
1001{ 1020{
1002 struct cred *cred = current->cred; 1021 struct cred *new;
1003 int ret; 1022 int ret, old_setting;
1023
1024 old_setting = current_cred_xxx(jit_keyring);
1025
1026 if (reqkey_defl == KEY_REQKEY_DEFL_NO_CHANGE)
1027 return old_setting;
1028
1029 new = prepare_creds();
1030 if (!new)
1031 return -ENOMEM;
1004 1032
1005 switch (reqkey_defl) { 1033 switch (reqkey_defl) {
1006 case KEY_REQKEY_DEFL_THREAD_KEYRING: 1034 case KEY_REQKEY_DEFL_THREAD_KEYRING:
1007 ret = install_thread_keyring(); 1035 ret = install_thread_keyring_to_cred(new);
1008 if (ret < 0) 1036 if (ret < 0)
1009 return ret; 1037 goto error;
1010 goto set; 1038 goto set;
1011 1039
1012 case KEY_REQKEY_DEFL_PROCESS_KEYRING: 1040 case KEY_REQKEY_DEFL_PROCESS_KEYRING:
1013 ret = install_process_keyring(); 1041 ret = install_process_keyring_to_cred(new);
1014 if (ret < 0) 1042 if (ret < 0) {
1015 return ret; 1043 if (ret != -EEXIST)
1044 goto error;
1045 ret = 0;
1046 }
1047 goto set;
1016 1048
1017 case KEY_REQKEY_DEFL_DEFAULT: 1049 case KEY_REQKEY_DEFL_DEFAULT:
1018 case KEY_REQKEY_DEFL_SESSION_KEYRING: 1050 case KEY_REQKEY_DEFL_SESSION_KEYRING:
1019 case KEY_REQKEY_DEFL_USER_KEYRING: 1051 case KEY_REQKEY_DEFL_USER_KEYRING:
1020 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 1052 case KEY_REQKEY_DEFL_USER_SESSION_KEYRING:
1021 set: 1053 case KEY_REQKEY_DEFL_REQUESTOR_KEYRING:
1022 cred->jit_keyring = reqkey_defl; 1054 goto set;
1023 1055
1024 case KEY_REQKEY_DEFL_NO_CHANGE: 1056 case KEY_REQKEY_DEFL_NO_CHANGE:
1025 return cred->jit_keyring;
1026
1027 case KEY_REQKEY_DEFL_GROUP_KEYRING: 1057 case KEY_REQKEY_DEFL_GROUP_KEYRING:
1028 default: 1058 default:
1029 return -EINVAL; 1059 ret = -EINVAL;
1060 goto error;
1030 } 1061 }
1031 1062
1063set:
1064 new->jit_keyring = reqkey_defl;
1065 commit_creds(new);
1066 return old_setting;
1067error:
1068 abort_creds(new);
1069 return -EINVAL;
1070
1032} /* end keyctl_set_reqkey_keyring() */ 1071} /* end keyctl_set_reqkey_keyring() */
1033 1072
1034/*****************************************************************************/ 1073/*****************************************************************************/
@@ -1087,9 +1126,7 @@ long keyctl_assume_authority(key_serial_t id)
1087 1126
1088 /* we divest ourselves of authority if given an ID of 0 */ 1127 /* we divest ourselves of authority if given an ID of 0 */
1089 if (id == 0) { 1128 if (id == 0) {
1090 key_put(current->cred->request_key_auth); 1129 ret = keyctl_change_reqkey_auth(NULL);
1091 current->cred->request_key_auth = NULL;
1092 ret = 0;
1093 goto error; 1130 goto error;
1094 } 1131 }
1095 1132
@@ -1104,10 +1141,12 @@ long keyctl_assume_authority(key_serial_t id)
1104 goto error; 1141 goto error;
1105 } 1142 }
1106 1143
1107 key_put(current->cred->request_key_auth); 1144 ret = keyctl_change_reqkey_auth(authkey);
1108 current->cred->request_key_auth = authkey; 1145 if (ret < 0)
1109 ret = authkey->serial; 1146 goto error;
1147 key_put(authkey);
1110 1148
1149 ret = authkey->serial;
1111error: 1150error:
1112 return ret; 1151 return ret;
1113 1152
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index fdf75f901991..ed851574d073 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -245,14 +245,14 @@ static long keyring_read(const struct key *keyring,
245 * allocate a keyring and link into the destination keyring 245 * allocate a keyring and link into the destination keyring
246 */ 246 */
247struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, 247struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
248 struct task_struct *ctx, unsigned long flags, 248 const struct cred *cred, unsigned long flags,
249 struct key *dest) 249 struct key *dest)
250{ 250{
251 struct key *keyring; 251 struct key *keyring;
252 int ret; 252 int ret;
253 253
254 keyring = key_alloc(&key_type_keyring, description, 254 keyring = key_alloc(&key_type_keyring, description,
255 uid, gid, ctx, 255 uid, gid, cred,
256 (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, 256 (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
257 flags); 257 flags);
258 258
@@ -281,7 +281,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
281 * - we propagate the possession attribute from the keyring ref to the key ref 281 * - we propagate the possession attribute from the keyring ref to the key ref
282 */ 282 */
283key_ref_t keyring_search_aux(key_ref_t keyring_ref, 283key_ref_t keyring_search_aux(key_ref_t keyring_ref,
284 struct task_struct *context, 284 const struct cred *cred,
285 struct key_type *type, 285 struct key_type *type,
286 const void *description, 286 const void *description,
287 key_match_func_t match) 287 key_match_func_t match)
@@ -304,7 +304,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
304 key_check(keyring); 304 key_check(keyring);
305 305
306 /* top keyring must have search permission to begin the search */ 306 /* top keyring must have search permission to begin the search */
307 err = key_task_permission(keyring_ref, context, KEY_SEARCH); 307 err = key_task_permission(keyring_ref, cred, KEY_SEARCH);
308 if (err < 0) { 308 if (err < 0) {
309 key_ref = ERR_PTR(err); 309 key_ref = ERR_PTR(err);
310 goto error; 310 goto error;
@@ -377,7 +377,7 @@ descend:
377 377
378 /* key must have search permissions */ 378 /* key must have search permissions */
379 if (key_task_permission(make_key_ref(key, possessed), 379 if (key_task_permission(make_key_ref(key, possessed),
380 context, KEY_SEARCH) < 0) 380 cred, KEY_SEARCH) < 0)
381 continue; 381 continue;
382 382
383 /* we set a different error code if we pass a negative key */ 383 /* we set a different error code if we pass a negative key */
@@ -404,7 +404,7 @@ ascend:
404 continue; 404 continue;
405 405
406 if (key_task_permission(make_key_ref(key, possessed), 406 if (key_task_permission(make_key_ref(key, possessed),
407 context, KEY_SEARCH) < 0) 407 cred, KEY_SEARCH) < 0)
408 continue; 408 continue;
409 409
410 /* stack the current position */ 410 /* stack the current position */
@@ -459,7 +459,7 @@ key_ref_t keyring_search(key_ref_t keyring,
459 if (!type->match) 459 if (!type->match)
460 return ERR_PTR(-ENOKEY); 460 return ERR_PTR(-ENOKEY);
461 461
462 return keyring_search_aux(keyring, current, 462 return keyring_search_aux(keyring, current->cred,
463 type, description, type->match); 463 type, description, type->match);
464 464
465} /* end keyring_search() */ 465} /* end keyring_search() */
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 13c36164f284..5d9fc7b93f2e 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -14,24 +14,27 @@
14#include "internal.h" 14#include "internal.h"
15 15
16/*****************************************************************************/ 16/*****************************************************************************/
17/* 17/**
18 * check to see whether permission is granted to use a key in the desired way, 18 * key_task_permission - Check a key can be used
19 * but permit the security modules to override 19 * @key_ref: The key to check
20 * @cred: The credentials to use
21 * @perm: The permissions to check for
22 *
23 * Check to see whether permission is granted to use a key in the desired way,
24 * but permit the security modules to override.
25 *
26 * The caller must hold either a ref on cred or must hold the RCU readlock or a
27 * spinlock.
20 */ 28 */
21int key_task_permission(const key_ref_t key_ref, 29int key_task_permission(const key_ref_t key_ref, const struct cred *cred,
22 struct task_struct *context,
23 key_perm_t perm) 30 key_perm_t perm)
24{ 31{
25 const struct cred *cred;
26 struct key *key; 32 struct key *key;
27 key_perm_t kperm; 33 key_perm_t kperm;
28 int ret; 34 int ret;
29 35
30 key = key_ref_to_ptr(key_ref); 36 key = key_ref_to_ptr(key_ref);
31 37
32 rcu_read_lock();
33 cred = __task_cred(context);
34
35 /* use the second 8-bits of permissions for keys the caller owns */ 38 /* use the second 8-bits of permissions for keys the caller owns */
36 if (key->uid == cred->fsuid) { 39 if (key->uid == cred->fsuid) {
37 kperm = key->perm >> 16; 40 kperm = key->perm >> 16;
@@ -57,7 +60,6 @@ int key_task_permission(const key_ref_t key_ref,
57 kperm = key->perm; 60 kperm = key->perm;
58 61
59use_these_perms: 62use_these_perms:
60 rcu_read_lock();
61 63
62 /* use the top 8-bits of permissions for keys the caller possesses 64 /* use the top 8-bits of permissions for keys the caller possesses
63 * - possessor permissions are additive with other permissions 65 * - possessor permissions are additive with other permissions
@@ -71,7 +73,7 @@ use_these_perms:
71 return -EACCES; 73 return -EACCES;
72 74
73 /* let LSM be the final arbiter */ 75 /* let LSM be the final arbiter */
74 return security_key_permission(key_ref, context, perm); 76 return security_key_permission(key_ref, cred, perm);
75 77
76} /* end key_task_permission() */ 78} /* end key_task_permission() */
77 79
diff --git a/security/keys/proc.c b/security/keys/proc.c
index f619170da760..7f508def50e3 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -136,8 +136,12 @@ static int proc_keys_show(struct seq_file *m, void *v)
136 int rc; 136 int rc;
137 137
138 /* check whether the current task is allowed to view the key (assuming 138 /* check whether the current task is allowed to view the key (assuming
139 * non-possession) */ 139 * non-possession)
140 rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW); 140 * - the caller holds a spinlock, and thus the RCU read lock, making our
141 * access to __current_cred() safe
142 */
143 rc = key_task_permission(make_key_ref(key, 0), current_cred(),
144 KEY_VIEW);
141 if (rc < 0) 145 if (rc < 0)
142 return 0; 146 return 0;
143 147
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index 70ee93406f30..df329f684a65 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -42,11 +42,15 @@ struct key_user root_key_user = {
42 */ 42 */
43int install_user_keyrings(void) 43int install_user_keyrings(void)
44{ 44{
45 struct user_struct *user = current->cred->user; 45 struct user_struct *user;
46 const struct cred *cred;
46 struct key *uid_keyring, *session_keyring; 47 struct key *uid_keyring, *session_keyring;
47 char buf[20]; 48 char buf[20];
48 int ret; 49 int ret;
49 50
51 cred = current_cred();
52 user = cred->user;
53
50 kenter("%p{%u}", user, user->uid); 54 kenter("%p{%u}", user, user->uid);
51 55
52 if (user->uid_keyring) { 56 if (user->uid_keyring) {
@@ -67,7 +71,7 @@ int install_user_keyrings(void)
67 uid_keyring = find_keyring_by_name(buf, true); 71 uid_keyring = find_keyring_by_name(buf, true);
68 if (IS_ERR(uid_keyring)) { 72 if (IS_ERR(uid_keyring)) {
69 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, 73 uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1,
70 current, KEY_ALLOC_IN_QUOTA, 74 cred, KEY_ALLOC_IN_QUOTA,
71 NULL); 75 NULL);
72 if (IS_ERR(uid_keyring)) { 76 if (IS_ERR(uid_keyring)) {
73 ret = PTR_ERR(uid_keyring); 77 ret = PTR_ERR(uid_keyring);
@@ -83,8 +87,7 @@ int install_user_keyrings(void)
83 if (IS_ERR(session_keyring)) { 87 if (IS_ERR(session_keyring)) {
84 session_keyring = 88 session_keyring =
85 keyring_alloc(buf, user->uid, (gid_t) -1, 89 keyring_alloc(buf, user->uid, (gid_t) -1,
86 current, KEY_ALLOC_IN_QUOTA, 90 cred, KEY_ALLOC_IN_QUOTA, NULL);
87 NULL);
88 if (IS_ERR(session_keyring)) { 91 if (IS_ERR(session_keyring)) {
89 ret = PTR_ERR(session_keyring); 92 ret = PTR_ERR(session_keyring);
90 goto error_release; 93 goto error_release;
@@ -116,142 +119,128 @@ error:
116 return ret; 119 return ret;
117} 120}
118 121
119/*****************************************************************************/
120/* 122/*
121 * deal with the UID changing 123 * install a fresh thread keyring directly to new credentials
122 */ 124 */
123void switch_uid_keyring(struct user_struct *new_user) 125int install_thread_keyring_to_cred(struct cred *new)
124{ 126{
125#if 0 /* do nothing for now */ 127 struct key *keyring;
126 struct key *old;
127
128 /* switch to the new user's session keyring if we were running under
129 * root's default session keyring */
130 if (new_user->uid != 0 &&
131 current->session_keyring == &root_session_keyring
132 ) {
133 atomic_inc(&new_user->session_keyring->usage);
134
135 task_lock(current);
136 old = current->session_keyring;
137 current->session_keyring = new_user->session_keyring;
138 task_unlock(current);
139 128
140 key_put(old); 129 keyring = keyring_alloc("_tid", new->uid, new->gid, new,
141 } 130 KEY_ALLOC_QUOTA_OVERRUN, NULL);
142#endif 131 if (IS_ERR(keyring))
132 return PTR_ERR(keyring);
143 133
144} /* end switch_uid_keyring() */ 134 new->thread_keyring = keyring;
135 return 0;
136}
145 137
146/*****************************************************************************/
147/* 138/*
148 * install a fresh thread keyring, discarding the old one 139 * install a fresh thread keyring, discarding the old one
149 */ 140 */
150int install_thread_keyring(void) 141static int install_thread_keyring(void)
151{ 142{
152 struct task_struct *tsk = current; 143 struct cred *new;
153 struct key *keyring, *old;
154 char buf[20];
155 int ret; 144 int ret;
156 145
157 sprintf(buf, "_tid.%u", tsk->pid); 146 new = prepare_creds();
147 if (!new)
148 return -ENOMEM;
158 149
159 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk, 150 BUG_ON(new->thread_keyring);
160 KEY_ALLOC_QUOTA_OVERRUN, NULL); 151
161 if (IS_ERR(keyring)) { 152 ret = install_thread_keyring_to_cred(new);
162 ret = PTR_ERR(keyring); 153 if (ret < 0) {
163 goto error; 154 abort_creds(new);
155 return ret;
164 } 156 }
165 157
166 task_lock(tsk); 158 return commit_creds(new);
167 old = tsk->cred->thread_keyring; 159}
168 tsk->cred->thread_keyring = keyring;
169 task_unlock(tsk);
170 160
171 ret = 0; 161/*
162 * install a process keyring directly to a credentials struct
163 * - returns -EEXIST if there was already a process keyring, 0 if one installed,
164 * and other -ve on any other error
165 */
166int install_process_keyring_to_cred(struct cred *new)
167{
168 struct key *keyring;
169 int ret;
172 170
173 key_put(old); 171 if (new->tgcred->process_keyring)
174error: 172 return -EEXIST;
173
174 keyring = keyring_alloc("_pid", new->uid, new->gid,
175 new, KEY_ALLOC_QUOTA_OVERRUN, NULL);
176 if (IS_ERR(keyring))
177 return PTR_ERR(keyring);
178
179 spin_lock_irq(&new->tgcred->lock);
180 if (!new->tgcred->process_keyring) {
181 new->tgcred->process_keyring = keyring;
182 keyring = NULL;
183 ret = 0;
184 } else {
185 ret = -EEXIST;
186 }
187 spin_unlock_irq(&new->tgcred->lock);
188 key_put(keyring);
175 return ret; 189 return ret;
190}
176 191
177} /* end install_thread_keyring() */
178
179/*****************************************************************************/
180/* 192/*
181 * make sure a process keyring is installed 193 * make sure a process keyring is installed
194 * - we
182 */ 195 */
183int install_process_keyring(void) 196static int install_process_keyring(void)
184{ 197{
185 struct task_struct *tsk = current; 198 struct cred *new;
186 struct key *keyring;
187 char buf[20];
188 int ret; 199 int ret;
189 200
190 might_sleep(); 201 new = prepare_creds();
191 202 if (!new)
192 if (!tsk->cred->tgcred->process_keyring) { 203 return -ENOMEM;
193 sprintf(buf, "_pid.%u", tsk->tgid);
194
195 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, tsk,
196 KEY_ALLOC_QUOTA_OVERRUN, NULL);
197 if (IS_ERR(keyring)) {
198 ret = PTR_ERR(keyring);
199 goto error;
200 }
201
202 /* attach keyring */
203 spin_lock_irq(&tsk->cred->tgcred->lock);
204 if (!tsk->cred->tgcred->process_keyring) {
205 tsk->cred->tgcred->process_keyring = keyring;
206 keyring = NULL;
207 }
208 spin_unlock_irq(&tsk->cred->tgcred->lock);
209 204
210 key_put(keyring); 205 ret = install_process_keyring_to_cred(new);
206 if (ret < 0) {
207 abort_creds(new);
208 return ret != -EEXIST ?: 0;
211 } 209 }
212 210
213 ret = 0; 211 return commit_creds(new);
214error: 212}
215 return ret;
216
217} /* end install_process_keyring() */
218 213
219/*****************************************************************************/
220/* 214/*
221 * install a session keyring, discarding the old one 215 * install a session keyring directly to a credentials struct
222 * - if a keyring is not supplied, an empty one is invented
223 */ 216 */
224static int install_session_keyring(struct key *keyring) 217static int install_session_keyring_to_cred(struct cred *cred,
218 struct key *keyring)
225{ 219{
226 struct task_struct *tsk = current;
227 unsigned long flags; 220 unsigned long flags;
228 struct key *old; 221 struct key *old;
229 char buf[20];
230 222
231 might_sleep(); 223 might_sleep();
232 224
233 /* create an empty session keyring */ 225 /* create an empty session keyring */
234 if (!keyring) { 226 if (!keyring) {
235 sprintf(buf, "_ses.%u", tsk->tgid);
236
237 flags = KEY_ALLOC_QUOTA_OVERRUN; 227 flags = KEY_ALLOC_QUOTA_OVERRUN;
238 if (tsk->cred->tgcred->session_keyring) 228 if (cred->tgcred->session_keyring)
239 flags = KEY_ALLOC_IN_QUOTA; 229 flags = KEY_ALLOC_IN_QUOTA;
240 230
241 keyring = keyring_alloc(buf, tsk->cred->uid, tsk->cred->gid, 231 keyring = keyring_alloc("_ses", cred->uid, cred->gid,
242 tsk, flags, NULL); 232 cred, flags, NULL);
243 if (IS_ERR(keyring)) 233 if (IS_ERR(keyring))
244 return PTR_ERR(keyring); 234 return PTR_ERR(keyring);
245 } 235 } else {
246 else {
247 atomic_inc(&keyring->usage); 236 atomic_inc(&keyring->usage);
248 } 237 }
249 238
250 /* install the keyring */ 239 /* install the keyring */
251 spin_lock_irq(&tsk->cred->tgcred->lock); 240 spin_lock_irq(&cred->tgcred->lock);
252 old = tsk->cred->tgcred->session_keyring; 241 old = cred->tgcred->session_keyring;
253 rcu_assign_pointer(tsk->cred->tgcred->session_keyring, keyring); 242 rcu_assign_pointer(cred->tgcred->session_keyring, keyring);
254 spin_unlock_irq(&tsk->cred->tgcred->lock); 243 spin_unlock_irq(&cred->tgcred->lock);
255 244
256 /* we're using RCU on the pointer, but there's no point synchronising 245 /* we're using RCU on the pointer, but there's no point synchronising
257 * on it if it didn't previously point to anything */ 246 * on it if it didn't previously point to anything */
@@ -261,38 +250,29 @@ static int install_session_keyring(struct key *keyring)
261 } 250 }
262 251
263 return 0; 252 return 0;
253}
264 254
265} /* end install_session_keyring() */
266
267/*****************************************************************************/
268/* 255/*
269 * copy the keys for fork 256 * install a session keyring, discarding the old one
257 * - if a keyring is not supplied, an empty one is invented
270 */ 258 */
271int copy_keys(unsigned long clone_flags, struct task_struct *tsk) 259static int install_session_keyring(struct key *keyring)
272{ 260{
273 key_check(tsk->cred->thread_keyring); 261 struct cred *new;
274 key_check(tsk->cred->request_key_auth); 262 int ret;
275
276 /* no thread keyring yet */
277 tsk->cred->thread_keyring = NULL;
278
279 /* copy the request_key() authorisation for this thread */
280 key_get(tsk->cred->request_key_auth);
281
282 return 0;
283 263
284} /* end copy_keys() */ 264 new = prepare_creds();
265 if (!new)
266 return -ENOMEM;
285 267
286/*****************************************************************************/ 268 ret = install_session_keyring_to_cred(new, NULL);
287/* 269 if (ret < 0) {
288 * dispose of per-thread keys upon thread exit 270 abort_creds(new);
289 */ 271 return ret;
290void exit_keys(struct task_struct *tsk) 272 }
291{
292 key_put(tsk->cred->thread_keyring);
293 key_put(tsk->cred->request_key_auth);
294 273
295} /* end exit_keys() */ 274 return commit_creds(new);
275}
296 276
297/*****************************************************************************/ 277/*****************************************************************************/
298/* 278/*
@@ -300,38 +280,41 @@ void exit_keys(struct task_struct *tsk)
300 */ 280 */
301int exec_keys(struct task_struct *tsk) 281int exec_keys(struct task_struct *tsk)
302{ 282{
303 struct key *old; 283 struct thread_group_cred *tgcred = NULL;
284 struct cred *new;
304 285
305 /* newly exec'd tasks don't get a thread keyring */ 286#ifdef CONFIG_KEYS
306 task_lock(tsk); 287 tgcred = kmalloc(sizeof(*tgcred), GFP_KERNEL);
307 old = tsk->cred->thread_keyring; 288 if (!tgcred)
308 tsk->cred->thread_keyring = NULL; 289 return -ENOMEM;
309 task_unlock(tsk); 290#endif
310 291
311 key_put(old); 292 new = prepare_creds();
293 if (new < 0)
294 return -ENOMEM;
312 295
313 /* discard the process keyring from a newly exec'd task */ 296 /* newly exec'd tasks don't get a thread keyring */
314 spin_lock_irq(&tsk->cred->tgcred->lock); 297 key_put(new->thread_keyring);
315 old = tsk->cred->tgcred->process_keyring; 298 new->thread_keyring = NULL;
316 tsk->cred->tgcred->process_keyring = NULL;
317 spin_unlock_irq(&tsk->cred->tgcred->lock);
318 299
319 key_put(old); 300 /* create a new per-thread-group creds for all this set of threads to
301 * share */
302 memcpy(tgcred, new->tgcred, sizeof(struct thread_group_cred));
320 303
321 return 0; 304 atomic_set(&tgcred->usage, 1);
305 spin_lock_init(&tgcred->lock);
322 306
323} /* end exec_keys() */ 307 /* inherit the session keyring; new process keyring */
308 key_get(tgcred->session_keyring);
309 tgcred->process_keyring = NULL;
324 310
325/*****************************************************************************/ 311 release_tgcred(new);
326/* 312 new->tgcred = tgcred;
327 * deal with SUID programs 313
328 * - we might want to make this invent a new session keyring 314 commit_creds(new);
329 */
330int suid_keys(struct task_struct *tsk)
331{
332 return 0; 315 return 0;
333 316
334} /* end suid_keys() */ 317} /* end exec_keys() */
335 318
336/*****************************************************************************/ 319/*****************************************************************************/
337/* 320/*
@@ -376,16 +359,13 @@ void key_fsgid_changed(struct task_struct *tsk)
376key_ref_t search_process_keyrings(struct key_type *type, 359key_ref_t search_process_keyrings(struct key_type *type,
377 const void *description, 360 const void *description,
378 key_match_func_t match, 361 key_match_func_t match,
379 struct task_struct *context) 362 const struct cred *cred)
380{ 363{
381 struct request_key_auth *rka; 364 struct request_key_auth *rka;
382 struct cred *cred;
383 key_ref_t key_ref, ret, err; 365 key_ref_t key_ref, ret, err;
384 366
385 might_sleep(); 367 might_sleep();
386 368
387 cred = get_task_cred(context);
388
389 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 369 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were
390 * searchable, but we failed to find a key or we found a negative key; 370 * searchable, but we failed to find a key or we found a negative key;
391 * otherwise we want to return a sample error (probably -EACCES) if 371 * otherwise we want to return a sample error (probably -EACCES) if
@@ -401,7 +381,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
401 if (cred->thread_keyring) { 381 if (cred->thread_keyring) {
402 key_ref = keyring_search_aux( 382 key_ref = keyring_search_aux(
403 make_key_ref(cred->thread_keyring, 1), 383 make_key_ref(cred->thread_keyring, 1),
404 context, type, description, match); 384 cred, type, description, match);
405 if (!IS_ERR(key_ref)) 385 if (!IS_ERR(key_ref))
406 goto found; 386 goto found;
407 387
@@ -422,7 +402,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
422 if (cred->tgcred->process_keyring) { 402 if (cred->tgcred->process_keyring) {
423 key_ref = keyring_search_aux( 403 key_ref = keyring_search_aux(
424 make_key_ref(cred->tgcred->process_keyring, 1), 404 make_key_ref(cred->tgcred->process_keyring, 1),
425 context, type, description, match); 405 cred, type, description, match);
426 if (!IS_ERR(key_ref)) 406 if (!IS_ERR(key_ref))
427 goto found; 407 goto found;
428 408
@@ -446,7 +426,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
446 make_key_ref(rcu_dereference( 426 make_key_ref(rcu_dereference(
447 cred->tgcred->session_keyring), 427 cred->tgcred->session_keyring),
448 1), 428 1),
449 context, type, description, match); 429 cred, type, description, match);
450 rcu_read_unlock(); 430 rcu_read_unlock();
451 431
452 if (!IS_ERR(key_ref)) 432 if (!IS_ERR(key_ref))
@@ -468,7 +448,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
468 else if (cred->user->session_keyring) { 448 else if (cred->user->session_keyring) {
469 key_ref = keyring_search_aux( 449 key_ref = keyring_search_aux(
470 make_key_ref(cred->user->session_keyring, 1), 450 make_key_ref(cred->user->session_keyring, 1),
471 context, type, description, match); 451 cred, type, description, match);
472 if (!IS_ERR(key_ref)) 452 if (!IS_ERR(key_ref))
473 goto found; 453 goto found;
474 454
@@ -490,7 +470,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
490 * - we don't permit access to request_key auth keys via this method 470 * - we don't permit access to request_key auth keys via this method
491 */ 471 */
492 if (cred->request_key_auth && 472 if (cred->request_key_auth &&
493 context == current && 473 cred == current_cred() &&
494 type != &key_type_request_key_auth 474 type != &key_type_request_key_auth
495 ) { 475 ) {
496 /* defend against the auth key being revoked */ 476 /* defend against the auth key being revoked */
@@ -500,7 +480,7 @@ key_ref_t search_process_keyrings(struct key_type *type,
500 rka = cred->request_key_auth->payload.data; 480 rka = cred->request_key_auth->payload.data;
501 481
502 key_ref = search_process_keyrings(type, description, 482 key_ref = search_process_keyrings(type, description,
503 match, rka->context); 483 match, rka->cred);
504 484
505 up_read(&cred->request_key_auth->sem); 485 up_read(&cred->request_key_auth->sem);
506 486
@@ -527,7 +507,6 @@ key_ref_t search_process_keyrings(struct key_type *type,
527 key_ref = ret ? ret : err; 507 key_ref = ret ? ret : err;
528 508
529found: 509found:
530 put_cred(cred);
531 return key_ref; 510 return key_ref;
532 511
533} /* end search_process_keyrings() */ 512} /* end search_process_keyrings() */
@@ -552,8 +531,7 @@ key_ref_t lookup_user_key(key_serial_t id, int create, int partial,
552 key_perm_t perm) 531 key_perm_t perm)
553{ 532{
554 struct request_key_auth *rka; 533 struct request_key_auth *rka;
555 struct task_struct *t = current; 534 const struct cred *cred;
556 struct cred *cred;
557 struct key *key; 535 struct key *key;
558 key_ref_t key_ref, skey_ref; 536 key_ref_t key_ref, skey_ref;
559 int ret; 537 int ret;
@@ -608,6 +586,7 @@ try_again:
608 goto error; 586 goto error;
609 ret = install_session_keyring( 587 ret = install_session_keyring(
610 cred->user->session_keyring); 588 cred->user->session_keyring);
589
611 if (ret < 0) 590 if (ret < 0)
612 goto error; 591 goto error;
613 goto reget_creds; 592 goto reget_creds;
@@ -693,7 +672,7 @@ try_again:
693 /* check to see if we possess the key */ 672 /* check to see if we possess the key */
694 skey_ref = search_process_keyrings(key->type, key, 673 skey_ref = search_process_keyrings(key->type, key,
695 lookup_user_key_possessed, 674 lookup_user_key_possessed,
696 current); 675 cred);
697 676
698 if (!IS_ERR(skey_ref)) { 677 if (!IS_ERR(skey_ref)) {
699 key_put(key); 678 key_put(key);
@@ -725,7 +704,7 @@ try_again:
725 goto invalid_key; 704 goto invalid_key;
726 705
727 /* check the permissions */ 706 /* check the permissions */
728 ret = key_task_permission(key_ref, t, perm); 707 ret = key_task_permission(key_ref, cred, perm);
729 if (ret < 0) 708 if (ret < 0)
730 goto invalid_key; 709 goto invalid_key;
731 710
@@ -755,21 +734,33 @@ reget_creds:
755 */ 734 */
756long join_session_keyring(const char *name) 735long join_session_keyring(const char *name)
757{ 736{
758 struct task_struct *tsk = current; 737 const struct cred *old;
759 struct cred *cred = current->cred; 738 struct cred *new;
760 struct key *keyring; 739 struct key *keyring;
761 long ret; 740 long ret, serial;
741
742 /* only permit this if there's a single thread in the thread group -
743 * this avoids us having to adjust the creds on all threads and risking
744 * ENOMEM */
745 if (!is_single_threaded(current))
746 return -EMLINK;
747
748 new = prepare_creds();
749 if (!new)
750 return -ENOMEM;
751 old = current_cred();
762 752
763 /* if no name is provided, install an anonymous keyring */ 753 /* if no name is provided, install an anonymous keyring */
764 if (!name) { 754 if (!name) {
765 ret = install_session_keyring(NULL); 755 ret = install_session_keyring_to_cred(new, NULL);
766 if (ret < 0) 756 if (ret < 0)
767 goto error; 757 goto error;
768 758
769 rcu_read_lock(); 759 serial = new->tgcred->session_keyring->serial;
770 ret = rcu_dereference(cred->tgcred->session_keyring)->serial; 760 ret = commit_creds(new);
771 rcu_read_unlock(); 761 if (ret == 0)
772 goto error; 762 ret = serial;
763 goto okay;
773 } 764 }
774 765
775 /* allow the user to join or create a named keyring */ 766 /* allow the user to join or create a named keyring */
@@ -779,29 +770,33 @@ long join_session_keyring(const char *name)
779 keyring = find_keyring_by_name(name, false); 770 keyring = find_keyring_by_name(name, false);
780 if (PTR_ERR(keyring) == -ENOKEY) { 771 if (PTR_ERR(keyring) == -ENOKEY) {
781 /* not found - try and create a new one */ 772 /* not found - try and create a new one */
782 keyring = keyring_alloc(name, cred->uid, cred->gid, tsk, 773 keyring = keyring_alloc(name, old->uid, old->gid, old,
783 KEY_ALLOC_IN_QUOTA, NULL); 774 KEY_ALLOC_IN_QUOTA, NULL);
784 if (IS_ERR(keyring)) { 775 if (IS_ERR(keyring)) {
785 ret = PTR_ERR(keyring); 776 ret = PTR_ERR(keyring);
786 goto error2; 777 goto error2;
787 } 778 }
788 } 779 } else if (IS_ERR(keyring)) {
789 else if (IS_ERR(keyring)) {
790 ret = PTR_ERR(keyring); 780 ret = PTR_ERR(keyring);
791 goto error2; 781 goto error2;
792 } 782 }
793 783
794 /* we've got a keyring - now to install it */ 784 /* we've got a keyring - now to install it */
795 ret = install_session_keyring(keyring); 785 ret = install_session_keyring_to_cred(new, keyring);
796 if (ret < 0) 786 if (ret < 0)
797 goto error2; 787 goto error2;
798 788
789 commit_creds(new);
790 mutex_unlock(&key_session_mutex);
791
799 ret = keyring->serial; 792 ret = keyring->serial;
800 key_put(keyring); 793 key_put(keyring);
794okay:
795 return ret;
801 796
802error2: 797error2:
803 mutex_unlock(&key_session_mutex); 798 mutex_unlock(&key_session_mutex);
804error: 799error:
800 abort_creds(new);
805 return ret; 801 return ret;
806 802}
807} /* end join_session_keyring() */
diff --git a/security/keys/request_key.c b/security/keys/request_key.c
index 3d12558362df..0e04f72ef2d4 100644
--- a/security/keys/request_key.c
+++ b/security/keys/request_key.c
@@ -83,8 +83,10 @@ static int call_sbin_request_key(struct key_construction *cons,
83 /* allocate a new session keyring */ 83 /* allocate a new session keyring */
84 sprintf(desc, "_req.%u", key->serial); 84 sprintf(desc, "_req.%u", key->serial);
85 85
86 keyring = keyring_alloc(desc, current_fsuid(), current_fsgid(), current, 86 cred = get_current_cred();
87 keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred,
87 KEY_ALLOC_QUOTA_OVERRUN, NULL); 88 KEY_ALLOC_QUOTA_OVERRUN, NULL);
89 put_cred(cred);
88 if (IS_ERR(keyring)) { 90 if (IS_ERR(keyring)) {
89 ret = PTR_ERR(keyring); 91 ret = PTR_ERR(keyring);
90 goto error_alloc; 92 goto error_alloc;
@@ -104,8 +106,7 @@ static int call_sbin_request_key(struct key_construction *cons,
104 106
105 /* we specify the process's default keyrings */ 107 /* we specify the process's default keyrings */
106 sprintf(keyring_str[0], "%d", 108 sprintf(keyring_str[0], "%d",
107 cred->thread_keyring ? 109 cred->thread_keyring ? cred->thread_keyring->serial : 0);
108 cred->thread_keyring->serial : 0);
109 110
110 prkey = 0; 111 prkey = 0;
111 if (cred->tgcred->process_keyring) 112 if (cred->tgcred->process_keyring)
@@ -155,8 +156,8 @@ error_link:
155 key_put(keyring); 156 key_put(keyring);
156 157
157error_alloc: 158error_alloc:
158 kleave(" = %d", ret);
159 complete_request_key(cons, ret); 159 complete_request_key(cons, ret);
160 kleave(" = %d", ret);
160 return ret; 161 return ret;
161} 162}
162 163
@@ -295,6 +296,7 @@ static int construct_alloc_key(struct key_type *type,
295 struct key_user *user, 296 struct key_user *user,
296 struct key **_key) 297 struct key **_key)
297{ 298{
299 const struct cred *cred = current_cred();
298 struct key *key; 300 struct key *key;
299 key_ref_t key_ref; 301 key_ref_t key_ref;
300 302
@@ -302,9 +304,8 @@ static int construct_alloc_key(struct key_type *type,
302 304
303 mutex_lock(&user->cons_lock); 305 mutex_lock(&user->cons_lock);
304 306
305 key = key_alloc(type, description, 307 key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred,
306 current_fsuid(), current_fsgid(), current, KEY_POS_ALL, 308 KEY_POS_ALL, flags);
307 flags);
308 if (IS_ERR(key)) 309 if (IS_ERR(key))
309 goto alloc_failed; 310 goto alloc_failed;
310 311
@@ -317,8 +318,7 @@ static int construct_alloc_key(struct key_type *type,
317 * waited for locks */ 318 * waited for locks */
318 mutex_lock(&key_construction_mutex); 319 mutex_lock(&key_construction_mutex);
319 320
320 key_ref = search_process_keyrings(type, description, type->match, 321 key_ref = search_process_keyrings(type, description, type->match, cred);
321 current);
322 if (!IS_ERR(key_ref)) 322 if (!IS_ERR(key_ref))
323 goto key_already_present; 323 goto key_already_present;
324 324
@@ -363,6 +363,8 @@ static struct key *construct_key_and_link(struct key_type *type,
363 struct key *key; 363 struct key *key;
364 int ret; 364 int ret;
365 365
366 kenter("");
367
366 user = key_user_lookup(current_fsuid()); 368 user = key_user_lookup(current_fsuid());
367 if (!user) 369 if (!user)
368 return ERR_PTR(-ENOMEM); 370 return ERR_PTR(-ENOMEM);
@@ -376,17 +378,21 @@ static struct key *construct_key_and_link(struct key_type *type,
376 if (ret == 0) { 378 if (ret == 0) {
377 ret = construct_key(key, callout_info, callout_len, aux, 379 ret = construct_key(key, callout_info, callout_len, aux,
378 dest_keyring); 380 dest_keyring);
379 if (ret < 0) 381 if (ret < 0) {
382 kdebug("cons failed");
380 goto construction_failed; 383 goto construction_failed;
384 }
381 } 385 }
382 386
383 key_put(dest_keyring); 387 key_put(dest_keyring);
388 kleave(" = key %d", key_serial(key));
384 return key; 389 return key;
385 390
386construction_failed: 391construction_failed:
387 key_negate_and_link(key, key_negative_timeout, NULL, NULL); 392 key_negate_and_link(key, key_negative_timeout, NULL, NULL);
388 key_put(key); 393 key_put(key);
389 key_put(dest_keyring); 394 key_put(dest_keyring);
395 kleave(" = %d", ret);
390 return ERR_PTR(ret); 396 return ERR_PTR(ret);
391} 397}
392 398
@@ -405,6 +411,7 @@ struct key *request_key_and_link(struct key_type *type,
405 struct key *dest_keyring, 411 struct key *dest_keyring,
406 unsigned long flags) 412 unsigned long flags)
407{ 413{
414 const struct cred *cred = current_cred();
408 struct key *key; 415 struct key *key;
409 key_ref_t key_ref; 416 key_ref_t key_ref;
410 417
@@ -414,7 +421,7 @@ struct key *request_key_and_link(struct key_type *type,
414 421
415 /* search all the process keyrings for a key */ 422 /* search all the process keyrings for a key */
416 key_ref = search_process_keyrings(type, description, type->match, 423 key_ref = search_process_keyrings(type, description, type->match,
417 current); 424 cred);
418 425
419 if (!IS_ERR(key_ref)) { 426 if (!IS_ERR(key_ref)) {
420 key = key_ref_to_ptr(key_ref); 427 key = key_ref_to_ptr(key_ref);
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c
index 2125579d5d73..86747151ee5b 100644
--- a/security/keys/request_key_auth.c
+++ b/security/keys/request_key_auth.c
@@ -105,9 +105,9 @@ static void request_key_auth_revoke(struct key *key)
105 105
106 kenter("{%d}", key->serial); 106 kenter("{%d}", key->serial);
107 107
108 if (rka->context) { 108 if (rka->cred) {
109 put_task_struct(rka->context); 109 put_cred(rka->cred);
110 rka->context = NULL; 110 rka->cred = NULL;
111 } 111 }
112 112
113} /* end request_key_auth_revoke() */ 113} /* end request_key_auth_revoke() */
@@ -122,9 +122,9 @@ static void request_key_auth_destroy(struct key *key)
122 122
123 kenter("{%d}", key->serial); 123 kenter("{%d}", key->serial);
124 124
125 if (rka->context) { 125 if (rka->cred) {
126 put_task_struct(rka->context); 126 put_cred(rka->cred);
127 rka->context = NULL; 127 rka->cred = NULL;
128 } 128 }
129 129
130 key_put(rka->target_key); 130 key_put(rka->target_key);
@@ -143,6 +143,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
143 size_t callout_len, struct key *dest_keyring) 143 size_t callout_len, struct key *dest_keyring)
144{ 144{
145 struct request_key_auth *rka, *irka; 145 struct request_key_auth *rka, *irka;
146 const struct cred *cred = current->cred;
146 struct key *authkey = NULL; 147 struct key *authkey = NULL;
147 char desc[20]; 148 char desc[20];
148 int ret; 149 int ret;
@@ -164,28 +165,25 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
164 165
165 /* see if the calling process is already servicing the key request of 166 /* see if the calling process is already servicing the key request of
166 * another process */ 167 * another process */
167 if (current->cred->request_key_auth) { 168 if (cred->request_key_auth) {
168 /* it is - use that instantiation context here too */ 169 /* it is - use that instantiation context here too */
169 down_read(&current->cred->request_key_auth->sem); 170 down_read(&cred->request_key_auth->sem);
170 171
171 /* if the auth key has been revoked, then the key we're 172 /* if the auth key has been revoked, then the key we're
172 * servicing is already instantiated */ 173 * servicing is already instantiated */
173 if (test_bit(KEY_FLAG_REVOKED, 174 if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags))
174 &current->cred->request_key_auth->flags))
175 goto auth_key_revoked; 175 goto auth_key_revoked;
176 176
177 irka = current->cred->request_key_auth->payload.data; 177 irka = cred->request_key_auth->payload.data;
178 rka->context = irka->context; 178 rka->cred = get_cred(irka->cred);
179 rka->pid = irka->pid; 179 rka->pid = irka->pid;
180 get_task_struct(rka->context);
181 180
182 up_read(&current->cred->request_key_auth->sem); 181 up_read(&cred->request_key_auth->sem);
183 } 182 }
184 else { 183 else {
185 /* it isn't - use this process as the context */ 184 /* it isn't - use this process as the context */
186 rka->context = current; 185 rka->cred = get_cred(cred);
187 rka->pid = current->pid; 186 rka->pid = current->pid;
188 get_task_struct(rka->context);
189 } 187 }
190 188
191 rka->target_key = key_get(target); 189 rka->target_key = key_get(target);
@@ -197,7 +195,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
197 sprintf(desc, "%x", target->serial); 195 sprintf(desc, "%x", target->serial);
198 196
199 authkey = key_alloc(&key_type_request_key_auth, desc, 197 authkey = key_alloc(&key_type_request_key_auth, desc,
200 current_fsuid(), current_fsgid(), current, 198 cred->fsuid, cred->fsgid, cred,
201 KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | 199 KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH |
202 KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); 200 KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA);
203 if (IS_ERR(authkey)) { 201 if (IS_ERR(authkey)) {
@@ -205,16 +203,16 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
205 goto error_alloc; 203 goto error_alloc;
206 } 204 }
207 205
208 /* construct and attach to the keyring */ 206 /* construct the auth key */
209 ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); 207 ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL);
210 if (ret < 0) 208 if (ret < 0)
211 goto error_inst; 209 goto error_inst;
212 210
213 kleave(" = {%d}", authkey->serial); 211 kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage));
214 return authkey; 212 return authkey;
215 213
216auth_key_revoked: 214auth_key_revoked:
217 up_read(&current->cred->request_key_auth->sem); 215 up_read(&cred->request_key_auth->sem);
218 kfree(rka->callout_info); 216 kfree(rka->callout_info);
219 kfree(rka); 217 kfree(rka);
220 kleave("= -EKEYREVOKED"); 218 kleave("= -EKEYREVOKED");
@@ -257,6 +255,7 @@ static int key_get_instantiation_authkey_match(const struct key *key,
257 */ 255 */
258struct key *key_get_instantiation_authkey(key_serial_t target_id) 256struct key *key_get_instantiation_authkey(key_serial_t target_id)
259{ 257{
258 const struct cred *cred = current_cred();
260 struct key *authkey; 259 struct key *authkey;
261 key_ref_t authkey_ref; 260 key_ref_t authkey_ref;
262 261
@@ -264,7 +263,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
264 &key_type_request_key_auth, 263 &key_type_request_key_auth,
265 (void *) (unsigned long) target_id, 264 (void *) (unsigned long) target_id,
266 key_get_instantiation_authkey_match, 265 key_get_instantiation_authkey_match,
267 current); 266 cred);
268 267
269 if (IS_ERR(authkey_ref)) { 268 if (IS_ERR(authkey_ref)) {
270 authkey = ERR_CAST(authkey_ref); 269 authkey = ERR_CAST(authkey_ref);