diff options
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/fork.c | 40 | ||||
| -rw-r--r-- | kernel/kexec.c | 2 | ||||
| -rw-r--r-- | kernel/kmod.c | 37 | ||||
| -rw-r--r-- | kernel/panic.c | 8 | ||||
| -rw-r--r-- | kernel/power/suspend.c | 3 | ||||
| -rw-r--r-- | kernel/printk.c | 32 | ||||
| -rw-r--r-- | kernel/resource.c | 24 | ||||
| -rw-r--r-- | kernel/sys.c | 57 | ||||
| -rw-r--r-- | kernel/sysctl.c | 43 | ||||
| -rw-r--r-- | kernel/taskstats.c | 5 | ||||
| -rw-r--r-- | kernel/watchdog.c | 21 |
11 files changed, 200 insertions, 72 deletions
diff --git a/kernel/fork.c b/kernel/fork.c index ff1cad3b7bdc..8efac1fe56bc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
| @@ -114,6 +114,10 @@ int nr_processes(void) | |||
| 114 | return total; | 114 | return total; |
| 115 | } | 115 | } |
| 116 | 116 | ||
| 117 | void __weak arch_release_task_struct(struct task_struct *tsk) | ||
| 118 | { | ||
| 119 | } | ||
| 120 | |||
| 117 | #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR | 121 | #ifndef CONFIG_ARCH_TASK_STRUCT_ALLOCATOR |
| 118 | static struct kmem_cache *task_struct_cachep; | 122 | static struct kmem_cache *task_struct_cachep; |
| 119 | 123 | ||
| @@ -122,17 +126,17 @@ static inline struct task_struct *alloc_task_struct_node(int node) | |||
| 122 | return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node); | 126 | return kmem_cache_alloc_node(task_struct_cachep, GFP_KERNEL, node); |
| 123 | } | 127 | } |
| 124 | 128 | ||
| 125 | void __weak arch_release_task_struct(struct task_struct *tsk) { } | ||
| 126 | |||
| 127 | static inline void free_task_struct(struct task_struct *tsk) | 129 | static inline void free_task_struct(struct task_struct *tsk) |
| 128 | { | 130 | { |
| 129 | arch_release_task_struct(tsk); | ||
| 130 | kmem_cache_free(task_struct_cachep, tsk); | 131 | kmem_cache_free(task_struct_cachep, tsk); |
| 131 | } | 132 | } |
| 132 | #endif | 133 | #endif |
| 133 | 134 | ||
| 135 | void __weak arch_release_thread_info(struct thread_info *ti) | ||
| 136 | { | ||
| 137 | } | ||
| 138 | |||
| 134 | #ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR | 139 | #ifndef CONFIG_ARCH_THREAD_INFO_ALLOCATOR |
| 135 | void __weak arch_release_thread_info(struct thread_info *ti) { } | ||
| 136 | 140 | ||
| 137 | /* | 141 | /* |
| 138 | * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a | 142 | * Allocate pages if THREAD_SIZE is >= PAGE_SIZE, otherwise use a |
| @@ -150,7 +154,6 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, | |||
| 150 | 154 | ||
| 151 | static inline void free_thread_info(struct thread_info *ti) | 155 | static inline void free_thread_info(struct thread_info *ti) |
| 152 | { | 156 | { |
| 153 | arch_release_thread_info(ti); | ||
| 154 | free_pages((unsigned long)ti, THREAD_SIZE_ORDER); | 157 | free_pages((unsigned long)ti, THREAD_SIZE_ORDER); |
| 155 | } | 158 | } |
| 156 | # else | 159 | # else |
| @@ -164,7 +167,6 @@ static struct thread_info *alloc_thread_info_node(struct task_struct *tsk, | |||
| 164 | 167 | ||
| 165 | static void free_thread_info(struct thread_info *ti) | 168 | static void free_thread_info(struct thread_info *ti) |
| 166 | { | 169 | { |
| 167 | arch_release_thread_info(ti); | ||
| 168 | kmem_cache_free(thread_info_cache, ti); | 170 | kmem_cache_free(thread_info_cache, ti); |
| 169 | } | 171 | } |
| 170 | 172 | ||
| @@ -205,10 +207,12 @@ static void account_kernel_stack(struct thread_info *ti, int account) | |||
| 205 | void free_task(struct task_struct *tsk) | 207 | void free_task(struct task_struct *tsk) |
| 206 | { | 208 | { |
| 207 | account_kernel_stack(tsk->stack, -1); | 209 | account_kernel_stack(tsk->stack, -1); |
| 210 | arch_release_thread_info(tsk->stack); | ||
| 208 | free_thread_info(tsk->stack); | 211 | free_thread_info(tsk->stack); |
| 209 | rt_mutex_debug_task_free(tsk); | 212 | rt_mutex_debug_task_free(tsk); |
| 210 | ftrace_graph_exit_task(tsk); | 213 | ftrace_graph_exit_task(tsk); |
| 211 | put_seccomp_filter(tsk); | 214 | put_seccomp_filter(tsk); |
| 215 | arch_release_task_struct(tsk); | ||
| 212 | free_task_struct(tsk); | 216 | free_task_struct(tsk); |
| 213 | } | 217 | } |
| 214 | EXPORT_SYMBOL(free_task); | 218 | EXPORT_SYMBOL(free_task); |
| @@ -298,23 +302,16 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
| 298 | return NULL; | 302 | return NULL; |
| 299 | 303 | ||
| 300 | ti = alloc_thread_info_node(tsk, node); | 304 | ti = alloc_thread_info_node(tsk, node); |
| 301 | if (!ti) { | 305 | if (!ti) |
| 302 | free_task_struct(tsk); | 306 | goto free_tsk; |
| 303 | return NULL; | ||
| 304 | } | ||
| 305 | 307 | ||
| 306 | err = arch_dup_task_struct(tsk, orig); | 308 | err = arch_dup_task_struct(tsk, orig); |
| 309 | if (err) | ||
| 310 | goto free_ti; | ||
| 307 | 311 | ||
| 308 | /* | ||
| 309 | * We defer looking at err, because we will need this setup | ||
| 310 | * for the clean up path to work correctly. | ||
| 311 | */ | ||
| 312 | tsk->stack = ti; | 312 | tsk->stack = ti; |
| 313 | setup_thread_stack(tsk, orig); | ||
| 314 | |||
| 315 | if (err) | ||
| 316 | goto out; | ||
| 317 | 313 | ||
| 314 | setup_thread_stack(tsk, orig); | ||
| 318 | clear_user_return_notifier(tsk); | 315 | clear_user_return_notifier(tsk); |
| 319 | clear_tsk_need_resched(tsk); | 316 | clear_tsk_need_resched(tsk); |
| 320 | stackend = end_of_stack(tsk); | 317 | stackend = end_of_stack(tsk); |
| @@ -338,8 +335,9 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
| 338 | 335 | ||
| 339 | return tsk; | 336 | return tsk; |
| 340 | 337 | ||
| 341 | out: | 338 | free_ti: |
| 342 | free_thread_info(ti); | 339 | free_thread_info(ti); |
| 340 | free_tsk: | ||
| 343 | free_task_struct(tsk); | 341 | free_task_struct(tsk); |
| 344 | return NULL; | 342 | return NULL; |
| 345 | } | 343 | } |
| @@ -391,8 +389,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm) | |||
| 391 | } | 389 | } |
| 392 | charge = 0; | 390 | charge = 0; |
| 393 | if (mpnt->vm_flags & VM_ACCOUNT) { | 391 | if (mpnt->vm_flags & VM_ACCOUNT) { |
| 394 | unsigned long len; | 392 | unsigned long len = vma_pages(mpnt); |
| 395 | len = (mpnt->vm_end - mpnt->vm_start) >> PAGE_SHIFT; | 393 | |
| 396 | if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ | 394 | if (security_vm_enough_memory_mm(oldmm, len)) /* sic */ |
| 397 | goto fail_nomem; | 395 | goto fail_nomem; |
| 398 | charge = len; | 396 | charge = len; |
diff --git a/kernel/kexec.c b/kernel/kexec.c index 4e2e472f6aeb..0668d58d6413 100644 --- a/kernel/kexec.c +++ b/kernel/kexec.c | |||
| @@ -1424,7 +1424,7 @@ static void update_vmcoreinfo_note(void) | |||
| 1424 | 1424 | ||
| 1425 | void crash_save_vmcoreinfo(void) | 1425 | void crash_save_vmcoreinfo(void) |
| 1426 | { | 1426 | { |
| 1427 | vmcoreinfo_append_str("CRASHTIME=%ld", get_seconds()); | 1427 | vmcoreinfo_append_str("CRASHTIME=%ld\n", get_seconds()); |
| 1428 | update_vmcoreinfo_note(); | 1428 | update_vmcoreinfo_note(); |
| 1429 | } | 1429 | } |
| 1430 | 1430 | ||
diff --git a/kernel/kmod.c b/kernel/kmod.c index ff2c7cb86d77..6f99aead66c6 100644 --- a/kernel/kmod.c +++ b/kernel/kmod.c | |||
| @@ -45,6 +45,13 @@ extern int max_threads; | |||
| 45 | 45 | ||
| 46 | static struct workqueue_struct *khelper_wq; | 46 | static struct workqueue_struct *khelper_wq; |
| 47 | 47 | ||
| 48 | /* | ||
| 49 | * kmod_thread_locker is used for deadlock avoidance. There is no explicit | ||
| 50 | * locking to protect this global - it is private to the singleton khelper | ||
| 51 | * thread and should only ever be modified by that thread. | ||
| 52 | */ | ||
| 53 | static const struct task_struct *kmod_thread_locker; | ||
| 54 | |||
| 48 | #define CAP_BSET (void *)1 | 55 | #define CAP_BSET (void *)1 |
| 49 | #define CAP_PI (void *)2 | 56 | #define CAP_PI (void *)2 |
| 50 | 57 | ||
| @@ -221,6 +228,13 @@ fail: | |||
| 221 | return 0; | 228 | return 0; |
| 222 | } | 229 | } |
| 223 | 230 | ||
| 231 | static int call_helper(void *data) | ||
| 232 | { | ||
| 233 | /* Worker thread started blocking khelper thread. */ | ||
| 234 | kmod_thread_locker = current; | ||
| 235 | return ____call_usermodehelper(data); | ||
| 236 | } | ||
| 237 | |||
| 224 | static void call_usermodehelper_freeinfo(struct subprocess_info *info) | 238 | static void call_usermodehelper_freeinfo(struct subprocess_info *info) |
| 225 | { | 239 | { |
| 226 | if (info->cleanup) | 240 | if (info->cleanup) |
| @@ -295,9 +309,12 @@ static void __call_usermodehelper(struct work_struct *work) | |||
| 295 | if (wait == UMH_WAIT_PROC) | 309 | if (wait == UMH_WAIT_PROC) |
| 296 | pid = kernel_thread(wait_for_helper, sub_info, | 310 | pid = kernel_thread(wait_for_helper, sub_info, |
| 297 | CLONE_FS | CLONE_FILES | SIGCHLD); | 311 | CLONE_FS | CLONE_FILES | SIGCHLD); |
| 298 | else | 312 | else { |
| 299 | pid = kernel_thread(____call_usermodehelper, sub_info, | 313 | pid = kernel_thread(call_helper, sub_info, |
| 300 | CLONE_VFORK | SIGCHLD); | 314 | CLONE_VFORK | SIGCHLD); |
| 315 | /* Worker thread stopped blocking khelper thread. */ | ||
| 316 | kmod_thread_locker = NULL; | ||
| 317 | } | ||
| 301 | 318 | ||
| 302 | switch (wait) { | 319 | switch (wait) { |
| 303 | case UMH_NO_WAIT: | 320 | case UMH_NO_WAIT: |
| @@ -548,6 +565,16 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait) | |||
| 548 | retval = -EBUSY; | 565 | retval = -EBUSY; |
| 549 | goto out; | 566 | goto out; |
| 550 | } | 567 | } |
| 568 | /* | ||
| 569 | * Worker thread must not wait for khelper thread at below | ||
| 570 | * wait_for_completion() if the thread was created with CLONE_VFORK | ||
| 571 | * flag, for khelper thread is already waiting for the thread at | ||
| 572 | * wait_for_completion() in do_fork(). | ||
| 573 | */ | ||
| 574 | if (wait != UMH_NO_WAIT && current == kmod_thread_locker) { | ||
| 575 | retval = -EBUSY; | ||
| 576 | goto out; | ||
| 577 | } | ||
| 551 | 578 | ||
| 552 | sub_info->complete = &done; | 579 | sub_info->complete = &done; |
| 553 | sub_info->wait = wait; | 580 | sub_info->wait = wait; |
| @@ -577,6 +604,12 @@ unlock: | |||
| 577 | return retval; | 604 | return retval; |
| 578 | } | 605 | } |
| 579 | 606 | ||
| 607 | /* | ||
| 608 | * call_usermodehelper_fns() will not run the caller-provided cleanup function | ||
| 609 | * if a memory allocation failure is experienced. So the caller might need to | ||
| 610 | * check the call_usermodehelper_fns() return value: if it is -ENOMEM, perform | ||
| 611 | * the necessaary cleanup within the caller. | ||
| 612 | */ | ||
| 580 | int call_usermodehelper_fns( | 613 | int call_usermodehelper_fns( |
| 581 | char *path, char **argv, char **envp, int wait, | 614 | char *path, char **argv, char **envp, int wait, |
| 582 | int (*init)(struct subprocess_info *info, struct cred *new), | 615 | int (*init)(struct subprocess_info *info, struct cred *new), |
diff --git a/kernel/panic.c b/kernel/panic.c index d2a5f4ecc6dd..e1b2822fff97 100644 --- a/kernel/panic.c +++ b/kernel/panic.c | |||
| @@ -75,6 +75,14 @@ void panic(const char *fmt, ...) | |||
| 75 | int state = 0; | 75 | int state = 0; |
| 76 | 76 | ||
| 77 | /* | 77 | /* |
| 78 | * Disable local interrupts. This will prevent panic_smp_self_stop | ||
| 79 | * from deadlocking the first cpu that invokes the panic, since | ||
| 80 | * there is nothing to prevent an interrupt handler (that runs | ||
| 81 | * after the panic_lock is acquired) from invoking panic again. | ||
| 82 | */ | ||
| 83 | local_irq_disable(); | ||
| 84 | |||
| 85 | /* | ||
| 78 | * It's possible to come here directly from a panic-assertion and | 86 | * It's possible to come here directly from a panic-assertion and |
| 79 | * not have preempt disabled. Some functions called from here want | 87 | * not have preempt disabled. Some functions called from here want |
| 80 | * preempt to be disabled. No point enabling it later though... | 88 | * preempt to be disabled. No point enabling it later though... |
diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c index c8b7446b27df..1da39ea248fd 100644 --- a/kernel/power/suspend.c +++ b/kernel/power/suspend.c | |||
| @@ -178,6 +178,9 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) | |||
| 178 | arch_suspend_enable_irqs(); | 178 | arch_suspend_enable_irqs(); |
| 179 | BUG_ON(irqs_disabled()); | 179 | BUG_ON(irqs_disabled()); |
| 180 | 180 | ||
| 181 | /* Kick the lockup detector */ | ||
| 182 | lockup_detector_bootcpu_resume(); | ||
| 183 | |||
| 181 | Enable_cpus: | 184 | Enable_cpus: |
| 182 | enable_nonboot_cpus(); | 185 | enable_nonboot_cpus(); |
| 183 | 186 | ||
diff --git a/kernel/printk.c b/kernel/printk.c index 50c96b5651b6..6a76ab9d4476 100644 --- a/kernel/printk.c +++ b/kernel/printk.c | |||
| @@ -389,8 +389,10 @@ static ssize_t devkmsg_writev(struct kiocb *iocb, const struct iovec *iv, | |||
| 389 | 389 | ||
| 390 | line = buf; | 390 | line = buf; |
| 391 | for (i = 0; i < count; i++) { | 391 | for (i = 0; i < count; i++) { |
| 392 | if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len)) | 392 | if (copy_from_user(line, iv[i].iov_base, iv[i].iov_len)) { |
| 393 | ret = -EFAULT; | ||
| 393 | goto out; | 394 | goto out; |
| 395 | } | ||
| 394 | line += iv[i].iov_len; | 396 | line += iv[i].iov_len; |
| 395 | } | 397 | } |
| 396 | 398 | ||
| @@ -1540,17 +1542,23 @@ asmlinkage int vprintk_emit(int facility, int level, | |||
| 1540 | lflags |= LOG_NEWLINE; | 1542 | lflags |= LOG_NEWLINE; |
| 1541 | } | 1543 | } |
| 1542 | 1544 | ||
| 1543 | /* strip syslog prefix and extract log level or control flags */ | 1545 | /* strip kernel syslog prefix and extract log level or control flags */ |
| 1544 | if (text[0] == '<' && text[1] && text[2] == '>') { | 1546 | if (facility == 0) { |
| 1545 | switch (text[1]) { | 1547 | int kern_level = printk_get_level(text); |
| 1546 | case '0' ... '7': | 1548 | |
| 1547 | if (level == -1) | 1549 | if (kern_level) { |
| 1548 | level = text[1] - '0'; | 1550 | const char *end_of_header = printk_skip_level(text); |
| 1549 | case 'd': /* KERN_DEFAULT */ | 1551 | switch (kern_level) { |
| 1550 | lflags |= LOG_PREFIX; | 1552 | case '0' ... '7': |
| 1551 | case 'c': /* KERN_CONT */ | 1553 | if (level == -1) |
| 1552 | text += 3; | 1554 | level = kern_level - '0'; |
| 1553 | text_len -= 3; | 1555 | case 'd': /* KERN_DEFAULT */ |
| 1556 | lflags |= LOG_PREFIX; | ||
| 1557 | case 'c': /* KERN_CONT */ | ||
| 1558 | break; | ||
| 1559 | } | ||
| 1560 | text_len -= end_of_header - text; | ||
| 1561 | text = (char *)end_of_header; | ||
| 1554 | } | 1562 | } |
| 1555 | } | 1563 | } |
| 1556 | 1564 | ||
diff --git a/kernel/resource.c b/kernel/resource.c index dc8b47764443..34d45886ee84 100644 --- a/kernel/resource.c +++ b/kernel/resource.c | |||
| @@ -7,6 +7,8 @@ | |||
| 7 | * Arbitrary resource management. | 7 | * Arbitrary resource management. |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
| 11 | |||
| 10 | #include <linux/export.h> | 12 | #include <linux/export.h> |
| 11 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
| 12 | #include <linux/ioport.h> | 14 | #include <linux/ioport.h> |
| @@ -791,8 +793,28 @@ void __init reserve_region_with_split(struct resource *root, | |||
| 791 | resource_size_t start, resource_size_t end, | 793 | resource_size_t start, resource_size_t end, |
| 792 | const char *name) | 794 | const char *name) |
| 793 | { | 795 | { |
| 796 | int abort = 0; | ||
| 797 | |||
| 794 | write_lock(&resource_lock); | 798 | write_lock(&resource_lock); |
| 795 | __reserve_region_with_split(root, start, end, name); | 799 | if (root->start > start || root->end < end) { |
| 800 | pr_err("requested range [0x%llx-0x%llx] not in root %pr\n", | ||
| 801 | (unsigned long long)start, (unsigned long long)end, | ||
| 802 | root); | ||
| 803 | if (start > root->end || end < root->start) | ||
| 804 | abort = 1; | ||
| 805 | else { | ||
| 806 | if (end > root->end) | ||
| 807 | end = root->end; | ||
| 808 | if (start < root->start) | ||
| 809 | start = root->start; | ||
| 810 | pr_err("fixing request to [0x%llx-0x%llx]\n", | ||
| 811 | (unsigned long long)start, | ||
| 812 | (unsigned long long)end); | ||
| 813 | } | ||
| 814 | dump_stack(); | ||
| 815 | } | ||
| 816 | if (!abort) | ||
| 817 | __reserve_region_with_split(root, start, end, name); | ||
| 796 | write_unlock(&resource_lock); | 818 | write_unlock(&resource_lock); |
| 797 | } | 819 | } |
| 798 | 820 | ||
diff --git a/kernel/sys.c b/kernel/sys.c index 2d39a84cd857..241507f23eca 100644 --- a/kernel/sys.c +++ b/kernel/sys.c | |||
| @@ -2015,7 +2015,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2015 | break; | 2015 | break; |
| 2016 | } | 2016 | } |
| 2017 | me->pdeath_signal = arg2; | 2017 | me->pdeath_signal = arg2; |
| 2018 | error = 0; | ||
| 2019 | break; | 2018 | break; |
| 2020 | case PR_GET_PDEATHSIG: | 2019 | case PR_GET_PDEATHSIG: |
| 2021 | error = put_user(me->pdeath_signal, (int __user *)arg2); | 2020 | error = put_user(me->pdeath_signal, (int __user *)arg2); |
| @@ -2029,7 +2028,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2029 | break; | 2028 | break; |
| 2030 | } | 2029 | } |
| 2031 | set_dumpable(me->mm, arg2); | 2030 | set_dumpable(me->mm, arg2); |
| 2032 | error = 0; | ||
| 2033 | break; | 2031 | break; |
| 2034 | 2032 | ||
| 2035 | case PR_SET_UNALIGN: | 2033 | case PR_SET_UNALIGN: |
| @@ -2056,10 +2054,7 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2056 | case PR_SET_TIMING: | 2054 | case PR_SET_TIMING: |
| 2057 | if (arg2 != PR_TIMING_STATISTICAL) | 2055 | if (arg2 != PR_TIMING_STATISTICAL) |
| 2058 | error = -EINVAL; | 2056 | error = -EINVAL; |
| 2059 | else | ||
| 2060 | error = 0; | ||
| 2061 | break; | 2057 | break; |
| 2062 | |||
| 2063 | case PR_SET_NAME: | 2058 | case PR_SET_NAME: |
| 2064 | comm[sizeof(me->comm)-1] = 0; | 2059 | comm[sizeof(me->comm)-1] = 0; |
| 2065 | if (strncpy_from_user(comm, (char __user *)arg2, | 2060 | if (strncpy_from_user(comm, (char __user *)arg2, |
| @@ -2067,20 +2062,19 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2067 | return -EFAULT; | 2062 | return -EFAULT; |
| 2068 | set_task_comm(me, comm); | 2063 | set_task_comm(me, comm); |
| 2069 | proc_comm_connector(me); | 2064 | proc_comm_connector(me); |
| 2070 | return 0; | 2065 | break; |
| 2071 | case PR_GET_NAME: | 2066 | case PR_GET_NAME: |
| 2072 | get_task_comm(comm, me); | 2067 | get_task_comm(comm, me); |
| 2073 | if (copy_to_user((char __user *)arg2, comm, | 2068 | if (copy_to_user((char __user *)arg2, comm, |
| 2074 | sizeof(comm))) | 2069 | sizeof(comm))) |
| 2075 | return -EFAULT; | 2070 | return -EFAULT; |
| 2076 | return 0; | 2071 | break; |
| 2077 | case PR_GET_ENDIAN: | 2072 | case PR_GET_ENDIAN: |
| 2078 | error = GET_ENDIAN(me, arg2); | 2073 | error = GET_ENDIAN(me, arg2); |
| 2079 | break; | 2074 | break; |
| 2080 | case PR_SET_ENDIAN: | 2075 | case PR_SET_ENDIAN: |
| 2081 | error = SET_ENDIAN(me, arg2); | 2076 | error = SET_ENDIAN(me, arg2); |
| 2082 | break; | 2077 | break; |
| 2083 | |||
| 2084 | case PR_GET_SECCOMP: | 2078 | case PR_GET_SECCOMP: |
| 2085 | error = prctl_get_seccomp(); | 2079 | error = prctl_get_seccomp(); |
| 2086 | break; | 2080 | break; |
| @@ -2108,7 +2102,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2108 | current->default_timer_slack_ns; | 2102 | current->default_timer_slack_ns; |
| 2109 | else | 2103 | else |
| 2110 | current->timer_slack_ns = arg2; | 2104 | current->timer_slack_ns = arg2; |
| 2111 | error = 0; | ||
| 2112 | break; | 2105 | break; |
| 2113 | case PR_MCE_KILL: | 2106 | case PR_MCE_KILL: |
| 2114 | if (arg4 | arg5) | 2107 | if (arg4 | arg5) |
| @@ -2134,7 +2127,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2134 | default: | 2127 | default: |
| 2135 | return -EINVAL; | 2128 | return -EINVAL; |
| 2136 | } | 2129 | } |
| 2137 | error = 0; | ||
| 2138 | break; | 2130 | break; |
| 2139 | case PR_MCE_KILL_GET: | 2131 | case PR_MCE_KILL_GET: |
| 2140 | if (arg2 | arg3 | arg4 | arg5) | 2132 | if (arg2 | arg3 | arg4 | arg5) |
| @@ -2153,7 +2145,6 @@ SYSCALL_DEFINE5(prctl, int, option, unsigned long, arg2, unsigned long, arg3, | |||
| 2153 | break; | 2145 | break; |
| 2154 | case PR_SET_CHILD_SUBREAPER: | 2146 | case PR_SET_CHILD_SUBREAPER: |
| 2155 | me->signal->is_child_subreaper = !!arg2; | 2147 | me->signal->is_child_subreaper = !!arg2; |
| 2156 | error = 0; | ||
| 2157 | break; | 2148 | break; |
| 2158 | case PR_GET_CHILD_SUBREAPER: | 2149 | case PR_GET_CHILD_SUBREAPER: |
| 2159 | error = put_user(me->signal->is_child_subreaper, | 2150 | error = put_user(me->signal->is_child_subreaper, |
| @@ -2195,46 +2186,52 @@ static void argv_cleanup(struct subprocess_info *info) | |||
| 2195 | argv_free(info->argv); | 2186 | argv_free(info->argv); |
| 2196 | } | 2187 | } |
| 2197 | 2188 | ||
| 2198 | /** | 2189 | static int __orderly_poweroff(void) |
| 2199 | * orderly_poweroff - Trigger an orderly system poweroff | ||
| 2200 | * @force: force poweroff if command execution fails | ||
| 2201 | * | ||
| 2202 | * This may be called from any context to trigger a system shutdown. | ||
| 2203 | * If the orderly shutdown fails, it will force an immediate shutdown. | ||
| 2204 | */ | ||
| 2205 | int orderly_poweroff(bool force) | ||
| 2206 | { | 2190 | { |
| 2207 | int argc; | 2191 | int argc; |
| 2208 | char **argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); | 2192 | char **argv; |
| 2209 | static char *envp[] = { | 2193 | static char *envp[] = { |
| 2210 | "HOME=/", | 2194 | "HOME=/", |
| 2211 | "PATH=/sbin:/bin:/usr/sbin:/usr/bin", | 2195 | "PATH=/sbin:/bin:/usr/sbin:/usr/bin", |
| 2212 | NULL | 2196 | NULL |
| 2213 | }; | 2197 | }; |
| 2214 | int ret = -ENOMEM; | 2198 | int ret; |
| 2215 | 2199 | ||
| 2200 | argv = argv_split(GFP_ATOMIC, poweroff_cmd, &argc); | ||
| 2216 | if (argv == NULL) { | 2201 | if (argv == NULL) { |
| 2217 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", | 2202 | printk(KERN_WARNING "%s failed to allocate memory for \"%s\"\n", |
| 2218 | __func__, poweroff_cmd); | 2203 | __func__, poweroff_cmd); |
| 2219 | goto out; | 2204 | return -ENOMEM; |
| 2220 | } | 2205 | } |
| 2221 | 2206 | ||
| 2222 | ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, | 2207 | ret = call_usermodehelper_fns(argv[0], argv, envp, UMH_NO_WAIT, |
| 2223 | NULL, argv_cleanup, NULL); | 2208 | NULL, argv_cleanup, NULL); |
| 2224 | out: | ||
| 2225 | if (likely(!ret)) | ||
| 2226 | return 0; | ||
| 2227 | |||
| 2228 | if (ret == -ENOMEM) | 2209 | if (ret == -ENOMEM) |
| 2229 | argv_free(argv); | 2210 | argv_free(argv); |
| 2230 | 2211 | ||
| 2231 | if (force) { | 2212 | return ret; |
| 2213 | } | ||
| 2214 | |||
| 2215 | /** | ||
| 2216 | * orderly_poweroff - Trigger an orderly system poweroff | ||
| 2217 | * @force: force poweroff if command execution fails | ||
| 2218 | * | ||
| 2219 | * This may be called from any context to trigger a system shutdown. | ||
| 2220 | * If the orderly shutdown fails, it will force an immediate shutdown. | ||
| 2221 | */ | ||
| 2222 | int orderly_poweroff(bool force) | ||
| 2223 | { | ||
| 2224 | int ret = __orderly_poweroff(); | ||
| 2225 | |||
| 2226 | if (ret && force) { | ||
| 2232 | printk(KERN_WARNING "Failed to start orderly shutdown: " | 2227 | printk(KERN_WARNING "Failed to start orderly shutdown: " |
| 2233 | "forcing the issue\n"); | 2228 | "forcing the issue\n"); |
| 2234 | 2229 | ||
| 2235 | /* I guess this should try to kick off some daemon to | 2230 | /* |
| 2236 | sync and poweroff asap. Or not even bother syncing | 2231 | * I guess this should try to kick off some daemon to sync and |
| 2237 | if we're doing an emergency shutdown? */ | 2232 | * poweroff asap. Or not even bother syncing if we're doing an |
| 2233 | * emergency shutdown? | ||
| 2234 | */ | ||
| 2238 | emergency_sync(); | 2235 | emergency_sync(); |
| 2239 | kernel_power_off(); | 2236 | kernel_power_off(); |
| 2240 | } | 2237 | } |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 4ab11879aeb4..97186b99b0e4 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/security.h> | 30 | #include <linux/security.h> |
| 31 | #include <linux/ctype.h> | 31 | #include <linux/ctype.h> |
| 32 | #include <linux/kmemcheck.h> | 32 | #include <linux/kmemcheck.h> |
| 33 | #include <linux/kmemleak.h> | ||
| 33 | #include <linux/fs.h> | 34 | #include <linux/fs.h> |
| 34 | #include <linux/init.h> | 35 | #include <linux/init.h> |
| 35 | #include <linux/kernel.h> | 36 | #include <linux/kernel.h> |
| @@ -174,6 +175,11 @@ static int proc_dointvec_minmax_sysadmin(struct ctl_table *table, int write, | |||
| 174 | void __user *buffer, size_t *lenp, loff_t *ppos); | 175 | void __user *buffer, size_t *lenp, loff_t *ppos); |
| 175 | #endif | 176 | #endif |
| 176 | 177 | ||
| 178 | static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, | ||
| 179 | void __user *buffer, size_t *lenp, loff_t *ppos); | ||
| 180 | static int proc_dostring_coredump(struct ctl_table *table, int write, | ||
| 181 | void __user *buffer, size_t *lenp, loff_t *ppos); | ||
| 182 | |||
| 177 | #ifdef CONFIG_MAGIC_SYSRQ | 183 | #ifdef CONFIG_MAGIC_SYSRQ |
| 178 | /* Note: sysrq code uses it's own private copy */ | 184 | /* Note: sysrq code uses it's own private copy */ |
| 179 | static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; | 185 | static int __sysrq_enabled = SYSRQ_DEFAULT_ENABLE; |
| @@ -410,7 +416,7 @@ static struct ctl_table kern_table[] = { | |||
| 410 | .data = core_pattern, | 416 | .data = core_pattern, |
| 411 | .maxlen = CORENAME_MAX_SIZE, | 417 | .maxlen = CORENAME_MAX_SIZE, |
| 412 | .mode = 0644, | 418 | .mode = 0644, |
| 413 | .proc_handler = proc_dostring, | 419 | .proc_handler = proc_dostring_coredump, |
| 414 | }, | 420 | }, |
| 415 | { | 421 | { |
| 416 | .procname = "core_pipe_limit", | 422 | .procname = "core_pipe_limit", |
| @@ -1498,7 +1504,7 @@ static struct ctl_table fs_table[] = { | |||
| 1498 | .data = &suid_dumpable, | 1504 | .data = &suid_dumpable, |
| 1499 | .maxlen = sizeof(int), | 1505 | .maxlen = sizeof(int), |
| 1500 | .mode = 0644, | 1506 | .mode = 0644, |
| 1501 | .proc_handler = proc_dointvec_minmax, | 1507 | .proc_handler = proc_dointvec_minmax_coredump, |
| 1502 | .extra1 = &zero, | 1508 | .extra1 = &zero, |
| 1503 | .extra2 = &two, | 1509 | .extra2 = &two, |
| 1504 | }, | 1510 | }, |
| @@ -1551,7 +1557,10 @@ static struct ctl_table dev_table[] = { | |||
| 1551 | 1557 | ||
| 1552 | int __init sysctl_init(void) | 1558 | int __init sysctl_init(void) |
| 1553 | { | 1559 | { |
| 1554 | register_sysctl_table(sysctl_base_table); | 1560 | struct ctl_table_header *hdr; |
| 1561 | |||
| 1562 | hdr = register_sysctl_table(sysctl_base_table); | ||
| 1563 | kmemleak_not_leak(hdr); | ||
| 1555 | return 0; | 1564 | return 0; |
| 1556 | } | 1565 | } |
| 1557 | 1566 | ||
| @@ -2009,6 +2018,34 @@ int proc_dointvec_minmax(struct ctl_table *table, int write, | |||
| 2009 | do_proc_dointvec_minmax_conv, ¶m); | 2018 | do_proc_dointvec_minmax_conv, ¶m); |
| 2010 | } | 2019 | } |
| 2011 | 2020 | ||
| 2021 | static void validate_coredump_safety(void) | ||
| 2022 | { | ||
| 2023 | if (suid_dumpable == SUID_DUMPABLE_SAFE && | ||
| 2024 | core_pattern[0] != '/' && core_pattern[0] != '|') { | ||
| 2025 | printk(KERN_WARNING "Unsafe core_pattern used with "\ | ||
| 2026 | "suid_dumpable=2. Pipe handler or fully qualified "\ | ||
| 2027 | "core dump path required.\n"); | ||
| 2028 | } | ||
| 2029 | } | ||
| 2030 | |||
| 2031 | static int proc_dointvec_minmax_coredump(struct ctl_table *table, int write, | ||
| 2032 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
| 2033 | { | ||
| 2034 | int error = proc_dointvec_minmax(table, write, buffer, lenp, ppos); | ||
| 2035 | if (!error) | ||
| 2036 | validate_coredump_safety(); | ||
| 2037 | return error; | ||
| 2038 | } | ||
| 2039 | |||
| 2040 | static int proc_dostring_coredump(struct ctl_table *table, int write, | ||
| 2041 | void __user *buffer, size_t *lenp, loff_t *ppos) | ||
| 2042 | { | ||
| 2043 | int error = proc_dostring(table, write, buffer, lenp, ppos); | ||
| 2044 | if (!error) | ||
| 2045 | validate_coredump_safety(); | ||
| 2046 | return error; | ||
| 2047 | } | ||
| 2048 | |||
| 2012 | static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write, | 2049 | static int __do_proc_doulongvec_minmax(void *data, struct ctl_table *table, int write, |
| 2013 | void __user *buffer, | 2050 | void __user *buffer, |
| 2014 | size_t *lenp, loff_t *ppos, | 2051 | size_t *lenp, loff_t *ppos, |
diff --git a/kernel/taskstats.c b/kernel/taskstats.c index e66046456f4f..d0a32796550f 100644 --- a/kernel/taskstats.c +++ b/kernel/taskstats.c | |||
| @@ -436,6 +436,11 @@ static int cgroupstats_user_cmd(struct sk_buff *skb, struct genl_info *info) | |||
| 436 | 436 | ||
| 437 | na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS, | 437 | na = nla_reserve(rep_skb, CGROUPSTATS_TYPE_CGROUP_STATS, |
| 438 | sizeof(struct cgroupstats)); | 438 | sizeof(struct cgroupstats)); |
| 439 | if (na == NULL) { | ||
| 440 | rc = -EMSGSIZE; | ||
| 441 | goto err; | ||
| 442 | } | ||
| 443 | |||
| 439 | stats = nla_data(na); | 444 | stats = nla_data(na); |
| 440 | memset(stats, 0, sizeof(*stats)); | 445 | memset(stats, 0, sizeof(*stats)); |
| 441 | 446 | ||
diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 4b1dfba70f7c..69add8a9da68 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c | |||
| @@ -575,7 +575,7 @@ out: | |||
| 575 | /* | 575 | /* |
| 576 | * Create/destroy watchdog threads as CPUs come and go: | 576 | * Create/destroy watchdog threads as CPUs come and go: |
| 577 | */ | 577 | */ |
| 578 | static int __cpuinit | 578 | static int |
| 579 | cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | 579 | cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) |
| 580 | { | 580 | { |
| 581 | int hotcpu = (unsigned long)hcpu; | 581 | int hotcpu = (unsigned long)hcpu; |
| @@ -610,10 +610,27 @@ cpu_callback(struct notifier_block *nfb, unsigned long action, void *hcpu) | |||
| 610 | return NOTIFY_OK; | 610 | return NOTIFY_OK; |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | static struct notifier_block __cpuinitdata cpu_nfb = { | 613 | static struct notifier_block cpu_nfb = { |
| 614 | .notifier_call = cpu_callback | 614 | .notifier_call = cpu_callback |
| 615 | }; | 615 | }; |
| 616 | 616 | ||
| 617 | #ifdef CONFIG_SUSPEND | ||
| 618 | /* | ||
| 619 | * On exit from suspend we force an offline->online transition on the boot CPU | ||
| 620 | * so that the PMU state that was lost while in suspended state gets set up | ||
| 621 | * properly for the boot CPU. This information is required for restarting the | ||
| 622 | * NMI watchdog. | ||
| 623 | */ | ||
| 624 | void lockup_detector_bootcpu_resume(void) | ||
| 625 | { | ||
| 626 | void *cpu = (void *)(long)smp_processor_id(); | ||
| 627 | |||
| 628 | cpu_callback(&cpu_nfb, CPU_DEAD_FROZEN, cpu); | ||
| 629 | cpu_callback(&cpu_nfb, CPU_UP_PREPARE_FROZEN, cpu); | ||
| 630 | cpu_callback(&cpu_nfb, CPU_ONLINE_FROZEN, cpu); | ||
| 631 | } | ||
| 632 | #endif | ||
| 633 | |||
| 617 | void __init lockup_detector_init(void) | 634 | void __init lockup_detector_init(void) |
| 618 | { | 635 | { |
| 619 | void *cpu = (void *)(long)smp_processor_id(); | 636 | void *cpu = (void *)(long)smp_processor_id(); |
