aboutsummaryrefslogtreecommitdiffstats
path: root/security/keys/keyring.c
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2005-06-24 01:00:56 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-06-24 03:05:19 -0400
commit3e30148c3d524a9c1c63ca28261bc24c457eb07a (patch)
treea2fcc46cc11fe871ad976c07476d934a07313576 /security/keys/keyring.c
parent8589b4e00e352f983259140f25a262d973be6bc5 (diff)
[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>
Diffstat (limited to 'security/keys/keyring.c')
-rw-r--r--security/keys/keyring.c67
1 files changed, 59 insertions, 8 deletions
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index c9a5de197487..90a551e4da66 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -1,6 +1,6 @@
1/* keyring.c: keyring handling 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 * Written by David Howells (dhowells@redhat.com) 4 * Written by David Howells (dhowells@redhat.com)
5 * 5 *
6 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
@@ -308,7 +308,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
308 uid, gid, KEY_USR_ALL, not_in_quota); 308 uid, gid, KEY_USR_ALL, not_in_quota);
309 309
310 if (!IS_ERR(keyring)) { 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 if (ret < 0) { 312 if (ret < 0) {
313 key_put(keyring); 313 key_put(keyring);
314 keyring = ERR_PTR(ret); 314 keyring = ERR_PTR(ret);
@@ -326,11 +326,12 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
326 * - we only find keys on which we have search permission 326 * - we only find keys on which we have search permission
327 * - we use the supplied match function to see if the description (or other 327 * - we use the supplied match function to see if the description (or other
328 * feature of interest) matches 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 * - we return -EAGAIN if we didn't find any matching key 330 * - we return -EAGAIN if we didn't find any matching key
331 * - we return -ENOKEY if we only found negative matching keys 331 * - we return -ENOKEY if we only found negative matching keys
332 */ 332 */
333struct key *keyring_search_aux(struct key *keyring, 333struct key *keyring_search_aux(struct key *keyring,
334 struct task_struct *context,
334 struct key_type *type, 335 struct key_type *type,
335 const void *description, 336 const void *description,
336 key_match_func_t match) 337 key_match_func_t match)
@@ -352,7 +353,7 @@ struct key *keyring_search_aux(struct key *keyring,
352 353
353 /* top keyring must have search permission to begin the search */ 354 /* top keyring must have search permission to begin the search */
354 key = ERR_PTR(-EACCES); 355 key = ERR_PTR(-EACCES);
355 if (!key_permission(keyring, KEY_SEARCH)) 356 if (!key_task_permission(keyring, context, KEY_SEARCH))
356 goto error; 357 goto error;
357 358
358 key = ERR_PTR(-ENOTDIR); 359 key = ERR_PTR(-ENOTDIR);
@@ -392,7 +393,7 @@ struct key *keyring_search_aux(struct key *keyring,
392 continue; 393 continue;
393 394
394 /* key must have search permissions */ 395 /* key must have search permissions */
395 if (!key_permission(key, KEY_SEARCH)) 396 if (!key_task_permission(key, context, KEY_SEARCH))
396 continue; 397 continue;
397 398
398 /* we set a different error code if we find a negative key */ 399 /* we set a different error code if we find a negative key */
@@ -418,7 +419,7 @@ struct key *keyring_search_aux(struct key *keyring,
418 if (sp >= KEYRING_SEARCH_MAX_DEPTH) 419 if (sp >= KEYRING_SEARCH_MAX_DEPTH)
419 continue; 420 continue;
420 421
421 if (!key_permission(key, KEY_SEARCH)) 422 if (!key_task_permission(key, context, KEY_SEARCH))
422 continue; 423 continue;
423 424
424 /* stack the current position */ 425 /* stack the current position */
@@ -468,7 +469,11 @@ struct key *keyring_search(struct key *keyring,
468 struct key_type *type, 469 struct key_type *type,
469 const char *description) 470 const char *description)
470{ 471{
471 return keyring_search_aux(keyring, type, description, type->match); 472 if (!type->match)
473 return ERR_PTR(-ENOKEY);
474
475 return keyring_search_aux(keyring, current,
476 type, description, type->match);
472 477
473} /* end keyring_search() */ 478} /* end keyring_search() */
474 479
@@ -496,7 +501,8 @@ struct key *__keyring_search_one(struct key *keyring,
496 key = klist->keys[loop]; 501 key = klist->keys[loop];
497 502
498 if (key->type == ktype && 503 if (key->type == ktype &&
499 key->type->match(key, description) && 504 (!key->type->match ||
505 key->type->match(key, description)) &&
500 key_permission(key, perm) && 506 key_permission(key, perm) &&
501 !test_bit(KEY_FLAG_REVOKED, &key->flags) 507 !test_bit(KEY_FLAG_REVOKED, &key->flags)
502 ) 508 )
@@ -517,6 +523,51 @@ struct key *__keyring_search_one(struct key *keyring,
517 523
518/*****************************************************************************/ 524/*****************************************************************************/
519/* 525/*
526 * search for an instantiation authorisation key matching a target key
527 * - the RCU read lock must be held by the caller
528 * - a target_id of zero specifies any valid token
529 */
530struct key *keyring_search_instkey(struct key *keyring,
531 key_serial_t target_id)
532{
533 struct request_key_auth *rka;
534 struct keyring_list *klist;
535 struct key *instkey;
536 int loop;
537
538 klist = rcu_dereference(keyring->payload.subscriptions);
539 if (klist) {
540 for (loop = 0; loop < klist->nkeys; loop++) {
541 instkey = klist->keys[loop];
542
543 if (instkey->type != &key_type_request_key_auth)
544 continue;
545
546 rka = instkey->payload.data;
547 if (target_id && rka->target_key->serial != target_id)
548 continue;
549
550 /* the auth key is revoked during instantiation */
551 if (!test_bit(KEY_FLAG_REVOKED, &instkey->flags))
552 goto found;
553
554 instkey = ERR_PTR(-EKEYREVOKED);
555 goto error;
556 }
557 }
558
559 instkey = ERR_PTR(-EACCES);
560 goto error;
561
562found:
563 atomic_inc(&instkey->usage);
564error:
565 return instkey;
566
567} /* end keyring_search_instkey() */
568
569/*****************************************************************************/
570/*
520 * find a keyring with the specified name 571 * find a keyring with the specified name
521 * - all named keyrings are searched 572 * - all named keyrings are searched
522 * - only find keyrings with search permission for the process 573 * - only find keyrings with search permission for the process