aboutsummaryrefslogtreecommitdiffstats
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
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>
-rw-r--r--Documentation/keys.txt22
-rw-r--r--include/linux/key-ui.h3
-rw-r--r--include/linux/key.h13
-rw-r--r--include/linux/security.h73
-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
10 files changed, 191 insertions, 49 deletions
diff --git a/Documentation/keys.txt b/Documentation/keys.txt
index 4afe03a58c5b..31154882000a 100644
--- a/Documentation/keys.txt
+++ b/Documentation/keys.txt
@@ -196,7 +196,7 @@ KEY ACCESS PERMISSIONS
196 196
197Keys have an owner user ID, a group access ID, and a permissions mask. The mask 197Keys have an owner user ID, a group access ID, and a permissions mask. The mask
198has up to eight bits each for possessor, user, group and other access. Only 198has up to eight bits each for possessor, user, group and other access. Only
199five of each set of eight bits are defined. These permissions granted are: 199six of each set of eight bits are defined. These permissions granted are:
200 200
201 (*) View 201 (*) View
202 202
@@ -224,6 +224,10 @@ five of each set of eight bits are defined. These permissions granted are:
224 keyring to a key, a process must have Write permission on the keyring and 224 keyring to a key, a process must have Write permission on the keyring and
225 Link permission on the key. 225 Link permission on the key.
226 226
227 (*) Set Attribute
228
229 This permits a key's UID, GID and permissions mask to be changed.
230
227For changing the ownership, group ID or permissions mask, being the owner of 231For changing the ownership, group ID or permissions mask, being the owner of
228the key or having the sysadmin capability is sufficient. 232the key or having the sysadmin capability is sufficient.
229 233
@@ -242,15 +246,15 @@ about the status of the key service:
242 this way: 246 this way:
243 247
244 SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY 248 SERIAL FLAGS USAGE EXPY PERM UID GID TYPE DESCRIPTION: SUMMARY
245 00000001 I----- 39 perm 1f1f0000 0 0 keyring _uid_ses.0: 1/4 249 00000001 I----- 39 perm 1f3f0000 0 0 keyring _uid_ses.0: 1/4
246 00000002 I----- 2 perm 1f1f0000 0 0 keyring _uid.0: empty 250 00000002 I----- 2 perm 1f3f0000 0 0 keyring _uid.0: empty
247 00000007 I----- 1 perm 1f1f0000 0 0 keyring _pid.1: empty 251 00000007 I----- 1 perm 1f3f0000 0 0 keyring _pid.1: empty
248 0000018d I----- 1 perm 1f1f0000 0 0 keyring _pid.412: empty 252 0000018d I----- 1 perm 1f3f0000 0 0 keyring _pid.412: empty
249 000004d2 I--Q-- 1 perm 1f1f0000 32 -1 keyring _uid.32: 1/4 253 000004d2 I--Q-- 1 perm 1f3f0000 32 -1 keyring _uid.32: 1/4
250 000004d3 I--Q-- 3 perm 1f1f0000 32 -1 keyring _uid_ses.32: empty 254 000004d3 I--Q-- 3 perm 1f3f0000 32 -1 keyring _uid_ses.32: empty
251 00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0 255 00000892 I--QU- 1 perm 1f000000 0 0 user metal:copper: 0
252 00000893 I--Q-N 1 35s 1f1f0000 0 0 user metal:silver: 0 256 00000893 I--Q-N 1 35s 1f3f0000 0 0 user metal:silver: 0
253 00000894 I--Q-- 1 10h 001f0000 0 0 user metal:gold: 0 257 00000894 I--Q-- 1 10h 003f0000 0 0 user metal:gold: 0
254 258
255 The flags are: 259 The flags are:
256 260
diff --git a/include/linux/key-ui.h b/include/linux/key-ui.h
index 7a2e332067c3..e8b8a7a5c496 100644
--- a/include/linux/key-ui.h
+++ b/include/linux/key-ui.h
@@ -24,7 +24,8 @@ extern spinlock_t key_serial_lock;
24#define KEY_WRITE 0x04 /* require permission to update / modify */ 24#define KEY_WRITE 0x04 /* require permission to update / modify */
25#define KEY_SEARCH 0x08 /* require permission to search (keyring) or find (key) */ 25#define KEY_SEARCH 0x08 /* require permission to search (keyring) or find (key) */
26#define KEY_LINK 0x10 /* require permission to link */ 26#define KEY_LINK 0x10 /* require permission to link */
27#define KEY_ALL 0x1f /* all the above permissions */ 27#define KEY_SETATTR 0x20 /* require permission to change attributes */
28#define KEY_ALL 0x3f /* all the above permissions */
28 29
29/* 30/*
30 * the keyring payload contains a list of the keys to which the keyring is 31 * the keyring payload contains a list of the keys to which the keyring is
diff --git a/include/linux/key.h b/include/linux/key.h
index f1efa016dbf3..53513a3be53b 100644
--- a/include/linux/key.h
+++ b/include/linux/key.h
@@ -40,28 +40,32 @@ struct key;
40#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */ 40#define KEY_POS_WRITE 0x04000000 /* possessor can update key payload / add link to keyring */
41#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */ 41#define KEY_POS_SEARCH 0x08000000 /* possessor can find a key in search / search a keyring */
42#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */ 42#define KEY_POS_LINK 0x10000000 /* possessor can create a link to a key/keyring */
43#define KEY_POS_ALL 0x1f000000 43#define KEY_POS_SETATTR 0x20000000 /* possessor can set key attributes */
44#define KEY_POS_ALL 0x3f000000
44 45
45#define KEY_USR_VIEW 0x00010000 /* user permissions... */ 46#define KEY_USR_VIEW 0x00010000 /* user permissions... */
46#define KEY_USR_READ 0x00020000 47#define KEY_USR_READ 0x00020000
47#define KEY_USR_WRITE 0x00040000 48#define KEY_USR_WRITE 0x00040000
48#define KEY_USR_SEARCH 0x00080000 49#define KEY_USR_SEARCH 0x00080000
49#define KEY_USR_LINK 0x00100000 50#define KEY_USR_LINK 0x00100000
50#define KEY_USR_ALL 0x001f0000 51#define KEY_USR_SETATTR 0x00200000
52#define KEY_USR_ALL 0x003f0000
51 53
52#define KEY_GRP_VIEW 0x00000100 /* group permissions... */ 54#define KEY_GRP_VIEW 0x00000100 /* group permissions... */
53#define KEY_GRP_READ 0x00000200 55#define KEY_GRP_READ 0x00000200
54#define KEY_GRP_WRITE 0x00000400 56#define KEY_GRP_WRITE 0x00000400
55#define KEY_GRP_SEARCH 0x00000800 57#define KEY_GRP_SEARCH 0x00000800
56#define KEY_GRP_LINK 0x00001000 58#define KEY_GRP_LINK 0x00001000
57#define KEY_GRP_ALL 0x00001f00 59#define KEY_GRP_SETATTR 0x00002000
60#define KEY_GRP_ALL 0x00003f00
58 61
59#define KEY_OTH_VIEW 0x00000001 /* third party permissions... */ 62#define KEY_OTH_VIEW 0x00000001 /* third party permissions... */
60#define KEY_OTH_READ 0x00000002 63#define KEY_OTH_READ 0x00000002
61#define KEY_OTH_WRITE 0x00000004 64#define KEY_OTH_WRITE 0x00000004
62#define KEY_OTH_SEARCH 0x00000008 65#define KEY_OTH_SEARCH 0x00000008
63#define KEY_OTH_LINK 0x00000010 66#define KEY_OTH_LINK 0x00000010
64#define KEY_OTH_ALL 0x0000001f 67#define KEY_OTH_SETATTR 0x00000020
68#define KEY_OTH_ALL 0x0000003f
65 69
66struct seq_file; 70struct seq_file;
67struct user_struct; 71struct user_struct;
@@ -119,6 +123,7 @@ struct key {
119 struct key_type *type; /* type of key */ 123 struct key_type *type; /* type of key */
120 struct rw_semaphore sem; /* change vs change sem */ 124 struct rw_semaphore sem; /* change vs change sem */
121 struct key_user *user; /* owner of this key */ 125 struct key_user *user; /* owner of this key */
126 void *security; /* security data for this key */
122 time_t expiry; /* time at which key expires (or 0) */ 127 time_t expiry; /* time at which key expires (or 0) */
123 uid_t uid; 128 uid_t uid;
124 gid_t gid; 129 gid_t gid;
diff --git a/include/linux/security.h b/include/linux/security.h
index 607ee209ea3b..f7e0ae018712 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -30,6 +30,7 @@
30#include <linux/shm.h> 30#include <linux/shm.h>
31#include <linux/msg.h> 31#include <linux/msg.h>
32#include <linux/sched.h> 32#include <linux/sched.h>
33#include <linux/key.h>
33 34
34struct ctl_table; 35struct ctl_table;
35 36
@@ -788,6 +789,27 @@ struct swap_info_struct;
788 * @sk_free_security: 789 * @sk_free_security:
789 * Deallocate security structure. 790 * Deallocate security structure.
790 * 791 *
792 * Security hooks affecting all Key Management operations
793 *
794 * @key_alloc:
795 * Permit allocation of a key and assign security data. Note that key does
796 * not have a serial number assigned at this point.
797 * @key points to the key.
798 * Return 0 if permission is granted, -ve error otherwise.
799 * @key_free:
800 * Notification of destruction; free security data.
801 * @key points to the key.
802 * No return value.
803 * @key_permission:
804 * See whether a specific operational right is granted to a process on a
805 * key.
806 * @key_ref refers to the key (key pointer + possession attribute bit).
807 * @context points to the process to provide the context against which to
808 * evaluate the security data on the key.
809 * @perm describes the combination of permissions required of this key.
810 * Return 1 if permission granted, 0 if permission denied and -ve it the
811 * normal permissions model should be effected.
812 *
791 * Security hooks affecting all System V IPC operations. 813 * Security hooks affecting all System V IPC operations.
792 * 814 *
793 * @ipc_permission: 815 * @ipc_permission:
@@ -1216,6 +1238,17 @@ struct security_operations {
1216 int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority); 1238 int (*sk_alloc_security) (struct sock *sk, int family, gfp_t priority);
1217 void (*sk_free_security) (struct sock *sk); 1239 void (*sk_free_security) (struct sock *sk);
1218#endif /* CONFIG_SECURITY_NETWORK */ 1240#endif /* CONFIG_SECURITY_NETWORK */
1241
1242 /* key management security hooks */
1243#ifdef CONFIG_KEYS
1244 int (*key_alloc)(struct key *key);
1245 void (*key_free)(struct key *key);
1246 int (*key_permission)(key_ref_t key_ref,
1247 struct task_struct *context,
1248 key_perm_t perm);
1249
1250#endif /* CONFIG_KEYS */
1251
1219}; 1252};
1220 1253
1221/* global variables */ 1254/* global variables */
@@ -2764,5 +2797,45 @@ static inline void security_sk_free(struct sock *sk)
2764} 2797}
2765#endif /* CONFIG_SECURITY_NETWORK */ 2798#endif /* CONFIG_SECURITY_NETWORK */
2766 2799
2800#ifdef CONFIG_KEYS
2801#ifdef CONFIG_SECURITY
2802static inline int security_key_alloc(struct key *key)
2803{
2804 return security_ops->key_alloc(key);
2805}
2806
2807static inline void security_key_free(struct key *key)
2808{
2809 security_ops->key_free(key);
2810}
2811
2812static inline int security_key_permission(key_ref_t key_ref,
2813 struct task_struct *context,
2814 key_perm_t perm)
2815{
2816 return security_ops->key_permission(key_ref, context, perm);
2817}
2818
2819#else
2820
2821static inline int security_key_alloc(struct key *key)
2822{
2823 return 0;
2824}
2825
2826static inline void security_key_free(struct key *key)
2827{
2828}
2829
2830static inline int security_key_permission(key_ref_t key_ref,
2831 struct task_struct *context,
2832 key_perm_t perm)
2833{
2834 return 0;
2835}
2836
2837#endif
2838#endif /* CONFIG_KEYS */
2839
2767#endif /* ! __LINUX_SECURITY_H */ 2840#endif /* ! __LINUX_SECURITY_H */
2768 2841
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: