Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] Keys: Make request-key create an authorisation key

The attached patch makes the following changes:

(1) There's a new special key type called ".request_key_auth".

This is an authorisation key for when one process requests a key and
another process is started to construct it. This type of key cannot be
created by the user; nor can it be requested by kernel services.

Authorisation keys hold two references:

(a) Each refers to a key being constructed. When the key being
constructed is instantiated the authorisation key is revoked,
rendering it of no further use.

(b) The "authorising process". This is either:

(i) the process that called request_key(), or:

(ii) if the process that called request_key() itself had an
authorisation key in its session keyring, then the authorising
process referred to by that authorisation key will also be
referred to by the new authorisation key.

This means that the process that initiated a chain of key requests
will authorise the lot of them, and will, by default, wind up with
the keys obtained from them in its keyrings.

(2) request_key() creates an authorisation key which is then passed to
/sbin/request-key in as part of a new session keyring.

(3) When request_key() is searching for a key to hand back to the caller, if
it comes across an authorisation key in the session keyring of the
calling process, it will also search the keyrings of the process
specified therein and it will use the specified process's credentials
(fsuid, fsgid, groups) to do that rather than the calling process's
credentials.

This allows a process started by /sbin/request-key to find keys belonging
to the authorising process.

(4) A key can be read, even if the process executing KEYCTL_READ doesn't have
direct read or search permission if that key is contained within the
keyrings of a process specified by an authorisation key found within the
calling process's session keyring, and is searchable using the
credentials of the authorising process.

This allows a process started by /sbin/request-key to read keys belonging
to the authorising process.

(5) The magic KEY_SPEC_*_KEYRING key IDs when passed to KEYCTL_INSTANTIATE or
KEYCTL_NEGATE will specify a keyring of the authorising process, rather
than the process doing the instantiation.

(6) One of the process keyrings can be nominated as the default to which
request_key() should attach new keys if not otherwise specified. This is
done with KEYCTL_SET_REQKEY_KEYRING and one of the KEY_REQKEY_DEFL_*
constants. The current setting can also be read using this call.

(7) request_key() is partially interruptible. If it is waiting for another
process to finish constructing a key, it can be interrupted. This permits
a request-key cycle to be broken without recourse to rebooting.

Signed-Off-By: David Howells <dhowells@redhat.com>
Signed-Off-By: Benoit Boissinot <benoit.boissinot@ens-lyon.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

David Howells and committed by
Linus Torvalds
3e30148c 8589b4e0

+781 -193
+34
Documentation/keys.txt
··· 591 591 this case too. 592 592 593 593 594 + (*) Set the default request-key destination keyring. 595 + 596 + long keyctl(KEYCTL_SET_REQKEY_KEYRING, int reqkey_defl); 597 + 598 + This sets the default keyring to which implicitly requested keys will be 599 + attached for this thread. reqkey_defl should be one of these constants: 600 + 601 + CONSTANT VALUE NEW DEFAULT KEYRING 602 + ====================================== ====== ======================= 603 + KEY_REQKEY_DEFL_NO_CHANGE -1 No change 604 + KEY_REQKEY_DEFL_DEFAULT 0 Default[1] 605 + KEY_REQKEY_DEFL_THREAD_KEYRING 1 Thread keyring 606 + KEY_REQKEY_DEFL_PROCESS_KEYRING 2 Process keyring 607 + KEY_REQKEY_DEFL_SESSION_KEYRING 3 Session keyring 608 + KEY_REQKEY_DEFL_USER_KEYRING 4 User keyring 609 + KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 User session keyring 610 + KEY_REQKEY_DEFL_GROUP_KEYRING 6 Group keyring 611 + 612 + The old default will be returned if successful and error EINVAL will be 613 + returned if reqkey_defl is not one of the above values. 614 + 615 + The default keyring can be overridden by the keyring indicated to the 616 + request_key() system call. 617 + 618 + Note that this setting is inherited across fork/exec. 619 + 620 + [1] The default default is: the thread keyring if there is one, otherwise 621 + the process keyring if there is one, otherwise the session keyring if 622 + there is one, otherwise the user default session keyring. 623 + 624 + 594 625 =============== 595 626 KERNEL SERVICES 596 627 =============== ··· 656 625 657 626 Should the function fail error ENOKEY, EKEYEXPIRED or EKEYREVOKED will be 658 627 returned. 628 + 629 + If successful, the key will have been attached to the default keyring for 630 + implicitly obtained request-key keys, as set by KEYCTL_SET_REQKEY_KEYRING. 659 631 660 632 661 633 (*) When it is no longer required, the key should be released using:
+39 -2
include/linux/key-ui.h
··· 1 - /* key-ui.h: key userspace interface stuff for use by keyfs 1 + /* key-ui.h: key userspace interface stuff 2 2 * 3 3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) ··· 84 84 return kperm != 0; 85 85 } 86 86 87 + static inline int key_task_groups_search(struct task_struct *tsk, gid_t gid) 88 + { 89 + int ret; 87 90 88 - extern struct key *lookup_user_key(key_serial_t id, int create, int part, 91 + task_lock(tsk); 92 + ret = groups_search(tsk->group_info, gid); 93 + task_unlock(tsk); 94 + return ret; 95 + } 96 + 97 + static inline int key_task_permission(const struct key *key, 98 + struct task_struct *context, 99 + key_perm_t perm) 100 + { 101 + key_perm_t kperm; 102 + 103 + if (key->uid == context->fsuid) { 104 + kperm = key->perm >> 16; 105 + } 106 + else if (key->gid != -1 && 107 + key->perm & KEY_GRP_ALL && ( 108 + key->gid == context->fsgid || 109 + key_task_groups_search(context, key->gid) 110 + ) 111 + ) { 112 + kperm = key->perm >> 8; 113 + } 114 + else { 115 + kperm = key->perm; 116 + } 117 + 118 + kperm = kperm & perm & KEY_ALL; 119 + 120 + return kperm == perm; 121 + 122 + } 123 + 124 + extern struct key *lookup_user_key(struct task_struct *context, 125 + key_serial_t id, int create, int partial, 89 126 key_perm_t perm); 90 127 91 128 extern long join_session_keyring(const char *name);
+4 -5
include/linux/key.h
··· 199 199 extern int key_instantiate_and_link(struct key *key, 200 200 const void *data, 201 201 size_t datalen, 202 - struct key *keyring); 202 + struct key *keyring, 203 + struct key *instkey); 203 204 extern int key_negate_and_link(struct key *key, 204 205 unsigned timeout, 205 - struct key *keyring); 206 + struct key *keyring, 207 + struct key *instkey); 206 208 extern void key_revoke(struct key *key); 207 209 extern void key_put(struct key *key); 208 210 ··· 246 244 extern struct key *keyring_search(struct key *keyring, 247 245 struct key_type *type, 248 246 const char *description); 249 - 250 - extern struct key *search_process_keyrings(struct key_type *type, 251 - const char *description); 252 247 253 248 extern int keyring_add_key(struct key *keyring, 254 249 struct key *key);
+11
include/linux/keyctl.h
··· 20 20 #define KEY_SPEC_USER_SESSION_KEYRING -5 /* - key ID for UID-session keyring */ 21 21 #define KEY_SPEC_GROUP_KEYRING -6 /* - key ID for GID-specific keyring */ 22 22 23 + /* request-key default keyrings */ 24 + #define KEY_REQKEY_DEFL_NO_CHANGE -1 25 + #define KEY_REQKEY_DEFL_DEFAULT 0 26 + #define KEY_REQKEY_DEFL_THREAD_KEYRING 1 27 + #define KEY_REQKEY_DEFL_PROCESS_KEYRING 2 28 + #define KEY_REQKEY_DEFL_SESSION_KEYRING 3 29 + #define KEY_REQKEY_DEFL_USER_KEYRING 4 30 + #define KEY_REQKEY_DEFL_USER_SESSION_KEYRING 5 31 + #define KEY_REQKEY_DEFL_GROUP_KEYRING 6 32 + 23 33 /* keyctl commands */ 24 34 #define KEYCTL_GET_KEYRING_ID 0 /* ask for a keyring's ID */ 25 35 #define KEYCTL_JOIN_SESSION_KEYRING 1 /* join or start named session keyring */ ··· 45 35 #define KEYCTL_READ 11 /* read a key or keyring's contents */ 46 36 #define KEYCTL_INSTANTIATE 12 /* instantiate a partially constructed key */ 47 37 #define KEYCTL_NEGATE 13 /* negate a partially constructed key */ 38 + #define KEYCTL_SET_REQKEY_KEYRING 14 /* set default request-key keyring */ 48 39 49 40 #endif /* _LINUX_KEYCTL_H */
+5 -3
include/linux/sched.h
··· 561 561 groups_free(group_info); \ 562 562 } while (0) 563 563 564 - struct group_info *groups_alloc(int gidsetsize); 565 - void groups_free(struct group_info *group_info); 566 - int set_current_groups(struct group_info *group_info); 564 + extern struct group_info *groups_alloc(int gidsetsize); 565 + extern void groups_free(struct group_info *group_info); 566 + extern int set_current_groups(struct group_info *group_info); 567 + extern int groups_search(struct group_info *group_info, gid_t grp); 567 568 /* access the groups "array" with this macro */ 568 569 #define GROUP_AT(gi, i) \ 569 570 ((gi)->blocks[(i)/NGROUPS_PER_BLOCK][(i)%NGROUPS_PER_BLOCK]) ··· 661 660 struct user_struct *user; 662 661 #ifdef CONFIG_KEYS 663 662 struct key *thread_keyring; /* keyring private to this thread */ 663 + unsigned char jit_keyring; /* default keyring to attach requested keys to */ 664 664 #endif 665 665 int oomkilladj; /* OOM kill score adjustment (bit shift). */ 666 666 char comm[TASK_COMM_LEN]; /* executable name excluding path
+1 -1
kernel/sys.c
··· 1259 1259 } 1260 1260 1261 1261 /* a simple bsearch */ 1262 - static int groups_search(struct group_info *group_info, gid_t grp) 1262 + int groups_search(struct group_info *group_info, gid_t grp) 1263 1263 { 1264 1264 int left, right; 1265 1265
+3 -2
security/keys/Makefile
··· 7 7 keyring.o \ 8 8 keyctl.o \ 9 9 process_keys.o \ 10 - user_defined.o \ 11 - request_key.o 10 + request_key.o \ 11 + request_key_auth.o \ 12 + user_defined.o 12 13 13 14 obj-$(CONFIG_KEYS_COMPAT) += compat.o 14 15 obj-$(CONFIG_PROC_FS) += proc.o
+5 -2
security/keys/compat.c
··· 1 1 /* compat.c: 32-bit compatibility syscall for 64-bit systems 2 2 * 3 - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 24 24 * - if you can, you should call sys_keyctl directly 25 25 */ 26 26 asmlinkage long compat_sys_keyctl(u32 option, 27 - u32 arg2, u32 arg3, u32 arg4, u32 arg5) 27 + u32 arg2, u32 arg3, u32 arg4, u32 arg5) 28 28 { 29 29 switch (option) { 30 30 case KEYCTL_GET_KEYRING_ID: ··· 70 70 71 71 case KEYCTL_NEGATE: 72 72 return keyctl_negate_key(arg2, arg3, arg4); 73 + 74 + case KEYCTL_SET_REQKEY_KEYRING: 75 + return keyctl_set_reqkey_keyring(arg2); 73 76 74 77 default: 75 78 return -EOPNOTSUPP;
+41 -4
security/keys/internal.h
··· 1 1 /* internal.h: authentication token and access key management internal defs 2 2 * 3 - * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2003-5 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 14 14 15 15 #include <linux/key.h> 16 16 #include <linux/key-ui.h> 17 + 18 + #if 0 19 + #define kenter(FMT, a...) printk("==> %s("FMT")\n",__FUNCTION__ , ## a) 20 + #define kleave(FMT, a...) printk("<== %s()"FMT"\n",__FUNCTION__ , ## a) 21 + #define kdebug(FMT, a...) printk(FMT"\n" , ## a) 22 + #else 23 + #define kenter(FMT, a...) do {} while(0) 24 + #define kleave(FMT, a...) do {} while(0) 25 + #define kdebug(FMT, a...) do {} while(0) 26 + #endif 17 27 18 28 extern struct key_type key_type_dead; 19 29 extern struct key_type key_type_user; ··· 76 66 const char *description, 77 67 key_perm_t perm); 78 68 69 + extern struct key *keyring_search_instkey(struct key *keyring, 70 + key_serial_t target_id); 71 + 79 72 typedef int (*key_match_func_t)(const struct key *, const void *); 80 73 81 74 extern struct key *keyring_search_aux(struct key *keyring, 75 + struct task_struct *tsk, 82 76 struct key_type *type, 83 77 const void *description, 84 78 key_match_func_t match); 85 79 86 - extern struct key *search_process_keyrings_aux(struct key_type *type, 87 - const void *description, 88 - key_match_func_t match); 80 + extern struct key *search_process_keyrings(struct key_type *type, 81 + const void *description, 82 + key_match_func_t match, 83 + struct task_struct *tsk); 89 84 90 85 extern struct key *find_keyring_by_name(const char *name, key_serial_t bound); 91 86 92 87 extern int install_thread_keyring(struct task_struct *tsk); 88 + extern int install_process_keyring(struct task_struct *tsk); 89 + 90 + extern struct key *request_key_and_link(struct key_type *type, 91 + const char *description, 92 + const char *callout_info, 93 + struct key *dest_keyring); 94 + 95 + /* 96 + * request_key authorisation 97 + */ 98 + struct request_key_auth { 99 + struct key *target_key; 100 + struct task_struct *context; 101 + pid_t pid; 102 + }; 103 + 104 + extern struct key_type key_type_request_key_auth; 105 + extern struct key *request_key_auth_new(struct key *target, 106 + struct key **_rkakey); 107 + 108 + extern struct key *key_get_instantiation_authkey(key_serial_t target_id); 93 109 94 110 /* 95 111 * keyctl functions ··· 136 100 extern long keyctl_instantiate_key(key_serial_t, const void __user *, 137 101 size_t, key_serial_t); 138 102 extern long keyctl_negate_key(key_serial_t, unsigned, key_serial_t); 103 + extern long keyctl_set_reqkey_keyring(int); 139 104 140 105 141 106 /*
+18 -6
security/keys/key.c
··· 1 1 /* key.c: basic authentication token and access key management 2 2 * 3 - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 391 391 static int __key_instantiate_and_link(struct key *key, 392 392 const void *data, 393 393 size_t datalen, 394 - struct key *keyring) 394 + struct key *keyring, 395 + struct key *instkey) 395 396 { 396 397 int ret, awaken; 397 398 ··· 420 419 /* and link it into the destination keyring */ 421 420 if (keyring) 422 421 ret = __key_link(keyring, key); 422 + 423 + /* disable the authorisation key */ 424 + if (instkey) 425 + key_revoke(instkey); 423 426 } 424 427 } 425 428 ··· 444 439 int key_instantiate_and_link(struct key *key, 445 440 const void *data, 446 441 size_t datalen, 447 - struct key *keyring) 442 + struct key *keyring, 443 + struct key *instkey) 448 444 { 449 445 int ret; 450 446 451 447 if (keyring) 452 448 down_write(&keyring->sem); 453 449 454 - ret = __key_instantiate_and_link(key, data, datalen, keyring); 450 + ret = __key_instantiate_and_link(key, data, datalen, keyring, instkey); 455 451 456 452 if (keyring) 457 453 up_write(&keyring->sem); 458 454 459 455 return ret; 456 + 460 457 } /* end key_instantiate_and_link() */ 461 458 462 459 EXPORT_SYMBOL(key_instantiate_and_link); ··· 469 462 */ 470 463 int key_negate_and_link(struct key *key, 471 464 unsigned timeout, 472 - struct key *keyring) 465 + struct key *keyring, 466 + struct key *instkey) 473 467 { 474 468 struct timespec now; 475 469 int ret, awaken; ··· 503 495 /* and link it into the destination keyring */ 504 496 if (keyring) 505 497 ret = __key_link(keyring, key); 498 + 499 + /* disable the authorisation key */ 500 + if (instkey) 501 + key_revoke(instkey); 506 502 } 507 503 508 504 up_write(&key_construction_sem); ··· 793 781 } 794 782 795 783 /* instantiate it and link it into the target keyring */ 796 - ret = __key_instantiate_and_link(key, payload, plen, keyring); 784 + ret = __key_instantiate_and_link(key, payload, plen, keyring, NULL); 797 785 if (ret < 0) { 798 786 key_put(key); 799 787 key = ERR_PTR(ret);
+117 -57
security/keys/keyctl.c
··· 1 1 /* keyctl.c: userspace keyctl operations 2 2 * 3 - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 49 49 goto error; 50 50 type[31] = '\0'; 51 51 52 + if (!type[0]) 53 + goto error; 54 + 55 + ret = -EPERM; 56 + if (type[0] == '.') 57 + goto error; 58 + 52 59 ret = -EFAULT; 53 60 dlen = strnlen_user(_description, PAGE_SIZE - 1); 54 61 if (dlen <= 0) ··· 89 82 } 90 83 91 84 /* find the target keyring (which must be writable) */ 92 - keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 85 + keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); 93 86 if (IS_ERR(keyring)) { 94 87 ret = PTR_ERR(keyring); 95 88 goto error3; ··· 188 181 /* get the destination keyring if specified */ 189 182 dest = NULL; 190 183 if (destringid) { 191 - dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); 184 + dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); 192 185 if (IS_ERR(dest)) { 193 186 ret = PTR_ERR(dest); 194 187 goto error3; ··· 203 196 } 204 197 205 198 /* do the search */ 206 - key = request_key(ktype, description, callout_info); 199 + key = request_key_and_link(ktype, description, callout_info, dest); 207 200 if (IS_ERR(key)) { 208 201 ret = PTR_ERR(key); 209 202 goto error5; 210 203 } 211 204 212 - /* link the resulting key to the destination keyring */ 213 - if (dest) { 214 - ret = key_link(dest, key); 215 - if (ret < 0) 216 - goto error6; 217 - } 218 - 219 205 ret = key->serial; 220 206 221 - error6: 222 - key_put(key); 207 + key_put(key); 223 208 error5: 224 209 key_type_put(ktype); 225 210 error4: ··· 236 237 struct key *key; 237 238 long ret; 238 239 239 - key = lookup_user_key(id, create, 0, KEY_SEARCH); 240 + key = lookup_user_key(NULL, id, create, 0, KEY_SEARCH); 240 241 if (IS_ERR(key)) { 241 242 ret = PTR_ERR(key); 242 243 goto error; ··· 323 324 } 324 325 325 326 /* find the target key (which must be writable) */ 326 - key = lookup_user_key(id, 0, 0, KEY_WRITE); 327 + key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); 327 328 if (IS_ERR(key)) { 328 329 ret = PTR_ERR(key); 329 330 goto error2; ··· 351 352 struct key *key; 352 353 long ret; 353 354 354 - key = lookup_user_key(id, 0, 0, KEY_WRITE); 355 + key = lookup_user_key(NULL, id, 0, 0, KEY_WRITE); 355 356 if (IS_ERR(key)) { 356 357 ret = PTR_ERR(key); 357 358 goto error; ··· 377 378 struct key *keyring; 378 379 long ret; 379 380 380 - keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 381 + keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); 381 382 if (IS_ERR(keyring)) { 382 383 ret = PTR_ERR(keyring); 383 384 goto error; ··· 403 404 struct key *keyring, *key; 404 405 long ret; 405 406 406 - keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 407 + keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); 407 408 if (IS_ERR(keyring)) { 408 409 ret = PTR_ERR(keyring); 409 410 goto error; 410 411 } 411 412 412 - key = lookup_user_key(id, 1, 0, KEY_LINK); 413 + key = lookup_user_key(NULL, id, 1, 0, KEY_LINK); 413 414 if (IS_ERR(key)) { 414 415 ret = PTR_ERR(key); 415 416 goto error2; ··· 437 438 struct key *keyring, *key; 438 439 long ret; 439 440 440 - keyring = lookup_user_key(ringid, 0, 0, KEY_WRITE); 441 + keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_WRITE); 441 442 if (IS_ERR(keyring)) { 442 443 ret = PTR_ERR(keyring); 443 444 goto error; 444 445 } 445 446 446 - key = lookup_user_key(id, 0, 0, 0); 447 + key = lookup_user_key(NULL, id, 0, 0, 0); 447 448 if (IS_ERR(key)) { 448 449 ret = PTR_ERR(key); 449 450 goto error2; ··· 474 475 char __user *buffer, 475 476 size_t buflen) 476 477 { 477 - struct key *key; 478 + struct key *key, *instkey; 478 479 char *tmpbuf; 479 480 long ret; 480 481 481 - key = lookup_user_key(keyid, 0, 1, KEY_VIEW); 482 + key = lookup_user_key(NULL, keyid, 0, 1, KEY_VIEW); 482 483 if (IS_ERR(key)) { 484 + /* viewing a key under construction is permitted if we have the 485 + * authorisation token handy */ 486 + if (PTR_ERR(key) == -EACCES) { 487 + instkey = key_get_instantiation_authkey(keyid); 488 + if (!IS_ERR(instkey)) { 489 + key_put(instkey); 490 + key = lookup_user_key(NULL, keyid, 0, 1, 0); 491 + if (!IS_ERR(key)) 492 + goto okay; 493 + } 494 + } 495 + 483 496 ret = PTR_ERR(key); 484 497 goto error; 485 498 } 486 499 500 + okay: 487 501 /* calculate how much description we're going to return */ 488 502 ret = -ENOMEM; 489 503 tmpbuf = kmalloc(PAGE_SIZE, GFP_KERNEL); ··· 580 568 goto error2; 581 569 582 570 /* get the keyring at which to begin the search */ 583 - keyring = lookup_user_key(ringid, 0, 0, KEY_SEARCH); 571 + keyring = lookup_user_key(NULL, ringid, 0, 0, KEY_SEARCH); 584 572 if (IS_ERR(keyring)) { 585 573 ret = PTR_ERR(keyring); 586 574 goto error2; ··· 589 577 /* get the destination keyring if specified */ 590 578 dest = NULL; 591 579 if (destringid) { 592 - dest = lookup_user_key(destringid, 1, 0, KEY_WRITE); 580 + dest = lookup_user_key(NULL, destringid, 1, 0, KEY_WRITE); 593 581 if (IS_ERR(dest)) { 594 582 ret = PTR_ERR(dest); 595 583 goto error3; ··· 668 656 long ret; 669 657 670 658 /* find the key first */ 671 - key = lookup_user_key(keyid, 0, 0, 0); 659 + key = lookup_user_key(NULL, keyid, 0, 0, 0); 672 660 if (!IS_ERR(key)) { 673 661 /* see if we can read it directly */ 674 662 if (key_permission(key, KEY_READ)) 675 663 goto can_read_key; 676 664 677 - /* can't; see if it's searchable from this process's 678 - * keyrings */ 679 - ret = -ENOKEY; 680 - if (key_permission(key, KEY_SEARCH)) { 681 - /* okay - we do have search permission on the key 682 - * itself, but do we have the key? */ 683 - skey = search_process_keyrings_aux(key->type, key, 684 - keyctl_read_key_same); 685 - if (!IS_ERR(skey)) 686 - goto can_read_key2; 687 - } 665 + /* we can't; see if it's searchable from this process's 666 + * keyrings 667 + * - we automatically take account of the fact that it may be 668 + * dangling off an instantiation key 669 + */ 670 + skey = search_process_keyrings(key->type, key, 671 + keyctl_read_key_same, current); 672 + if (!IS_ERR(skey)) 673 + goto can_read_key2; 688 674 675 + ret = PTR_ERR(skey); 689 676 goto error2; 690 677 } 691 678 ··· 730 719 if (uid == (uid_t) -1 && gid == (gid_t) -1) 731 720 goto error; 732 721 733 - key = lookup_user_key(id, 1, 1, 0); 722 + key = lookup_user_key(NULL, id, 1, 1, 0); 734 723 if (IS_ERR(key)) { 735 724 ret = PTR_ERR(key); 736 725 goto error; ··· 787 776 if (perm & ~(KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) 788 777 goto error; 789 778 790 - key = lookup_user_key(id, 1, 1, 0); 779 + key = lookup_user_key(NULL, id, 1, 1, 0); 791 780 if (IS_ERR(key)) { 792 781 ret = PTR_ERR(key); 793 782 goto error; ··· 820 809 size_t plen, 821 810 key_serial_t ringid) 822 811 { 823 - struct key *key, *keyring; 812 + struct request_key_auth *rka; 813 + struct key *instkey, *keyring; 824 814 void *payload; 825 815 long ret; 826 816 ··· 843 831 goto error2; 844 832 } 845 833 846 - /* find the target key (which must be writable) */ 847 - key = lookup_user_key(id, 0, 1, KEY_WRITE); 848 - if (IS_ERR(key)) { 849 - ret = PTR_ERR(key); 834 + /* find the instantiation authorisation key */ 835 + instkey = key_get_instantiation_authkey(id); 836 + if (IS_ERR(instkey)) { 837 + ret = PTR_ERR(instkey); 850 838 goto error2; 851 839 } 852 840 853 - /* find the destination keyring if present (which must also be 854 - * writable) */ 841 + rka = instkey->payload.data; 842 + 843 + /* find the destination keyring amongst those belonging to the 844 + * requesting task */ 855 845 keyring = NULL; 856 846 if (ringid) { 857 - keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 847 + keyring = lookup_user_key(rka->context, ringid, 1, 0, 848 + KEY_WRITE); 858 849 if (IS_ERR(keyring)) { 859 850 ret = PTR_ERR(keyring); 860 851 goto error3; ··· 865 850 } 866 851 867 852 /* instantiate the key and link it into a keyring */ 868 - ret = key_instantiate_and_link(key, payload, plen, keyring); 853 + ret = key_instantiate_and_link(rka->target_key, payload, plen, 854 + keyring, instkey); 869 855 870 856 key_put(keyring); 871 857 error3: 872 - key_put(key); 858 + key_put(instkey); 873 859 error2: 874 860 kfree(payload); 875 861 error: ··· 885 869 */ 886 870 long keyctl_negate_key(key_serial_t id, unsigned timeout, key_serial_t ringid) 887 871 { 888 - struct key *key, *keyring; 872 + struct request_key_auth *rka; 873 + struct key *instkey, *keyring; 889 874 long ret; 890 875 891 - /* find the target key (which must be writable) */ 892 - key = lookup_user_key(id, 0, 1, KEY_WRITE); 893 - if (IS_ERR(key)) { 894 - ret = PTR_ERR(key); 876 + /* find the instantiation authorisation key */ 877 + instkey = key_get_instantiation_authkey(id); 878 + if (IS_ERR(instkey)) { 879 + ret = PTR_ERR(instkey); 895 880 goto error; 896 881 } 882 + 883 + rka = instkey->payload.data; 897 884 898 885 /* find the destination keyring if present (which must also be 899 886 * writable) */ 900 887 keyring = NULL; 901 888 if (ringid) { 902 - keyring = lookup_user_key(ringid, 1, 0, KEY_WRITE); 889 + keyring = lookup_user_key(NULL, ringid, 1, 0, KEY_WRITE); 903 890 if (IS_ERR(keyring)) { 904 891 ret = PTR_ERR(keyring); 905 892 goto error2; ··· 910 891 } 911 892 912 893 /* instantiate the key and link it into a keyring */ 913 - ret = key_negate_and_link(key, timeout, keyring); 894 + ret = key_negate_and_link(rka->target_key, timeout, keyring, instkey); 914 895 915 896 key_put(keyring); 916 897 error2: 917 - key_put(key); 898 + key_put(instkey); 918 899 error: 919 900 return ret; 920 901 921 902 } /* end keyctl_negate_key() */ 903 + 904 + /*****************************************************************************/ 905 + /* 906 + * set the default keyring in which request_key() will cache keys 907 + * - return the old setting 908 + */ 909 + long keyctl_set_reqkey_keyring(int reqkey_defl) 910 + { 911 + int ret; 912 + 913 + switch (reqkey_defl) { 914 + case KEY_REQKEY_DEFL_THREAD_KEYRING: 915 + ret = install_thread_keyring(current); 916 + if (ret < 0) 917 + return ret; 918 + goto set; 919 + 920 + case KEY_REQKEY_DEFL_PROCESS_KEYRING: 921 + ret = install_process_keyring(current); 922 + if (ret < 0) 923 + return ret; 924 + 925 + case KEY_REQKEY_DEFL_DEFAULT: 926 + case KEY_REQKEY_DEFL_SESSION_KEYRING: 927 + case KEY_REQKEY_DEFL_USER_KEYRING: 928 + case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 929 + set: 930 + current->jit_keyring = reqkey_defl; 931 + 932 + case KEY_REQKEY_DEFL_NO_CHANGE: 933 + return current->jit_keyring; 934 + 935 + case KEY_REQKEY_DEFL_GROUP_KEYRING: 936 + default: 937 + return -EINVAL; 938 + } 939 + 940 + } /* end keyctl_set_reqkey_keyring() */ 922 941 923 942 /*****************************************************************************/ 924 943 /* ··· 1027 970 return keyctl_negate_key((key_serial_t) arg2, 1028 971 (unsigned) arg3, 1029 972 (key_serial_t) arg4); 973 + 974 + case KEYCTL_SET_REQKEY_KEYRING: 975 + return keyctl_set_reqkey_keyring(arg2); 1030 976 1031 977 default: 1032 978 return -EOPNOTSUPP;
+59 -8
security/keys/keyring.c
··· 1 1 /* keyring.c: keyring handling 2 2 * 3 - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 308 308 uid, gid, KEY_USR_ALL, not_in_quota); 309 309 310 310 if (!IS_ERR(keyring)) { 311 - ret = key_instantiate_and_link(keyring, NULL, 0, dest); 311 + ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); 312 312 if (ret < 0) { 313 313 key_put(keyring); 314 314 keyring = ERR_PTR(ret); ··· 326 326 * - we only find keys on which we have search permission 327 327 * - we use the supplied match function to see if the description (or other 328 328 * feature of interest) matches 329 - * - we readlock the keyrings as we search down the tree 329 + * - we rely on RCU to prevent the keyring lists from disappearing on us 330 330 * - we return -EAGAIN if we didn't find any matching key 331 331 * - we return -ENOKEY if we only found negative matching keys 332 332 */ 333 333 struct key *keyring_search_aux(struct key *keyring, 334 + struct task_struct *context, 334 335 struct key_type *type, 335 336 const void *description, 336 337 key_match_func_t match) ··· 353 352 354 353 /* top keyring must have search permission to begin the search */ 355 354 key = ERR_PTR(-EACCES); 356 - if (!key_permission(keyring, KEY_SEARCH)) 355 + if (!key_task_permission(keyring, context, KEY_SEARCH)) 357 356 goto error; 358 357 359 358 key = ERR_PTR(-ENOTDIR); ··· 393 392 continue; 394 393 395 394 /* key must have search permissions */ 396 - if (!key_permission(key, KEY_SEARCH)) 395 + if (!key_task_permission(key, context, KEY_SEARCH)) 397 396 continue; 398 397 399 398 /* we set a different error code if we find a negative key */ ··· 419 418 if (sp >= KEYRING_SEARCH_MAX_DEPTH) 420 419 continue; 421 420 422 - if (!key_permission(key, KEY_SEARCH)) 421 + if (!key_task_permission(key, context, KEY_SEARCH)) 423 422 continue; 424 423 425 424 /* stack the current position */ ··· 469 468 struct key_type *type, 470 469 const char *description) 471 470 { 472 - return keyring_search_aux(keyring, type, description, type->match); 471 + if (!type->match) 472 + return ERR_PTR(-ENOKEY); 473 + 474 + return keyring_search_aux(keyring, current, 475 + type, description, type->match); 473 476 474 477 } /* end keyring_search() */ 475 478 ··· 501 496 key = klist->keys[loop]; 502 497 503 498 if (key->type == ktype && 504 - key->type->match(key, description) && 499 + (!key->type->match || 500 + key->type->match(key, description)) && 505 501 key_permission(key, perm) && 506 502 !test_bit(KEY_FLAG_REVOKED, &key->flags) 507 503 ) ··· 520 514 return key; 521 515 522 516 } /* end __keyring_search_one() */ 517 + 518 + /*****************************************************************************/ 519 + /* 520 + * search for an instantiation authorisation key matching a target key 521 + * - the RCU read lock must be held by the caller 522 + * - a target_id of zero specifies any valid token 523 + */ 524 + struct key *keyring_search_instkey(struct key *keyring, 525 + key_serial_t target_id) 526 + { 527 + struct request_key_auth *rka; 528 + struct keyring_list *klist; 529 + struct key *instkey; 530 + int loop; 531 + 532 + klist = rcu_dereference(keyring->payload.subscriptions); 533 + if (klist) { 534 + for (loop = 0; loop < klist->nkeys; loop++) { 535 + instkey = klist->keys[loop]; 536 + 537 + if (instkey->type != &key_type_request_key_auth) 538 + continue; 539 + 540 + rka = instkey->payload.data; 541 + if (target_id && rka->target_key->serial != target_id) 542 + continue; 543 + 544 + /* the auth key is revoked during instantiation */ 545 + if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags)) 546 + goto found; 547 + 548 + instkey = ERR_PTR(-EKEYREVOKED); 549 + goto error; 550 + } 551 + } 552 + 553 + instkey = ERR_PTR(-EACCES); 554 + goto error; 555 + 556 + found: 557 + atomic_inc(&instkey->usage); 558 + error: 559 + return instkey; 560 + 561 + } /* end keyring_search_instkey() */ 523 562 524 563 /*****************************************************************************/ 525 564 /*
+112 -69
security/keys/process_keys.c
··· 165 165 /* 166 166 * make sure a process keyring is installed 167 167 */ 168 - static int install_process_keyring(struct task_struct *tsk) 168 + int install_process_keyring(struct task_struct *tsk) 169 169 { 170 170 unsigned long flags; 171 171 struct key *keyring; ··· 376 376 * - we return -EAGAIN if we didn't find any matching key 377 377 * - we return -ENOKEY if we found only negative matching keys 378 378 */ 379 - struct key *search_process_keyrings_aux(struct key_type *type, 380 - const void *description, 381 - key_match_func_t match) 379 + struct key *search_process_keyrings(struct key_type *type, 380 + const void *description, 381 + key_match_func_t match, 382 + struct task_struct *context) 382 383 { 383 - struct task_struct *tsk = current; 384 - struct key *key, *ret, *err; 384 + struct request_key_auth *rka; 385 + struct key *key, *ret, *err, *instkey; 385 386 386 387 /* we want to return -EAGAIN or -ENOKEY if any of the keyrings were 387 388 * searchable, but we failed to find a key or we found a negative key; ··· 396 395 err = ERR_PTR(-EAGAIN); 397 396 398 397 /* search the thread keyring first */ 399 - if (tsk->thread_keyring) { 400 - key = keyring_search_aux(tsk->thread_keyring, type, 401 - description, match); 398 + if (context->thread_keyring) { 399 + key = keyring_search_aux(context->thread_keyring, 400 + context, type, description, match); 402 401 if (!IS_ERR(key)) 403 402 goto found; 404 403 ··· 416 415 } 417 416 418 417 /* search the process keyring second */ 419 - if (tsk->signal->process_keyring) { 420 - key = keyring_search_aux(tsk->signal->process_keyring, 421 - type, description, match); 418 + if (context->signal->process_keyring) { 419 + key = keyring_search_aux(context->signal->process_keyring, 420 + context, type, description, match); 422 421 if (!IS_ERR(key)) 423 422 goto found; 424 423 ··· 435 434 } 436 435 } 437 436 438 - /* search the session keyring last */ 439 - if (tsk->signal->session_keyring) { 437 + /* search the session keyring */ 438 + if (context->signal->session_keyring) { 440 439 rcu_read_lock(); 441 440 key = keyring_search_aux( 442 - rcu_dereference(tsk->signal->session_keyring), 443 - type, description, match); 441 + rcu_dereference(context->signal->session_keyring), 442 + context, type, description, match); 444 443 rcu_read_unlock(); 445 - } 446 - else { 447 - key = keyring_search_aux(tsk->user->session_keyring, 448 - type, description, match); 449 - } 450 444 451 - if (!IS_ERR(key)) 452 - goto found; 445 + if (!IS_ERR(key)) 446 + goto found; 453 447 454 - switch (PTR_ERR(key)) { 455 - case -EAGAIN: /* no key */ 456 - if (ret) 448 + switch (PTR_ERR(key)) { 449 + case -EAGAIN: /* no key */ 450 + if (ret) 451 + break; 452 + case -ENOKEY: /* negative key */ 453 + ret = key; 457 454 break; 458 - case -ENOKEY: /* negative key */ 459 - ret = key; 460 - break; 461 - default: 462 - err = key; 463 - break; 455 + default: 456 + err = key; 457 + break; 458 + } 459 + 460 + /* if this process has a session keyring and that has an 461 + * instantiation authorisation key in the bottom level, then we 462 + * also search the keyrings of the process mentioned there */ 463 + if (context != current) 464 + goto no_key; 465 + 466 + rcu_read_lock(); 467 + instkey = __keyring_search_one( 468 + rcu_dereference(context->signal->session_keyring), 469 + &key_type_request_key_auth, NULL, 0); 470 + rcu_read_unlock(); 471 + 472 + if (IS_ERR(instkey)) 473 + goto no_key; 474 + 475 + rka = instkey->payload.data; 476 + 477 + key = search_process_keyrings(type, description, match, 478 + rka->context); 479 + key_put(instkey); 480 + 481 + if (!IS_ERR(key)) 482 + goto found; 483 + 484 + switch (PTR_ERR(key)) { 485 + case -EAGAIN: /* no key */ 486 + if (ret) 487 + break; 488 + case -ENOKEY: /* negative key */ 489 + ret = key; 490 + break; 491 + default: 492 + err = key; 493 + break; 494 + } 495 + } 496 + /* or search the user-session keyring */ 497 + else { 498 + key = keyring_search_aux(context->user->session_keyring, 499 + context, type, description, match); 500 + if (!IS_ERR(key)) 501 + goto found; 502 + 503 + switch (PTR_ERR(key)) { 504 + case -EAGAIN: /* no key */ 505 + if (ret) 506 + break; 507 + case -ENOKEY: /* negative key */ 508 + ret = key; 509 + break; 510 + default: 511 + err = key; 512 + break; 513 + } 464 514 } 465 515 516 + 517 + no_key: 466 518 /* no key - decide on the error we're going to go for */ 467 519 key = ret ? ret : err; 468 520 469 - found: 521 + found: 470 522 return key; 471 - 472 - } /* end search_process_keyrings_aux() */ 473 - 474 - /*****************************************************************************/ 475 - /* 476 - * search the process keyrings for the first matching key 477 - * - we return -EAGAIN if we didn't find any matching key 478 - * - we return -ENOKEY if we found only negative matching keys 479 - */ 480 - struct key *search_process_keyrings(struct key_type *type, 481 - const char *description) 482 - { 483 - return search_process_keyrings_aux(type, description, type->match); 484 523 485 524 } /* end search_process_keyrings() */ 486 525 ··· 530 489 * - don't create special keyrings unless so requested 531 490 * - partially constructed keys aren't found unless requested 532 491 */ 533 - struct key *lookup_user_key(key_serial_t id, int create, int partial, 534 - key_perm_t perm) 492 + struct key *lookup_user_key(struct task_struct *context, key_serial_t id, 493 + int create, int partial, key_perm_t perm) 535 494 { 536 - struct task_struct *tsk = current; 537 - unsigned long flags; 538 495 struct key *key; 539 496 int ret; 497 + 498 + if (!context) 499 + context = current; 540 500 541 501 key = ERR_PTR(-ENOKEY); 542 502 543 503 switch (id) { 544 504 case KEY_SPEC_THREAD_KEYRING: 545 - if (!tsk->thread_keyring) { 505 + if (!context->thread_keyring) { 546 506 if (!create) 547 507 goto error; 548 508 549 - ret = install_thread_keyring(tsk); 509 + ret = install_thread_keyring(context); 550 510 if (ret < 0) { 551 511 key = ERR_PTR(ret); 552 512 goto error; 553 513 } 554 514 } 555 515 556 - key = tsk->thread_keyring; 516 + key = context->thread_keyring; 557 517 atomic_inc(&key->usage); 558 518 break; 559 519 560 520 case KEY_SPEC_PROCESS_KEYRING: 561 - if (!tsk->signal->process_keyring) { 521 + if (!context->signal->process_keyring) { 562 522 if (!create) 563 523 goto error; 564 524 565 - ret = install_process_keyring(tsk); 525 + ret = install_process_keyring(context); 566 526 if (ret < 0) { 567 527 key = ERR_PTR(ret); 568 528 goto error; 569 529 } 570 530 } 571 531 572 - key = tsk->signal->process_keyring; 532 + key = context->signal->process_keyring; 573 533 atomic_inc(&key->usage); 574 534 break; 575 535 576 536 case KEY_SPEC_SESSION_KEYRING: 577 - if (!tsk->signal->session_keyring) { 537 + if (!context->signal->session_keyring) { 578 538 /* always install a session keyring upon access if one 579 539 * doesn't exist yet */ 580 540 ret = install_session_keyring( 581 - tsk, tsk->user->session_keyring); 541 + context, context->user->session_keyring); 582 542 if (ret < 0) 583 543 goto error; 584 544 } 585 545 586 - spin_lock_irqsave(&tsk->sighand->siglock, flags); 587 - key = tsk->signal->session_keyring; 546 + rcu_read_lock(); 547 + key = rcu_dereference(context->signal->session_keyring); 588 548 atomic_inc(&key->usage); 589 - spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 549 + rcu_read_unlock(); 590 550 break; 591 551 592 552 case KEY_SPEC_USER_KEYRING: 593 - key = tsk->user->uid_keyring; 553 + key = context->user->uid_keyring; 594 554 atomic_inc(&key->usage); 595 555 break; 596 556 597 557 case KEY_SPEC_USER_SESSION_KEYRING: 598 - key = tsk->user->session_keyring; 558 + key = context->user->session_keyring; 599 559 atomic_inc(&key->usage); 600 560 break; 601 561 ··· 616 574 break; 617 575 } 618 576 619 - /* check the status and permissions */ 577 + /* check the status */ 620 578 if (perm) { 621 579 ret = key_validate(key); 622 580 if (ret < 0) ··· 627 585 if (!partial && !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) 628 586 goto invalid_key; 629 587 588 + /* check the permissions */ 630 589 ret = -EACCES; 631 - if (!key_permission(key, perm)) 590 + 591 + if (!key_task_permission(key, context, perm)) 632 592 goto invalid_key; 633 593 634 594 error: ··· 653 609 long join_session_keyring(const char *name) 654 610 { 655 611 struct task_struct *tsk = current; 656 - unsigned long flags; 657 612 struct key *keyring; 658 613 long ret; 659 614 ··· 662 619 if (ret < 0) 663 620 goto error; 664 621 665 - spin_lock_irqsave(&tsk->sighand->siglock, flags); 666 - ret = tsk->signal->session_keyring->serial; 667 - spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 622 + rcu_read_lock(); 623 + ret = rcu_dereference(tsk->signal->session_keyring)->serial; 624 + rcu_read_unlock(); 668 625 goto error; 669 626 } 670 627
+152 -34
security/keys/request_key.c
··· 1 1 /* request_key.c: request a key from userspace 2 2 * 3 - * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved. 3 + * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 4 4 * Written by David Howells (dhowells@redhat.com) 5 5 * 6 6 * This program is free software; you can redistribute it and/or ··· 13 13 #include <linux/sched.h> 14 14 #include <linux/kmod.h> 15 15 #include <linux/err.h> 16 + #include <linux/keyctl.h> 16 17 #include "internal.h" 17 18 18 19 struct key_construction { ··· 28 27 /* 29 28 * request userspace finish the construction of a key 30 29 * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring> <info>" 31 - * - if callout_info is an empty string, it'll be rendered as a "-" instead 32 30 */ 33 31 static int call_request_key(struct key *key, 34 32 const char *op, 35 33 const char *callout_info) 36 34 { 37 35 struct task_struct *tsk = current; 38 - unsigned long flags; 39 36 key_serial_t prkey, sskey; 37 + struct key *session_keyring, *rkakey; 40 38 char *argv[10], *envp[3], uid_str[12], gid_str[12]; 41 39 char key_str[12], keyring_str[3][12]; 42 - int i; 40 + int ret, i; 41 + 42 + kenter("{%d},%s,%s", key->serial, op, callout_info); 43 + 44 + /* generate a new session keyring with an auth key in it */ 45 + session_keyring = request_key_auth_new(key, &rkakey); 46 + if (IS_ERR(session_keyring)) { 47 + ret = PTR_ERR(session_keyring); 48 + goto error; 49 + } 43 50 44 51 /* record the UID and GID */ 45 52 sprintf(uid_str, "%d", current->fsuid); ··· 64 55 if (tsk->signal->process_keyring) 65 56 prkey = tsk->signal->process_keyring->serial; 66 57 67 - sskey = 0; 68 - spin_lock_irqsave(&tsk->sighand->siglock, flags); 69 - if (tsk->signal->session_keyring) 70 - sskey = tsk->signal->session_keyring->serial; 71 - spin_unlock_irqrestore(&tsk->sighand->siglock, flags); 72 - 73 - 74 - if (!sskey) 75 - sskey = tsk->user->session_keyring->serial; 76 - 77 58 sprintf(keyring_str[1], "%d", prkey); 59 + 60 + if (tsk->signal->session_keyring) { 61 + rcu_read_lock(); 62 + sskey = rcu_dereference(tsk->signal->session_keyring)->serial; 63 + rcu_read_unlock(); 64 + } 65 + else { 66 + sskey = tsk->user->session_keyring->serial; 67 + } 68 + 78 69 sprintf(keyring_str[2], "%d", sskey); 79 70 80 71 /* set up a minimal environment */ ··· 93 84 argv[i++] = keyring_str[0]; 94 85 argv[i++] = keyring_str[1]; 95 86 argv[i++] = keyring_str[2]; 96 - argv[i++] = callout_info[0] ? (char *) callout_info : "-"; 87 + argv[i++] = (char *) callout_info; 97 88 argv[i] = NULL; 98 89 99 90 /* do it */ 100 - return call_usermodehelper_keys(argv[0], argv, envp, NULL, 1); 91 + ret = call_usermodehelper_keys(argv[0], argv, envp, session_keyring, 1); 92 + 93 + /* dispose of the special keys */ 94 + key_revoke(rkakey); 95 + key_put(rkakey); 96 + key_put(session_keyring); 97 + 98 + error: 99 + kleave(" = %d", ret); 100 + return ret; 101 101 102 102 } /* end call_request_key() */ 103 103 ··· 124 106 struct timespec now; 125 107 struct key *key; 126 108 int ret, negated; 109 + 110 + kenter("%s,%s,%s", type->name, description, callout_info); 127 111 128 112 /* create a key and add it to the queue */ 129 113 key = key_alloc(type, description, ··· 163 143 } 164 144 165 145 out: 146 + kleave(" = %p", key); 166 147 return key; 167 148 168 149 request_failed: ··· 237 216 238 217 DECLARE_WAITQUEUE(myself, current); 239 218 219 + kenter("%s,%s,{%d},%s", 220 + type->name, description, user->uid, callout_info); 221 + 240 222 /* see if there's such a key under construction already */ 241 223 down_write(&key_construction_sem); 242 224 ··· 256 232 /* see about getting userspace to construct the key */ 257 233 key = __request_key_construction(type, description, callout_info); 258 234 error: 235 + kleave(" = %p", key); 259 236 return key; 260 237 261 238 /* someone else has the same key under construction ··· 270 245 add_wait_queue(&request_key_conswq, &myself); 271 246 272 247 for (;;) { 273 - set_current_state(TASK_UNINTERRUPTIBLE); 248 + set_current_state(TASK_INTERRUPTIBLE); 274 249 if (!test_bit(KEY_FLAG_USER_CONSTRUCT, &ckey->flags)) 250 + break; 251 + if (signal_pending(current)) 275 252 break; 276 253 schedule(); 277 254 } ··· 294 267 295 268 /*****************************************************************************/ 296 269 /* 270 + * link a freshly minted key to an appropriate destination keyring 271 + */ 272 + static void request_key_link(struct key *key, struct key *dest_keyring) 273 + { 274 + struct task_struct *tsk = current; 275 + struct key *drop = NULL; 276 + 277 + kenter("{%d},%p", key->serial, dest_keyring); 278 + 279 + /* find the appropriate keyring */ 280 + if (!dest_keyring) { 281 + switch (tsk->jit_keyring) { 282 + case KEY_REQKEY_DEFL_DEFAULT: 283 + case KEY_REQKEY_DEFL_THREAD_KEYRING: 284 + dest_keyring = tsk->thread_keyring; 285 + if (dest_keyring) 286 + break; 287 + 288 + case KEY_REQKEY_DEFL_PROCESS_KEYRING: 289 + dest_keyring = tsk->signal->process_keyring; 290 + if (dest_keyring) 291 + break; 292 + 293 + case KEY_REQKEY_DEFL_SESSION_KEYRING: 294 + rcu_read_lock(); 295 + dest_keyring = key_get( 296 + rcu_dereference(tsk->signal->session_keyring)); 297 + rcu_read_unlock(); 298 + drop = dest_keyring; 299 + 300 + if (dest_keyring) 301 + break; 302 + 303 + case KEY_REQKEY_DEFL_USER_SESSION_KEYRING: 304 + dest_keyring = current->user->session_keyring; 305 + break; 306 + 307 + case KEY_REQKEY_DEFL_USER_KEYRING: 308 + dest_keyring = current->user->uid_keyring; 309 + break; 310 + 311 + case KEY_REQKEY_DEFL_GROUP_KEYRING: 312 + default: 313 + BUG(); 314 + } 315 + } 316 + 317 + /* and attach the key to it */ 318 + key_link(dest_keyring, key); 319 + 320 + key_put(drop); 321 + 322 + kleave(""); 323 + 324 + } /* end request_key_link() */ 325 + 326 + /*****************************************************************************/ 327 + /* 297 328 * request a key 298 329 * - search the process's keyrings 299 330 * - check the list of keys being created or updated 300 - * - call out to userspace for a key if requested (supplementary info can be 301 - * passed) 331 + * - call out to userspace for a key if supplementary info was provided 332 + * - cache the key in an appropriate keyring 302 333 */ 303 - struct key *request_key(struct key_type *type, 304 - const char *description, 305 - const char *callout_info) 334 + struct key *request_key_and_link(struct key_type *type, 335 + const char *description, 336 + const char *callout_info, 337 + struct key *dest_keyring) 306 338 { 307 339 struct key_user *user; 308 340 struct key *key; 309 341 342 + kenter("%s,%s,%s,%p", 343 + type->name, description, callout_info, dest_keyring); 344 + 310 345 /* search all the process keyrings for a key */ 311 - key = search_process_keyrings_aux(type, description, type->match); 346 + key = search_process_keyrings(type, description, type->match, current); 312 347 313 348 if (PTR_ERR(key) == -EAGAIN) { 314 349 /* the search failed, but the keyrings were searchable, so we ··· 381 292 382 293 /* - get hold of the user's construction queue */ 383 294 user = key_user_lookup(current->fsuid); 384 - if (!user) { 385 - key = ERR_PTR(-ENOMEM); 386 - goto error; 387 - } 295 + if (!user) 296 + goto nomem; 388 297 389 - for (;;) { 298 + do { 299 + if (signal_pending(current)) 300 + goto interrupted; 301 + 390 302 /* ask userspace (returns NULL if it waited on a key 391 303 * being constructed) */ 392 304 key = request_key_construction(type, description, ··· 397 307 398 308 /* someone else made the key we want, so we need to 399 309 * search again as it might now be available to us */ 400 - key = search_process_keyrings_aux(type, description, 401 - type->match); 402 - if (PTR_ERR(key) != -EAGAIN) 403 - break; 404 - } 310 + key = search_process_keyrings(type, description, 311 + type->match, current); 312 + 313 + } while (PTR_ERR(key) == -EAGAIN); 405 314 406 315 key_user_put(user); 316 + 317 + /* link the new key into the appropriate keyring */ 318 + if (!PTR_ERR(key)) 319 + request_key_link(key, dest_keyring); 407 320 } 408 321 409 - error: 322 + error: 323 + kleave(" = %p", key); 410 324 return key; 325 + 326 + nomem: 327 + key = ERR_PTR(-ENOMEM); 328 + goto error; 329 + 330 + interrupted: 331 + key_user_put(user); 332 + key = ERR_PTR(-EINTR); 333 + goto error; 334 + 335 + } /* end request_key_and_link() */ 336 + 337 + /*****************************************************************************/ 338 + /* 339 + * request a key 340 + * - search the process's keyrings 341 + * - check the list of keys being created or updated 342 + * - call out to userspace for a key if supplementary info was provided 343 + */ 344 + struct key *request_key(struct key_type *type, 345 + const char *description, 346 + const char *callout_info) 347 + { 348 + return request_key_and_link(type, description, callout_info, NULL); 411 349 412 350 } /* end request_key() */ 413 351
+180
security/keys/request_key_auth.c
··· 1 + /* request_key_auth.c: request key authorisation controlling key def 2 + * 3 + * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved. 4 + * Written by David Howells (dhowells@redhat.com) 5 + * 6 + * This program is free software; you can redistribute it and/or 7 + * modify it under the terms of the GNU General Public License 8 + * as published by the Free Software Foundation; either version 9 + * 2 of the License, or (at your option) any later version. 10 + */ 11 + 12 + #include <linux/module.h> 13 + #include <linux/sched.h> 14 + #include <linux/err.h> 15 + #include <linux/seq_file.h> 16 + #include "internal.h" 17 + 18 + static int request_key_auth_instantiate(struct key *, const void *, size_t); 19 + static void request_key_auth_describe(const struct key *, struct seq_file *); 20 + static void request_key_auth_destroy(struct key *); 21 + 22 + /* 23 + * the request-key authorisation key type definition 24 + */ 25 + struct key_type key_type_request_key_auth = { 26 + .name = ".request_key_auth", 27 + .def_datalen = sizeof(struct request_key_auth), 28 + .instantiate = request_key_auth_instantiate, 29 + .describe = request_key_auth_describe, 30 + .destroy = request_key_auth_destroy, 31 + }; 32 + 33 + /*****************************************************************************/ 34 + /* 35 + * instantiate a request-key authorisation record 36 + */ 37 + static int request_key_auth_instantiate(struct key *key, 38 + const void *data, 39 + size_t datalen) 40 + { 41 + struct request_key_auth *rka, *irka; 42 + struct key *instkey; 43 + int ret; 44 + 45 + ret = -ENOMEM; 46 + rka = kmalloc(sizeof(*rka), GFP_KERNEL); 47 + if (rka) { 48 + /* see if the calling process is already servicing the key 49 + * request of another process */ 50 + instkey = key_get_instantiation_authkey(0); 51 + if (!IS_ERR(instkey)) { 52 + /* it is - use that instantiation context here too */ 53 + irka = instkey->payload.data; 54 + rka->context = irka->context; 55 + rka->pid = irka->pid; 56 + key_put(instkey); 57 + } 58 + else { 59 + /* it isn't - use this process as the context */ 60 + rka->context = current; 61 + rka->pid = current->pid; 62 + } 63 + 64 + rka->target_key = key_get((struct key *) data); 65 + key->payload.data = rka; 66 + ret = 0; 67 + } 68 + 69 + return ret; 70 + 71 + } /* end request_key_auth_instantiate() */ 72 + 73 + /*****************************************************************************/ 74 + /* 75 + * 76 + */ 77 + static void request_key_auth_describe(const struct key *key, 78 + struct seq_file *m) 79 + { 80 + struct request_key_auth *rka = key->payload.data; 81 + 82 + seq_puts(m, "key:"); 83 + seq_puts(m, key->description); 84 + seq_printf(m, " pid:%d", rka->pid); 85 + 86 + } /* end request_key_auth_describe() */ 87 + 88 + /*****************************************************************************/ 89 + /* 90 + * destroy an instantiation authorisation token key 91 + */ 92 + static void request_key_auth_destroy(struct key *key) 93 + { 94 + struct request_key_auth *rka = key->payload.data; 95 + 96 + kenter("{%d}", key->serial); 97 + 98 + key_put(rka->target_key); 99 + 100 + } /* end request_key_auth_destroy() */ 101 + 102 + /*****************************************************************************/ 103 + /* 104 + * create a session keyring to be for the invokation of /sbin/request-key and 105 + * stick an authorisation token in it 106 + */ 107 + struct key *request_key_auth_new(struct key *target, struct key **_rkakey) 108 + { 109 + struct key *keyring, *rkakey = NULL; 110 + char desc[20]; 111 + int ret; 112 + 113 + kenter("%d,", target->serial); 114 + 115 + /* allocate a new session keyring */ 116 + sprintf(desc, "_req.%u", target->serial); 117 + 118 + keyring = keyring_alloc(desc, current->fsuid, current->fsgid, 1, NULL); 119 + if (IS_ERR(keyring)) { 120 + kleave("= %ld", PTR_ERR(keyring)); 121 + return keyring; 122 + } 123 + 124 + /* allocate the auth key */ 125 + sprintf(desc, "%x", target->serial); 126 + 127 + rkakey = key_alloc(&key_type_request_key_auth, desc, 128 + current->fsuid, current->fsgid, 129 + KEY_USR_VIEW, 1); 130 + if (IS_ERR(rkakey)) { 131 + key_put(keyring); 132 + kleave("= %ld", PTR_ERR(rkakey)); 133 + return rkakey; 134 + } 135 + 136 + /* construct and attach to the keyring */ 137 + ret = key_instantiate_and_link(rkakey, target, 0, keyring, NULL); 138 + if (ret < 0) { 139 + key_revoke(rkakey); 140 + key_put(rkakey); 141 + key_put(keyring); 142 + kleave("= %d", ret); 143 + return ERR_PTR(ret); 144 + } 145 + 146 + *_rkakey = rkakey; 147 + kleave(" = {%d} ({%d})", keyring->serial, rkakey->serial); 148 + return keyring; 149 + 150 + } /* end request_key_auth_new() */ 151 + 152 + /*****************************************************************************/ 153 + /* 154 + * get the authorisation key for instantiation of a specific key if attached to 155 + * the current process's keyrings 156 + * - this key is inserted into a keyring and that is set as /sbin/request-key's 157 + * session keyring 158 + * - a target_id of zero specifies any valid token 159 + */ 160 + struct key *key_get_instantiation_authkey(key_serial_t target_id) 161 + { 162 + struct task_struct *tsk = current; 163 + struct key *instkey; 164 + 165 + /* we must have our own personal session keyring */ 166 + if (!tsk->signal->session_keyring) 167 + return ERR_PTR(-EACCES); 168 + 169 + /* and it must contain a suitable request authorisation key 170 + * - lock RCU against session keyring changing 171 + */ 172 + rcu_read_lock(); 173 + 174 + instkey = keyring_search_instkey( 175 + rcu_dereference(tsk->signal->session_keyring), target_id); 176 + 177 + rcu_read_unlock(); 178 + return instkey; 179 + 180 + } /* end key_get_instantiation_authkey() */