diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/internal.h | 49 | ||||
-rw-r--r-- | security/keys/key.c | 25 | ||||
-rw-r--r-- | security/keys/keyctl.c | 210 | ||||
-rw-r--r-- | security/keys/keyring.c | 15 | ||||
-rw-r--r-- | security/keys/permission.c | 29 | ||||
-rw-r--r-- | security/keys/proc.c | 8 | ||||
-rw-r--r-- | security/keys/process_keys.c | 469 | ||||
-rw-r--r-- | security/keys/request_key.c | 135 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 46 |
9 files changed, 542 insertions, 444 deletions
diff --git a/security/keys/internal.h b/security/keys/internal.h index 239098f0fd76..81932abefe7b 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -12,8 +12,8 @@ | |||
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 | #include <linux/key-ui.h> | ||
17 | 17 | ||
18 | static inline __attribute__((format(printf, 1, 2))) | 18 | static inline __attribute__((format(printf, 1, 2))) |
19 | void no_printk(const char *fmt, ...) | 19 | void no_printk(const char *fmt, ...) |
@@ -26,7 +26,7 @@ void no_printk(const char *fmt, ...) | |||
26 | #define kleave(FMT, ...) \ | 26 | #define kleave(FMT, ...) \ |
27 | printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) | 27 | printk(KERN_DEBUG "<== %s()"FMT"\n", __func__, ##__VA_ARGS__) |
28 | #define kdebug(FMT, ...) \ | 28 | #define kdebug(FMT, ...) \ |
29 | printk(KERN_DEBUG "xxx" FMT"yyy\n", ##__VA_ARGS__) | 29 | printk(KERN_DEBUG " "FMT"\n", ##__VA_ARGS__) |
30 | #else | 30 | #else |
31 | #define kenter(FMT, ...) \ | 31 | #define kenter(FMT, ...) \ |
32 | no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) | 32 | no_printk(KERN_DEBUG "==> %s("FMT")\n", __func__, ##__VA_ARGS__) |
@@ -82,6 +82,9 @@ extern struct mutex key_construction_mutex; | |||
82 | extern wait_queue_head_t request_key_conswq; | 82 | extern wait_queue_head_t request_key_conswq; |
83 | 83 | ||
84 | 84 | ||
85 | extern struct key_type *key_type_lookup(const char *type); | ||
86 | extern void key_type_put(struct key_type *ktype); | ||
87 | |||
85 | extern int __key_link(struct key *keyring, struct key *key); | 88 | extern int __key_link(struct key *keyring, struct key *key); |
86 | 89 | ||
87 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, | 90 | extern key_ref_t __keyring_search_one(key_ref_t keyring_ref, |
@@ -95,7 +98,7 @@ extern struct key *keyring_search_instkey(struct key *keyring, | |||
95 | typedef int (*key_match_func_t)(const struct key *, const void *); | 98 | typedef int (*key_match_func_t)(const struct key *, const void *); |
96 | 99 | ||
97 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 100 | extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
98 | struct task_struct *tsk, | 101 | const struct cred *cred, |
99 | struct key_type *type, | 102 | struct key_type *type, |
100 | const void *description, | 103 | const void *description, |
101 | key_match_func_t match); | 104 | key_match_func_t match); |
@@ -103,13 +106,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
103 | extern key_ref_t search_process_keyrings(struct key_type *type, | 106 | extern key_ref_t search_process_keyrings(struct key_type *type, |
104 | const void *description, | 107 | const void *description, |
105 | key_match_func_t match, | 108 | key_match_func_t match, |
106 | struct task_struct *tsk); | 109 | const struct cred *cred); |
107 | 110 | ||
108 | extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); | 111 | extern struct key *find_keyring_by_name(const char *name, bool skip_perm_check); |
109 | 112 | ||
110 | extern int install_user_keyrings(struct task_struct *tsk); | 113 | extern int install_user_keyrings(void); |
111 | extern int install_thread_keyring(struct task_struct *tsk); | 114 | extern int install_thread_keyring_to_cred(struct cred *); |
112 | extern int install_process_keyring(struct task_struct *tsk); | 115 | extern int install_process_keyring_to_cred(struct cred *); |
113 | 116 | ||
114 | extern struct key *request_key_and_link(struct key_type *type, | 117 | extern struct key *request_key_and_link(struct key_type *type, |
115 | const char *description, | 118 | const char *description, |
@@ -119,12 +122,39 @@ extern struct key *request_key_and_link(struct key_type *type, | |||
119 | struct key *dest_keyring, | 122 | struct key *dest_keyring, |
120 | unsigned long flags); | 123 | unsigned long flags); |
121 | 124 | ||
125 | extern key_ref_t lookup_user_key(key_serial_t id, int create, int partial, | ||
126 | key_perm_t perm); | ||
127 | |||
128 | extern long join_session_keyring(const char *name); | ||
129 | |||
130 | /* | ||
131 | * check to see whether permission is granted to use a key in the desired way | ||
132 | */ | ||
133 | extern int key_task_permission(const key_ref_t key_ref, | ||
134 | const struct cred *cred, | ||
135 | key_perm_t perm); | ||
136 | |||
137 | static inline int key_permission(const key_ref_t key_ref, key_perm_t perm) | ||
138 | { | ||
139 | return key_task_permission(key_ref, current_cred(), perm); | ||
140 | } | ||
141 | |||
142 | /* required permissions */ | ||
143 | #define KEY_VIEW 0x01 /* require permission to view attributes */ | ||
144 | #define KEY_READ 0x02 /* require permission to read content */ | ||
145 | #define KEY_WRITE 0x04 /* require permission to update / modify */ | ||
146 | #define KEY_SEARCH 0x08 /* require permission to search (keyring) or find (key) */ | ||
147 | #define KEY_LINK 0x10 /* require permission to link */ | ||
148 | #define KEY_SETATTR 0x20 /* require permission to change attributes */ | ||
149 | #define KEY_ALL 0x3f /* all the above permissions */ | ||
150 | |||
122 | /* | 151 | /* |
123 | * request_key authorisation | 152 | * request_key authorisation |
124 | */ | 153 | */ |
125 | struct request_key_auth { | 154 | struct request_key_auth { |
126 | struct key *target_key; | 155 | struct key *target_key; |
127 | struct task_struct *context; | 156 | struct key *dest_keyring; |
157 | const struct cred *cred; | ||
128 | void *callout_info; | 158 | void *callout_info; |
129 | size_t callout_len; | 159 | size_t callout_len; |
130 | pid_t pid; | 160 | pid_t pid; |
@@ -133,7 +163,8 @@ struct request_key_auth { | |||
133 | extern struct key_type key_type_request_key_auth; | 163 | extern struct key_type key_type_request_key_auth; |
134 | extern struct key *request_key_auth_new(struct key *target, | 164 | extern struct key *request_key_auth_new(struct key *target, |
135 | const void *callout_info, | 165 | const void *callout_info, |
136 | size_t callout_len); | 166 | size_t callout_len, |
167 | struct key *dest_keyring); | ||
137 | 168 | ||
138 | extern struct key *key_get_instantiation_authkey(key_serial_t target_id); | 169 | extern struct key *key_get_instantiation_authkey(key_serial_t target_id); |
139 | 170 | ||
diff --git a/security/keys/key.c b/security/keys/key.c index 14948cf83ef6..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 | */ |
220 | struct key *key_alloc(struct key_type *type, const char *desc, | 220 | struct 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); | |||
469 | int key_negate_and_link(struct key *key, | 469 | int 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 acc9c89e40a8..7c72baa02f2e 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -103,7 +103,7 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
103 | } | 103 | } |
104 | 104 | ||
105 | /* find the target keyring (which must be writable) */ | 105 | /* find the target keyring (which must be writable) */ |
106 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 106 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); |
107 | if (IS_ERR(keyring_ref)) { | 107 | if (IS_ERR(keyring_ref)) { |
108 | ret = PTR_ERR(keyring_ref); | 108 | ret = PTR_ERR(keyring_ref); |
109 | goto error3; | 109 | goto error3; |
@@ -185,7 +185,7 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
185 | /* get the destination keyring if specified */ | 185 | /* get the destination keyring if specified */ |
186 | dest_ref = NULL; | 186 | dest_ref = NULL; |
187 | if (destringid) { | 187 | if (destringid) { |
188 | dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); | 188 | dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE); |
189 | if (IS_ERR(dest_ref)) { | 189 | if (IS_ERR(dest_ref)) { |
190 | ret = PTR_ERR(dest_ref); | 190 | ret = PTR_ERR(dest_ref); |
191 | goto error3; | 191 | goto error3; |
@@ -235,7 +235,7 @@ long keyctl_get_keyring_ID(key_serial_t id, int create) | |||
235 | key_ref_t key_ref; | 235 | key_ref_t key_ref; |
236 | long ret; | 236 | long ret; |
237 | 237 | ||
238 | key_ref = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); | 238 | key_ref = lookup_user_key(id, create, 0, KEY_SEARCH); |
239 | if (IS_ERR(key_ref)) { | 239 | if (IS_ERR(key_ref)) { |
240 | ret = PTR_ERR(key_ref); | 240 | ret = PTR_ERR(key_ref); |
241 | goto error; | 241 | goto error; |
@@ -308,7 +308,7 @@ long keyctl_update_key(key_serial_t id, | |||
308 | } | 308 | } |
309 | 309 | ||
310 | /* find the target key (which must be writable) */ | 310 | /* find the target key (which must be writable) */ |
311 | key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); | 311 | key_ref = lookup_user_key(id, 0, 0, KEY_WRITE); |
312 | if (IS_ERR(key_ref)) { | 312 | if (IS_ERR(key_ref)) { |
313 | ret = PTR_ERR(key_ref); | 313 | ret = PTR_ERR(key_ref); |
314 | goto error2; | 314 | goto error2; |
@@ -336,7 +336,7 @@ long keyctl_revoke_key(key_serial_t id) | |||
336 | key_ref_t key_ref; | 336 | key_ref_t key_ref; |
337 | long ret; | 337 | long ret; |
338 | 338 | ||
339 | key_ref = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); | 339 | key_ref = lookup_user_key(id, 0, 0, KEY_WRITE); |
340 | if (IS_ERR(key_ref)) { | 340 | if (IS_ERR(key_ref)) { |
341 | ret = PTR_ERR(key_ref); | 341 | ret = PTR_ERR(key_ref); |
342 | goto error; | 342 | goto error; |
@@ -362,7 +362,7 @@ long keyctl_keyring_clear(key_serial_t ringid) | |||
362 | key_ref_t keyring_ref; | 362 | key_ref_t keyring_ref; |
363 | long ret; | 363 | long ret; |
364 | 364 | ||
365 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 365 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); |
366 | if (IS_ERR(keyring_ref)) { | 366 | if (IS_ERR(keyring_ref)) { |
367 | ret = PTR_ERR(keyring_ref); | 367 | ret = PTR_ERR(keyring_ref); |
368 | goto error; | 368 | goto error; |
@@ -388,13 +388,13 @@ long keyctl_keyring_link(key_serial_t id, key_serial_t ringid) | |||
388 | key_ref_t keyring_ref, key_ref; | 388 | key_ref_t keyring_ref, key_ref; |
389 | long ret; | 389 | long ret; |
390 | 390 | ||
391 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 391 | keyring_ref = lookup_user_key(ringid, 1, 0, KEY_WRITE); |
392 | if (IS_ERR(keyring_ref)) { | 392 | if (IS_ERR(keyring_ref)) { |
393 | ret = PTR_ERR(keyring_ref); | 393 | ret = PTR_ERR(keyring_ref); |
394 | goto error; | 394 | goto error; |
395 | } | 395 | } |
396 | 396 | ||
397 | key_ref = lookup_user_key(NULL, id, 1, 0, KEY_LINK); | 397 | key_ref = lookup_user_key(id, 1, 0, KEY_LINK); |
398 | if (IS_ERR(key_ref)) { | 398 | if (IS_ERR(key_ref)) { |
399 | ret = PTR_ERR(key_ref); | 399 | ret = PTR_ERR(key_ref); |
400 | goto error2; | 400 | goto error2; |
@@ -422,13 +422,13 @@ long keyctl_keyring_unlink(key_serial_t id, key_serial_t ringid) | |||
422 | key_ref_t keyring_ref, key_ref; | 422 | key_ref_t keyring_ref, key_ref; |
423 | long ret; | 423 | long ret; |
424 | 424 | ||
425 | keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); | 425 | keyring_ref = lookup_user_key(ringid, 0, 0, KEY_WRITE); |
426 | if (IS_ERR(keyring_ref)) { | 426 | if (IS_ERR(keyring_ref)) { |
427 | ret = PTR_ERR(keyring_ref); | 427 | ret = PTR_ERR(keyring_ref); |
428 | goto error; | 428 | goto error; |
429 | } | 429 | } |
430 | 430 | ||
431 | key_ref = lookup_user_key(NULL, id, 0, 0, 0); | 431 | key_ref = lookup_user_key(id, 0, 0, 0); |
432 | if (IS_ERR(key_ref)) { | 432 | if (IS_ERR(key_ref)) { |
433 | ret = PTR_ERR(key_ref); | 433 | ret = PTR_ERR(key_ref); |
434 | goto error2; | 434 | goto error2; |
@@ -464,7 +464,7 @@ long keyctl_describe_key(key_serial_t keyid, | |||
464 | char *tmpbuf; | 464 | char *tmpbuf; |
465 | long ret; | 465 | long ret; |
466 | 466 | ||
467 | key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); | 467 | key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW); |
468 | if (IS_ERR(key_ref)) { | 468 | if (IS_ERR(key_ref)) { |
469 | /* viewing a key under construction is permitted if we have the | 469 | /* viewing a key under construction is permitted if we have the |
470 | * authorisation token handy */ | 470 | * authorisation token handy */ |
@@ -472,7 +472,7 @@ long keyctl_describe_key(key_serial_t keyid, | |||
472 | instkey = key_get_instantiation_authkey(keyid); | 472 | instkey = key_get_instantiation_authkey(keyid); |
473 | if (!IS_ERR(instkey)) { | 473 | if (!IS_ERR(instkey)) { |
474 | key_put(instkey); | 474 | key_put(instkey); |
475 | key_ref = lookup_user_key(NULL, keyid, | 475 | key_ref = lookup_user_key(keyid, |
476 | 0, 1, 0); | 476 | 0, 1, 0); |
477 | if (!IS_ERR(key_ref)) | 477 | if (!IS_ERR(key_ref)) |
478 | goto okay; | 478 | goto okay; |
@@ -557,7 +557,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
557 | } | 557 | } |
558 | 558 | ||
559 | /* get the keyring at which to begin the search */ | 559 | /* get the keyring at which to begin the search */ |
560 | keyring_ref = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); | 560 | keyring_ref = lookup_user_key(ringid, 0, 0, KEY_SEARCH); |
561 | if (IS_ERR(keyring_ref)) { | 561 | if (IS_ERR(keyring_ref)) { |
562 | ret = PTR_ERR(keyring_ref); | 562 | ret = PTR_ERR(keyring_ref); |
563 | goto error2; | 563 | goto error2; |
@@ -566,7 +566,7 @@ long keyctl_keyring_search(key_serial_t ringid, | |||
566 | /* get the destination keyring if specified */ | 566 | /* get the destination keyring if specified */ |
567 | dest_ref = NULL; | 567 | dest_ref = NULL; |
568 | if (destringid) { | 568 | if (destringid) { |
569 | dest_ref = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); | 569 | dest_ref = lookup_user_key(destringid, 1, 0, KEY_WRITE); |
570 | if (IS_ERR(dest_ref)) { | 570 | if (IS_ERR(dest_ref)) { |
571 | ret = PTR_ERR(dest_ref); | 571 | ret = PTR_ERR(dest_ref); |
572 | goto error3; | 572 | goto error3; |
@@ -636,7 +636,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
636 | long ret; | 636 | long ret; |
637 | 637 | ||
638 | /* find the key first */ | 638 | /* find the key first */ |
639 | key_ref = lookup_user_key(NULL, keyid, 0, 0, 0); | 639 | key_ref = lookup_user_key(keyid, 0, 0, 0); |
640 | if (IS_ERR(key_ref)) { | 640 | if (IS_ERR(key_ref)) { |
641 | ret = -ENOKEY; | 641 | ret = -ENOKEY; |
642 | goto error; | 642 | goto error; |
@@ -699,7 +699,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
699 | if (uid == (uid_t) -1 && gid == (gid_t) -1) | 699 | if (uid == (uid_t) -1 && gid == (gid_t) -1) |
700 | goto error; | 700 | goto error; |
701 | 701 | ||
702 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | 702 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); |
703 | if (IS_ERR(key_ref)) { | 703 | if (IS_ERR(key_ref)) { |
704 | ret = PTR_ERR(key_ref); | 704 | ret = PTR_ERR(key_ref); |
705 | goto error; | 705 | goto error; |
@@ -804,7 +804,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
804 | if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) | 804 | if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) |
805 | goto error; | 805 | goto error; |
806 | 806 | ||
807 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | 807 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); |
808 | if (IS_ERR(key_ref)) { | 808 | if (IS_ERR(key_ref)) { |
809 | ret = PTR_ERR(key_ref); | 809 | ret = PTR_ERR(key_ref); |
810 | goto error; | 810 | goto error; |
@@ -817,7 +817,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm) | |||
817 | down_write(&key->sem); | 817 | down_write(&key->sem); |
818 | 818 | ||
819 | /* if we're not the sysadmin, we can only change a key that we own */ | 819 | /* if we're not the sysadmin, we can only change a key that we own */ |
820 | if (capable(CAP_SYS_ADMIN) || key->uid == current->fsuid) { | 820 | if (capable(CAP_SYS_ADMIN) || key->uid == current_fsuid()) { |
821 | key->perm = perm; | 821 | key->perm = perm; |
822 | ret = 0; | 822 | ret = 0; |
823 | } | 823 | } |
@@ -829,6 +829,60 @@ error: | |||
829 | 829 | ||
830 | } /* end keyctl_setperm_key() */ | 830 | } /* end keyctl_setperm_key() */ |
831 | 831 | ||
832 | /* | ||
833 | * get the destination keyring for instantiation | ||
834 | */ | ||
835 | static long get_instantiation_keyring(key_serial_t ringid, | ||
836 | struct request_key_auth *rka, | ||
837 | struct key **_dest_keyring) | ||
838 | { | ||
839 | key_ref_t dkref; | ||
840 | |||
841 | /* just return a NULL pointer if we weren't asked to make a link */ | ||
842 | if (ringid == 0) { | ||
843 | *_dest_keyring = NULL; | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | /* if a specific keyring is nominated by ID, then use that */ | ||
848 | if (ringid > 0) { | ||
849 | dkref = lookup_user_key(ringid, 1, 0, KEY_WRITE); | ||
850 | if (IS_ERR(dkref)) | ||
851 | return PTR_ERR(dkref); | ||
852 | *_dest_keyring = key_ref_to_ptr(dkref); | ||
853 | return 0; | ||
854 | } | ||
855 | |||
856 | if (ringid == KEY_SPEC_REQKEY_AUTH_KEY) | ||
857 | return -EINVAL; | ||
858 | |||
859 | /* otherwise specify the destination keyring recorded in the | ||
860 | * authorisation key (any KEY_SPEC_*_KEYRING) */ | ||
861 | if (ringid >= KEY_SPEC_REQUESTOR_KEYRING) { | ||
862 | *_dest_keyring = rka->dest_keyring; | ||
863 | return 0; | ||
864 | } | ||
865 | |||
866 | return -ENOKEY; | ||
867 | } | ||
868 | |||
869 | /* | ||
870 | * change the request_key authorisation key on the current process | ||
871 | */ | ||
872 | static 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 | |||
832 | /*****************************************************************************/ | 886 | /*****************************************************************************/ |
833 | /* | 887 | /* |
834 | * 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 |
@@ -839,13 +893,15 @@ long keyctl_instantiate_key(key_serial_t id, | |||
839 | size_t plen, | 893 | size_t plen, |
840 | key_serial_t ringid) | 894 | key_serial_t ringid) |
841 | { | 895 | { |
896 | const struct cred *cred = current_cred(); | ||
842 | struct request_key_auth *rka; | 897 | struct request_key_auth *rka; |
843 | struct key *instkey; | 898 | struct key *instkey, *dest_keyring; |
844 | key_ref_t keyring_ref; | ||
845 | void *payload; | 899 | void *payload; |
846 | long ret; | 900 | long ret; |
847 | bool vm = false; | 901 | bool vm = false; |
848 | 902 | ||
903 | kenter("%d,,%zu,%d", id, plen, ringid); | ||
904 | |||
849 | ret = -EINVAL; | 905 | ret = -EINVAL; |
850 | if (plen > 1024 * 1024 - 1) | 906 | if (plen > 1024 * 1024 - 1) |
851 | goto error; | 907 | goto error; |
@@ -853,7 +909,7 @@ long keyctl_instantiate_key(key_serial_t id, | |||
853 | /* the appropriate instantiation authorisation key must have been | 909 | /* the appropriate instantiation authorisation key must have been |
854 | * assumed before calling this */ | 910 | * assumed before calling this */ |
855 | ret = -EPERM; | 911 | ret = -EPERM; |
856 | instkey = current->request_key_auth; | 912 | instkey = cred->request_key_auth; |
857 | if (!instkey) | 913 | if (!instkey) |
858 | goto error; | 914 | goto error; |
859 | 915 | ||
@@ -883,28 +939,20 @@ long keyctl_instantiate_key(key_serial_t id, | |||
883 | 939 | ||
884 | /* find the destination keyring amongst those belonging to the | 940 | /* find the destination keyring amongst those belonging to the |
885 | * requesting task */ | 941 | * requesting task */ |
886 | keyring_ref = NULL; | 942 | ret = get_instantiation_keyring(ringid, rka, &dest_keyring); |
887 | if (ringid) { | 943 | if (ret < 0) |
888 | keyring_ref = lookup_user_key(rka->context, ringid, 1, 0, | 944 | goto error2; |
889 | KEY_WRITE); | ||
890 | if (IS_ERR(keyring_ref)) { | ||
891 | ret = PTR_ERR(keyring_ref); | ||
892 | goto error2; | ||
893 | } | ||
894 | } | ||
895 | 945 | ||
896 | /* instantiate the key and link it into a keyring */ | 946 | /* instantiate the key and link it into a keyring */ |
897 | ret = key_instantiate_and_link(rka->target_key, payload, plen, | 947 | ret = key_instantiate_and_link(rka->target_key, payload, plen, |
898 | key_ref_to_ptr(keyring_ref), instkey); | 948 | dest_keyring, instkey); |
899 | 949 | ||
900 | key_ref_put(keyring_ref); | 950 | key_put(dest_keyring); |
901 | 951 | ||
902 | /* discard the assumed authority if it's just been disabled by | 952 | /* discard the assumed authority if it's just been disabled by |
903 | * instantiation of the key */ | 953 | * instantiation of the key */ |
904 | if (ret == 0) { | 954 | if (ret == 0) |
905 | key_put(current->request_key_auth); | 955 | keyctl_change_reqkey_auth(NULL); |
906 | current->request_key_auth = NULL; | ||
907 | } | ||
908 | 956 | ||
909 | error2: | 957 | error2: |
910 | if (!vm) | 958 | if (!vm) |
@@ -923,15 +971,17 @@ error: | |||
923 | */ | 971 | */ |
924 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | 972 | long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) |
925 | { | 973 | { |
974 | const struct cred *cred = current_cred(); | ||
926 | struct request_key_auth *rka; | 975 | struct request_key_auth *rka; |
927 | struct key *instkey; | 976 | struct key *instkey, *dest_keyring; |
928 | key_ref_t keyring_ref; | ||
929 | long ret; | 977 | long ret; |
930 | 978 | ||
979 | kenter("%d,%u,%d", id, timeout, ringid); | ||
980 | |||
931 | /* the appropriate instantiation authorisation key must have been | 981 | /* the appropriate instantiation authorisation key must have been |
932 | * assumed before calling this */ | 982 | * assumed before calling this */ |
933 | ret = -EPERM; | 983 | ret = -EPERM; |
934 | instkey = current->request_key_auth; | 984 | instkey = cred->request_key_auth; |
935 | if (!instkey) | 985 | if (!instkey) |
936 | goto error; | 986 | goto error; |
937 | 987 | ||
@@ -941,27 +991,20 @@ long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) | |||
941 | 991 | ||
942 | /* find the destination keyring if present (which must also be | 992 | /* find the destination keyring if present (which must also be |
943 | * writable) */ | 993 | * writable) */ |
944 | keyring_ref = NULL; | 994 | ret = get_instantiation_keyring(ringid, rka, &dest_keyring); |
945 | if (ringid) { | 995 | if (ret < 0) |
946 | keyring_ref = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); | 996 | goto error; |
947 | if (IS_ERR(keyring_ref)) { | ||
948 | ret = PTR_ERR(keyring_ref); | ||
949 | goto error; | ||
950 | } | ||
951 | } | ||
952 | 997 | ||
953 | /* instantiate the key and link it into a keyring */ | 998 | /* instantiate the key and link it into a keyring */ |
954 | ret = key_negate_and_link(rka->target_key, timeout, | 999 | ret = key_negate_and_link(rka->target_key, timeout, |
955 | key_ref_to_ptr(keyring_ref), instkey); | 1000 | dest_keyring, instkey); |
956 | 1001 | ||
957 | key_ref_put(keyring_ref); | 1002 | key_put(dest_keyring); |
958 | 1003 | ||
959 | /* discard the assumed authority if it's just been disabled by | 1004 | /* discard the assumed authority if it's just been disabled by |
960 | * instantiation of the key */ | 1005 | * instantiation of the key */ |
961 | if (ret == 0) { | 1006 | if (ret == 0) |
962 | key_put(current->request_key_auth); | 1007 | keyctl_change_reqkey_auth(NULL); |
963 | current->request_key_auth = NULL; | ||
964 | } | ||
965 | 1008 | ||
966 | error: | 1009 | error: |
967 | return ret; | 1010 | return ret; |
@@ -975,35 +1018,56 @@ error: | |||
975 | */ | 1018 | */ |
976 | long keyctl_set_reqkey_keyring(int reqkey_defl) | 1019 | long keyctl_set_reqkey_keyring(int reqkey_defl) |
977 | { | 1020 | { |
978 | int ret; | 1021 | struct cred *new; |
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; | ||
979 | 1032 | ||
980 | switch (reqkey_defl) { | 1033 | switch (reqkey_defl) { |
981 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 1034 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
982 | ret = install_thread_keyring(current); | 1035 | ret = install_thread_keyring_to_cred(new); |
983 | if (ret < 0) | 1036 | if (ret < 0) |
984 | return ret; | 1037 | goto error; |
985 | goto set; | 1038 | goto set; |
986 | 1039 | ||
987 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 1040 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
988 | ret = install_process_keyring(current); | 1041 | ret = install_process_keyring_to_cred(new); |
989 | if (ret < 0) | 1042 | if (ret < 0) { |
990 | return ret; | 1043 | if (ret != -EEXIST) |
1044 | goto error; | ||
1045 | ret = 0; | ||
1046 | } | ||
1047 | goto set; | ||
991 | 1048 | ||
992 | case KEY_REQKEY_DEFL_DEFAULT: | 1049 | case KEY_REQKEY_DEFL_DEFAULT: |
993 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 1050 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
994 | case KEY_REQKEY_DEFL_USER_KEYRING: | 1051 | case KEY_REQKEY_DEFL_USER_KEYRING: |
995 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 1052 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
996 | set: | 1053 | case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: |
997 | current->jit_keyring = reqkey_defl; | 1054 | goto set; |
998 | 1055 | ||
999 | case KEY_REQKEY_DEFL_NO_CHANGE: | 1056 | case KEY_REQKEY_DEFL_NO_CHANGE: |
1000 | return current->jit_keyring; | ||
1001 | |||
1002 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | 1057 | case KEY_REQKEY_DEFL_GROUP_KEYRING: |
1003 | default: | 1058 | default: |
1004 | return -EINVAL; | 1059 | ret = -EINVAL; |
1060 | goto error; | ||
1005 | } | 1061 | } |
1006 | 1062 | ||
1063 | set: | ||
1064 | new->jit_keyring = reqkey_defl; | ||
1065 | commit_creds(new); | ||
1066 | return old_setting; | ||
1067 | error: | ||
1068 | abort_creds(new); | ||
1069 | return -EINVAL; | ||
1070 | |||
1007 | } /* end keyctl_set_reqkey_keyring() */ | 1071 | } /* end keyctl_set_reqkey_keyring() */ |
1008 | 1072 | ||
1009 | /*****************************************************************************/ | 1073 | /*****************************************************************************/ |
@@ -1018,7 +1082,7 @@ long keyctl_set_timeout(key_serial_t id, unsigned timeout) | |||
1018 | time_t expiry; | 1082 | time_t expiry; |
1019 | long ret; | 1083 | long ret; |
1020 | 1084 | ||
1021 | key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR); | 1085 | key_ref = lookup_user_key(id, 1, 1, KEY_SETATTR); |
1022 | if (IS_ERR(key_ref)) { | 1086 | if (IS_ERR(key_ref)) { |
1023 | ret = PTR_ERR(key_ref); | 1087 | ret = PTR_ERR(key_ref); |
1024 | goto error; | 1088 | goto error; |
@@ -1062,9 +1126,7 @@ long keyctl_assume_authority(key_serial_t id) | |||
1062 | 1126 | ||
1063 | /* we divest ourselves of authority if given an ID of 0 */ | 1127 | /* we divest ourselves of authority if given an ID of 0 */ |
1064 | if (id == 0) { | 1128 | if (id == 0) { |
1065 | key_put(current->request_key_auth); | 1129 | ret = keyctl_change_reqkey_auth(NULL); |
1066 | current->request_key_auth = NULL; | ||
1067 | ret = 0; | ||
1068 | goto error; | 1130 | goto error; |
1069 | } | 1131 | } |
1070 | 1132 | ||
@@ -1079,10 +1141,12 @@ long keyctl_assume_authority(key_serial_t id) | |||
1079 | goto error; | 1141 | goto error; |
1080 | } | 1142 | } |
1081 | 1143 | ||
1082 | key_put(current->request_key_auth); | 1144 | ret = keyctl_change_reqkey_auth(authkey); |
1083 | current->request_key_auth = authkey; | 1145 | if (ret < 0) |
1084 | ret = authkey->serial; | 1146 | goto error; |
1147 | key_put(authkey); | ||
1085 | 1148 | ||
1149 | ret = authkey->serial; | ||
1086 | error: | 1150 | error: |
1087 | return ret; | 1151 | return ret; |
1088 | 1152 | ||
@@ -1105,7 +1169,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1105 | char *context; | 1169 | char *context; |
1106 | long ret; | 1170 | long ret; |
1107 | 1171 | ||
1108 | key_ref = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); | 1172 | key_ref = lookup_user_key(keyid, 0, 1, KEY_VIEW); |
1109 | if (IS_ERR(key_ref)) { | 1173 | if (IS_ERR(key_ref)) { |
1110 | if (PTR_ERR(key_ref) != -EACCES) | 1174 | if (PTR_ERR(key_ref) != -EACCES) |
1111 | return PTR_ERR(key_ref); | 1175 | return PTR_ERR(key_ref); |
@@ -1117,7 +1181,7 @@ long keyctl_get_security(key_serial_t keyid, | |||
1117 | return PTR_ERR(key_ref); | 1181 | return PTR_ERR(key_ref); |
1118 | key_put(instkey); | 1182 | key_put(instkey); |
1119 | 1183 | ||
1120 | key_ref = lookup_user_key(NULL, keyid, 0, 1, 0); | 1184 | key_ref = lookup_user_key(keyid, 0, 1, 0); |
1121 | if (IS_ERR(key_ref)) | 1185 | if (IS_ERR(key_ref)) |
1122 | return PTR_ERR(key_ref); | 1186 | return PTR_ERR(key_ref); |
1123 | } | 1187 | } |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index a9ab8affc092..ed851574d073 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/security.h> | 16 | #include <linux/security.h> |
17 | #include <linux/seq_file.h> | 17 | #include <linux/seq_file.h> |
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <keys/keyring-type.h> | ||
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include "internal.h" | 21 | #include "internal.h" |
21 | 22 | ||
@@ -244,14 +245,14 @@ static long keyring_read(const struct key *keyring, | |||
244 | * allocate a keyring and link into the destination keyring | 245 | * allocate a keyring and link into the destination keyring |
245 | */ | 246 | */ |
246 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 247 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
247 | struct task_struct *ctx, unsigned long flags, | 248 | const struct cred *cred, unsigned long flags, |
248 | struct key *dest) | 249 | struct key *dest) |
249 | { | 250 | { |
250 | struct key *keyring; | 251 | struct key *keyring; |
251 | int ret; | 252 | int ret; |
252 | 253 | ||
253 | keyring = key_alloc(&key_type_keyring, description, | 254 | keyring = key_alloc(&key_type_keyring, description, |
254 | uid, gid, ctx, | 255 | uid, gid, cred, |
255 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | 256 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, |
256 | flags); | 257 | flags); |
257 | 258 | ||
@@ -280,7 +281,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
280 | * - 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 |
281 | */ | 282 | */ |
282 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, | 283 | key_ref_t keyring_search_aux(key_ref_t keyring_ref, |
283 | struct task_struct *context, | 284 | const struct cred *cred, |
284 | struct key_type *type, | 285 | struct key_type *type, |
285 | const void *description, | 286 | const void *description, |
286 | key_match_func_t match) | 287 | key_match_func_t match) |
@@ -303,7 +304,7 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
303 | key_check(keyring); | 304 | key_check(keyring); |
304 | 305 | ||
305 | /* top keyring must have search permission to begin the search */ | 306 | /* top keyring must have search permission to begin the search */ |
306 | err = key_task_permission(keyring_ref, context, KEY_SEARCH); | 307 | err = key_task_permission(keyring_ref, cred, KEY_SEARCH); |
307 | if (err < 0) { | 308 | if (err < 0) { |
308 | key_ref = ERR_PTR(err); | 309 | key_ref = ERR_PTR(err); |
309 | goto error; | 310 | goto error; |
@@ -376,7 +377,7 @@ descend: | |||
376 | 377 | ||
377 | /* key must have search permissions */ | 378 | /* key must have search permissions */ |
378 | if (key_task_permission(make_key_ref(key, possessed), | 379 | if (key_task_permission(make_key_ref(key, possessed), |
379 | context, KEY_SEARCH) < 0) | 380 | cred, KEY_SEARCH) < 0) |
380 | continue; | 381 | continue; |
381 | 382 | ||
382 | /* 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 */ |
@@ -403,7 +404,7 @@ ascend: | |||
403 | continue; | 404 | continue; |
404 | 405 | ||
405 | if (key_task_permission(make_key_ref(key, possessed), | 406 | if (key_task_permission(make_key_ref(key, possessed), |
406 | context, KEY_SEARCH) < 0) | 407 | cred, KEY_SEARCH) < 0) |
407 | continue; | 408 | continue; |
408 | 409 | ||
409 | /* stack the current position */ | 410 | /* stack the current position */ |
@@ -458,7 +459,7 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
458 | if (!type->match) | 459 | if (!type->match) |
459 | return ERR_PTR(-ENOKEY); | 460 | return ERR_PTR(-ENOKEY); |
460 | 461 | ||
461 | return keyring_search_aux(keyring, current, | 462 | return keyring_search_aux(keyring, current->cred, |
462 | type, description, type->match); | 463 | type, description, type->match); |
463 | 464 | ||
464 | } /* end keyring_search() */ | 465 | } /* end keyring_search() */ |
diff --git a/security/keys/permission.c b/security/keys/permission.c index 3b41f9b52537..5d9fc7b93f2e 100644 --- a/security/keys/permission.c +++ b/security/keys/permission.c | |||
@@ -14,12 +14,19 @@ | |||
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 | */ |
21 | int key_task_permission(const key_ref_t key_ref, | 29 | int 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 | struct key *key; | 32 | struct key *key; |
@@ -29,7 +36,7 @@ int key_task_permission(const key_ref_t key_ref, | |||
29 | key = key_ref_to_ptr(key_ref); | 36 | key = key_ref_to_ptr(key_ref); |
30 | 37 | ||
31 | /* 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 */ |
32 | if (key->uid == context->fsuid) { | 39 | if (key->uid == cred->fsuid) { |
33 | kperm = key->perm >> 16; | 40 | kperm = key->perm >> 16; |
34 | goto use_these_perms; | 41 | goto use_these_perms; |
35 | } | 42 | } |
@@ -37,15 +44,12 @@ int key_task_permission(const key_ref_t key_ref, | |||
37 | /* use the third 8-bits of permissions for keys the caller has a group | 44 | /* use the third 8-bits of permissions for keys the caller has a group |
38 | * membership in common with */ | 45 | * membership in common with */ |
39 | if (key->gid != -1 && key->perm & KEY_GRP_ALL) { | 46 | if (key->gid != -1 && key->perm & KEY_GRP_ALL) { |
40 | if (key->gid == context->fsgid) { | 47 | if (key->gid == cred->fsgid) { |
41 | kperm = key->perm >> 8; | 48 | kperm = key->perm >> 8; |
42 | goto use_these_perms; | 49 | goto use_these_perms; |
43 | } | 50 | } |
44 | 51 | ||
45 | task_lock(context); | 52 | ret = groups_search(cred->group_info, key->gid); |
46 | ret = groups_search(context->group_info, key->gid); | ||
47 | task_unlock(context); | ||
48 | |||
49 | if (ret) { | 53 | if (ret) { |
50 | kperm = key->perm >> 8; | 54 | kperm = key->perm >> 8; |
51 | goto use_these_perms; | 55 | goto use_these_perms; |
@@ -56,6 +60,7 @@ int key_task_permission(const key_ref_t key_ref, | |||
56 | kperm = key->perm; | 60 | kperm = key->perm; |
57 | 61 | ||
58 | use_these_perms: | 62 | use_these_perms: |
63 | |||
59 | /* 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 |
60 | * - possessor permissions are additive with other permissions | 65 | * - possessor permissions are additive with other permissions |
61 | */ | 66 | */ |
@@ -68,7 +73,7 @@ use_these_perms: | |||
68 | return -EACCES; | 73 | return -EACCES; |
69 | 74 | ||
70 | /* let LSM be the final arbiter */ | 75 | /* let LSM be the final arbiter */ |
71 | return security_key_permission(key_ref, context, perm); | 76 | return security_key_permission(key_ref, cred, perm); |
72 | 77 | ||
73 | } /* end key_task_permission() */ | 78 | } /* end key_task_permission() */ |
74 | 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 45b240af6dbe..2f5d89e92b85 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -40,13 +40,17 @@ 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 | */ |
43 | int install_user_keyrings(struct task_struct *tsk) | 43 | int install_user_keyrings(void) |
44 | { | 44 | { |
45 | struct user_struct *user = tsk->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(struct task_struct *tsk) | |||
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 | tsk, 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,7 +87,7 @@ int install_user_keyrings(struct task_struct *tsk) | |||
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 | tsk, KEY_ALLOC_IN_QUOTA, NULL); | 90 | cred, KEY_ALLOC_IN_QUOTA, NULL); |
87 | if (IS_ERR(session_keyring)) { | 91 | if (IS_ERR(session_keyring)) { |
88 | ret = PTR_ERR(session_keyring); | 92 | ret = PTR_ERR(session_keyring); |
89 | goto error_release; | 93 | goto error_release; |
@@ -115,140 +119,128 @@ error: | |||
115 | return ret; | 119 | return ret; |
116 | } | 120 | } |
117 | 121 | ||
118 | /*****************************************************************************/ | ||
119 | /* | 122 | /* |
120 | * deal with the UID changing | 123 | * install a fresh thread keyring directly to new credentials |
121 | */ | 124 | */ |
122 | void switch_uid_keyring(struct user_struct *new_user) | 125 | int install_thread_keyring_to_cred(struct cred *new) |
123 | { | 126 | { |
124 | #if 0 /* do nothing for now */ | 127 | struct key *keyring; |
125 | struct key *old; | ||
126 | |||
127 | /* switch to the new user's session keyring if we were running under | ||
128 | * root's default session keyring */ | ||
129 | if (new_user->uid != 0 && | ||
130 | current->session_keyring == &root_session_keyring | ||
131 | ) { | ||
132 | atomic_inc(&new_user->session_keyring->usage); | ||
133 | |||
134 | task_lock(current); | ||
135 | old = current->session_keyring; | ||
136 | current->session_keyring = new_user->session_keyring; | ||
137 | task_unlock(current); | ||
138 | 128 | ||
139 | key_put(old); | 129 | keyring = keyring_alloc("_tid", new->uid, new->gid, new, |
140 | } | 130 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
141 | #endif | 131 | if (IS_ERR(keyring)) |
132 | return PTR_ERR(keyring); | ||
142 | 133 | ||
143 | } /* end switch_uid_keyring() */ | 134 | new->thread_keyring = keyring; |
135 | return 0; | ||
136 | } | ||
144 | 137 | ||
145 | /*****************************************************************************/ | ||
146 | /* | 138 | /* |
147 | * install a fresh thread keyring, discarding the old one | 139 | * install a fresh thread keyring, discarding the old one |
148 | */ | 140 | */ |
149 | int install_thread_keyring(struct task_struct *tsk) | 141 | static int install_thread_keyring(void) |
150 | { | 142 | { |
151 | struct key *keyring, *old; | 143 | struct cred *new; |
152 | char buf[20]; | ||
153 | int ret; | 144 | int ret; |
154 | 145 | ||
155 | sprintf(buf, "_tid.%u", tsk->pid); | 146 | new = prepare_creds(); |
147 | if (!new) | ||
148 | return -ENOMEM; | ||
156 | 149 | ||
157 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, | 150 | BUG_ON(new->thread_keyring); |
158 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 151 | |
159 | if (IS_ERR(keyring)) { | 152 | ret = install_thread_keyring_to_cred(new); |
160 | ret = PTR_ERR(keyring); | 153 | if (ret < 0) { |
161 | goto error; | 154 | abort_creds(new); |
155 | return ret; | ||
162 | } | 156 | } |
163 | 157 | ||
164 | task_lock(tsk); | 158 | return commit_creds(new); |
165 | old = tsk->thread_keyring; | 159 | } |
166 | tsk->thread_keyring = keyring; | ||
167 | task_unlock(tsk); | ||
168 | 160 | ||
169 | 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 | */ | ||
166 | int install_process_keyring_to_cred(struct cred *new) | ||
167 | { | ||
168 | struct key *keyring; | ||
169 | int ret; | ||
170 | 170 | ||
171 | key_put(old); | 171 | if (new->tgcred->process_keyring) |
172 | error: | 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); | ||
173 | return ret; | 189 | return ret; |
190 | } | ||
174 | 191 | ||
175 | } /* end install_thread_keyring() */ | ||
176 | |||
177 | /*****************************************************************************/ | ||
178 | /* | 192 | /* |
179 | * make sure a process keyring is installed | 193 | * make sure a process keyring is installed |
194 | * - we | ||
180 | */ | 195 | */ |
181 | int install_process_keyring(struct task_struct *tsk) | 196 | static int install_process_keyring(void) |
182 | { | 197 | { |
183 | struct key *keyring; | 198 | struct cred *new; |
184 | char buf[20]; | ||
185 | int ret; | 199 | int ret; |
186 | 200 | ||
187 | might_sleep(); | 201 | new = prepare_creds(); |
188 | 202 | if (!new) | |
189 | if (!tsk->signal->process_keyring) { | 203 | return -ENOMEM; |
190 | sprintf(buf, "_pid.%u", tsk->tgid); | ||
191 | |||
192 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, | ||
193 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
194 | if (IS_ERR(keyring)) { | ||
195 | ret = PTR_ERR(keyring); | ||
196 | goto error; | ||
197 | } | ||
198 | |||
199 | /* attach keyring */ | ||
200 | spin_lock_irq(&tsk->sighand->siglock); | ||
201 | if (!tsk->signal->process_keyring) { | ||
202 | tsk->signal->process_keyring = keyring; | ||
203 | keyring = NULL; | ||
204 | } | ||
205 | spin_unlock_irq(&tsk->sighand->siglock); | ||
206 | 204 | ||
207 | key_put(keyring); | 205 | ret = install_process_keyring_to_cred(new); |
206 | if (ret < 0) { | ||
207 | abort_creds(new); | ||
208 | return ret != -EEXIST ?: 0; | ||
208 | } | 209 | } |
209 | 210 | ||
210 | ret = 0; | 211 | return commit_creds(new); |
211 | error: | 212 | } |
212 | return ret; | ||
213 | |||
214 | } /* end install_process_keyring() */ | ||
215 | 213 | ||
216 | /*****************************************************************************/ | ||
217 | /* | 214 | /* |
218 | * install a session keyring, discarding the old one | 215 | * install a session keyring directly to a credentials struct |
219 | * - if a keyring is not supplied, an empty one is invented | ||
220 | */ | 216 | */ |
221 | static int install_session_keyring(struct task_struct *tsk, | 217 | static int install_session_keyring_to_cred(struct cred *cred, |
222 | struct key *keyring) | 218 | struct key *keyring) |
223 | { | 219 | { |
224 | unsigned long flags; | 220 | unsigned long flags; |
225 | struct key *old; | 221 | struct key *old; |
226 | char buf[20]; | ||
227 | 222 | ||
228 | might_sleep(); | 223 | might_sleep(); |
229 | 224 | ||
230 | /* create an empty session keyring */ | 225 | /* create an empty session keyring */ |
231 | if (!keyring) { | 226 | if (!keyring) { |
232 | sprintf(buf, "_ses.%u", tsk->tgid); | ||
233 | |||
234 | flags = KEY_ALLOC_QUOTA_OVERRUN; | 227 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
235 | if (tsk->signal->session_keyring) | 228 | if (cred->tgcred->session_keyring) |
236 | flags = KEY_ALLOC_IN_QUOTA; | 229 | flags = KEY_ALLOC_IN_QUOTA; |
237 | 230 | ||
238 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, | 231 | keyring = keyring_alloc("_ses", cred->uid, cred->gid, |
239 | flags, NULL); | 232 | cred, flags, NULL); |
240 | if (IS_ERR(keyring)) | 233 | if (IS_ERR(keyring)) |
241 | return PTR_ERR(keyring); | 234 | return PTR_ERR(keyring); |
242 | } | 235 | } else { |
243 | else { | ||
244 | atomic_inc(&keyring->usage); | 236 | atomic_inc(&keyring->usage); |
245 | } | 237 | } |
246 | 238 | ||
247 | /* install the keyring */ | 239 | /* install the keyring */ |
248 | spin_lock_irq(&tsk->sighand->siglock); | 240 | spin_lock_irq(&cred->tgcred->lock); |
249 | old = tsk->signal->session_keyring; | 241 | old = cred->tgcred->session_keyring; |
250 | rcu_assign_pointer(tsk->signal->session_keyring, keyring); | 242 | rcu_assign_pointer(cred->tgcred->session_keyring, keyring); |
251 | spin_unlock_irq(&tsk->sighand->siglock); | 243 | spin_unlock_irq(&cred->tgcred->lock); |
252 | 244 | ||
253 | /* 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 |
254 | * on it if it didn't previously point to anything */ | 246 | * on it if it didn't previously point to anything */ |
@@ -258,110 +250,29 @@ static int install_session_keyring(struct task_struct *tsk, | |||
258 | } | 250 | } |
259 | 251 | ||
260 | return 0; | 252 | return 0; |
253 | } | ||
261 | 254 | ||
262 | } /* end install_session_keyring() */ | ||
263 | |||
264 | /*****************************************************************************/ | ||
265 | /* | ||
266 | * copy the keys in a thread group for fork without CLONE_THREAD | ||
267 | */ | ||
268 | int copy_thread_group_keys(struct task_struct *tsk) | ||
269 | { | ||
270 | key_check(current->thread_group->session_keyring); | ||
271 | key_check(current->thread_group->process_keyring); | ||
272 | |||
273 | /* no process keyring yet */ | ||
274 | tsk->signal->process_keyring = NULL; | ||
275 | |||
276 | /* same session keyring */ | ||
277 | rcu_read_lock(); | ||
278 | tsk->signal->session_keyring = | ||
279 | key_get(rcu_dereference(current->signal->session_keyring)); | ||
280 | rcu_read_unlock(); | ||
281 | |||
282 | return 0; | ||
283 | |||
284 | } /* end copy_thread_group_keys() */ | ||
285 | |||
286 | /*****************************************************************************/ | ||
287 | /* | ||
288 | * copy the keys for fork | ||
289 | */ | ||
290 | int copy_keys(unsigned long clone_flags, struct task_struct *tsk) | ||
291 | { | ||
292 | key_check(tsk->thread_keyring); | ||
293 | key_check(tsk->request_key_auth); | ||
294 | |||
295 | /* no thread keyring yet */ | ||
296 | tsk->thread_keyring = NULL; | ||
297 | |||
298 | /* copy the request_key() authorisation for this thread */ | ||
299 | key_get(tsk->request_key_auth); | ||
300 | |||
301 | return 0; | ||
302 | |||
303 | } /* end copy_keys() */ | ||
304 | |||
305 | /*****************************************************************************/ | ||
306 | /* | ||
307 | * dispose of thread group keys upon thread group destruction | ||
308 | */ | ||
309 | void exit_thread_group_keys(struct signal_struct *tg) | ||
310 | { | ||
311 | key_put(tg->session_keyring); | ||
312 | key_put(tg->process_keyring); | ||
313 | |||
314 | } /* end exit_thread_group_keys() */ | ||
315 | |||
316 | /*****************************************************************************/ | ||
317 | /* | ||
318 | * dispose of per-thread keys upon thread exit | ||
319 | */ | ||
320 | void exit_keys(struct task_struct *tsk) | ||
321 | { | ||
322 | key_put(tsk->thread_keyring); | ||
323 | key_put(tsk->request_key_auth); | ||
324 | |||
325 | } /* end exit_keys() */ | ||
326 | |||
327 | /*****************************************************************************/ | ||
328 | /* | 255 | /* |
329 | * deal with execve() | 256 | * install a session keyring, discarding the old one |
257 | * - if a keyring is not supplied, an empty one is invented | ||
330 | */ | 258 | */ |
331 | int exec_keys(struct task_struct *tsk) | 259 | static int install_session_keyring(struct key *keyring) |
332 | { | 260 | { |
333 | struct key *old; | 261 | struct cred *new; |
334 | 262 | int ret; | |
335 | /* newly exec'd tasks don't get a thread keyring */ | ||
336 | task_lock(tsk); | ||
337 | old = tsk->thread_keyring; | ||
338 | tsk->thread_keyring = NULL; | ||
339 | task_unlock(tsk); | ||
340 | |||
341 | key_put(old); | ||
342 | |||
343 | /* discard the process keyring from a newly exec'd task */ | ||
344 | spin_lock_irq(&tsk->sighand->siglock); | ||
345 | old = tsk->signal->process_keyring; | ||
346 | tsk->signal->process_keyring = NULL; | ||
347 | spin_unlock_irq(&tsk->sighand->siglock); | ||
348 | |||
349 | key_put(old); | ||
350 | |||
351 | return 0; | ||
352 | 263 | ||
353 | } /* end exec_keys() */ | 264 | new = prepare_creds(); |
265 | if (!new) | ||
266 | return -ENOMEM; | ||
354 | 267 | ||
355 | /*****************************************************************************/ | 268 | ret = install_session_keyring_to_cred(new, NULL); |
356 | /* | 269 | if (ret < 0) { |
357 | * deal with SUID programs | 270 | abort_creds(new); |
358 | * - we might want to make this invent a new session keyring | 271 | return ret; |
359 | */ | 272 | } |
360 | int suid_keys(struct task_struct *tsk) | ||
361 | { | ||
362 | return 0; | ||
363 | 273 | ||
364 | } /* end suid_keys() */ | 274 | return commit_creds(new); |
275 | } | ||
365 | 276 | ||
366 | /*****************************************************************************/ | 277 | /*****************************************************************************/ |
367 | /* | 278 | /* |
@@ -370,10 +281,11 @@ int suid_keys(struct task_struct *tsk) | |||
370 | void key_fsuid_changed(struct task_struct *tsk) | 281 | void key_fsuid_changed(struct task_struct *tsk) |
371 | { | 282 | { |
372 | /* update the ownership of the thread keyring */ | 283 | /* update the ownership of the thread keyring */ |
373 | if (tsk->thread_keyring) { | 284 | BUG_ON(!tsk->cred); |
374 | down_write(&tsk->thread_keyring->sem); | 285 | if (tsk->cred->thread_keyring) { |
375 | tsk->thread_keyring->uid = tsk->fsuid; | 286 | down_write(&tsk->cred->thread_keyring->sem); |
376 | up_write(&tsk->thread_keyring->sem); | 287 | tsk->cred->thread_keyring->uid = tsk->cred->fsuid; |
288 | up_write(&tsk->cred->thread_keyring->sem); | ||
377 | } | 289 | } |
378 | 290 | ||
379 | } /* end key_fsuid_changed() */ | 291 | } /* end key_fsuid_changed() */ |
@@ -385,10 +297,11 @@ void key_fsuid_changed(struct task_struct *tsk) | |||
385 | void key_fsgid_changed(struct task_struct *tsk) | 297 | void key_fsgid_changed(struct task_struct *tsk) |
386 | { | 298 | { |
387 | /* update the ownership of the thread keyring */ | 299 | /* update the ownership of the thread keyring */ |
388 | if (tsk->thread_keyring) { | 300 | BUG_ON(!tsk->cred); |
389 | down_write(&tsk->thread_keyring->sem); | 301 | if (tsk->cred->thread_keyring) { |
390 | tsk->thread_keyring->gid = tsk->fsgid; | 302 | down_write(&tsk->cred->thread_keyring->sem); |
391 | up_write(&tsk->thread_keyring->sem); | 303 | tsk->cred->thread_keyring->gid = tsk->cred->fsgid; |
304 | up_write(&tsk->cred->thread_keyring->sem); | ||
392 | } | 305 | } |
393 | 306 | ||
394 | } /* end key_fsgid_changed() */ | 307 | } /* end key_fsgid_changed() */ |
@@ -404,7 +317,7 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
404 | key_ref_t search_process_keyrings(struct key_type *type, | 317 | key_ref_t search_process_keyrings(struct key_type *type, |
405 | const void *description, | 318 | const void *description, |
406 | key_match_func_t match, | 319 | key_match_func_t match, |
407 | struct task_struct *context) | 320 | const struct cred *cred) |
408 | { | 321 | { |
409 | struct request_key_auth *rka; | 322 | struct request_key_auth *rka; |
410 | key_ref_t key_ref, ret, err; | 323 | key_ref_t key_ref, ret, err; |
@@ -423,10 +336,10 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
423 | err = ERR_PTR(-EAGAIN); | 336 | err = ERR_PTR(-EAGAIN); |
424 | 337 | ||
425 | /* search the thread keyring first */ | 338 | /* search the thread keyring first */ |
426 | if (context->thread_keyring) { | 339 | if (cred->thread_keyring) { |
427 | key_ref = keyring_search_aux( | 340 | key_ref = keyring_search_aux( |
428 | make_key_ref(context->thread_keyring, 1), | 341 | make_key_ref(cred->thread_keyring, 1), |
429 | context, type, description, match); | 342 | cred, type, description, match); |
430 | if (!IS_ERR(key_ref)) | 343 | if (!IS_ERR(key_ref)) |
431 | goto found; | 344 | goto found; |
432 | 345 | ||
@@ -444,10 +357,10 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
444 | } | 357 | } |
445 | 358 | ||
446 | /* search the process keyring second */ | 359 | /* search the process keyring second */ |
447 | if (context->signal->process_keyring) { | 360 | if (cred->tgcred->process_keyring) { |
448 | key_ref = keyring_search_aux( | 361 | key_ref = keyring_search_aux( |
449 | make_key_ref(context->signal->process_keyring, 1), | 362 | make_key_ref(cred->tgcred->process_keyring, 1), |
450 | context, type, description, match); | 363 | cred, type, description, match); |
451 | if (!IS_ERR(key_ref)) | 364 | if (!IS_ERR(key_ref)) |
452 | goto found; | 365 | goto found; |
453 | 366 | ||
@@ -465,13 +378,13 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
465 | } | 378 | } |
466 | 379 | ||
467 | /* search the session keyring */ | 380 | /* search the session keyring */ |
468 | if (context->signal->session_keyring) { | 381 | if (cred->tgcred->session_keyring) { |
469 | rcu_read_lock(); | 382 | rcu_read_lock(); |
470 | key_ref = keyring_search_aux( | 383 | key_ref = keyring_search_aux( |
471 | make_key_ref(rcu_dereference( | 384 | make_key_ref(rcu_dereference( |
472 | context->signal->session_keyring), | 385 | cred->tgcred->session_keyring), |
473 | 1), | 386 | 1), |
474 | context, type, description, match); | 387 | cred, type, description, match); |
475 | rcu_read_unlock(); | 388 | rcu_read_unlock(); |
476 | 389 | ||
477 | if (!IS_ERR(key_ref)) | 390 | if (!IS_ERR(key_ref)) |
@@ -490,10 +403,10 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
490 | } | 403 | } |
491 | } | 404 | } |
492 | /* or search the user-session keyring */ | 405 | /* or search the user-session keyring */ |
493 | else if (context->user->session_keyring) { | 406 | else if (cred->user->session_keyring) { |
494 | key_ref = keyring_search_aux( | 407 | key_ref = keyring_search_aux( |
495 | make_key_ref(context->user->session_keyring, 1), | 408 | make_key_ref(cred->user->session_keyring, 1), |
496 | context, type, description, match); | 409 | cred, type, description, match); |
497 | if (!IS_ERR(key_ref)) | 410 | if (!IS_ERR(key_ref)) |
498 | goto found; | 411 | goto found; |
499 | 412 | ||
@@ -514,20 +427,20 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
514 | * search the keyrings of the process mentioned there | 427 | * search the keyrings of the process mentioned there |
515 | * - we don't permit access to request_key auth keys via this method | 428 | * - we don't permit access to request_key auth keys via this method |
516 | */ | 429 | */ |
517 | if (context->request_key_auth && | 430 | if (cred->request_key_auth && |
518 | context == current && | 431 | cred == current_cred() && |
519 | type != &key_type_request_key_auth | 432 | type != &key_type_request_key_auth |
520 | ) { | 433 | ) { |
521 | /* defend against the auth key being revoked */ | 434 | /* defend against the auth key being revoked */ |
522 | down_read(&context->request_key_auth->sem); | 435 | down_read(&cred->request_key_auth->sem); |
523 | 436 | ||
524 | if (key_validate(context->request_key_auth) == 0) { | 437 | if (key_validate(cred->request_key_auth) == 0) { |
525 | rka = context->request_key_auth->payload.data; | 438 | rka = cred->request_key_auth->payload.data; |
526 | 439 | ||
527 | key_ref = search_process_keyrings(type, description, | 440 | key_ref = search_process_keyrings(type, description, |
528 | match, rka->context); | 441 | match, rka->cred); |
529 | 442 | ||
530 | up_read(&context->request_key_auth->sem); | 443 | up_read(&cred->request_key_auth->sem); |
531 | 444 | ||
532 | if (!IS_ERR(key_ref)) | 445 | if (!IS_ERR(key_ref)) |
533 | goto found; | 446 | goto found; |
@@ -544,7 +457,7 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
544 | break; | 457 | break; |
545 | } | 458 | } |
546 | } else { | 459 | } else { |
547 | up_read(&context->request_key_auth->sem); | 460 | up_read(&cred->request_key_auth->sem); |
548 | } | 461 | } |
549 | } | 462 | } |
550 | 463 | ||
@@ -572,93 +485,98 @@ static int lookup_user_key_possessed(const struct key *key, const void *target) | |||
572 | * - don't create special keyrings unless so requested | 485 | * - don't create special keyrings unless so requested |
573 | * - partially constructed keys aren't found unless requested | 486 | * - partially constructed keys aren't found unless requested |
574 | */ | 487 | */ |
575 | key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | 488 | key_ref_t lookup_user_key(key_serial_t id, int create, int partial, |
576 | int create, int partial, key_perm_t perm) | 489 | key_perm_t perm) |
577 | { | 490 | { |
578 | key_ref_t key_ref, skey_ref; | 491 | struct request_key_auth *rka; |
492 | const struct cred *cred; | ||
579 | struct key *key; | 493 | struct key *key; |
494 | key_ref_t key_ref, skey_ref; | ||
580 | int ret; | 495 | int ret; |
581 | 496 | ||
582 | if (!context) | 497 | try_again: |
583 | context = current; | 498 | cred = get_current_cred(); |
584 | |||
585 | key_ref = ERR_PTR(-ENOKEY); | 499 | key_ref = ERR_PTR(-ENOKEY); |
586 | 500 | ||
587 | switch (id) { | 501 | switch (id) { |
588 | case KEY_SPEC_THREAD_KEYRING: | 502 | case KEY_SPEC_THREAD_KEYRING: |
589 | if (!context->thread_keyring) { | 503 | if (!cred->thread_keyring) { |
590 | if (!create) | 504 | if (!create) |
591 | goto error; | 505 | goto error; |
592 | 506 | ||
593 | ret = install_thread_keyring(context); | 507 | ret = install_thread_keyring(); |
594 | if (ret < 0) { | 508 | if (ret < 0) { |
595 | key = ERR_PTR(ret); | 509 | key = ERR_PTR(ret); |
596 | goto error; | 510 | goto error; |
597 | } | 511 | } |
512 | goto reget_creds; | ||
598 | } | 513 | } |
599 | 514 | ||
600 | key = context->thread_keyring; | 515 | key = cred->thread_keyring; |
601 | atomic_inc(&key->usage); | 516 | atomic_inc(&key->usage); |
602 | key_ref = make_key_ref(key, 1); | 517 | key_ref = make_key_ref(key, 1); |
603 | break; | 518 | break; |
604 | 519 | ||
605 | case KEY_SPEC_PROCESS_KEYRING: | 520 | case KEY_SPEC_PROCESS_KEYRING: |
606 | if (!context->signal->process_keyring) { | 521 | if (!cred->tgcred->process_keyring) { |
607 | if (!create) | 522 | if (!create) |
608 | goto error; | 523 | goto error; |
609 | 524 | ||
610 | ret = install_process_keyring(context); | 525 | ret = install_process_keyring(); |
611 | if (ret < 0) { | 526 | if (ret < 0) { |
612 | key = ERR_PTR(ret); | 527 | key = ERR_PTR(ret); |
613 | goto error; | 528 | goto error; |
614 | } | 529 | } |
530 | goto reget_creds; | ||
615 | } | 531 | } |
616 | 532 | ||
617 | key = context->signal->process_keyring; | 533 | key = cred->tgcred->process_keyring; |
618 | atomic_inc(&key->usage); | 534 | atomic_inc(&key->usage); |
619 | key_ref = make_key_ref(key, 1); | 535 | key_ref = make_key_ref(key, 1); |
620 | break; | 536 | break; |
621 | 537 | ||
622 | case KEY_SPEC_SESSION_KEYRING: | 538 | case KEY_SPEC_SESSION_KEYRING: |
623 | if (!context->signal->session_keyring) { | 539 | if (!cred->tgcred->session_keyring) { |
624 | /* always install a session keyring upon access if one | 540 | /* always install a session keyring upon access if one |
625 | * doesn't exist yet */ | 541 | * doesn't exist yet */ |
626 | ret = install_user_keyrings(context); | 542 | ret = install_user_keyrings(); |
627 | if (ret < 0) | 543 | if (ret < 0) |
628 | goto error; | 544 | goto error; |
629 | ret = install_session_keyring( | 545 | ret = install_session_keyring( |
630 | context, context->user->session_keyring); | 546 | cred->user->session_keyring); |
547 | |||
631 | if (ret < 0) | 548 | if (ret < 0) |
632 | goto error; | 549 | goto error; |
550 | goto reget_creds; | ||
633 | } | 551 | } |
634 | 552 | ||
635 | rcu_read_lock(); | 553 | rcu_read_lock(); |
636 | key = rcu_dereference(context->signal->session_keyring); | 554 | key = rcu_dereference(cred->tgcred->session_keyring); |
637 | atomic_inc(&key->usage); | 555 | atomic_inc(&key->usage); |
638 | rcu_read_unlock(); | 556 | rcu_read_unlock(); |
639 | key_ref = make_key_ref(key, 1); | 557 | key_ref = make_key_ref(key, 1); |
640 | break; | 558 | break; |
641 | 559 | ||
642 | case KEY_SPEC_USER_KEYRING: | 560 | case KEY_SPEC_USER_KEYRING: |
643 | if (!context->user->uid_keyring) { | 561 | if (!cred->user->uid_keyring) { |
644 | ret = install_user_keyrings(context); | 562 | ret = install_user_keyrings(); |
645 | if (ret < 0) | 563 | if (ret < 0) |
646 | goto error; | 564 | goto error; |
647 | } | 565 | } |
648 | 566 | ||
649 | key = context->user->uid_keyring; | 567 | key = cred->user->uid_keyring; |
650 | atomic_inc(&key->usage); | 568 | atomic_inc(&key->usage); |
651 | key_ref = make_key_ref(key, 1); | 569 | key_ref = make_key_ref(key, 1); |
652 | break; | 570 | break; |
653 | 571 | ||
654 | case KEY_SPEC_USER_SESSION_KEYRING: | 572 | case KEY_SPEC_USER_SESSION_KEYRING: |
655 | if (!context->user->session_keyring) { | 573 | if (!cred->user->session_keyring) { |
656 | ret = install_user_keyrings(context); | 574 | ret = install_user_keyrings(); |
657 | if (ret < 0) | 575 | if (ret < 0) |
658 | goto error; | 576 | goto error; |
659 | } | 577 | } |
660 | 578 | ||
661 | key = context->user->session_keyring; | 579 | key = cred->user->session_keyring; |
662 | atomic_inc(&key->usage); | 580 | atomic_inc(&key->usage); |
663 | key_ref = make_key_ref(key, 1); | 581 | key_ref = make_key_ref(key, 1); |
664 | break; | 582 | break; |
@@ -669,7 +587,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
669 | goto error; | 587 | goto error; |
670 | 588 | ||
671 | case KEY_SPEC_REQKEY_AUTH_KEY: | 589 | case KEY_SPEC_REQKEY_AUTH_KEY: |
672 | key = context->request_key_auth; | 590 | key = cred->request_key_auth; |
673 | if (!key) | 591 | if (!key) |
674 | goto error; | 592 | goto error; |
675 | 593 | ||
@@ -677,6 +595,25 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
677 | key_ref = make_key_ref(key, 1); | 595 | key_ref = make_key_ref(key, 1); |
678 | break; | 596 | break; |
679 | 597 | ||
598 | case KEY_SPEC_REQUESTOR_KEYRING: | ||
599 | if (!cred->request_key_auth) | ||
600 | goto error; | ||
601 | |||
602 | down_read(&cred->request_key_auth->sem); | ||
603 | if (cred->request_key_auth->flags & KEY_FLAG_REVOKED) { | ||
604 | key_ref = ERR_PTR(-EKEYREVOKED); | ||
605 | key = NULL; | ||
606 | } else { | ||
607 | rka = cred->request_key_auth->payload.data; | ||
608 | key = rka->dest_keyring; | ||
609 | atomic_inc(&key->usage); | ||
610 | } | ||
611 | up_read(&cred->request_key_auth->sem); | ||
612 | if (!key) | ||
613 | goto error; | ||
614 | key_ref = make_key_ref(key, 1); | ||
615 | break; | ||
616 | |||
680 | default: | 617 | default: |
681 | key_ref = ERR_PTR(-EINVAL); | 618 | key_ref = ERR_PTR(-EINVAL); |
682 | if (id < 1) | 619 | if (id < 1) |
@@ -693,7 +630,7 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
693 | /* check to see if we possess the key */ | 630 | /* check to see if we possess the key */ |
694 | skey_ref = search_process_keyrings(key->type, key, | 631 | skey_ref = search_process_keyrings(key->type, key, |
695 | lookup_user_key_possessed, | 632 | lookup_user_key_possessed, |
696 | current); | 633 | cred); |
697 | 634 | ||
698 | if (!IS_ERR(skey_ref)) { | 635 | if (!IS_ERR(skey_ref)) { |
699 | key_put(key); | 636 | key_put(key); |
@@ -725,11 +662,12 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id, | |||
725 | goto invalid_key; | 662 | goto invalid_key; |
726 | 663 | ||
727 | /* check the permissions */ | 664 | /* check the permissions */ |
728 | ret = key_task_permission(key_ref, context, perm); | 665 | ret = key_task_permission(key_ref, cred, perm); |
729 | if (ret < 0) | 666 | if (ret < 0) |
730 | goto invalid_key; | 667 | goto invalid_key; |
731 | 668 | ||
732 | error: | 669 | error: |
670 | put_cred(cred); | ||
733 | return key_ref; | 671 | return key_ref; |
734 | 672 | ||
735 | invalid_key: | 673 | invalid_key: |
@@ -737,6 +675,12 @@ invalid_key: | |||
737 | key_ref = ERR_PTR(ret); | 675 | key_ref = ERR_PTR(ret); |
738 | goto error; | 676 | goto error; |
739 | 677 | ||
678 | /* if we attempted to install a keyring, then it may have caused new | ||
679 | * creds to be installed */ | ||
680 | reget_creds: | ||
681 | put_cred(cred); | ||
682 | goto try_again; | ||
683 | |||
740 | } /* end lookup_user_key() */ | 684 | } /* end lookup_user_key() */ |
741 | 685 | ||
742 | /*****************************************************************************/ | 686 | /*****************************************************************************/ |
@@ -748,20 +692,33 @@ invalid_key: | |||
748 | */ | 692 | */ |
749 | long join_session_keyring(const char *name) | 693 | long join_session_keyring(const char *name) |
750 | { | 694 | { |
751 | struct task_struct *tsk = current; | 695 | const struct cred *old; |
696 | struct cred *new; | ||
752 | struct key *keyring; | 697 | struct key *keyring; |
753 | long ret; | 698 | long ret, serial; |
699 | |||
700 | /* only permit this if there's a single thread in the thread group - | ||
701 | * this avoids us having to adjust the creds on all threads and risking | ||
702 | * ENOMEM */ | ||
703 | if (!is_single_threaded(current)) | ||
704 | return -EMLINK; | ||
705 | |||
706 | new = prepare_creds(); | ||
707 | if (!new) | ||
708 | return -ENOMEM; | ||
709 | old = current_cred(); | ||
754 | 710 | ||
755 | /* if no name is provided, install an anonymous keyring */ | 711 | /* if no name is provided, install an anonymous keyring */ |
756 | if (!name) { | 712 | if (!name) { |
757 | ret = install_session_keyring(tsk, NULL); | 713 | ret = install_session_keyring_to_cred(new, NULL); |
758 | if (ret < 0) | 714 | if (ret < 0) |
759 | goto error; | 715 | goto error; |
760 | 716 | ||
761 | rcu_read_lock(); | 717 | serial = new->tgcred->session_keyring->serial; |
762 | ret = rcu_dereference(tsk->signal->session_keyring)->serial; | 718 | ret = commit_creds(new); |
763 | rcu_read_unlock(); | 719 | if (ret == 0) |
764 | goto error; | 720 | ret = serial; |
721 | goto okay; | ||
765 | } | 722 | } |
766 | 723 | ||
767 | /* allow the user to join or create a named keyring */ | 724 | /* allow the user to join or create a named keyring */ |
@@ -771,29 +728,33 @@ long join_session_keyring(const char *name) | |||
771 | keyring = find_keyring_by_name(name, false); | 728 | keyring = find_keyring_by_name(name, false); |
772 | if (PTR_ERR(keyring) == -ENOKEY) { | 729 | if (PTR_ERR(keyring) == -ENOKEY) { |
773 | /* not found - try and create a new one */ | 730 | /* not found - try and create a new one */ |
774 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, | 731 | keyring = keyring_alloc(name, old->uid, old->gid, old, |
775 | KEY_ALLOC_IN_QUOTA, NULL); | 732 | KEY_ALLOC_IN_QUOTA, NULL); |
776 | if (IS_ERR(keyring)) { | 733 | if (IS_ERR(keyring)) { |
777 | ret = PTR_ERR(keyring); | 734 | ret = PTR_ERR(keyring); |
778 | goto error2; | 735 | goto error2; |
779 | } | 736 | } |
780 | } | 737 | } else if (IS_ERR(keyring)) { |
781 | else if (IS_ERR(keyring)) { | ||
782 | ret = PTR_ERR(keyring); | 738 | ret = PTR_ERR(keyring); |
783 | goto error2; | 739 | goto error2; |
784 | } | 740 | } |
785 | 741 | ||
786 | /* we've got a keyring - now to install it */ | 742 | /* we've got a keyring - now to install it */ |
787 | ret = install_session_keyring(tsk, keyring); | 743 | ret = install_session_keyring_to_cred(new, keyring); |
788 | if (ret < 0) | 744 | if (ret < 0) |
789 | goto error2; | 745 | goto error2; |
790 | 746 | ||
747 | commit_creds(new); | ||
748 | mutex_unlock(&key_session_mutex); | ||
749 | |||
791 | ret = keyring->serial; | 750 | ret = keyring->serial; |
792 | key_put(keyring); | 751 | key_put(keyring); |
752 | okay: | ||
753 | return ret; | ||
793 | 754 | ||
794 | error2: | 755 | error2: |
795 | mutex_unlock(&key_session_mutex); | 756 | mutex_unlock(&key_session_mutex); |
796 | error: | 757 | error: |
758 | abort_creds(new); | ||
797 | return ret; | 759 | return ret; |
798 | 760 | } | |
799 | } /* end join_session_keyring() */ | ||
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index abea08f87fe2..0e04f72ef2d4 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | #define key_negative_timeout 60 /* default timeout on a negative key's existence */ | ||
23 | |||
22 | /* | 24 | /* |
23 | * wait_on_bit() sleep function for uninterruptible waiting | 25 | * wait_on_bit() sleep function for uninterruptible waiting |
24 | */ | 26 | */ |
@@ -64,7 +66,7 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
64 | const char *op, | 66 | const char *op, |
65 | void *aux) | 67 | void *aux) |
66 | { | 68 | { |
67 | struct task_struct *tsk = current; | 69 | const struct cred *cred = current_cred(); |
68 | key_serial_t prkey, sskey; | 70 | key_serial_t prkey, sskey; |
69 | struct key *key = cons->key, *authkey = cons->authkey, *keyring; | 71 | struct key *key = cons->key, *authkey = cons->authkey, *keyring; |
70 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; | 72 | char *argv[9], *envp[3], uid_str[12], gid_str[12]; |
@@ -74,15 +76,17 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
74 | 76 | ||
75 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); | 77 | kenter("{%d},{%d},%s", key->serial, authkey->serial, op); |
76 | 78 | ||
77 | ret = install_user_keyrings(tsk); | 79 | ret = install_user_keyrings(); |
78 | if (ret < 0) | 80 | if (ret < 0) |
79 | goto error_alloc; | 81 | goto error_alloc; |
80 | 82 | ||
81 | /* allocate a new session keyring */ | 83 | /* allocate a new session keyring */ |
82 | sprintf(desc, "_req.%u", key->serial); | 84 | sprintf(desc, "_req.%u", key->serial); |
83 | 85 | ||
84 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, | 86 | cred = get_current_cred(); |
87 | keyring = keyring_alloc(desc, cred->fsuid, cred->fsgid, cred, | ||
85 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | 88 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
89 | put_cred(cred); | ||
86 | if (IS_ERR(keyring)) { | 90 | if (IS_ERR(keyring)) { |
87 | ret = PTR_ERR(keyring); | 91 | ret = PTR_ERR(keyring); |
88 | goto error_alloc; | 92 | goto error_alloc; |
@@ -94,29 +98,24 @@ static int call_sbin_request_key(struct key_construction *cons, | |||
94 | goto error_link; | 98 | goto error_link; |
95 | 99 | ||
96 | /* record the UID and GID */ | 100 | /* record the UID and GID */ |
97 | sprintf(uid_str, "%d", current->fsuid); | 101 | sprintf(uid_str, "%d", cred->fsuid); |
98 | sprintf(gid_str, "%d", current->fsgid); | 102 | sprintf(gid_str, "%d", cred->fsgid); |
99 | 103 | ||
100 | /* we say which key is under construction */ | 104 | /* we say which key is under construction */ |
101 | sprintf(key_str, "%d", key->serial); | 105 | sprintf(key_str, "%d", key->serial); |
102 | 106 | ||
103 | /* we specify the process's default keyrings */ | 107 | /* we specify the process's default keyrings */ |
104 | sprintf(keyring_str[0], "%d", | 108 | sprintf(keyring_str[0], "%d", |
105 | tsk->thread_keyring ? tsk->thread_keyring->serial : 0); | 109 | cred->thread_keyring ? cred->thread_keyring->serial : 0); |
106 | 110 | ||
107 | prkey = 0; | 111 | prkey = 0; |
108 | if (tsk->signal->process_keyring) | 112 | if (cred->tgcred->process_keyring) |
109 | prkey = tsk->signal->process_keyring->serial; | 113 | prkey = cred->tgcred->process_keyring->serial; |
110 | |||
111 | sprintf(keyring_str[1], "%d", prkey); | ||
112 | 114 | ||
113 | if (tsk->signal->session_keyring) { | 115 | if (cred->tgcred->session_keyring) |
114 | rcu_read_lock(); | 116 | sskey = rcu_dereference(cred->tgcred->session_keyring)->serial; |
115 | sskey = rcu_dereference(tsk->signal->session_keyring)->serial; | 117 | else |
116 | rcu_read_unlock(); | 118 | sskey = cred->user->session_keyring->serial; |
117 | } else { | ||
118 | sskey = tsk->user->session_keyring->serial; | ||
119 | } | ||
120 | 119 | ||
121 | sprintf(keyring_str[2], "%d", sskey); | 120 | sprintf(keyring_str[2], "%d", sskey); |
122 | 121 | ||
@@ -157,8 +156,8 @@ error_link: | |||
157 | key_put(keyring); | 156 | key_put(keyring); |
158 | 157 | ||
159 | error_alloc: | 158 | error_alloc: |
160 | kleave(" = %d", ret); | ||
161 | complete_request_key(cons, ret); | 159 | complete_request_key(cons, ret); |
160 | kleave(" = %d", ret); | ||
162 | return ret; | 161 | return ret; |
163 | } | 162 | } |
164 | 163 | ||
@@ -167,7 +166,8 @@ error_alloc: | |||
167 | * - we ignore program failure and go on key status instead | 166 | * - we ignore program failure and go on key status instead |
168 | */ | 167 | */ |
169 | static int construct_key(struct key *key, const void *callout_info, | 168 | static int construct_key(struct key *key, const void *callout_info, |
170 | size_t callout_len, void *aux) | 169 | size_t callout_len, void *aux, |
170 | struct key *dest_keyring) | ||
171 | { | 171 | { |
172 | struct key_construction *cons; | 172 | struct key_construction *cons; |
173 | request_key_actor_t actor; | 173 | request_key_actor_t actor; |
@@ -181,7 +181,8 @@ static int construct_key(struct key *key, const void *callout_info, | |||
181 | return -ENOMEM; | 181 | return -ENOMEM; |
182 | 182 | ||
183 | /* allocate an authorisation key */ | 183 | /* allocate an authorisation key */ |
184 | authkey = request_key_auth_new(key, callout_info, callout_len); | 184 | authkey = request_key_auth_new(key, callout_info, callout_len, |
185 | dest_keyring); | ||
185 | if (IS_ERR(authkey)) { | 186 | if (IS_ERR(authkey)) { |
186 | kfree(cons); | 187 | kfree(cons); |
187 | ret = PTR_ERR(authkey); | 188 | ret = PTR_ERR(authkey); |
@@ -209,46 +210,67 @@ static int construct_key(struct key *key, const void *callout_info, | |||
209 | } | 210 | } |
210 | 211 | ||
211 | /* | 212 | /* |
212 | * link a key to the appropriate destination keyring | 213 | * get the appropriate destination keyring for the request |
213 | * - the caller must hold a write lock on the destination keyring | 214 | * - we return whatever keyring we select with an extra reference upon it which |
215 | * the caller must release | ||
214 | */ | 216 | */ |
215 | static void construct_key_make_link(struct key *key, struct key *dest_keyring) | 217 | static void construct_get_dest_keyring(struct key **_dest_keyring) |
216 | { | 218 | { |
217 | struct task_struct *tsk = current; | 219 | struct request_key_auth *rka; |
218 | struct key *drop = NULL; | 220 | const struct cred *cred = current_cred(); |
221 | struct key *dest_keyring = *_dest_keyring, *authkey; | ||
219 | 222 | ||
220 | kenter("{%d},%p", key->serial, dest_keyring); | 223 | kenter("%p", dest_keyring); |
221 | 224 | ||
222 | /* find the appropriate keyring */ | 225 | /* find the appropriate keyring */ |
223 | if (!dest_keyring) { | 226 | if (dest_keyring) { |
224 | switch (tsk->jit_keyring) { | 227 | /* the caller supplied one */ |
228 | key_get(dest_keyring); | ||
229 | } else { | ||
230 | /* use a default keyring; falling through the cases until we | ||
231 | * find one that we actually have */ | ||
232 | switch (cred->jit_keyring) { | ||
225 | case KEY_REQKEY_DEFL_DEFAULT: | 233 | case KEY_REQKEY_DEFL_DEFAULT: |
234 | case KEY_REQKEY_DEFL_REQUESTOR_KEYRING: | ||
235 | if (cred->request_key_auth) { | ||
236 | authkey = cred->request_key_auth; | ||
237 | down_read(&authkey->sem); | ||
238 | rka = authkey->payload.data; | ||
239 | if (!test_bit(KEY_FLAG_REVOKED, | ||
240 | &authkey->flags)) | ||
241 | dest_keyring = | ||
242 | key_get(rka->dest_keyring); | ||
243 | up_read(&authkey->sem); | ||
244 | if (dest_keyring) | ||
245 | break; | ||
246 | } | ||
247 | |||
226 | case KEY_REQKEY_DEFL_THREAD_KEYRING: | 248 | case KEY_REQKEY_DEFL_THREAD_KEYRING: |
227 | dest_keyring = tsk->thread_keyring; | 249 | dest_keyring = key_get(cred->thread_keyring); |
228 | if (dest_keyring) | 250 | if (dest_keyring) |
229 | break; | 251 | break; |
230 | 252 | ||
231 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: | 253 | case KEY_REQKEY_DEFL_PROCESS_KEYRING: |
232 | dest_keyring = tsk->signal->process_keyring; | 254 | dest_keyring = key_get(cred->tgcred->process_keyring); |
233 | if (dest_keyring) | 255 | if (dest_keyring) |
234 | break; | 256 | break; |
235 | 257 | ||
236 | case KEY_REQKEY_DEFL_SESSION_KEYRING: | 258 | case KEY_REQKEY_DEFL_SESSION_KEYRING: |
237 | rcu_read_lock(); | 259 | rcu_read_lock(); |
238 | dest_keyring = key_get( | 260 | dest_keyring = key_get( |
239 | rcu_dereference(tsk->signal->session_keyring)); | 261 | rcu_dereference(cred->tgcred->session_keyring)); |
240 | rcu_read_unlock(); | 262 | rcu_read_unlock(); |
241 | drop = dest_keyring; | ||
242 | 263 | ||
243 | if (dest_keyring) | 264 | if (dest_keyring) |
244 | break; | 265 | break; |
245 | 266 | ||
246 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: | 267 | case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: |
247 | dest_keyring = tsk->user->session_keyring; | 268 | dest_keyring = |
269 | key_get(cred->user->session_keyring); | ||
248 | break; | 270 | break; |
249 | 271 | ||
250 | case KEY_REQKEY_DEFL_USER_KEYRING: | 272 | case KEY_REQKEY_DEFL_USER_KEYRING: |
251 | dest_keyring = tsk->user->uid_keyring; | 273 | dest_keyring = key_get(cred->user->uid_keyring); |
252 | break; | 274 | break; |
253 | 275 | ||
254 | case KEY_REQKEY_DEFL_GROUP_KEYRING: | 276 | case KEY_REQKEY_DEFL_GROUP_KEYRING: |
@@ -257,10 +279,9 @@ static void construct_key_make_link(struct key *key, struct key *dest_keyring) | |||
257 | } | 279 | } |
258 | } | 280 | } |
259 | 281 | ||
260 | /* and attach the key to it */ | 282 | *_dest_keyring = dest_keyring; |
261 | __key_link(dest_keyring, key); | 283 | kleave(" [dk %d]", key_serial(dest_keyring)); |
262 | key_put(drop); | 284 | return; |
263 | kleave(""); | ||
264 | } | 285 | } |
265 | 286 | ||
266 | /* | 287 | /* |
@@ -275,6 +296,7 @@ static int construct_alloc_key(struct key_type *type, | |||
275 | struct key_user *user, | 296 | struct key_user *user, |
276 | struct key **_key) | 297 | struct key **_key) |
277 | { | 298 | { |
299 | const struct cred *cred = current_cred(); | ||
278 | struct key *key; | 300 | struct key *key; |
279 | key_ref_t key_ref; | 301 | key_ref_t key_ref; |
280 | 302 | ||
@@ -282,33 +304,28 @@ static int construct_alloc_key(struct key_type *type, | |||
282 | 304 | ||
283 | mutex_lock(&user->cons_lock); | 305 | mutex_lock(&user->cons_lock); |
284 | 306 | ||
285 | key = key_alloc(type, description, | 307 | key = key_alloc(type, description, cred->fsuid, cred->fsgid, cred, |
286 | current->fsuid, current->fsgid, current, KEY_POS_ALL, | 308 | KEY_POS_ALL, flags); |
287 | flags); | ||
288 | if (IS_ERR(key)) | 309 | if (IS_ERR(key)) |
289 | goto alloc_failed; | 310 | goto alloc_failed; |
290 | 311 | ||
291 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); | 312 | set_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags); |
292 | 313 | ||
293 | if (dest_keyring) | 314 | down_write(&dest_keyring->sem); |
294 | down_write(&dest_keyring->sem); | ||
295 | 315 | ||
296 | /* attach the key to the destination keyring under lock, but we do need | 316 | /* attach the key to the destination keyring under lock, but we do need |
297 | * to do another check just in case someone beat us to it whilst we | 317 | * to do another check just in case someone beat us to it whilst we |
298 | * waited for locks */ | 318 | * waited for locks */ |
299 | mutex_lock(&key_construction_mutex); | 319 | mutex_lock(&key_construction_mutex); |
300 | 320 | ||
301 | key_ref = search_process_keyrings(type, description, type->match, | 321 | key_ref = search_process_keyrings(type, description, type->match, cred); |
302 | current); | ||
303 | if (!IS_ERR(key_ref)) | 322 | if (!IS_ERR(key_ref)) |
304 | goto key_already_present; | 323 | goto key_already_present; |
305 | 324 | ||
306 | if (dest_keyring) | 325 | __key_link(dest_keyring, key); |
307 | construct_key_make_link(key, dest_keyring); | ||
308 | 326 | ||
309 | mutex_unlock(&key_construction_mutex); | 327 | mutex_unlock(&key_construction_mutex); |
310 | if (dest_keyring) | 328 | up_write(&dest_keyring->sem); |
311 | up_write(&dest_keyring->sem); | ||
312 | mutex_unlock(&user->cons_lock); | 329 | mutex_unlock(&user->cons_lock); |
313 | *_key = key; | 330 | *_key = key; |
314 | kleave(" = 0 [%d]", key_serial(key)); | 331 | kleave(" = 0 [%d]", key_serial(key)); |
@@ -346,25 +363,36 @@ static struct key *construct_key_and_link(struct key_type *type, | |||
346 | struct key *key; | 363 | struct key *key; |
347 | int ret; | 364 | int ret; |
348 | 365 | ||
349 | user = key_user_lookup(current->fsuid); | 366 | kenter(""); |
367 | |||
368 | user = key_user_lookup(current_fsuid()); | ||
350 | if (!user) | 369 | if (!user) |
351 | return ERR_PTR(-ENOMEM); | 370 | return ERR_PTR(-ENOMEM); |
352 | 371 | ||
372 | construct_get_dest_keyring(&dest_keyring); | ||
373 | |||
353 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, | 374 | ret = construct_alloc_key(type, description, dest_keyring, flags, user, |
354 | &key); | 375 | &key); |
355 | key_user_put(user); | 376 | key_user_put(user); |
356 | 377 | ||
357 | if (ret == 0) { | 378 | if (ret == 0) { |
358 | ret = construct_key(key, callout_info, callout_len, aux); | 379 | ret = construct_key(key, callout_info, callout_len, aux, |
359 | if (ret < 0) | 380 | dest_keyring); |
381 | if (ret < 0) { | ||
382 | kdebug("cons failed"); | ||
360 | goto construction_failed; | 383 | goto construction_failed; |
384 | } | ||
361 | } | 385 | } |
362 | 386 | ||
387 | key_put(dest_keyring); | ||
388 | kleave(" = key %d", key_serial(key)); | ||
363 | return key; | 389 | return key; |
364 | 390 | ||
365 | construction_failed: | 391 | construction_failed: |
366 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); | 392 | key_negate_and_link(key, key_negative_timeout, NULL, NULL); |
367 | key_put(key); | 393 | key_put(key); |
394 | key_put(dest_keyring); | ||
395 | kleave(" = %d", ret); | ||
368 | return ERR_PTR(ret); | 396 | return ERR_PTR(ret); |
369 | } | 397 | } |
370 | 398 | ||
@@ -383,6 +411,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
383 | struct key *dest_keyring, | 411 | struct key *dest_keyring, |
384 | unsigned long flags) | 412 | unsigned long flags) |
385 | { | 413 | { |
414 | const struct cred *cred = current_cred(); | ||
386 | struct key *key; | 415 | struct key *key; |
387 | key_ref_t key_ref; | 416 | key_ref_t key_ref; |
388 | 417 | ||
@@ -392,7 +421,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
392 | 421 | ||
393 | /* search all the process keyrings for a key */ | 422 | /* search all the process keyrings for a key */ |
394 | key_ref = search_process_keyrings(type, description, type->match, | 423 | key_ref = search_process_keyrings(type, description, type->match, |
395 | current); | 424 | cred); |
396 | 425 | ||
397 | if (!IS_ERR(key_ref)) { | 426 | if (!IS_ERR(key_ref)) { |
398 | 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 bd237b0a6331..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,12 +122,13 @@ 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); |
131 | key_put(rka->dest_keyring); | ||
131 | kfree(rka->callout_info); | 132 | kfree(rka->callout_info); |
132 | kfree(rka); | 133 | kfree(rka); |
133 | 134 | ||
@@ -139,9 +140,10 @@ static void request_key_auth_destroy(struct key *key) | |||
139 | * access to the caller's security data | 140 | * access to the caller's security data |
140 | */ | 141 | */ |
141 | struct key *request_key_auth_new(struct key *target, const void *callout_info, | 142 | struct key *request_key_auth_new(struct key *target, const void *callout_info, |
142 | size_t callout_len) | 143 | size_t callout_len, struct key *dest_keyring) |
143 | { | 144 | { |
144 | struct request_key_auth *rka, *irka; | 145 | struct request_key_auth *rka, *irka; |
146 | const struct cred *cred = current->cred; | ||
145 | struct key *authkey = NULL; | 147 | struct key *authkey = NULL; |
146 | char desc[20]; | 148 | char desc[20]; |
147 | int ret; | 149 | int ret; |
@@ -163,31 +165,29 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
163 | 165 | ||
164 | /* 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 |
165 | * another process */ | 167 | * another process */ |
166 | if (current->request_key_auth) { | 168 | if (cred->request_key_auth) { |
167 | /* it is - use that instantiation context here too */ | 169 | /* it is - use that instantiation context here too */ |
168 | down_read(¤t->request_key_auth->sem); | 170 | down_read(&cred->request_key_auth->sem); |
169 | 171 | ||
170 | /* 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 |
171 | * servicing is already instantiated */ | 173 | * servicing is already instantiated */ |
172 | if (test_bit(KEY_FLAG_REVOKED, | 174 | if (test_bit(KEY_FLAG_REVOKED, &cred->request_key_auth->flags)) |
173 | ¤t->request_key_auth->flags)) | ||
174 | goto auth_key_revoked; | 175 | goto auth_key_revoked; |
175 | 176 | ||
176 | irka = current->request_key_auth->payload.data; | 177 | irka = cred->request_key_auth->payload.data; |
177 | rka->context = irka->context; | 178 | rka->cred = get_cred(irka->cred); |
178 | rka->pid = irka->pid; | 179 | rka->pid = irka->pid; |
179 | get_task_struct(rka->context); | ||
180 | 180 | ||
181 | up_read(¤t->request_key_auth->sem); | 181 | up_read(&cred->request_key_auth->sem); |
182 | } | 182 | } |
183 | else { | 183 | else { |
184 | /* it isn't - use this process as the context */ | 184 | /* it isn't - use this process as the context */ |
185 | rka->context = current; | 185 | rka->cred = get_cred(cred); |
186 | rka->pid = current->pid; | 186 | rka->pid = current->pid; |
187 | get_task_struct(rka->context); | ||
188 | } | 187 | } |
189 | 188 | ||
190 | rka->target_key = key_get(target); | 189 | rka->target_key = key_get(target); |
190 | rka->dest_keyring = key_get(dest_keyring); | ||
191 | memcpy(rka->callout_info, callout_info, callout_len); | 191 | memcpy(rka->callout_info, callout_info, callout_len); |
192 | rka->callout_len = callout_len; | 192 | rka->callout_len = callout_len; |
193 | 193 | ||
@@ -195,7 +195,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
195 | sprintf(desc, "%x", target->serial); | 195 | sprintf(desc, "%x", target->serial); |
196 | 196 | ||
197 | authkey = key_alloc(&key_type_request_key_auth, desc, | 197 | authkey = key_alloc(&key_type_request_key_auth, desc, |
198 | current->fsuid, current->fsgid, current, | 198 | cred->fsuid, cred->fsgid, cred, |
199 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 199 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
200 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); | 200 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); |
201 | if (IS_ERR(authkey)) { | 201 | if (IS_ERR(authkey)) { |
@@ -203,16 +203,16 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info, | |||
203 | goto error_alloc; | 203 | goto error_alloc; |
204 | } | 204 | } |
205 | 205 | ||
206 | /* construct and attach to the keyring */ | 206 | /* construct the auth key */ |
207 | ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); | 207 | ret = key_instantiate_and_link(authkey, rka, 0, NULL, NULL); |
208 | if (ret < 0) | 208 | if (ret < 0) |
209 | goto error_inst; | 209 | goto error_inst; |
210 | 210 | ||
211 | kleave(" = {%d}", authkey->serial); | 211 | kleave(" = {%d,%d}", authkey->serial, atomic_read(&authkey->usage)); |
212 | return authkey; | 212 | return authkey; |
213 | 213 | ||
214 | auth_key_revoked: | 214 | auth_key_revoked: |
215 | up_read(¤t->request_key_auth->sem); | 215 | up_read(&cred->request_key_auth->sem); |
216 | kfree(rka->callout_info); | 216 | kfree(rka->callout_info); |
217 | kfree(rka); | 217 | kfree(rka); |
218 | kleave("= -EKEYREVOKED"); | 218 | kleave("= -EKEYREVOKED"); |
@@ -223,6 +223,7 @@ error_inst: | |||
223 | key_put(authkey); | 223 | key_put(authkey); |
224 | error_alloc: | 224 | error_alloc: |
225 | key_put(rka->target_key); | 225 | key_put(rka->target_key); |
226 | key_put(rka->dest_keyring); | ||
226 | kfree(rka->callout_info); | 227 | kfree(rka->callout_info); |
227 | kfree(rka); | 228 | kfree(rka); |
228 | kleave("= %d", ret); | 229 | kleave("= %d", ret); |
@@ -254,6 +255,7 @@ static int key_get_instantiation_authkey_match(const struct key *key, | |||
254 | */ | 255 | */ |
255 | struct key *key_get_instantiation_authkey(key_serial_t target_id) | 256 | struct key *key_get_instantiation_authkey(key_serial_t target_id) |
256 | { | 257 | { |
258 | const struct cred *cred = current_cred(); | ||
257 | struct key *authkey; | 259 | struct key *authkey; |
258 | key_ref_t authkey_ref; | 260 | key_ref_t authkey_ref; |
259 | 261 | ||
@@ -261,7 +263,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id) | |||
261 | &key_type_request_key_auth, | 263 | &key_type_request_key_auth, |
262 | (void *) (unsigned long) target_id, | 264 | (void *) (unsigned long) target_id, |
263 | key_get_instantiation_authkey_match, | 265 | key_get_instantiation_authkey_match, |
264 | current); | 266 | cred); |
265 | 267 | ||
266 | if (IS_ERR(authkey_ref)) { | 268 | if (IS_ERR(authkey_ref)) { |
267 | authkey = ERR_CAST(authkey_ref); | 269 | authkey = ERR_CAST(authkey_ref); |