diff options
| author | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-05-25 19:41:21 -0400 |
|---|---|---|
| committer | Russell King <rmk+kernel@arm.linux.org.uk> | 2011-05-25 19:41:21 -0400 |
| commit | ae1d3b974e091b5fc9008bd41bcbdaac68110b62 (patch) | |
| tree | 82e50a66925ced79f59ed4504f6e073ef55edee3 /kernel | |
| parent | 586893ebc42943008010b4c210cfc9167df615e5 (diff) | |
| parent | 7a2207a0e1142a9b214b323e43ab2ecc592e5b0e (diff) | |
Merge branch 'for-rmk' of git://github.com/at91linux/linux-2.6-at91 into devel-stable
Diffstat (limited to 'kernel')
| -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-- | kernel/workqueue.c | 4 |
5 files changed, 110 insertions, 10 deletions
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/kernel/workqueue.c b/kernel/workqueue.c index e3378e8d3a5c..0400553f0d04 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c | |||
| @@ -2866,9 +2866,7 @@ static int alloc_cwqs(struct workqueue_struct *wq) | |||
| 2866 | } | 2866 | } |
| 2867 | } | 2867 | } |
| 2868 | 2868 | ||
| 2869 | /* just in case, make sure it's actually aligned | 2869 | /* just in case, make sure it's actually aligned */ |
| 2870 | * - this is affected by PERCPU() alignment in vmlinux.lds.S | ||
| 2871 | */ | ||
| 2872 | BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align)); | 2870 | BUG_ON(!IS_ALIGNED(wq->cpu_wq.v, align)); |
| 2873 | return wq->cpu_wq.v ? 0 : -ENOMEM; | 2871 | return wq->cpu_wq.v ? 0 : -ENOMEM; |
| 2874 | } | 2872 | } |
