diff options
-rw-r--r-- | Documentation/keys.txt | 22 | ||||
-rw-r--r-- | include/linux/key-ui.h | 3 | ||||
-rw-r--r-- | include/linux/key.h | 13 | ||||
-rw-r--r-- | include/linux/security.h | 73 | ||||
-rw-r--r-- | security/dummy.c | 23 | ||||
-rw-r--r-- | security/keys/key.c | 56 | ||||
-rw-r--r-- | security/keys/keyctl.c | 13 | ||||
-rw-r--r-- | security/keys/keyring.c | 21 | ||||
-rw-r--r-- | security/keys/permission.c | 7 | ||||
-rw-r--r-- | security/keys/process_keys.c | 9 |
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 | ||
197 | Keys have an owner user ID, a group access ID, and a permissions mask. The mask | 197 | Keys have an owner user ID, a group access ID, and a permissions mask. The mask |
198 | has up to eight bits each for possessor, user, group and other access. Only | 198 | has up to eight bits each for possessor, user, group and other access. Only |
199 | five of each set of eight bits are defined. These permissions granted are: | 199 | six 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 | |||
227 | For changing the ownership, group ID or permissions mask, being the owner of | 231 | For changing the ownership, group ID or permissions mask, being the owner of |
228 | the key or having the sysadmin capability is sufficient. | 232 | the 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 | ||
66 | struct seq_file; | 70 | struct seq_file; |
67 | struct user_struct; | 71 | struct 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 | ||
34 | struct ctl_table; | 35 | struct 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 | ||
2802 | static inline int security_key_alloc(struct key *key) | ||
2803 | { | ||
2804 | return security_ops->key_alloc(key); | ||
2805 | } | ||
2806 | |||
2807 | static inline void security_key_free(struct key *key) | ||
2808 | { | ||
2809 | security_ops->key_free(key); | ||
2810 | } | ||
2811 | |||
2812 | static 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 | |||
2821 | static inline int security_key_alloc(struct key *key) | ||
2822 | { | ||
2823 | return 0; | ||
2824 | } | ||
2825 | |||
2826 | static inline void security_key_free(struct key *key) | ||
2827 | { | ||
2828 | } | ||
2829 | |||
2830 | static 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 | ||
807 | static inline int dummy_key_alloc(struct key *key) | ||
808 | { | ||
809 | return 0; | ||
810 | } | ||
811 | |||
812 | static inline void dummy_key_free(struct key *key) | ||
813 | { | ||
814 | } | ||
815 | |||
816 | static 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 | ||
807 | struct security_operations dummy_security_ops; | 824 | struct 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: | 330 | error: |
323 | return key; | 331 | return key; |
324 | 332 | ||
325 | no_memory_3: | 333 | security_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 | |||
346 | no_memory_3: | ||
326 | kmem_cache_free(key_jar, key); | 347 | kmem_cache_free(key_jar, key); |
327 | no_memory_2: | 348 | no_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: | 356 | no_memory_1: |
336 | key = ERR_PTR(-ENOMEM); | 357 | key = ERR_PTR(-ENOMEM); |
337 | goto error; | 358 | goto error; |
338 | 359 | ||
339 | no_quota: | 360 | no_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 | ||
674 | error: | 673 | error: |