diff options
author | James Morris <jmorris@namei.org> | 2011-05-24 08:55:24 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2011-05-24 08:55:24 -0400 |
commit | 434d42cfd05a7cc452457a81d2029540cba12150 (patch) | |
tree | 3a6b9b7f9ff2e1b7409dd66c15242b2a75aa4422 | |
parent | d762f4383100c2a87b1a3f2d678cd3b5425655b4 (diff) | |
parent | 12a5a2621b1ee14d32beca35304d7c6076a58815 (diff) |
Merge branch 'next' into for-linus
-rw-r--r-- | fs/binfmt_flat.c | 8 | ||||
-rw-r--r-- | include/linux/capability.h | 5 | ||||
-rw-r--r-- | include/linux/init_task.h | 7 | ||||
-rw-r--r-- | include/linux/key.h | 13 | ||||
-rw-r--r-- | include/linux/kmod.h | 3 | ||||
-rw-r--r-- | kernel/capability.c | 4 | ||||
-rw-r--r-- | kernel/cred.c | 6 | ||||
-rw-r--r-- | kernel/kmod.c | 100 | ||||
-rw-r--r-- | kernel/sysctl.c | 6 | ||||
-rw-r--r-- | net/dns_resolver/dns_key.c | 10 | ||||
-rw-r--r-- | security/Kconfig | 1 | ||||
-rw-r--r-- | security/commoncap.c | 13 | ||||
-rw-r--r-- | security/keys/internal.h | 4 | ||||
-rw-r--r-- | security/keys/keyctl.c | 6 | ||||
-rw-r--r-- | security/keys/keyring.c | 37 | ||||
-rw-r--r-- | security/keys/proc.c | 2 | ||||
-rw-r--r-- | security/keys/process_keys.c | 12 | ||||
-rw-r--r-- | security/keys/request_key.c | 3 | ||||
-rw-r--r-- | security/keys/request_key_auth.c | 3 | ||||
-rw-r--r-- | security/keys/user_defined.c | 4 | ||||
-rw-r--r-- | security/tomoyo/common.c | 17 | ||||
-rw-r--r-- | security/tomoyo/file.c | 1 | ||||
-rw-r--r-- | security/tomoyo/memory.c | 1 | ||||
-rw-r--r-- | security/tomoyo/mount.c | 1 | ||||
-rw-r--r-- | security/tomoyo/util.c | 2 |
25 files changed, 205 insertions, 64 deletions
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c index 397d3057d336..1bffbe0ed778 100644 --- a/fs/binfmt_flat.c +++ b/fs/binfmt_flat.c | |||
@@ -820,6 +820,8 @@ static int load_flat_shared_library(int id, struct lib_info *libs) | |||
820 | int res; | 820 | int res; |
821 | char buf[16]; | 821 | char buf[16]; |
822 | 822 | ||
823 | memset(&bprm, 0, sizeof(bprm)); | ||
824 | |||
823 | /* Create the file name */ | 825 | /* Create the file name */ |
824 | sprintf(buf, "/lib/lib%d.so", id); | 826 | sprintf(buf, "/lib/lib%d.so", id); |
825 | 827 | ||
@@ -835,6 +837,12 @@ static int load_flat_shared_library(int id, struct lib_info *libs) | |||
835 | if (!bprm.cred) | 837 | if (!bprm.cred) |
836 | goto out; | 838 | goto out; |
837 | 839 | ||
840 | /* We don't really care about recalculating credentials at this point | ||
841 | * as we're past the point of no return and are dealing with shared | ||
842 | * libraries. | ||
843 | */ | ||
844 | bprm.cred_prepared = 1; | ||
845 | |||
838 | res = prepare_binprm(&bprm); | 846 | res = prepare_binprm(&bprm); |
839 | 847 | ||
840 | if (!IS_ERR_VALUE(res)) | 848 | if (!IS_ERR_VALUE(res)) |
diff --git a/include/linux/capability.h b/include/linux/capability.h index 4554db0cde86..c42112350003 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h | |||
@@ -417,7 +417,6 @@ extern const kernel_cap_t __cap_init_eff_set; | |||
417 | 417 | ||
418 | # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) | 418 | # define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }}) |
419 | # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) | 419 | # define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }}) |
420 | # define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }}) | ||
421 | # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ | 420 | # define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \ |
422 | | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ | 421 | | CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \ |
423 | CAP_FS_MASK_B1 } }) | 422 | CAP_FS_MASK_B1 } }) |
@@ -427,11 +426,7 @@ extern const kernel_cap_t __cap_init_eff_set; | |||
427 | 426 | ||
428 | #endif /* _KERNEL_CAPABILITY_U32S != 2 */ | 427 | #endif /* _KERNEL_CAPABILITY_U32S != 2 */ |
429 | 428 | ||
430 | #define CAP_INIT_INH_SET CAP_EMPTY_SET | ||
431 | |||
432 | # define cap_clear(c) do { (c) = __cap_empty_set; } while (0) | 429 | # define cap_clear(c) do { (c) = __cap_empty_set; } while (0) |
433 | # define cap_set_full(c) do { (c) = __cap_full_set; } while (0) | ||
434 | # define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0) | ||
435 | 430 | ||
436 | #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) | 431 | #define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag)) |
437 | #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) | 432 | #define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag)) |
diff --git a/include/linux/init_task.h b/include/linux/init_task.h index 689496bb6654..bafc58c00fc3 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h | |||
@@ -83,13 +83,6 @@ extern struct group_info init_groups; | |||
83 | #define INIT_IDS | 83 | #define INIT_IDS |
84 | #endif | 84 | #endif |
85 | 85 | ||
86 | /* | ||
87 | * Because of the reduced scope of CAP_SETPCAP when filesystem | ||
88 | * capabilities are in effect, it is safe to allow CAP_SETPCAP to | ||
89 | * be available in the default configuration. | ||
90 | */ | ||
91 | # define CAP_INIT_BSET CAP_FULL_SET | ||
92 | |||
93 | #ifdef CONFIG_RCU_BOOST | 86 | #ifdef CONFIG_RCU_BOOST |
94 | #define INIT_TASK_RCU_BOOST() \ | 87 | #define INIT_TASK_RCU_BOOST() \ |
95 | .rcu_boost_mutex = NULL, | 88 | .rcu_boost_mutex = NULL, |
diff --git a/include/linux/key.h b/include/linux/key.h index b2bb01719561..ef19b99aff98 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key) | |||
276 | return key ? key->serial : 0; | 276 | return key ? key->serial : 0; |
277 | } | 277 | } |
278 | 278 | ||
279 | /** | ||
280 | * key_is_instantiated - Determine if a key has been positively instantiated | ||
281 | * @key: The key to check. | ||
282 | * | ||
283 | * Return true if the specified key has been positively instantiated, false | ||
284 | * otherwise. | ||
285 | */ | ||
286 | static inline bool key_is_instantiated(const struct key *key) | ||
287 | { | ||
288 | return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && | ||
289 | !test_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
290 | } | ||
291 | |||
279 | #define rcu_dereference_key(KEY) \ | 292 | #define rcu_dereference_key(KEY) \ |
280 | (rcu_dereference_protected((KEY)->payload.rcudata, \ | 293 | (rcu_dereference_protected((KEY)->payload.rcudata, \ |
281 | rwsem_is_locked(&((struct key *)(KEY))->sem))) | 294 | rwsem_is_locked(&((struct key *)(KEY))->sem))) |
diff --git a/include/linux/kmod.h b/include/linux/kmod.h index 310231823852..d4a5c84c503d 100644 --- a/include/linux/kmod.h +++ b/include/linux/kmod.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/errno.h> | 24 | #include <linux/errno.h> |
25 | #include <linux/compiler.h> | 25 | #include <linux/compiler.h> |
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/sysctl.h> | ||
27 | 28 | ||
28 | #define KMOD_PATH_LEN 256 | 29 | #define KMOD_PATH_LEN 256 |
29 | 30 | ||
@@ -109,6 +110,8 @@ call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait) | |||
109 | NULL, NULL, NULL); | 110 | NULL, NULL, NULL); |
110 | } | 111 | } |
111 | 112 | ||
113 | extern struct ctl_table usermodehelper_table[]; | ||
114 | |||
112 | extern void usermodehelper_init(void); | 115 | extern void usermodehelper_init(void); |
113 | 116 | ||
114 | extern int usermodehelper_disable(void); | 117 | extern int usermodehelper_disable(void); |
diff --git a/kernel/capability.c b/kernel/capability.c index 32a80e08ff4b..283c529f8b1c 100644 --- a/kernel/capability.c +++ b/kernel/capability.c | |||
@@ -22,12 +22,8 @@ | |||
22 | */ | 22 | */ |
23 | 23 | ||
24 | const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; | 24 | const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET; |
25 | const kernel_cap_t __cap_full_set = CAP_FULL_SET; | ||
26 | const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET; | ||
27 | 25 | ||
28 | EXPORT_SYMBOL(__cap_empty_set); | 26 | EXPORT_SYMBOL(__cap_empty_set); |
29 | EXPORT_SYMBOL(__cap_full_set); | ||
30 | EXPORT_SYMBOL(__cap_init_eff_set); | ||
31 | 27 | ||
32 | int file_caps_enabled = 1; | 28 | int file_caps_enabled = 1; |
33 | 29 | ||
diff --git a/kernel/cred.c b/kernel/cred.c index 8093c16b84b1..e12c8af793f8 100644 --- a/kernel/cred.c +++ b/kernel/cred.c | |||
@@ -49,10 +49,10 @@ struct cred init_cred = { | |||
49 | .magic = CRED_MAGIC, | 49 | .magic = CRED_MAGIC, |
50 | #endif | 50 | #endif |
51 | .securebits = SECUREBITS_DEFAULT, | 51 | .securebits = SECUREBITS_DEFAULT, |
52 | .cap_inheritable = CAP_INIT_INH_SET, | 52 | .cap_inheritable = CAP_EMPTY_SET, |
53 | .cap_permitted = CAP_FULL_SET, | 53 | .cap_permitted = CAP_FULL_SET, |
54 | .cap_effective = CAP_INIT_EFF_SET, | 54 | .cap_effective = CAP_FULL_SET, |
55 | .cap_bset = CAP_INIT_BSET, | 55 | .cap_bset = CAP_FULL_SET, |
56 | .user = INIT_USER, | 56 | .user = INIT_USER, |
57 | .user_ns = &init_user_ns, | 57 | .user_ns = &init_user_ns, |
58 | .group_info = &init_groups, | 58 | .group_info = &init_groups, |
diff --git a/kernel/kmod.c b/kernel/kmod.c index 5ae0ff38425f..ad6a81c58b44 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/kmod.h> | 25 | #include <linux/kmod.h> |
26 | #include <linux/slab.h> | 26 | #include <linux/slab.h> |
27 | #include <linux/completion.h> | 27 | #include <linux/completion.h> |
28 | #include <linux/cred.h> | ||
28 | #include <linux/file.h> | 29 | #include <linux/file.h> |
29 | #include <linux/fdtable.h> | 30 | #include <linux/fdtable.h> |
30 | #include <linux/workqueue.h> | 31 | #include <linux/workqueue.h> |
@@ -43,6 +44,13 @@ extern int max_threads; | |||
43 | 44 | ||
44 | static struct workqueue_struct *khelper_wq; | 45 | static struct workqueue_struct *khelper_wq; |
45 | 46 | ||
47 | #define CAP_BSET (void *)1 | ||
48 | #define CAP_PI (void *)2 | ||
49 | |||
50 | static kernel_cap_t usermodehelper_bset = CAP_FULL_SET; | ||
51 | static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET; | ||
52 | static DEFINE_SPINLOCK(umh_sysctl_lock); | ||
53 | |||
46 | #ifdef CONFIG_MODULES | 54 | #ifdef CONFIG_MODULES |
47 | 55 | ||
48 | /* | 56 | /* |
@@ -132,6 +140,7 @@ EXPORT_SYMBOL(__request_module); | |||
132 | static int ____call_usermodehelper(void *data) | 140 | static int ____call_usermodehelper(void *data) |
133 | { | 141 | { |
134 | struct subprocess_info *sub_info = data; | 142 | struct subprocess_info *sub_info = data; |
143 | struct cred *new; | ||
135 | int retval; | 144 | int retval; |
136 | 145 | ||
137 | spin_lock_irq(¤t->sighand->siglock); | 146 | spin_lock_irq(¤t->sighand->siglock); |
@@ -153,6 +162,19 @@ static int ____call_usermodehelper(void *data) | |||
153 | goto fail; | 162 | goto fail; |
154 | } | 163 | } |
155 | 164 | ||
165 | retval = -ENOMEM; | ||
166 | new = prepare_kernel_cred(current); | ||
167 | if (!new) | ||
168 | goto fail; | ||
169 | |||
170 | spin_lock(&umh_sysctl_lock); | ||
171 | new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset); | ||
172 | new->cap_inheritable = cap_intersect(usermodehelper_inheritable, | ||
173 | new->cap_inheritable); | ||
174 | spin_unlock(&umh_sysctl_lock); | ||
175 | |||
176 | commit_creds(new); | ||
177 | |||
156 | retval = kernel_execve(sub_info->path, | 178 | retval = kernel_execve(sub_info->path, |
157 | (const char *const *)sub_info->argv, | 179 | (const char *const *)sub_info->argv, |
158 | (const char *const *)sub_info->envp); | 180 | (const char *const *)sub_info->envp); |
@@ -420,6 +442,84 @@ unlock: | |||
420 | } | 442 | } |
421 | EXPORT_SYMBOL(call_usermodehelper_exec); | 443 | EXPORT_SYMBOL(call_usermodehelper_exec); |
422 | 444 | ||
445 | static int proc_cap_handler(struct ctl_table *table, int write, | ||
446 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
447 | { | ||
448 | struct ctl_table t; | ||
449 | unsigned long cap_array[_KERNEL_CAPABILITY_U32S]; | ||
450 | kernel_cap_t new_cap; | ||
451 | int err, i; | ||
452 | |||
453 | if (write && (!capable(CAP_SETPCAP) || | ||
454 | !capable(CAP_SYS_MODULE))) | ||
455 | return -EPERM; | ||
456 | |||
457 | /* | ||
458 | * convert from the global kernel_cap_t to the ulong array to print to | ||
459 | * userspace if this is a read. | ||
460 | */ | ||
461 | spin_lock(&umh_sysctl_lock); | ||
462 | for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) { | ||
463 | if (table->data == CAP_BSET) | ||
464 | cap_array[i] = usermodehelper_bset.cap[i]; | ||
465 | else if (table->data == CAP_PI) | ||
466 | cap_array[i] = usermodehelper_inheritable.cap[i]; | ||
467 | else | ||
468 | BUG(); | ||
469 | } | ||
470 | spin_unlock(&umh_sysctl_lock); | ||
471 | |||
472 | t = *table; | ||
473 | t.data = &cap_array; | ||
474 | |||
475 | /* | ||
476 | * actually read or write and array of ulongs from userspace. Remember | ||
477 | * these are least significant 32 bits first | ||
478 | */ | ||
479 | err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos); | ||
480 | if (err < 0) | ||
481 | return err; | ||
482 | |||
483 | /* | ||
484 | * convert from the sysctl array of ulongs to the kernel_cap_t | ||
485 | * internal representation | ||
486 | */ | ||
487 | for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) | ||
488 | new_cap.cap[i] = cap_array[i]; | ||
489 | |||
490 | /* | ||
491 | * Drop everything not in the new_cap (but don't add things) | ||
492 | */ | ||
493 | spin_lock(&umh_sysctl_lock); | ||
494 | if (write) { | ||
495 | if (table->data == CAP_BSET) | ||
496 | usermodehelper_bset = cap_intersect(usermodehelper_bset, new_cap); | ||
497 | if (table->data == CAP_PI) | ||
498 | usermodehelper_inheritable = cap_intersect(usermodehelper_inheritable, new_cap); | ||
499 | } | ||
500 | spin_unlock(&umh_sysctl_lock); | ||
501 | |||
502 | return 0; | ||
503 | } | ||
504 | |||
505 | struct ctl_table usermodehelper_table[] = { | ||
506 | { | ||
507 | .procname = "bset", | ||
508 | .data = CAP_BSET, | ||
509 | .maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long), | ||
510 | .mode = 0600, | ||
511 | .proc_handler = proc_cap_handler, | ||
512 | }, | ||
513 | { | ||
514 | .procname = "inheritable", | ||
515 | .data = CAP_PI, | ||
516 | .maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long), | ||
517 | .mode = 0600, | ||
518 | .proc_handler = proc_cap_handler, | ||
519 | }, | ||
520 | { } | ||
521 | }; | ||
522 | |||
423 | void __init usermodehelper_init(void) | 523 | void __init usermodehelper_init(void) |
424 | { | 524 | { |
425 | khelper_wq = create_singlethread_workqueue("khelper"); | 525 | khelper_wq = create_singlethread_workqueue("khelper"); |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 3dd0c46fa3bb..4bffd62c2f13 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -56,6 +56,7 @@ | |||
56 | #include <linux/kprobes.h> | 56 | #include <linux/kprobes.h> |
57 | #include <linux/pipe_fs_i.h> | 57 | #include <linux/pipe_fs_i.h> |
58 | #include <linux/oom.h> | 58 | #include <linux/oom.h> |
59 | #include <linux/kmod.h> | ||
59 | 60 | ||
60 | #include <asm/uaccess.h> | 61 | #include <asm/uaccess.h> |
61 | #include <asm/processor.h> | 62 | #include <asm/processor.h> |
@@ -616,6 +617,11 @@ static struct ctl_table kern_table[] = { | |||
616 | .child = random_table, | 617 | .child = random_table, |
617 | }, | 618 | }, |
618 | { | 619 | { |
620 | .procname = "usermodehelper", | ||
621 | .mode = 0555, | ||
622 | .child = usermodehelper_table, | ||
623 | }, | ||
624 | { | ||
619 | .procname = "overflowuid", | 625 | .procname = "overflowuid", |
620 | .data = &overflowuid, | 626 | .data = &overflowuid, |
621 | .maxlen = sizeof(int), | 627 | .maxlen = sizeof(int), |
diff --git a/net/dns_resolver/dns_key.c b/net/dns_resolver/dns_key.c index cfa7a5e1c5c9..fa000d26dc60 100644 --- a/net/dns_resolver/dns_key.c +++ b/net/dns_resolver/dns_key.c | |||
@@ -212,10 +212,12 @@ static void dns_resolver_describe(const struct key *key, struct seq_file *m) | |||
212 | int err = key->type_data.x[0]; | 212 | int err = key->type_data.x[0]; |
213 | 213 | ||
214 | seq_puts(m, key->description); | 214 | seq_puts(m, key->description); |
215 | if (err) | 215 | if (key_is_instantiated(key)) { |
216 | seq_printf(m, ": %d", err); | 216 | if (err) |
217 | else | 217 | seq_printf(m, ": %d", err); |
218 | seq_printf(m, ": %u", key->datalen); | 218 | else |
219 | seq_printf(m, ": %u", key->datalen); | ||
220 | } | ||
219 | } | 221 | } |
220 | 222 | ||
221 | /* | 223 | /* |
diff --git a/security/Kconfig b/security/Kconfig index 95accd442d55..e0f08b52e4ab 100644 --- a/security/Kconfig +++ b/security/Kconfig | |||
@@ -167,6 +167,7 @@ config INTEL_TXT | |||
167 | config LSM_MMAP_MIN_ADDR | 167 | config LSM_MMAP_MIN_ADDR |
168 | int "Low address space for LSM to protect from user allocation" | 168 | int "Low address space for LSM to protect from user allocation" |
169 | depends on SECURITY && SECURITY_SELINUX | 169 | depends on SECURITY && SECURITY_SELINUX |
170 | default 32768 if ARM | ||
170 | default 65536 | 171 | default 65536 |
171 | help | 172 | help |
172 | This is the portion of low virtual memory which should be protected | 173 | This is the portion of low virtual memory which should be protected |
diff --git a/security/commoncap.c b/security/commoncap.c index f20e984ccfb4..a93b3b733079 100644 --- a/security/commoncap.c +++ b/security/commoncap.c | |||
@@ -529,15 +529,10 @@ skip: | |||
529 | new->suid = new->fsuid = new->euid; | 529 | new->suid = new->fsuid = new->euid; |
530 | new->sgid = new->fsgid = new->egid; | 530 | new->sgid = new->fsgid = new->egid; |
531 | 531 | ||
532 | /* For init, we want to retain the capabilities set in the initial | 532 | if (effective) |
533 | * task. Thus we skip the usual capability rules | 533 | new->cap_effective = new->cap_permitted; |
534 | */ | 534 | else |
535 | if (!is_global_init(current)) { | 535 | cap_clear(new->cap_effective); |
536 | if (effective) | ||
537 | new->cap_effective = new->cap_permitted; | ||
538 | else | ||
539 | cap_clear(new->cap_effective); | ||
540 | } | ||
541 | bprm->cap_effective = effective; | 536 | bprm->cap_effective = effective; |
542 | 537 | ||
543 | /* | 538 | /* |
diff --git a/security/keys/internal.h b/security/keys/internal.h index 07a025f81902..f375152a2500 100644 --- a/security/keys/internal.h +++ b/security/keys/internal.h | |||
@@ -109,11 +109,13 @@ extern key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
109 | const struct cred *cred, | 109 | const struct cred *cred, |
110 | struct key_type *type, | 110 | struct key_type *type, |
111 | const void *description, | 111 | const void *description, |
112 | key_match_func_t match); | 112 | key_match_func_t match, |
113 | bool no_state_check); | ||
113 | 114 | ||
114 | extern key_ref_t search_my_process_keyrings(struct key_type *type, | 115 | extern key_ref_t search_my_process_keyrings(struct key_type *type, |
115 | const void *description, | 116 | const void *description, |
116 | key_match_func_t match, | 117 | key_match_func_t match, |
118 | bool no_state_check, | ||
117 | const struct cred *cred); | 119 | const struct cred *cred); |
118 | extern key_ref_t search_process_keyrings(struct key_type *type, | 120 | extern key_ref_t search_process_keyrings(struct key_type *type, |
119 | const void *description, | 121 | const void *description, |
diff --git a/security/keys/keyctl.c b/security/keys/keyctl.c index 427fddcaeb19..eca51918c951 100644 --- a/security/keys/keyctl.c +++ b/security/keys/keyctl.c | |||
@@ -206,8 +206,14 @@ SYSCALL_DEFINE4(request_key, const char __user *, _type, | |||
206 | goto error5; | 206 | goto error5; |
207 | } | 207 | } |
208 | 208 | ||
209 | /* wait for the key to finish being constructed */ | ||
210 | ret = wait_for_key_construction(key, 1); | ||
211 | if (ret < 0) | ||
212 | goto error6; | ||
213 | |||
209 | ret = key->serial; | 214 | ret = key->serial; |
210 | 215 | ||
216 | error6: | ||
211 | key_put(key); | 217 | key_put(key); |
212 | error5: | 218 | error5: |
213 | key_type_put(ktype); | 219 | key_type_put(ktype); |
diff --git a/security/keys/keyring.c b/security/keys/keyring.c index cdd2f3f88c88..a06ffab38568 100644 --- a/security/keys/keyring.c +++ b/security/keys/keyring.c | |||
@@ -176,13 +176,15 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) | |||
176 | else | 176 | else |
177 | seq_puts(m, "[anon]"); | 177 | seq_puts(m, "[anon]"); |
178 | 178 | ||
179 | rcu_read_lock(); | 179 | if (key_is_instantiated(keyring)) { |
180 | klist = rcu_dereference(keyring->payload.subscriptions); | 180 | rcu_read_lock(); |
181 | if (klist) | 181 | klist = rcu_dereference(keyring->payload.subscriptions); |
182 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); | 182 | if (klist) |
183 | else | 183 | seq_printf(m, ": %u/%u", klist->nkeys, klist->maxkeys); |
184 | seq_puts(m, ": empty"); | 184 | else |
185 | rcu_read_unlock(); | 185 | seq_puts(m, ": empty"); |
186 | rcu_read_unlock(); | ||
187 | } | ||
186 | } | 188 | } |
187 | 189 | ||
188 | /* | 190 | /* |
@@ -271,6 +273,7 @@ struct key *keyring_alloc(const char *description, uid_t uid, gid_t gid, | |||
271 | * @type: The type of key to search for. | 273 | * @type: The type of key to search for. |
272 | * @description: Parameter for @match. | 274 | * @description: Parameter for @match. |
273 | * @match: Function to rule on whether or not a key is the one required. | 275 | * @match: Function to rule on whether or not a key is the one required. |
276 | * @no_state_check: Don't check if a matching key is bad | ||
274 | * | 277 | * |
275 | * Search the supplied keyring tree for a key that matches the criteria given. | 278 | * Search the supplied keyring tree for a key that matches the criteria given. |
276 | * The root keyring and any linked keyrings must grant Search permission to the | 279 | * The root keyring and any linked keyrings must grant Search permission to the |
@@ -303,7 +306,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
303 | const struct cred *cred, | 306 | const struct cred *cred, |
304 | struct key_type *type, | 307 | struct key_type *type, |
305 | const void *description, | 308 | const void *description, |
306 | key_match_func_t match) | 309 | key_match_func_t match, |
310 | bool no_state_check) | ||
307 | { | 311 | { |
308 | struct { | 312 | struct { |
309 | struct keyring_list *keylist; | 313 | struct keyring_list *keylist; |
@@ -345,6 +349,8 @@ key_ref_t keyring_search_aux(key_ref_t keyring_ref, | |||
345 | kflags = keyring->flags; | 349 | kflags = keyring->flags; |
346 | if (keyring->type == type && match(keyring, description)) { | 350 | if (keyring->type == type && match(keyring, description)) { |
347 | key = keyring; | 351 | key = keyring; |
352 | if (no_state_check) | ||
353 | goto found; | ||
348 | 354 | ||
349 | /* check it isn't negative and hasn't expired or been | 355 | /* check it isn't negative and hasn't expired or been |
350 | * revoked */ | 356 | * revoked */ |
@@ -384,11 +390,13 @@ descend: | |||
384 | continue; | 390 | continue; |
385 | 391 | ||
386 | /* skip revoked keys and expired keys */ | 392 | /* skip revoked keys and expired keys */ |
387 | if (kflags & (1 << KEY_FLAG_REVOKED)) | 393 | if (!no_state_check) { |
388 | continue; | 394 | if (kflags & (1 << KEY_FLAG_REVOKED)) |
395 | continue; | ||
389 | 396 | ||
390 | if (key->expiry && now.tv_sec >= key->expiry) | 397 | if (key->expiry && now.tv_sec >= key->expiry) |
391 | continue; | 398 | continue; |
399 | } | ||
392 | 400 | ||
393 | /* keys that don't match */ | 401 | /* keys that don't match */ |
394 | if (!match(key, description)) | 402 | if (!match(key, description)) |
@@ -399,6 +407,9 @@ descend: | |||
399 | cred, KEY_SEARCH) < 0) | 407 | cred, KEY_SEARCH) < 0) |
400 | continue; | 408 | continue; |
401 | 409 | ||
410 | if (no_state_check) | ||
411 | goto found; | ||
412 | |||
402 | /* we set a different error code if we pass a negative key */ | 413 | /* we set a different error code if we pass a negative key */ |
403 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { | 414 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { |
404 | err = key->type_data.reject_error; | 415 | err = key->type_data.reject_error; |
@@ -478,7 +489,7 @@ key_ref_t keyring_search(key_ref_t keyring, | |||
478 | return ERR_PTR(-ENOKEY); | 489 | return ERR_PTR(-ENOKEY); |
479 | 490 | ||
480 | return keyring_search_aux(keyring, current->cred, | 491 | return keyring_search_aux(keyring, current->cred, |
481 | type, description, type->match); | 492 | type, description, type->match, false); |
482 | } | 493 | } |
483 | EXPORT_SYMBOL(keyring_search); | 494 | EXPORT_SYMBOL(keyring_search); |
484 | 495 | ||
diff --git a/security/keys/proc.c b/security/keys/proc.c index 525cf8a29cdd..49bbc97943ad 100644 --- a/security/keys/proc.c +++ b/security/keys/proc.c | |||
@@ -199,7 +199,7 @@ static int proc_keys_show(struct seq_file *m, void *v) | |||
199 | if (key->perm & KEY_POS_VIEW) { | 199 | if (key->perm & KEY_POS_VIEW) { |
200 | skey_ref = search_my_process_keyrings(key->type, key, | 200 | skey_ref = search_my_process_keyrings(key->type, key, |
201 | lookup_user_key_possessed, | 201 | lookup_user_key_possessed, |
202 | cred); | 202 | true, cred); |
203 | if (!IS_ERR(skey_ref)) { | 203 | if (!IS_ERR(skey_ref)) { |
204 | key_ref_put(skey_ref); | 204 | key_ref_put(skey_ref); |
205 | key_ref = make_key_ref(key, 1); | 205 | key_ref = make_key_ref(key, 1); |
diff --git a/security/keys/process_keys.c b/security/keys/process_keys.c index 930634e45149..6c0480db8885 100644 --- a/security/keys/process_keys.c +++ b/security/keys/process_keys.c | |||
@@ -331,6 +331,7 @@ void key_fsgid_changed(struct task_struct *tsk) | |||
331 | key_ref_t search_my_process_keyrings(struct key_type *type, | 331 | key_ref_t search_my_process_keyrings(struct key_type *type, |
332 | const void *description, | 332 | const void *description, |
333 | key_match_func_t match, | 333 | key_match_func_t match, |
334 | bool no_state_check, | ||
334 | const struct cred *cred) | 335 | const struct cred *cred) |
335 | { | 336 | { |
336 | key_ref_t key_ref, ret, err; | 337 | key_ref_t key_ref, ret, err; |
@@ -350,7 +351,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
350 | if (cred->thread_keyring) { | 351 | if (cred->thread_keyring) { |
351 | key_ref = keyring_search_aux( | 352 | key_ref = keyring_search_aux( |
352 | make_key_ref(cred->thread_keyring, 1), | 353 | make_key_ref(cred->thread_keyring, 1), |
353 | cred, type, description, match); | 354 | cred, type, description, match, no_state_check); |
354 | if (!IS_ERR(key_ref)) | 355 | if (!IS_ERR(key_ref)) |
355 | goto found; | 356 | goto found; |
356 | 357 | ||
@@ -371,7 +372,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
371 | if (cred->tgcred->process_keyring) { | 372 | if (cred->tgcred->process_keyring) { |
372 | key_ref = keyring_search_aux( | 373 | key_ref = keyring_search_aux( |
373 | make_key_ref(cred->tgcred->process_keyring, 1), | 374 | make_key_ref(cred->tgcred->process_keyring, 1), |
374 | cred, type, description, match); | 375 | cred, type, description, match, no_state_check); |
375 | if (!IS_ERR(key_ref)) | 376 | if (!IS_ERR(key_ref)) |
376 | goto found; | 377 | goto found; |
377 | 378 | ||
@@ -395,7 +396,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
395 | make_key_ref(rcu_dereference( | 396 | make_key_ref(rcu_dereference( |
396 | cred->tgcred->session_keyring), | 397 | cred->tgcred->session_keyring), |
397 | 1), | 398 | 1), |
398 | cred, type, description, match); | 399 | cred, type, description, match, no_state_check); |
399 | rcu_read_unlock(); | 400 | rcu_read_unlock(); |
400 | 401 | ||
401 | if (!IS_ERR(key_ref)) | 402 | if (!IS_ERR(key_ref)) |
@@ -417,7 +418,7 @@ key_ref_t search_my_process_keyrings(struct key_type *type, | |||
417 | else if (cred->user->session_keyring) { | 418 | else if (cred->user->session_keyring) { |
418 | key_ref = keyring_search_aux( | 419 | key_ref = keyring_search_aux( |
419 | make_key_ref(cred->user->session_keyring, 1), | 420 | make_key_ref(cred->user->session_keyring, 1), |
420 | cred, type, description, match); | 421 | cred, type, description, match, no_state_check); |
421 | if (!IS_ERR(key_ref)) | 422 | if (!IS_ERR(key_ref)) |
422 | goto found; | 423 | goto found; |
423 | 424 | ||
@@ -459,7 +460,8 @@ key_ref_t search_process_keyrings(struct key_type *type, | |||
459 | 460 | ||
460 | might_sleep(); | 461 | might_sleep(); |
461 | 462 | ||
462 | key_ref = search_my_process_keyrings(type, description, match, cred); | 463 | key_ref = search_my_process_keyrings(type, description, match, |
464 | false, cred); | ||
463 | if (!IS_ERR(key_ref)) | 465 | if (!IS_ERR(key_ref)) |
464 | goto found; | 466 | goto found; |
465 | err = key_ref; | 467 | err = key_ref; |
diff --git a/security/keys/request_key.c b/security/keys/request_key.c index df3c0417ee40..b18a71745901 100644 --- a/security/keys/request_key.c +++ b/security/keys/request_key.c | |||
@@ -530,8 +530,7 @@ struct key *request_key_and_link(struct key_type *type, | |||
530 | dest_keyring, flags); | 530 | dest_keyring, flags); |
531 | 531 | ||
532 | /* search all the process keyrings for a key */ | 532 | /* search all the process keyrings for a key */ |
533 | key_ref = search_process_keyrings(type, description, type->match, | 533 | key_ref = search_process_keyrings(type, description, type->match, cred); |
534 | cred); | ||
535 | 534 | ||
536 | if (!IS_ERR(key_ref)) { | 535 | if (!IS_ERR(key_ref)) { |
537 | key = key_ref_to_ptr(key_ref); | 536 | key = key_ref_to_ptr(key_ref); |
diff --git a/security/keys/request_key_auth.c b/security/keys/request_key_auth.c index 68164031a74e..f6337c9082eb 100644 --- a/security/keys/request_key_auth.c +++ b/security/keys/request_key_auth.c | |||
@@ -59,7 +59,8 @@ static void request_key_auth_describe(const struct key *key, | |||
59 | 59 | ||
60 | seq_puts(m, "key:"); | 60 | seq_puts(m, "key:"); |
61 | seq_puts(m, key->description); | 61 | seq_puts(m, key->description); |
62 | seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); | 62 | if (key_is_instantiated(key)) |
63 | seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); | ||
63 | } | 64 | } |
64 | 65 | ||
65 | /* | 66 | /* |
diff --git a/security/keys/user_defined.c b/security/keys/user_defined.c index f66baf44f32d..5b366d7af3c4 100644 --- a/security/keys/user_defined.c +++ b/security/keys/user_defined.c | |||
@@ -157,8 +157,8 @@ EXPORT_SYMBOL_GPL(user_destroy); | |||
157 | void user_describe(const struct key *key, struct seq_file *m) | 157 | void user_describe(const struct key *key, struct seq_file *m) |
158 | { | 158 | { |
159 | seq_puts(m, key->description); | 159 | seq_puts(m, key->description); |
160 | 160 | if (key_is_instantiated(key)) | |
161 | seq_printf(m, ": %u", key->datalen); | 161 | seq_printf(m, ": %u", key->datalen); |
162 | } | 162 | } |
163 | 163 | ||
164 | EXPORT_SYMBOL_GPL(user_describe); | 164 | EXPORT_SYMBOL_GPL(user_describe); |
diff --git a/security/tomoyo/common.c b/security/tomoyo/common.c index 7556315c1978..a0d09e56874b 100644 --- a/security/tomoyo/common.c +++ b/security/tomoyo/common.c | |||
@@ -108,10 +108,9 @@ static bool tomoyo_flush(struct tomoyo_io_buffer *head) | |||
108 | head->read_user_buf += len; | 108 | head->read_user_buf += len; |
109 | w += len; | 109 | w += len; |
110 | } | 110 | } |
111 | if (*w) { | 111 | head->r.w[0] = w; |
112 | head->r.w[0] = w; | 112 | if (*w) |
113 | return false; | 113 | return false; |
114 | } | ||
115 | /* Add '\0' for query. */ | 114 | /* Add '\0' for query. */ |
116 | if (head->poll) { | 115 | if (head->poll) { |
117 | if (!head->read_user_buf_avail || | 116 | if (!head->read_user_buf_avail || |
@@ -459,8 +458,16 @@ static int tomoyo_write_profile(struct tomoyo_io_buffer *head) | |||
459 | if (profile == &tomoyo_default_profile) | 458 | if (profile == &tomoyo_default_profile) |
460 | return -EINVAL; | 459 | return -EINVAL; |
461 | if (!strcmp(data, "COMMENT")) { | 460 | if (!strcmp(data, "COMMENT")) { |
462 | const struct tomoyo_path_info *old_comment = profile->comment; | 461 | static DEFINE_SPINLOCK(lock); |
463 | profile->comment = tomoyo_get_name(cp); | 462 | const struct tomoyo_path_info *new_comment |
463 | = tomoyo_get_name(cp); | ||
464 | const struct tomoyo_path_info *old_comment; | ||
465 | if (!new_comment) | ||
466 | return -ENOMEM; | ||
467 | spin_lock(&lock); | ||
468 | old_comment = profile->comment; | ||
469 | profile->comment = new_comment; | ||
470 | spin_unlock(&lock); | ||
464 | tomoyo_put_name(old_comment); | 471 | tomoyo_put_name(old_comment); |
465 | return 0; | 472 | return 0; |
466 | } | 473 | } |
diff --git a/security/tomoyo/file.c b/security/tomoyo/file.c index cb09f1fce910..d64e8ecb6fb3 100644 --- a/security/tomoyo/file.c +++ b/security/tomoyo/file.c | |||
@@ -1011,7 +1011,6 @@ int tomoyo_path_perm(const u8 operation, struct path *path) | |||
1011 | break; | 1011 | break; |
1012 | case TOMOYO_TYPE_RMDIR: | 1012 | case TOMOYO_TYPE_RMDIR: |
1013 | case TOMOYO_TYPE_CHROOT: | 1013 | case TOMOYO_TYPE_CHROOT: |
1014 | case TOMOYO_TYPE_UMOUNT: | ||
1015 | tomoyo_add_slash(&buf); | 1014 | tomoyo_add_slash(&buf); |
1016 | break; | 1015 | break; |
1017 | } | 1016 | } |
diff --git a/security/tomoyo/memory.c b/security/tomoyo/memory.c index 297612669c74..42a7b1ba8cbf 100644 --- a/security/tomoyo/memory.c +++ b/security/tomoyo/memory.c | |||
@@ -75,6 +75,7 @@ void *tomoyo_commit_ok(void *data, const unsigned int size) | |||
75 | memset(data, 0, size); | 75 | memset(data, 0, size); |
76 | return ptr; | 76 | return ptr; |
77 | } | 77 | } |
78 | kfree(ptr); | ||
78 | return NULL; | 79 | return NULL; |
79 | } | 80 | } |
80 | 81 | ||
diff --git a/security/tomoyo/mount.c b/security/tomoyo/mount.c index 82bf8c2390bc..162a864dba24 100644 --- a/security/tomoyo/mount.c +++ b/security/tomoyo/mount.c | |||
@@ -143,6 +143,7 @@ static int tomoyo_mount_acl(struct tomoyo_request_info *r, char *dev_name, | |||
143 | goto out; | 143 | goto out; |
144 | } | 144 | } |
145 | requested_dev_name = tomoyo_realpath_from_path(&path); | 145 | requested_dev_name = tomoyo_realpath_from_path(&path); |
146 | path_put(&path); | ||
146 | if (!requested_dev_name) { | 147 | if (!requested_dev_name) { |
147 | error = -ENOENT; | 148 | error = -ENOENT; |
148 | goto out; | 149 | goto out; |
diff --git a/security/tomoyo/util.c b/security/tomoyo/util.c index 9bfc1ee8222d..6d5393204d95 100644 --- a/security/tomoyo/util.c +++ b/security/tomoyo/util.c | |||
@@ -390,7 +390,7 @@ bool tomoyo_correct_domain(const unsigned char *domainname) | |||
390 | if (!cp) | 390 | if (!cp) |
391 | break; | 391 | break; |
392 | if (*domainname != '/' || | 392 | if (*domainname != '/' || |
393 | !tomoyo_correct_word2(domainname, cp - domainname - 1)) | 393 | !tomoyo_correct_word2(domainname, cp - domainname)) |
394 | goto out; | 394 | goto out; |
395 | domainname = cp + 1; | 395 | domainname = cp + 1; |
396 | } | 396 | } |