aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorDavid Howells <dhowells@redhat.com>2005-10-30 18:02:44 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2005-10-30 20:37:23 -0500
commit29db9190634067c5a328ee5fcc2890251b836b4b (patch)
tree07ec242789230824f1fa8bcbbe681fd5bf166fa8 /security
parent2aa349f6e37ce030060c994d3aebbff4ab703565 (diff)
[PATCH] Keys: Add LSM hooks for key management [try #3]
The attached patch adds LSM hooks for key management facilities. The notable changes are: (1) The key struct now supports a security pointer for the use of security modules. This will permit key labelling and restrictions on which programs may access a key. (2) Security modules get a chance to note (or abort) the allocation of a key. (3) The key permission checking can now be enhanced by the security modules; the permissions check consults LSM if all other checks bear out. (4) The key permissions checking functions now return an error code rather than a boolean value. (5) An extra permission has been added to govern the modification of attributes (UID, GID, permissions). Note that there isn't an LSM hook specifically for each keyctl() operation, but rather the permissions hook allows control of individual operations based on the permission request bits. Key management access control through LSM is enabled by automatically if both CONFIG_KEYS and CONFIG_SECURITY are enabled. This should be applied on top of the patch ensubjected: [PATCH] Keys: Possessor permissions should be additive Signed-Off-By: David Howells <dhowells@redhat.com> Signed-off-by: Chris Wright <chrisw@osdl.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'security')
-rw-r--r--security/dummy.c23
-rw-r--r--security/keys/key.c56
-rw-r--r--security/keys/keyctl.c13
-rw-r--r--security/keys/keyring.c21
-rw-r--r--security/keys/permission.c7
-rw-r--r--security/keys/process_keys.c9
6 files changed, 94 insertions, 35 deletions
diff --git a/security/dummy.c b/security/dummy.c
index 2a0337a52d32..3ca5f2b828a0 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -803,6 +803,23 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz
803 return -EINVAL; 803 return -EINVAL;
804} 804}
805 805
806#ifdef CONFIG_KEYS
807static inline int dummy_key_alloc(struct key *key)
808{
809 return 0;
810}
811
812static inline void dummy_key_free(struct key *key)
813{
814}
815
816static inline int dummy_key_permission(key_ref_t key_ref,
817 struct task_struct *context,
818 key_perm_t perm)
819{
820 return 0;
821}
822#endif /* CONFIG_KEYS */
806 823
807struct security_operations dummy_security_ops; 824struct security_operations dummy_security_ops;
808 825
@@ -954,5 +971,11 @@ void security_fixup_ops (struct security_operations *ops)
954 set_to_dummy_if_null(ops, sk_alloc_security); 971 set_to_dummy_if_null(ops, sk_alloc_security);
955 set_to_dummy_if_null(ops, sk_free_security); 972 set_to_dummy_if_null(ops, sk_free_security);
956#endif /* CONFIG_SECURITY_NETWORK */ 973#endif /* CONFIG_SECURITY_NETWORK */
974#ifdef CONFIG_KEYS
975 set_to_dummy_if_null(ops, key_alloc);
976 set_to_dummy_if_null(ops, key_free);
977 set_to_dummy_if_null(ops, key_permission);
978#endif /* CONFIG_KEYS */
979
957} 980}
958 981
diff --git a/security/keys/key.c b/security/keys/key.c
index 2182be9e9309..ccde17aff616 100644
--- a/security/keys/key.c
+++ b/security/keys/key.c
@@ -1,6 +1,6 @@
1/* key.c: basic authentication token and access key management 1/* key.c: basic authentication token and access key management
2 * 2 *
3 * Copyright (C) 2004-5 Red Hat, Inc. All Rights Reserved. 3 * Copyright (C) 2004 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
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/security.h>
16#include <linux/workqueue.h> 17#include <linux/workqueue.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include "internal.h" 19#include "internal.h"
@@ -253,6 +254,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
253 struct key_user *user = NULL; 254 struct key_user *user = NULL;
254 struct key *key; 255 struct key *key;
255 size_t desclen, quotalen; 256 size_t desclen, quotalen;
257 int ret;
256 258
257 key = ERR_PTR(-EINVAL); 259 key = ERR_PTR(-EINVAL);
258 if (!desc || !*desc) 260 if (!desc || !*desc)
@@ -305,6 +307,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
305 key->flags = 0; 307 key->flags = 0;
306 key->expiry = 0; 308 key->expiry = 0;
307 key->payload.data = NULL; 309 key->payload.data = NULL;
310 key->security = NULL;
308 311
309 if (!not_in_quota) 312 if (!not_in_quota)
310 key->flags |= 1 << KEY_FLAG_IN_QUOTA; 313 key->flags |= 1 << KEY_FLAG_IN_QUOTA;
@@ -315,16 +318,34 @@ struct key *key_alloc(struct key_type *type, const char *desc,
315 key->magic = KEY_DEBUG_MAGIC; 318 key->magic = KEY_DEBUG_MAGIC;
316#endif 319#endif
317 320
321 /* let the security module know about the key */
322 ret = security_key_alloc(key);
323 if (ret < 0)
324 goto security_error;
325
318 /* publish the key by giving it a serial number */ 326 /* publish the key by giving it a serial number */
319 atomic_inc(&user->nkeys); 327 atomic_inc(&user->nkeys);
320 key_alloc_serial(key); 328 key_alloc_serial(key);
321 329
322 error: 330error:
323 return key; 331 return key;
324 332
325 no_memory_3: 333security_error:
334 kfree(key->description);
335 kmem_cache_free(key_jar, key);
336 if (!not_in_quota) {
337 spin_lock(&user->lock);
338 user->qnkeys--;
339 user->qnbytes -= quotalen;
340 spin_unlock(&user->lock);
341 }
342 key_user_put(user);
343 key = ERR_PTR(ret);
344 goto error;
345
346no_memory_3:
326 kmem_cache_free(key_jar, key); 347 kmem_cache_free(key_jar, key);
327 no_memory_2: 348no_memory_2:
328 if (!not_in_quota) { 349 if (!not_in_quota) {
329 spin_lock(&user->lock); 350 spin_lock(&user->lock);
330 user->qnkeys--; 351 user->qnkeys--;
@@ -332,11 +353,11 @@ struct key *key_alloc(struct key_type *type, const char *desc,
332 spin_unlock(&user->lock); 353 spin_unlock(&user->lock);
333 } 354 }
334 key_user_put(user); 355 key_user_put(user);
335 no_memory_1: 356no_memory_1:
336 key = ERR_PTR(-ENOMEM); 357 key = ERR_PTR(-ENOMEM);
337 goto error; 358 goto error;
338 359
339 no_quota: 360no_quota:
340 spin_unlock(&user->lock); 361 spin_unlock(&user->lock);
341 key_user_put(user); 362 key_user_put(user);
342 key = ERR_PTR(-EDQUOT); 363 key = ERR_PTR(-EDQUOT);
@@ -556,6 +577,8 @@ static void key_cleanup(void *data)
556 577
557 key_check(key); 578 key_check(key);
558 579
580 security_key_free(key);
581
559 /* deal with the user's key tracking and quota */ 582 /* deal with the user's key tracking and quota */
560 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { 583 if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) {
561 spin_lock(&key->user->lock); 584 spin_lock(&key->user->lock);
@@ -700,8 +723,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
700 int ret; 723 int ret;
701 724
702 /* need write permission on the key to update it */ 725 /* need write permission on the key to update it */
703 ret = -EACCES; 726 ret = key_permission(key_ref, KEY_WRITE);
704 if (!key_permission(key_ref, KEY_WRITE)) 727 if (ret < 0)
705 goto error; 728 goto error;
706 729
707 ret = -EEXIST; 730 ret = -EEXIST;
@@ -711,7 +734,6 @@ static inline key_ref_t __key_update(key_ref_t key_ref,
711 down_write(&key->sem); 734 down_write(&key->sem);
712 735
713 ret = key->type->update(key, payload, plen); 736 ret = key->type->update(key, payload, plen);
714
715 if (ret == 0) 737 if (ret == 0)
716 /* updating a negative key instantiates it */ 738 /* updating a negative key instantiates it */
717 clear_bit(KEY_FLAG_NEGATIVE, &key->flags); 739 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
@@ -768,9 +790,11 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
768 790
769 /* if we're going to allocate a new key, we're going to have 791 /* if we're going to allocate a new key, we're going to have
770 * to modify the keyring */ 792 * to modify the keyring */
771 key_ref = ERR_PTR(-EACCES); 793 ret = key_permission(keyring_ref, KEY_WRITE);
772 if (!key_permission(keyring_ref, KEY_WRITE)) 794 if (ret < 0) {
795 key_ref = ERR_PTR(ret);
773 goto error_3; 796 goto error_3;
797 }
774 798
775 /* search for an existing key of the same type and description in the 799 /* search for an existing key of the same type and description in the
776 * destination keyring 800 * destination keyring
@@ -780,8 +804,8 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref,
780 goto found_matching_key; 804 goto found_matching_key;
781 805
782 /* decide on the permissions we want */ 806 /* decide on the permissions we want */
783 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK; 807 perm = KEY_POS_VIEW | KEY_POS_SEARCH | KEY_POS_LINK | KEY_POS_SETATTR;
784 perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK; 808 perm |= KEY_USR_VIEW | KEY_USR_SEARCH | KEY_USR_LINK | KEY_USR_SETATTR;
785 809
786 if (ktype->read) 810 if (ktype->read)
787 perm |= KEY_POS_READ | KEY_USR_READ; 811 perm |= KEY_POS_READ | KEY_USR_READ;
@@ -840,16 +864,16 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)
840 key_check(key); 864 key_check(key);
841 865
842 /* the key must be writable */ 866 /* the key must be writable */
843 ret = -EACCES; 867 ret = key_permission(key_ref, KEY_WRITE);
844 if (!key_permission(key_ref, KEY_WRITE)) 868 if (ret < 0)
845 goto error; 869 goto error;
846 870
847 /* attempt to update it if supported */ 871 /* attempt to update it if supported */
848 ret = -EOPNOTSUPP; 872 ret = -EOPNOTSUPP;
849 if (key->type->update) { 873 if (key->type->update) {
850 down_write(&key->sem); 874 down_write(&key->sem);
851 ret = key->type->update(key, payload, plen);
852 875
876 ret = key->type->update(key, payload, plen);
853 if (ret == 0) 877 if (ret == 0)
854 /* updating a negative key instantiates it */ 878 /* updating a negative key instantiates it */
855 clear_bit(KEY_FLAG_NEGATIVE, &key->flags); 879 clear_bit(KEY_FLAG_NEGATIVE, &key->flags);
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c
index 4c670ee6acf9..b7a468fabdf9 100644
--- a/security/keys/keyctl.c
+++ b/security/keys/keyctl.c
@@ -624,8 +624,8 @@ long keyctl_keyring_search(key_serial_t ringid,
624 624
625 /* link the resulting key to the destination keyring if we can */ 625 /* link the resulting key to the destination keyring if we can */
626 if (dest_ref) { 626 if (dest_ref) {
627 ret = -EACCES; 627 ret = key_permission(key_ref, KEY_LINK);
628 if (!key_permission(key_ref, KEY_LINK)) 628 if (ret < 0)
629 goto error6; 629 goto error6;
630 630
631 ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref)); 631 ret = key_link(key_ref_to_ptr(dest_ref), key_ref_to_ptr(key_ref));
@@ -676,8 +676,11 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen)
676 key = key_ref_to_ptr(key_ref); 676 key = key_ref_to_ptr(key_ref);
677 677
678 /* see if we can read it directly */ 678 /* see if we can read it directly */
679 if (key_permission(key_ref, KEY_READ)) 679 ret = key_permission(key_ref, KEY_READ);
680 if (ret == 0)
680 goto can_read_key; 681 goto can_read_key;
682 if (ret != -EACCES)
683 goto error;
681 684
682 /* we can't; see if it's searchable from this process's keyrings 685 /* we can't; see if it's searchable from this process's keyrings
683 * - we automatically take account of the fact that it may be 686 * - we automatically take account of the fact that it may be
@@ -726,7 +729,7 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid)
726 if (uid == (uid_t) -1 && gid == (gid_t) -1) 729 if (uid == (uid_t) -1 && gid == (gid_t) -1)
727 goto error; 730 goto error;
728 731
729 key_ref = lookup_user_key(NULL, id, 1, 1, 0); 732 key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
730 if (IS_ERR(key_ref)) { 733 if (IS_ERR(key_ref)) {
731 ret = PTR_ERR(key_ref); 734 ret = PTR_ERR(key_ref);
732 goto error; 735 goto error;
@@ -786,7 +789,7 @@ long keyctl_setperm_key(key_serial_t id, key_perm_t perm)
786 if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL)) 789 if (perm & ~(KEY_POS_ALL | KEY_USR_ALL | KEY_GRP_ALL | KEY_OTH_ALL))
787 goto error; 790 goto error;
788 791
789 key_ref = lookup_user_key(NULL, id, 1, 1, 0); 792 key_ref = lookup_user_key(NULL, id, 1, 1, KEY_SETATTR);
790 if (IS_ERR(key_ref)) { 793 if (IS_ERR(key_ref)) {
791 ret = PTR_ERR(key_ref); 794 ret = PTR_ERR(key_ref);
792 goto error; 795 goto error;
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index 0639396dd441..e1cc4dd79012 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -13,6 +13,7 @@
13#include <linux/init.h> 13#include <linux/init.h>
14#include <linux/sched.h> 14#include <linux/sched.h>
15#include <linux/slab.h> 15#include <linux/slab.h>
16#include <linux/security.h>
16#include <linux/seq_file.h> 17#include <linux/seq_file.h>
17#include <linux/err.h> 18#include <linux/err.h>
18#include <asm/uaccess.h> 19#include <asm/uaccess.h>
@@ -309,7 +310,9 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid,
309 int ret; 310 int ret;
310 311
311 keyring = key_alloc(&key_type_keyring, description, 312 keyring = key_alloc(&key_type_keyring, description,
312 uid, gid, KEY_POS_ALL | KEY_USR_ALL, not_in_quota); 313 uid, gid,
314 (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
315 not_in_quota);
313 316
314 if (!IS_ERR(keyring)) { 317 if (!IS_ERR(keyring)) {
315 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); 318 ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL);
@@ -359,9 +362,11 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref,
359 key_check(keyring); 362 key_check(keyring);
360 363
361 /* top keyring must have search permission to begin the search */ 364 /* top keyring must have search permission to begin the search */
362 key_ref = ERR_PTR(-EACCES); 365 err = key_task_permission(keyring_ref, context, KEY_SEARCH);
363 if (!key_task_permission(keyring_ref, context, KEY_SEARCH)) 366 if (err < 0) {
367 key_ref = ERR_PTR(err);
364 goto error; 368 goto error;
369 }
365 370
366 key_ref = ERR_PTR(-ENOTDIR); 371 key_ref = ERR_PTR(-ENOTDIR);
367 if (keyring->type != &key_type_keyring) 372 if (keyring->type != &key_type_keyring)
@@ -402,8 +407,8 @@ descend:
402 continue; 407 continue;
403 408
404 /* key must have search permissions */ 409 /* key must have search permissions */
405 if (!key_task_permission(make_key_ref(key, possessed), 410 if (key_task_permission(make_key_ref(key, possessed),
406 context, KEY_SEARCH)) 411 context, KEY_SEARCH) < 0)
407 continue; 412 continue;
408 413
409 /* we set a different error code if we find a negative key */ 414 /* we set a different error code if we find a negative key */
@@ -430,7 +435,7 @@ ascend:
430 continue; 435 continue;
431 436
432 if (!key_task_permission(make_key_ref(key, possessed), 437 if (!key_task_permission(make_key_ref(key, possessed),
433 context, KEY_SEARCH)) 438 context, KEY_SEARCH) < 0)
434 continue; 439 continue;
435 440
436 /* stack the current position */ 441 /* stack the current position */
@@ -521,7 +526,7 @@ key_ref_t __keyring_search_one(key_ref_t keyring_ref,
521 (!key->type->match || 526 (!key->type->match ||
522 key->type->match(key, description)) && 527 key->type->match(key, description)) &&
523 key_permission(make_key_ref(key, possessed), 528 key_permission(make_key_ref(key, possessed),
524 perm) && 529 perm) < 0 &&
525 !test_bit(KEY_FLAG_REVOKED, &key->flags) 530 !test_bit(KEY_FLAG_REVOKED, &key->flags)
526 ) 531 )
527 goto found; 532 goto found;
@@ -617,7 +622,7 @@ struct key *find_keyring_by_name(const char *name, key_serial_t bound)
617 continue; 622 continue;
618 623
619 if (!key_permission(make_key_ref(keyring, 0), 624 if (!key_permission(make_key_ref(keyring, 0),
620 KEY_SEARCH)) 625 KEY_SEARCH) < 0)
621 continue; 626 continue;
622 627
623 /* found a potential candidate, but we still need to 628 /* found a potential candidate, but we still need to
diff --git a/security/keys/permission.c b/security/keys/permission.c
index 03db073ba45c..e7f579c0eaf5 100644
--- a/security/keys/permission.c
+++ b/security/keys/permission.c
@@ -10,6 +10,7 @@
10 */ 10 */
11 11
12#include <linux/module.h> 12#include <linux/module.h>
13#include <linux/security.h>
13#include "internal.h" 14#include "internal.h"
14 15
15/*****************************************************************************/ 16/*****************************************************************************/
@@ -63,7 +64,11 @@ use_these_perms:
63 64
64 kperm = kperm & perm & KEY_ALL; 65 kperm = kperm & perm & KEY_ALL;
65 66
66 return kperm == perm; 67 if (kperm != perm)
68 return -EACCES;
69
70 /* let LSM be the final arbiter */
71 return security_key_permission(key_ref, context, perm);
67 72
68} /* end key_task_permission() */ 73} /* end key_task_permission() */
69 74
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c
index d42d2158ce13..566b1cc0118a 100644
--- a/security/keys/process_keys.c
+++ b/security/keys/process_keys.c
@@ -39,7 +39,7 @@ struct key root_user_keyring = {
39 .type = &key_type_keyring, 39 .type = &key_type_keyring,
40 .user = &root_key_user, 40 .user = &root_key_user,
41 .sem = __RWSEM_INITIALIZER(root_user_keyring.sem), 41 .sem = __RWSEM_INITIALIZER(root_user_keyring.sem),
42 .perm = KEY_POS_ALL | KEY_USR_ALL, 42 .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
43 .flags = 1 << KEY_FLAG_INSTANTIATED, 43 .flags = 1 << KEY_FLAG_INSTANTIATED,
44 .description = "_uid.0", 44 .description = "_uid.0",
45#ifdef KEY_DEBUGGING 45#ifdef KEY_DEBUGGING
@@ -54,7 +54,7 @@ struct key root_session_keyring = {
54 .type = &key_type_keyring, 54 .type = &key_type_keyring,
55 .user = &root_key_user, 55 .user = &root_key_user,
56 .sem = __RWSEM_INITIALIZER(root_session_keyring.sem), 56 .sem = __RWSEM_INITIALIZER(root_session_keyring.sem),
57 .perm = KEY_POS_ALL | KEY_USR_ALL, 57 .perm = (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL,
58 .flags = 1 << KEY_FLAG_INSTANTIATED, 58 .flags = 1 << KEY_FLAG_INSTANTIATED,
59 .description = "_uid_ses.0", 59 .description = "_uid_ses.0",
60#ifdef KEY_DEBUGGING 60#ifdef KEY_DEBUGGING
@@ -666,9 +666,8 @@ key_ref_t lookup_user_key(struct task_struct *context, key_serial_t id,
666 goto invalid_key; 666 goto invalid_key;
667 667
668 /* check the permissions */ 668 /* check the permissions */
669 ret = -EACCES; 669 ret = key_task_permission(key_ref, context, perm);
670 670 if (ret < 0)
671 if (!key_task_permission(key_ref, context, perm))
672 goto invalid_key; 671 goto invalid_key;
673 672
674error: 673error: