diff options
author | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-28 14:06:39 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-06-28 14:06:39 -0400 |
commit | f28e71617ddaf2483e3e5c5237103484a303743f (patch) | |
tree | 67627d2d8ddbf6a4449371e9261d796c013b1fa1 /security | |
parent | dc6a78f1af10d28fb8c395034ae1e099b85c05b0 (diff) | |
parent | a39727f212426b9d5f9267b3318a2afaf9922d3b (diff) |
Merge ../linux-2.6/
Conflicts:
drivers/scsi/aacraid/comminit.c
Fixed up by removing the now renamed CONFIG_IOMMU option from
aacraid
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'security')
-rw-r--r-- | security/Kconfig | 20 | ||||
-rw-r--r-- | security/dummy.c | 3 | ||||
-rw-r--r-- | security/keys/internal.h | 3 | ||||
-rw-r--r-- | security/keys/key.c | 57 | ||||
-rw-r--r-- | security/keys/keyctl.c | 61 | ||||
-rw-r--r-- | security/keys/keyring.c | 25 | ||||
-rw-r--r-- | security/keys/proc.c | 7 | ||||
-rw-r--r-- | security/keys/process_keys.c | 24 | ||||
-rw-r--r-- | security/keys/request_key.c | 36 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 2 | ||||
-rw-r--r-- | security/keys/user_defined.c | 25 | ||||
-rw-r--r-- | security/selinux/hooks.c | 56 | ||||
-rw-r--r-- | security/selinux/include/av_perm_to_string.h | 3 | ||||
-rw-r--r-- | security/selinux/include/av_permissions.h | 4 | ||||
-rw-r--r-- | security/selinux/include/objsec.h | 2 |
15 files changed, 247 insertions, 81 deletions
diff --git a/security/Kconfig b/security/Kconfig index 34f593410d57..67785df264e5 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -22,16 +22,22 @@ config KEYS | |||
22 | If you are unsure as to whether this is required, answer N. | 22 | If you are unsure as to whether this is required, answer N. |
23 | 23 | ||
24 | config KEYS_DEBUG_PROC_KEYS | 24 | config KEYS_DEBUG_PROC_KEYS |
25 | bool "Enable the /proc/keys file by which all keys may be viewed" | 25 | bool "Enable the /proc/keys file by which keys may be viewed" |
26 | depends on KEYS | 26 | depends on KEYS |
27 | help | 27 | help |
28 | This option turns on support for the /proc/keys file through which | 28 | This option turns on support for the /proc/keys file - through which |
29 | all the keys on the system can be listed. | 29 | can be listed all the keys on the system that are viewable by the |
30 | reading process. | ||
30 | 31 | ||
31 | This option is a slight security risk in that it makes it possible | 32 | The only keys included in the list are those that grant View |
32 | for anyone to see all the keys on the system. Normally the manager | 33 | permission to the reading process whether or not it possesses them. |
33 | pretends keys that are inaccessible to a process don't exist as far | 34 | Note that LSM security checks are still performed, and may further |
34 | as that process is concerned. | 35 | filter out keys that the current process is not authorised to view. |
36 | |||
37 | Only key attributes are listed here; key payloads are not included in | ||
38 | the resulting table. | ||
39 | |||
40 | If you are unsure as to whether this is required, answer N. | ||
35 | 41 | ||
36 | config SECURITY | 42 | config SECURITY |
37 | bool "Enable different security models" | 43 | bool "Enable different security models" |
diff --git a/security/dummy.c b/security/dummy.c index c3c5493581e2..310fcdf7b749 100644 --- a/security/dummy.c +++ b/security/dummy.c | |||
@@ -870,7 +870,8 @@ static int dummy_setprocattr(struct task_struct *p, char *name, void *value, siz | |||
870 | } | 870 | } |
871 | 871 | ||
872 | #ifdef CONFIG_KEYS | 872 | #ifdef CONFIG_KEYS |
873 | static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx) | 873 | static inline int dummy_key_alloc(struct key *key, struct task_struct *ctx, |
874 | unsigned long flags) | ||
874 | { | 875 | { |
875 | return 0; | 876 | return 0; |
876 | } | 877 | } |
diff --git a/security/keys/internal.h b/security/keys/internal.h index e066e6057955..3c2877f0663e 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -99,7 +99,8 @@ extern int install_process_keyring(struct task_struct *tsk); | |||
99 | extern struct key *request_key_and_link(struct key_type *type, | 99 | extern struct key *request_key_and_link(struct key_type *type, |
100 | const char *description, | 100 | const char *description, |
101 | const char *callout_info, | 101 | const char *callout_info, |
102 | struct key *dest_keyring); | 102 | struct key *dest_keyring, |
103 | unsigned long flags); | ||
103 | 104 | ||
104 | /* | 105 | /* |
105 | * request_key authorisation | 106 | * request_key authorisation |
diff --git a/security/keys/key.c b/security/keys/key.c index 51f851557389..80de8c3e9cc3 100644 --- a/security/keys/key.c +++ b/security/keys/key.c | |||
@@ -11,15 +11,16 @@ | |||
11 | 11 | ||
12 | #include <linux/module.h> | 12 | #include <linux/module.h> |
13 | #include <linux/init.h> | 13 | #include <linux/init.h> |
14 | #include <linux/poison.h> | ||
14 | #include <linux/sched.h> | 15 | #include <linux/sched.h> |
15 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
16 | #include <linux/security.h> | 17 | #include <linux/security.h> |
17 | #include <linux/workqueue.h> | 18 | #include <linux/workqueue.h> |
19 | #include <linux/random.h> | ||
18 | #include <linux/err.h> | 20 | #include <linux/err.h> |
19 | #include "internal.h" | 21 | #include "internal.h" |
20 | 22 | ||
21 | static kmem_cache_t *key_jar; | 23 | static kmem_cache_t *key_jar; |
22 | static key_serial_t key_serial_next = 3; | ||
23 | struct rb_root key_serial_tree; /* tree of keys indexed by serial */ | 24 | struct rb_root key_serial_tree; /* tree of keys indexed by serial */ |
24 | DEFINE_SPINLOCK(key_serial_lock); | 25 | DEFINE_SPINLOCK(key_serial_lock); |
25 | 26 | ||
@@ -169,22 +170,23 @@ static void __init __key_insert_serial(struct key *key) | |||
169 | /*****************************************************************************/ | 170 | /*****************************************************************************/ |
170 | /* | 171 | /* |
171 | * assign a key the next unique serial number | 172 | * assign a key the next unique serial number |
172 | * - we work through all the serial numbers between 2 and 2^31-1 in turn and | 173 | * - these are assigned randomly to avoid security issues through covert |
173 | * then wrap | 174 | * channel problems |
174 | */ | 175 | */ |
175 | static inline void key_alloc_serial(struct key *key) | 176 | static inline void key_alloc_serial(struct key *key) |
176 | { | 177 | { |
177 | struct rb_node *parent, **p; | 178 | struct rb_node *parent, **p; |
178 | struct key *xkey; | 179 | struct key *xkey; |
179 | 180 | ||
180 | spin_lock(&key_serial_lock); | 181 | /* propose a random serial number and look for a hole for it in the |
181 | |||
182 | /* propose a likely serial number and look for a hole for it in the | ||
183 | * serial number tree */ | 182 | * serial number tree */ |
184 | key->serial = key_serial_next; | 183 | do { |
185 | if (key->serial < 3) | 184 | get_random_bytes(&key->serial, sizeof(key->serial)); |
186 | key->serial = 3; | 185 | |
187 | key_serial_next = key->serial + 1; | 186 | key->serial >>= 1; /* negative numbers are not permitted */ |
187 | } while (key->serial < 3); | ||
188 | |||
189 | spin_lock(&key_serial_lock); | ||
188 | 190 | ||
189 | parent = NULL; | 191 | parent = NULL; |
190 | p = &key_serial_tree.rb_node; | 192 | p = &key_serial_tree.rb_node; |
@@ -204,12 +206,11 @@ static inline void key_alloc_serial(struct key *key) | |||
204 | 206 | ||
205 | /* we found a key with the proposed serial number - walk the tree from | 207 | /* we found a key with the proposed serial number - walk the tree from |
206 | * that point looking for the next unused serial number */ | 208 | * that point looking for the next unused serial number */ |
207 | serial_exists: | 209 | serial_exists: |
208 | for (;;) { | 210 | for (;;) { |
209 | key->serial = key_serial_next; | 211 | key->serial++; |
210 | if (key->serial < 2) | 212 | if (key->serial < 2) |
211 | key->serial = 2; | 213 | key->serial = 2; |
212 | key_serial_next = key->serial + 1; | ||
213 | 214 | ||
214 | if (!rb_parent(parent)) | 215 | if (!rb_parent(parent)) |
215 | p = &key_serial_tree.rb_node; | 216 | p = &key_serial_tree.rb_node; |
@@ -228,7 +229,7 @@ static inline void key_alloc_serial(struct key *key) | |||
228 | } | 229 | } |
229 | 230 | ||
230 | /* we've found a suitable hole - arrange for this key to occupy it */ | 231 | /* we've found a suitable hole - arrange for this key to occupy it */ |
231 | insert_here: | 232 | insert_here: |
232 | rb_link_node(&key->serial_node, parent, p); | 233 | rb_link_node(&key->serial_node, parent, p); |
233 | rb_insert_color(&key->serial_node, &key_serial_tree); | 234 | rb_insert_color(&key->serial_node, &key_serial_tree); |
234 | 235 | ||
@@ -248,7 +249,7 @@ static inline void key_alloc_serial(struct key *key) | |||
248 | */ | 249 | */ |
249 | struct key *key_alloc(struct key_type *type, const char *desc, | 250 | struct key *key_alloc(struct key_type *type, const char *desc, |
250 | uid_t uid, gid_t gid, struct task_struct *ctx, | 251 | uid_t uid, gid_t gid, struct task_struct *ctx, |
251 | key_perm_t perm, int not_in_quota) | 252 | key_perm_t perm, unsigned long flags) |
252 | { | 253 | { |
253 | struct key_user *user = NULL; | 254 | struct key_user *user = NULL; |
254 | struct key *key; | 255 | struct key *key; |
@@ -269,12 +270,14 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
269 | 270 | ||
270 | /* check that the user's quota permits allocation of another key and | 271 | /* check that the user's quota permits allocation of another key and |
271 | * its description */ | 272 | * its description */ |
272 | if (!not_in_quota) { | 273 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
273 | spin_lock(&user->lock); | 274 | spin_lock(&user->lock); |
274 | if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || | 275 | if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) { |
275 | user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES | 276 | if (user->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || |
276 | ) | 277 | user->qnbytes + quotalen >= KEYQUOTA_MAX_BYTES |
277 | goto no_quota; | 278 | ) |
279 | goto no_quota; | ||
280 | } | ||
278 | 281 | ||
279 | user->qnkeys++; | 282 | user->qnkeys++; |
280 | user->qnbytes += quotalen; | 283 | user->qnbytes += quotalen; |
@@ -308,7 +311,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
308 | key->payload.data = NULL; | 311 | key->payload.data = NULL; |
309 | key->security = NULL; | 312 | key->security = NULL; |
310 | 313 | ||
311 | if (!not_in_quota) | 314 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) |
312 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; | 315 | key->flags |= 1 << KEY_FLAG_IN_QUOTA; |
313 | 316 | ||
314 | memset(&key->type_data, 0, sizeof(key->type_data)); | 317 | memset(&key->type_data, 0, sizeof(key->type_data)); |
@@ -318,7 +321,7 @@ struct key *key_alloc(struct key_type *type, const char *desc, | |||
318 | #endif | 321 | #endif |
319 | 322 | ||
320 | /* let the security module know about the key */ | 323 | /* let the security module know about the key */ |
321 | ret = security_key_alloc(key, ctx); | 324 | ret = security_key_alloc(key, ctx, flags); |
322 | if (ret < 0) | 325 | if (ret < 0) |
323 | goto security_error; | 326 | goto security_error; |
324 | 327 | ||
@@ -332,7 +335,7 @@ error: | |||
332 | security_error: | 335 | security_error: |
333 | kfree(key->description); | 336 | kfree(key->description); |
334 | kmem_cache_free(key_jar, key); | 337 | kmem_cache_free(key_jar, key); |
335 | if (!not_in_quota) { | 338 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
336 | spin_lock(&user->lock); | 339 | spin_lock(&user->lock); |
337 | user->qnkeys--; | 340 | user->qnkeys--; |
338 | user->qnbytes -= quotalen; | 341 | user->qnbytes -= quotalen; |
@@ -345,7 +348,7 @@ security_error: | |||
345 | no_memory_3: | 348 | no_memory_3: |
346 | kmem_cache_free(key_jar, key); | 349 | kmem_cache_free(key_jar, key); |
347 | no_memory_2: | 350 | no_memory_2: |
348 | if (!not_in_quota) { | 351 | if (!(flags & KEY_ALLOC_NOT_IN_QUOTA)) { |
349 | spin_lock(&user->lock); | 352 | spin_lock(&user->lock); |
350 | user->qnkeys--; | 353 | user->qnkeys--; |
351 | user->qnbytes -= quotalen; | 354 | user->qnbytes -= quotalen; |
@@ -761,7 +764,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
761 | const char *description, | 764 | const char *description, |
762 | const void *payload, | 765 | const void *payload, |
763 | size_t plen, | 766 | size_t plen, |
764 | int not_in_quota) | 767 | unsigned long flags) |
765 | { | 768 | { |
766 | struct key_type *ktype; | 769 | struct key_type *ktype; |
767 | struct key *keyring, *key = NULL; | 770 | struct key *keyring, *key = NULL; |
@@ -822,7 +825,7 @@ key_ref_t key_create_or_update(key_ref_t keyring_ref, | |||
822 | 825 | ||
823 | /* allocate a new key */ | 826 | /* allocate a new key */ |
824 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, | 827 | key = key_alloc(ktype, description, current->fsuid, current->fsgid, |
825 | current, perm, not_in_quota); | 828 | current, perm, flags); |
826 | if (IS_ERR(key)) { | 829 | if (IS_ERR(key)) { |
827 | key_ref = ERR_PTR(PTR_ERR(key)); | 830 | key_ref = ERR_PTR(PTR_ERR(key)); |
828 | goto error_3; | 831 | goto error_3; |
@@ -986,7 +989,7 @@ void unregister_key_type(struct key_type *ktype) | |||
986 | if (key->type == ktype) { | 989 | if (key->type == ktype) { |
987 | if (ktype->destroy) | 990 | if (ktype->destroy) |
988 | ktype->destroy(key); | 991 | ktype->destroy(key); |
989 | memset(&key->payload, 0xbd, sizeof(key->payload)); | 992 | memset(&key->payload, KEY_DESTROY, sizeof(key->payload)); |
990 | } | 993 | } |
991 | } | 994 | } |
992 | 995 | ||
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index ed71d86d2ce2..329411cf8768 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -102,7 +102,7 @@ asmlinkage long sys_add_key(const char __user *_type, | |||
102 | /* create or update the requested key and add it to the target | 102 | /* create or update the requested key and add it to the target |
103 | * keyring */ | 103 | * keyring */ |
104 | key_ref = key_create_or_update(keyring_ref, type, description, | 104 | key_ref = key_create_or_update(keyring_ref, type, description, |
105 | payload, plen, 0); | 105 | payload, plen, KEY_ALLOC_IN_QUOTA); |
106 | if (!IS_ERR(key_ref)) { | 106 | if (!IS_ERR(key_ref)) { |
107 | ret = key_ref_to_ptr(key_ref)->serial; | 107 | ret = key_ref_to_ptr(key_ref)->serial; |
108 | key_ref_put(key_ref); | 108 | key_ref_put(key_ref); |
@@ -184,7 +184,8 @@ asmlinkage long sys_request_key(const char __user *_type, | |||
184 | 184 | ||
185 | /* do the search */ | 185 | /* do the search */ |
186 | key = request_key_and_link(ktype, description, callout_info, | 186 | key = request_key_and_link(ktype, description, callout_info, |
187 | key_ref_to_ptr(dest_ref)); | 187 | key_ref_to_ptr(dest_ref), |
188 | KEY_ALLOC_IN_QUOTA); | ||
188 | if (IS_ERR(key)) { | 189 | if (IS_ERR(key)) { |
189 | ret = PTR_ERR(key); | 190 | ret = PTR_ERR(key); |
190 | goto error5; | 191 | goto error5; |
@@ -672,6 +673,7 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) | |||
672 | */ | 673 | */ |
673 | long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | 674 | long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) |
674 | { | 675 | { |
676 | struct key_user *newowner, *zapowner = NULL; | ||
675 | struct key *key; | 677 | struct key *key; |
676 | key_ref_t key_ref; | 678 | key_ref_t key_ref; |
677 | long ret; | 679 | long ret; |
@@ -695,19 +697,50 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
695 | if (!capable(CAP_SYS_ADMIN)) { | 697 | if (!capable(CAP_SYS_ADMIN)) { |
696 | /* only the sysadmin can chown a key to some other UID */ | 698 | /* only the sysadmin can chown a key to some other UID */ |
697 | if (uid != (uid_t) -1 && key->uid != uid) | 699 | if (uid != (uid_t) -1 && key->uid != uid) |
698 | goto no_access; | 700 | goto error_put; |
699 | 701 | ||
700 | /* only the sysadmin can set the key's GID to a group other | 702 | /* only the sysadmin can set the key's GID to a group other |
701 | * than one of those that the current process subscribes to */ | 703 | * than one of those that the current process subscribes to */ |
702 | if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid)) | 704 | if (gid != (gid_t) -1 && gid != key->gid && !in_group_p(gid)) |
703 | goto no_access; | 705 | goto error_put; |
704 | } | 706 | } |
705 | 707 | ||
706 | /* change the UID (have to update the quotas) */ | 708 | /* change the UID */ |
707 | if (uid != (uid_t) -1 && uid != key->uid) { | 709 | if (uid != (uid_t) -1 && uid != key->uid) { |
708 | /* don't support UID changing yet */ | 710 | ret = -ENOMEM; |
709 | ret = -EOPNOTSUPP; | 711 | newowner = key_user_lookup(uid); |
710 | goto no_access; | 712 | if (!newowner) |
713 | goto error_put; | ||
714 | |||
715 | /* transfer the quota burden to the new user */ | ||
716 | if (test_bit(KEY_FLAG_IN_QUOTA, &key->flags)) { | ||
717 | spin_lock(&newowner->lock); | ||
718 | if (newowner->qnkeys + 1 >= KEYQUOTA_MAX_KEYS || | ||
719 | newowner->qnbytes + key->quotalen >= | ||
720 | KEYQUOTA_MAX_BYTES) | ||
721 | goto quota_overrun; | ||
722 | |||
723 | newowner->qnkeys++; | ||
724 | newowner->qnbytes += key->quotalen; | ||
725 | spin_unlock(&newowner->lock); | ||
726 | |||
727 | spin_lock(&key->user->lock); | ||
728 | key->user->qnkeys--; | ||
729 | key->user->qnbytes -= key->quotalen; | ||
730 | spin_unlock(&key->user->lock); | ||
731 | } | ||
732 | |||
733 | atomic_dec(&key->user->nkeys); | ||
734 | atomic_inc(&newowner->nkeys); | ||
735 | |||
736 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | ||
737 | atomic_dec(&key->user->nikeys); | ||
738 | atomic_inc(&newowner->nikeys); | ||
739 | } | ||
740 | |||
741 | zapowner = key->user; | ||
742 | key->user = newowner; | ||
743 | key->uid = uid; | ||
711 | } | 744 | } |
712 | 745 | ||
713 | /* change the GID */ | 746 | /* change the GID */ |
@@ -716,12 +749,20 @@ long keyctl_chown_key(key_serial_t id, uid_t uid, gid_t gid) | |||
716 | 749 | ||
717 | ret = 0; | 750 | ret = 0; |
718 | 751 | ||
719 | no_access: | 752 | error_put: |
720 | up_write(&key->sem); | 753 | up_write(&key->sem); |
721 | key_put(key); | 754 | key_put(key); |
722 | error: | 755 | if (zapowner) |
756 | key_user_put(zapowner); | ||
757 | error: | ||
723 | return ret; | 758 | return ret; |
724 | 759 | ||
760 | quota_overrun: | ||
761 | spin_unlock(&newowner->lock); | ||
762 | zapowner = newowner; | ||
763 | ret = -EDQUOT; | ||
764 | goto error_put; | ||
765 | |||
725 | } /* end keyctl_chown_key() */ | 766 | } /* end keyctl_chown_key() */ |
726 | 767 | ||
727 | /*****************************************************************************/ | 768 | /*****************************************************************************/ |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index 1357207fc9df..e8d02acc51e7 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -49,6 +49,7 @@ static inline unsigned keyring_hash(const char *desc) | |||
49 | static int keyring_instantiate(struct key *keyring, | 49 | static int keyring_instantiate(struct key *keyring, |
50 | const void *data, size_t datalen); | 50 | const void *data, size_t datalen); |
51 | static int keyring_match(const struct key *keyring, const void *criterion); | 51 | static int keyring_match(const struct key *keyring, const void *criterion); |
52 | static void keyring_revoke(struct key *keyring); | ||
52 | static void keyring_destroy(struct key *keyring); | 53 | static void keyring_destroy(struct key *keyring); |
53 | static void keyring_describe(const struct key *keyring, struct seq_file *m); | 54 | static void keyring_describe(const struct key *keyring, struct seq_file *m); |
54 | static long keyring_read(const struct key *keyring, | 55 | static long keyring_read(const struct key *keyring, |
@@ -59,6 +60,7 @@ struct key_type key_type_keyring = { | |||
59 | .def_datalen = sizeof(struct keyring_list), | 60 | .def_datalen = sizeof(struct keyring_list), |
60 | .instantiate = keyring_instantiate, | 61 | .instantiate = keyring_instantiate, |
61 | .match = keyring_match, | 62 | .match = keyring_match, |
63 | .revoke = keyring_revoke, | ||
62 | .destroy = keyring_destroy, | 64 | .destroy = keyring_destroy, |
63 | .describe = keyring_describe, | 65 | .describe = keyring_describe, |
64 | .read = keyring_read, | 66 | .read = keyring_read, |
@@ -240,7 +242,7 @@ static long keyring_read(const struct key *keyring, | |||
240 | * allocate a keyring and link into the destination keyring | 242 | * allocate a keyring and link into the destination keyring |
241 | */ | 243 | */ |
242 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | 244 | struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, |
243 | struct task_struct *ctx, int not_in_quota, | 245 | struct task_struct *ctx, unsigned long flags, |
244 | struct key *dest) | 246 | struct key *dest) |
245 | { | 247 | { |
246 | struct key *keyring; | 248 | struct key *keyring; |
@@ -249,7 +251,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
249 | keyring = key_alloc(&key_type_keyring, description, | 251 | keyring = key_alloc(&key_type_keyring, description, |
250 | uid, gid, ctx, | 252 | uid, gid, ctx, |
251 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, | 253 | (KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_ALL, |
252 | not_in_quota); | 254 | flags); |
253 | 255 | ||
254 | if (!IS_ERR(keyring)) { | 256 | if (!IS_ERR(keyring)) { |
255 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); | 257 | ret = key_instantiate_and_link(keyring, NULL, 0, dest, NULL); |
@@ -953,3 +955,22 @@ int keyring_clear(struct key *keyring) | |||
953 | } /* end keyring_clear() */ | 955 | } /* end keyring_clear() */ |
954 | 956 | ||
955 | EXPORT_SYMBOL(keyring_clear); | 957 | EXPORT_SYMBOL(keyring_clear); |
958 | |||
959 | /*****************************************************************************/ | ||
960 | /* | ||
961 | * dispose of the links from a revoked keyring | ||
962 | * - called with the key sem write-locked | ||
963 | */ | ||
964 | static void keyring_revoke(struct key *keyring) | ||
965 | { | ||
966 | struct keyring_list *klist = keyring->payload.subscriptions; | ||
967 | |||
968 | /* adjust the quota */ | ||
969 | key_payload_reserve(keyring, 0); | ||
970 | |||
971 | if (klist) { | ||
972 | rcu_assign_pointer(keyring->payload.subscriptions, NULL); | ||
973 | call_rcu(&klist->rcu, keyring_clear_rcu_disposal); | ||
974 | } | ||
975 | |||
976 | } /* end keyring_revoke() */ | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 12b750e51fbf..686a9ee0c5de 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -137,6 +137,13 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
137 | struct timespec now; | 137 | struct timespec now; |
138 | unsigned long timo; | 138 | unsigned long timo; |
139 | char xbuf[12]; | 139 | char xbuf[12]; |
140 | int rc; | ||
141 | |||
142 | /* check whether the current task is allowed to view the key (assuming | ||
143 | * non-possession) */ | ||
144 | rc = key_task_permission(make_key_ref(key, 0), current, KEY_VIEW); | ||
145 | if (rc < 0) | ||
146 | return 0; | ||
140 | 147 | ||
141 | now = current_kernel_time(); | 148 | now = current_kernel_time(); |
142 | 149 | ||
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 4d9825f9962c..32150cf7c37f 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -77,7 +77,8 @@ int alloc_uid_keyring(struct user_struct *user, | |||
77 | /* concoct a default session keyring */ | 77 | /* concoct a default session keyring */ |
78 | sprintf(buf, "_uid_ses.%u", user->uid); | 78 | sprintf(buf, "_uid_ses.%u", user->uid); |
79 | 79 | ||
80 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, NULL); | 80 | session_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, |
81 | KEY_ALLOC_IN_QUOTA, NULL); | ||
81 | if (IS_ERR(session_keyring)) { | 82 | if (IS_ERR(session_keyring)) { |
82 | ret = PTR_ERR(session_keyring); | 83 | ret = PTR_ERR(session_keyring); |
83 | goto error; | 84 | goto error; |
@@ -87,8 +88,8 @@ int alloc_uid_keyring(struct user_struct *user, | |||
87 | * keyring */ | 88 | * keyring */ |
88 | sprintf(buf, "_uid.%u", user->uid); | 89 | sprintf(buf, "_uid.%u", user->uid); |
89 | 90 | ||
90 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, 0, | 91 | uid_keyring = keyring_alloc(buf, user->uid, (gid_t) -1, ctx, |
91 | session_keyring); | 92 | KEY_ALLOC_IN_QUOTA, session_keyring); |
92 | if (IS_ERR(uid_keyring)) { | 93 | if (IS_ERR(uid_keyring)) { |
93 | key_put(session_keyring); | 94 | key_put(session_keyring); |
94 | ret = PTR_ERR(uid_keyring); | 95 | ret = PTR_ERR(uid_keyring); |
@@ -144,7 +145,8 @@ int install_thread_keyring(struct task_struct *tsk) | |||
144 | 145 | ||
145 | sprintf(buf, "_tid.%u", tsk->pid); | 146 | sprintf(buf, "_tid.%u", tsk->pid); |
146 | 147 | ||
147 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); | 148 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, |
149 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
148 | if (IS_ERR(keyring)) { | 150 | if (IS_ERR(keyring)) { |
149 | ret = PTR_ERR(keyring); | 151 | ret = PTR_ERR(keyring); |
150 | goto error; | 152 | goto error; |
@@ -178,7 +180,8 @@ int install_process_keyring(struct task_struct *tsk) | |||
178 | if (!tsk->signal->process_keyring) { | 180 | if (!tsk->signal->process_keyring) { |
179 | sprintf(buf, "_pid.%u", tsk->tgid); | 181 | sprintf(buf, "_pid.%u", tsk->tgid); |
180 | 182 | ||
181 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); | 183 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, |
184 | KEY_ALLOC_QUOTA_OVERRUN, NULL); | ||
182 | if (IS_ERR(keyring)) { | 185 | if (IS_ERR(keyring)) { |
183 | ret = PTR_ERR(keyring); | 186 | ret = PTR_ERR(keyring); |
184 | goto error; | 187 | goto error; |
@@ -209,6 +212,7 @@ error: | |||
209 | static int install_session_keyring(struct task_struct *tsk, | 212 | static int install_session_keyring(struct task_struct *tsk, |
210 | struct key *keyring) | 213 | struct key *keyring) |
211 | { | 214 | { |
215 | unsigned long flags; | ||
212 | struct key *old; | 216 | struct key *old; |
213 | char buf[20]; | 217 | char buf[20]; |
214 | 218 | ||
@@ -218,7 +222,12 @@ static int install_session_keyring(struct task_struct *tsk, | |||
218 | if (!keyring) { | 222 | if (!keyring) { |
219 | sprintf(buf, "_ses.%u", tsk->tgid); | 223 | sprintf(buf, "_ses.%u", tsk->tgid); |
220 | 224 | ||
221 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, 1, NULL); | 225 | flags = KEY_ALLOC_QUOTA_OVERRUN; |
226 | if (tsk->signal->session_keyring) | ||
227 | flags = KEY_ALLOC_IN_QUOTA; | ||
228 | |||
229 | keyring = keyring_alloc(buf, tsk->uid, tsk->gid, tsk, | ||
230 | flags, NULL); | ||
222 | if (IS_ERR(keyring)) | 231 | if (IS_ERR(keyring)) |
223 | return PTR_ERR(keyring); | 232 | return PTR_ERR(keyring); |
224 | } | 233 | } |
@@ -728,7 +737,8 @@ long join_session_keyring(const char *name) | |||
728 | keyring = find_keyring_by_name(name, 0); | 737 | keyring = find_keyring_by_name(name, 0); |
729 | if (PTR_ERR(keyring) == -ENOKEY) { | 738 | if (PTR_ERR(keyring) == -ENOKEY) { |
730 | /* not found - try and create a new one */ | 739 | /* not found - try and create a new one */ |
731 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, 0, NULL); | 740 | keyring = keyring_alloc(name, tsk->uid, tsk->gid, tsk, |
741 | KEY_ALLOC_IN_QUOTA, NULL); | ||
732 | if (IS_ERR(keyring)) { | 742 | if (IS_ERR(keyring)) { |
733 | ret = PTR_ERR(keyring); | 743 | ret = PTR_ERR(keyring); |
734 | goto error2; | 744 | goto error2; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index eab66a06ca53..58d1efd4fc2c 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -48,8 +48,8 @@ static int call_sbin_request_key(struct key *key, | |||
48 | /* allocate a new session keyring */ | 48 | /* allocate a new session keyring */ |
49 | sprintf(desc, "_req.%u", key->serial); | 49 | sprintf(desc, "_req.%u", key->serial); |
50 | 50 | ||
51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, | 51 | keyring = keyring_alloc(desc, current->fsuid, current->fsgid, current, |
52 | current, 1, NULL); | 52 | KEY_ALLOC_QUOTA_OVERRUN, NULL); |
53 | if (IS_ERR(keyring)) { | 53 | if (IS_ERR(keyring)) { |
54 | ret = PTR_ERR(keyring); | 54 | ret = PTR_ERR(keyring); |
55 | goto error_alloc; | 55 | goto error_alloc; |
@@ -126,7 +126,8 @@ error_alloc: | |||
126 | */ | 126 | */ |
127 | static struct key *__request_key_construction(struct key_type *type, | 127 | static struct key *__request_key_construction(struct key_type *type, |
128 | const char *description, | 128 | const char *description, |
129 | const char *callout_info) | 129 | const char *callout_info, |
130 | unsigned long flags) | ||
130 | { | 131 | { |
131 | request_key_actor_t actor; | 132 | request_key_actor_t actor; |
132 | struct key_construction cons; | 133 | struct key_construction cons; |
@@ -134,12 +135,12 @@ static struct key *__request_key_construction(struct key_type *type, | |||
134 | struct key *key, *authkey; | 135 | struct key *key, *authkey; |
135 | int ret, negated; | 136 | int ret, negated; |
136 | 137 | ||
137 | kenter("%s,%s,%s", type->name, description, callout_info); | 138 | kenter("%s,%s,%s,%lx", type->name, description, callout_info, flags); |
138 | 139 | ||
139 | /* create a key and add it to the queue */ | 140 | /* create a key and add it to the queue */ |
140 | key = key_alloc(type, description, | 141 | key = key_alloc(type, description, |
141 | current->fsuid, current->fsgid, | 142 | current->fsuid, current->fsgid, current, KEY_POS_ALL, |
142 | current, KEY_POS_ALL, 0); | 143 | flags); |
143 | if (IS_ERR(key)) | 144 | if (IS_ERR(key)) |
144 | goto alloc_failed; | 145 | goto alloc_failed; |
145 | 146 | ||
@@ -258,15 +259,16 @@ alloc_failed: | |||
258 | static struct key *request_key_construction(struct key_type *type, | 259 | static struct key *request_key_construction(struct key_type *type, |
259 | const char *description, | 260 | const char *description, |
260 | struct key_user *user, | 261 | struct key_user *user, |
261 | const char *callout_info) | 262 | const char *callout_info, |
263 | unsigned long flags) | ||
262 | { | 264 | { |
263 | struct key_construction *pcons; | 265 | struct key_construction *pcons; |
264 | struct key *key, *ckey; | 266 | struct key *key, *ckey; |
265 | 267 | ||
266 | DECLARE_WAITQUEUE(myself, current); | 268 | DECLARE_WAITQUEUE(myself, current); |
267 | 269 | ||
268 | kenter("%s,%s,{%d},%s", | 270 | kenter("%s,%s,{%d},%s,%lx", |
269 | type->name, description, user->uid, callout_info); | 271 | type->name, description, user->uid, callout_info, flags); |
270 | 272 | ||
271 | /* see if there's such a key under construction already */ | 273 | /* see if there's such a key under construction already */ |
272 | down_write(&key_construction_sem); | 274 | down_write(&key_construction_sem); |
@@ -282,7 +284,8 @@ static struct key *request_key_construction(struct key_type *type, | |||
282 | } | 284 | } |
283 | 285 | ||
284 | /* see about getting userspace to construct the key */ | 286 | /* see about getting userspace to construct the key */ |
285 | key = __request_key_construction(type, description, callout_info); | 287 | key = __request_key_construction(type, description, callout_info, |
288 | flags); | ||
286 | error: | 289 | error: |
287 | kleave(" = %p", key); | 290 | kleave(" = %p", key); |
288 | return key; | 291 | return key; |
@@ -389,14 +392,15 @@ static void request_key_link(struct key *key, struct key *dest_keyring) | |||
389 | struct key *request_key_and_link(struct key_type *type, | 392 | struct key *request_key_and_link(struct key_type *type, |
390 | const char *description, | 393 | const char *description, |
391 | const char *callout_info, | 394 | const char *callout_info, |
392 | struct key *dest_keyring) | 395 | struct key *dest_keyring, |
396 | unsigned long flags) | ||
393 | { | 397 | { |
394 | struct key_user *user; | 398 | struct key_user *user; |
395 | struct key *key; | 399 | struct key *key; |
396 | key_ref_t key_ref; | 400 | key_ref_t key_ref; |
397 | 401 | ||
398 | kenter("%s,%s,%s,%p", | 402 | kenter("%s,%s,%s,%p,%lx", |
399 | type->name, description, callout_info, dest_keyring); | 403 | type->name, description, callout_info, dest_keyring, flags); |
400 | 404 | ||
401 | /* search all the process keyrings for a key */ | 405 | /* search all the process keyrings for a key */ |
402 | key_ref = search_process_keyrings(type, description, type->match, | 406 | key_ref = search_process_keyrings(type, description, type->match, |
@@ -429,7 +433,8 @@ struct key *request_key_and_link(struct key_type *type, | |||
429 | /* ask userspace (returns NULL if it waited on a key | 433 | /* ask userspace (returns NULL if it waited on a key |
430 | * being constructed) */ | 434 | * being constructed) */ |
431 | key = request_key_construction(type, description, | 435 | key = request_key_construction(type, description, |
432 | user, callout_info); | 436 | user, callout_info, |
437 | flags); | ||
433 | if (key) | 438 | if (key) |
434 | break; | 439 | break; |
435 | 440 | ||
@@ -485,7 +490,8 @@ struct key *request_key(struct key_type *type, | |||
485 | const char *description, | 490 | const char *description, |
486 | const char *callout_info) | 491 | const char *callout_info) |
487 | { | 492 | { |
488 | return request_key_and_link(type, description, callout_info, NULL); | 493 | return request_key_and_link(type, description, callout_info, NULL, |
494 | KEY_ALLOC_IN_QUOTA); | ||
489 | 495 | ||
490 | } /* end request_key() */ | 496 | } /* end request_key() */ |
491 | 497 | ||
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index cb9817ced3fd..cbf58a91b00a 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -187,7 +187,7 @@ struct key *request_key_auth_new(struct key *target, const char *callout_info) | |||
187 | authkey = key_alloc(&key_type_request_key_auth, desc, | 187 | authkey = key_alloc(&key_type_request_key_auth, desc, |
188 | current->fsuid, current->fsgid, current, | 188 | current->fsuid, current->fsgid, current, |
189 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | | 189 | KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | |
190 | KEY_USR_VIEW, 1); | 190 | KEY_USR_VIEW, KEY_ALLOC_NOT_IN_QUOTA); |
191 | if (IS_ERR(authkey)) { | 191 | if (IS_ERR(authkey)) { |
192 | ret = PTR_ERR(authkey); | 192 | ret = PTR_ERR(authkey); |
193 | goto error_alloc; | 193 | goto error_alloc; |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index 8e71895b97a7..5bbfdebb7acf 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -28,6 +28,7 @@ struct key_type key_type_user = { | |||
28 | .instantiate = user_instantiate, | 28 | .instantiate = user_instantiate, |
29 | .update = user_update, | 29 | .update = user_update, |
30 | .match = user_match, | 30 | .match = user_match, |
31 | .revoke = user_revoke, | ||
31 | .destroy = user_destroy, | 32 | .destroy = user_destroy, |
32 | .describe = user_describe, | 33 | .describe = user_describe, |
33 | .read = user_read, | 34 | .read = user_read, |
@@ -67,6 +68,7 @@ error: | |||
67 | return ret; | 68 | return ret; |
68 | 69 | ||
69 | } /* end user_instantiate() */ | 70 | } /* end user_instantiate() */ |
71 | |||
70 | EXPORT_SYMBOL_GPL(user_instantiate); | 72 | EXPORT_SYMBOL_GPL(user_instantiate); |
71 | 73 | ||
72 | /*****************************************************************************/ | 74 | /*****************************************************************************/ |
@@ -141,7 +143,28 @@ EXPORT_SYMBOL_GPL(user_match); | |||
141 | 143 | ||
142 | /*****************************************************************************/ | 144 | /*****************************************************************************/ |
143 | /* | 145 | /* |
144 | * dispose of the data dangling from the corpse of a user | 146 | * dispose of the links from a revoked keyring |
147 | * - called with the key sem write-locked | ||
148 | */ | ||
149 | void user_revoke(struct key *key) | ||
150 | { | ||
151 | struct user_key_payload *upayload = key->payload.data; | ||
152 | |||
153 | /* clear the quota */ | ||
154 | key_payload_reserve(key, 0); | ||
155 | |||
156 | if (upayload) { | ||
157 | rcu_assign_pointer(key->payload.data, NULL); | ||
158 | call_rcu(&upayload->rcu, user_update_rcu_disposal); | ||
159 | } | ||
160 | |||
161 | } /* end user_revoke() */ | ||
162 | |||
163 | EXPORT_SYMBOL(user_revoke); | ||
164 | |||
165 | /*****************************************************************************/ | ||
166 | /* | ||
167 | * dispose of the data dangling from the corpse of a user key | ||
145 | */ | 168 | */ |
146 | void user_destroy(struct key *key) | 169 | void user_destroy(struct key *key) |
147 | { | 170 | { |
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 79c16e31c884..28832e689800 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c | |||
@@ -1099,6 +1099,17 @@ static int may_create(struct inode *dir, | |||
1099 | FILESYSTEM__ASSOCIATE, &ad); | 1099 | FILESYSTEM__ASSOCIATE, &ad); |
1100 | } | 1100 | } |
1101 | 1101 | ||
1102 | /* Check whether a task can create a key. */ | ||
1103 | static int may_create_key(u32 ksid, | ||
1104 | struct task_struct *ctx) | ||
1105 | { | ||
1106 | struct task_security_struct *tsec; | ||
1107 | |||
1108 | tsec = ctx->security; | ||
1109 | |||
1110 | return avc_has_perm(tsec->sid, ksid, SECCLASS_KEY, KEY__CREATE, NULL); | ||
1111 | } | ||
1112 | |||
1102 | #define MAY_LINK 0 | 1113 | #define MAY_LINK 0 |
1103 | #define MAY_UNLINK 1 | 1114 | #define MAY_UNLINK 1 |
1104 | #define MAY_RMDIR 2 | 1115 | #define MAY_RMDIR 2 |
@@ -1521,8 +1532,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) | |||
1521 | /* Default to the current task SID. */ | 1532 | /* Default to the current task SID. */ |
1522 | bsec->sid = tsec->sid; | 1533 | bsec->sid = tsec->sid; |
1523 | 1534 | ||
1524 | /* Reset create SID on execve. */ | 1535 | /* Reset fs, key, and sock SIDs on execve. */ |
1525 | tsec->create_sid = 0; | 1536 | tsec->create_sid = 0; |
1537 | tsec->keycreate_sid = 0; | ||
1538 | tsec->sockcreate_sid = 0; | ||
1526 | 1539 | ||
1527 | if (tsec->exec_sid) { | 1540 | if (tsec->exec_sid) { |
1528 | newsid = tsec->exec_sid; | 1541 | newsid = tsec->exec_sid; |
@@ -2574,9 +2587,11 @@ static int selinux_task_alloc_security(struct task_struct *tsk) | |||
2574 | tsec2->osid = tsec1->osid; | 2587 | tsec2->osid = tsec1->osid; |
2575 | tsec2->sid = tsec1->sid; | 2588 | tsec2->sid = tsec1->sid; |
2576 | 2589 | ||
2577 | /* Retain the exec and create SIDs across fork */ | 2590 | /* Retain the exec, fs, key, and sock SIDs across fork */ |
2578 | tsec2->exec_sid = tsec1->exec_sid; | 2591 | tsec2->exec_sid = tsec1->exec_sid; |
2579 | tsec2->create_sid = tsec1->create_sid; | 2592 | tsec2->create_sid = tsec1->create_sid; |
2593 | tsec2->keycreate_sid = tsec1->keycreate_sid; | ||
2594 | tsec2->sockcreate_sid = tsec1->sockcreate_sid; | ||
2580 | 2595 | ||
2581 | /* Retain ptracer SID across fork, if any. | 2596 | /* Retain ptracer SID across fork, if any. |
2582 | This will be reset by the ptrace hook upon any | 2597 | This will be reset by the ptrace hook upon any |
@@ -2926,12 +2941,14 @@ static int selinux_socket_create(int family, int type, | |||
2926 | { | 2941 | { |
2927 | int err = 0; | 2942 | int err = 0; |
2928 | struct task_security_struct *tsec; | 2943 | struct task_security_struct *tsec; |
2944 | u32 newsid; | ||
2929 | 2945 | ||
2930 | if (kern) | 2946 | if (kern) |
2931 | goto out; | 2947 | goto out; |
2932 | 2948 | ||
2933 | tsec = current->security; | 2949 | tsec = current->security; |
2934 | err = avc_has_perm(tsec->sid, tsec->sid, | 2950 | newsid = tsec->sockcreate_sid ? : tsec->sid; |
2951 | err = avc_has_perm(tsec->sid, newsid, | ||
2935 | socket_type_to_security_class(family, type, | 2952 | socket_type_to_security_class(family, type, |
2936 | protocol), SOCKET__CREATE, NULL); | 2953 | protocol), SOCKET__CREATE, NULL); |
2937 | 2954 | ||
@@ -2944,12 +2961,14 @@ static void selinux_socket_post_create(struct socket *sock, int family, | |||
2944 | { | 2961 | { |
2945 | struct inode_security_struct *isec; | 2962 | struct inode_security_struct *isec; |
2946 | struct task_security_struct *tsec; | 2963 | struct task_security_struct *tsec; |
2964 | u32 newsid; | ||
2947 | 2965 | ||
2948 | isec = SOCK_INODE(sock)->i_security; | 2966 | isec = SOCK_INODE(sock)->i_security; |
2949 | 2967 | ||
2950 | tsec = current->security; | 2968 | tsec = current->security; |
2969 | newsid = tsec->sockcreate_sid ? : tsec->sid; | ||
2951 | isec->sclass = socket_type_to_security_class(family, type, protocol); | 2970 | isec->sclass = socket_type_to_security_class(family, type, protocol); |
2952 | isec->sid = kern ? SECINITSID_KERNEL : tsec->sid; | 2971 | isec->sid = kern ? SECINITSID_KERNEL : newsid; |
2953 | isec->initialized = 1; | 2972 | isec->initialized = 1; |
2954 | 2973 | ||
2955 | return; | 2974 | return; |
@@ -4150,6 +4169,10 @@ static int selinux_getprocattr(struct task_struct *p, | |||
4150 | sid = tsec->exec_sid; | 4169 | sid = tsec->exec_sid; |
4151 | else if (!strcmp(name, "fscreate")) | 4170 | else if (!strcmp(name, "fscreate")) |
4152 | sid = tsec->create_sid; | 4171 | sid = tsec->create_sid; |
4172 | else if (!strcmp(name, "keycreate")) | ||
4173 | sid = tsec->keycreate_sid; | ||
4174 | else if (!strcmp(name, "sockcreate")) | ||
4175 | sid = tsec->sockcreate_sid; | ||
4153 | else | 4176 | else |
4154 | return -EINVAL; | 4177 | return -EINVAL; |
4155 | 4178 | ||
@@ -4182,6 +4205,10 @@ static int selinux_setprocattr(struct task_struct *p, | |||
4182 | error = task_has_perm(current, p, PROCESS__SETEXEC); | 4205 | error = task_has_perm(current, p, PROCESS__SETEXEC); |
4183 | else if (!strcmp(name, "fscreate")) | 4206 | else if (!strcmp(name, "fscreate")) |
4184 | error = task_has_perm(current, p, PROCESS__SETFSCREATE); | 4207 | error = task_has_perm(current, p, PROCESS__SETFSCREATE); |
4208 | else if (!strcmp(name, "keycreate")) | ||
4209 | error = task_has_perm(current, p, PROCESS__SETKEYCREATE); | ||
4210 | else if (!strcmp(name, "sockcreate")) | ||
4211 | error = task_has_perm(current, p, PROCESS__SETSOCKCREATE); | ||
4185 | else if (!strcmp(name, "current")) | 4212 | else if (!strcmp(name, "current")) |
4186 | error = task_has_perm(current, p, PROCESS__SETCURRENT); | 4213 | error = task_has_perm(current, p, PROCESS__SETCURRENT); |
4187 | else | 4214 | else |
@@ -4211,6 +4238,13 @@ static int selinux_setprocattr(struct task_struct *p, | |||
4211 | tsec->exec_sid = sid; | 4238 | tsec->exec_sid = sid; |
4212 | else if (!strcmp(name, "fscreate")) | 4239 | else if (!strcmp(name, "fscreate")) |
4213 | tsec->create_sid = sid; | 4240 | tsec->create_sid = sid; |
4241 | else if (!strcmp(name, "keycreate")) { | ||
4242 | error = may_create_key(sid, p); | ||
4243 | if (error) | ||
4244 | return error; | ||
4245 | tsec->keycreate_sid = sid; | ||
4246 | } else if (!strcmp(name, "sockcreate")) | ||
4247 | tsec->sockcreate_sid = sid; | ||
4214 | else if (!strcmp(name, "current")) { | 4248 | else if (!strcmp(name, "current")) { |
4215 | struct av_decision avd; | 4249 | struct av_decision avd; |
4216 | 4250 | ||
@@ -4264,7 +4298,8 @@ static int selinux_setprocattr(struct task_struct *p, | |||
4264 | 4298 | ||
4265 | #ifdef CONFIG_KEYS | 4299 | #ifdef CONFIG_KEYS |
4266 | 4300 | ||
4267 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk) | 4301 | static int selinux_key_alloc(struct key *k, struct task_struct *tsk, |
4302 | unsigned long flags) | ||
4268 | { | 4303 | { |
4269 | struct task_security_struct *tsec = tsk->security; | 4304 | struct task_security_struct *tsec = tsk->security; |
4270 | struct key_security_struct *ksec; | 4305 | struct key_security_struct *ksec; |
@@ -4274,7 +4309,10 @@ static int selinux_key_alloc(struct key *k, struct task_struct *tsk) | |||
4274 | return -ENOMEM; | 4309 | return -ENOMEM; |
4275 | 4310 | ||
4276 | ksec->obj = k; | 4311 | ksec->obj = k; |
4277 | ksec->sid = tsec->sid; | 4312 | if (tsec->keycreate_sid) |
4313 | ksec->sid = tsec->keycreate_sid; | ||
4314 | else | ||
4315 | ksec->sid = tsec->sid; | ||
4278 | k->security = ksec; | 4316 | k->security = ksec; |
4279 | 4317 | ||
4280 | return 0; | 4318 | return 0; |
@@ -4513,8 +4551,10 @@ static __init int selinux_init(void) | |||
4513 | 4551 | ||
4514 | #ifdef CONFIG_KEYS | 4552 | #ifdef CONFIG_KEYS |
4515 | /* Add security information to initial keyrings */ | 4553 | /* Add security information to initial keyrings */ |
4516 | security_key_alloc(&root_user_keyring, current); | 4554 | selinux_key_alloc(&root_user_keyring, current, |
4517 | security_key_alloc(&root_session_keyring, current); | 4555 | KEY_ALLOC_NOT_IN_QUOTA); |
4556 | selinux_key_alloc(&root_session_keyring, current, | ||
4557 | KEY_ALLOC_NOT_IN_QUOTA); | ||
4518 | #endif | 4558 | #endif |
4519 | 4559 | ||
4520 | return 0; | 4560 | return 0; |
diff --git a/security/selinux/include/av_perm_to_string.h b/security/selinux/include/av_perm_to_string.h index bc020bde6c86..7c9b58380833 100644 --- a/security/selinux/include/av_perm_to_string.h +++ b/security/selinux/include/av_perm_to_string.h | |||
@@ -72,6 +72,8 @@ | |||
72 | S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") | 72 | S_(SECCLASS_PROCESS, PROCESS__EXECMEM, "execmem") |
73 | S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") | 73 | S_(SECCLASS_PROCESS, PROCESS__EXECSTACK, "execstack") |
74 | S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") | 74 | S_(SECCLASS_PROCESS, PROCESS__EXECHEAP, "execheap") |
75 | S_(SECCLASS_PROCESS, PROCESS__SETKEYCREATE, "setkeycreate") | ||
76 | S_(SECCLASS_PROCESS, PROCESS__SETSOCKCREATE, "setsockcreate") | ||
75 | S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") | 77 | S_(SECCLASS_MSGQ, MSGQ__ENQUEUE, "enqueue") |
76 | S_(SECCLASS_MSG, MSG__SEND, "send") | 78 | S_(SECCLASS_MSG, MSG__SEND, "send") |
77 | S_(SECCLASS_MSG, MSG__RECEIVE, "receive") | 79 | S_(SECCLASS_MSG, MSG__RECEIVE, "receive") |
@@ -248,3 +250,4 @@ | |||
248 | S_(SECCLASS_KEY, KEY__SEARCH, "search") | 250 | S_(SECCLASS_KEY, KEY__SEARCH, "search") |
249 | S_(SECCLASS_KEY, KEY__LINK, "link") | 251 | S_(SECCLASS_KEY, KEY__LINK, "link") |
250 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") | 252 | S_(SECCLASS_KEY, KEY__SETATTR, "setattr") |
253 | S_(SECCLASS_KEY, KEY__CREATE, "create") | ||
diff --git a/security/selinux/include/av_permissions.h b/security/selinux/include/av_permissions.h index 1205227a3a33..69fd4b48202c 100644 --- a/security/selinux/include/av_permissions.h +++ b/security/selinux/include/av_permissions.h | |||
@@ -467,6 +467,8 @@ | |||
467 | #define PROCESS__EXECMEM 0x02000000UL | 467 | #define PROCESS__EXECMEM 0x02000000UL |
468 | #define PROCESS__EXECSTACK 0x04000000UL | 468 | #define PROCESS__EXECSTACK 0x04000000UL |
469 | #define PROCESS__EXECHEAP 0x08000000UL | 469 | #define PROCESS__EXECHEAP 0x08000000UL |
470 | #define PROCESS__SETKEYCREATE 0x10000000UL | ||
471 | #define PROCESS__SETSOCKCREATE 0x20000000UL | ||
470 | 472 | ||
471 | #define IPC__CREATE 0x00000001UL | 473 | #define IPC__CREATE 0x00000001UL |
472 | #define IPC__DESTROY 0x00000002UL | 474 | #define IPC__DESTROY 0x00000002UL |
@@ -966,4 +968,4 @@ | |||
966 | #define KEY__SEARCH 0x00000008UL | 968 | #define KEY__SEARCH 0x00000008UL |
967 | #define KEY__LINK 0x00000010UL | 969 | #define KEY__LINK 0x00000010UL |
968 | #define KEY__SETATTR 0x00000020UL | 970 | #define KEY__SETATTR 0x00000020UL |
969 | 971 | #define KEY__CREATE 0x00000040UL | |
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h index 8f5547ad1856..cf54a304169a 100644 --- a/security/selinux/include/objsec.h +++ b/security/selinux/include/objsec.h | |||
@@ -32,6 +32,8 @@ struct task_security_struct { | |||
32 | u32 sid; /* current SID */ | 32 | u32 sid; /* current SID */ |
33 | u32 exec_sid; /* exec SID */ | 33 | u32 exec_sid; /* exec SID */ |
34 | u32 create_sid; /* fscreate SID */ | 34 | u32 create_sid; /* fscreate SID */ |
35 | u32 keycreate_sid; /* keycreate SID */ | ||
36 | u32 sockcreate_sid; /* fscreate SID */ | ||
35 | u32 ptrace_sid; /* SID of ptrace parent */ | 37 | u32 ptrace_sid; /* SID of ptrace parent */ |
36 | }; | 38 | }; |
37 | 39 | ||