aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAaron Tomlin <atomlin@redhat.com>2014-09-12 09:16:17 -0400
committerIngo Molnar <mingo@kernel.org>2014-09-19 06:35:22 -0400
commitd4311ff1a8da48d609db9500f121c15580dfeeb7 (patch)
tree620cbe6099315aa528f173ae2ff70ee13ddd55f5
parenta15b12ac36ad4e7b856a4ae54937ae26a51aebad (diff)
init/main.c: Give init_task a canary
Tasks get their end of stack set to STACK_END_MAGIC with the aim to catch stack overruns. Currently this feature does not apply to init_task. This patch removes this restriction. Note that a similar patch was posted by Prarit Bhargava some time ago but was never merged: http://marc.info/?l=linux-kernel&m=127144305403241&w=2 Signed-off-by: Aaron Tomlin <atomlin@redhat.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Acked-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Michael Ellerman <mpe@ellerman.id.au> Cc: aneesh.kumar@linux.vnet.ibm.com Cc: dzickus@redhat.com Cc: bmr@redhat.com Cc: jcastillo@redhat.com Cc: jgh@redhat.com Cc: minchan@kernel.org Cc: tglx@linutronix.de Cc: hannes@cmpxchg.org Cc: Alex Thorlton <athorlton@sgi.com> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Daeseok Youn <daeseok.youn@gmail.com> Cc: David Rientjes <rientjes@google.com> Cc: Fabian Frederick <fabf@skynet.be> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Jiri Olsa <jolsa@redhat.com> Cc: Kees Cook <keescook@chromium.org> Cc: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com> Cc: Michael Opdenacker <michael.opdenacker@free-electrons.com> Cc: Paul Mackerras <paulus@samba.org> Cc: Prarit Bhargava <prarit@redhat.com> Cc: Rik van Riel <riel@redhat.com> Cc: Rusty Russell <rusty@rustcorp.com.au> Cc: Seiji Aguchi <seiji.aguchi@hds.com> Cc: Steven Rostedt <rostedt@goodmis.org> Cc: Vladimir Davydov <vdavydov@parallels.com> Cc: Yasuaki Ishimatsu <isimatu.yasuaki@jp.fujitsu.com> Cc: linuxppc-dev@lists.ozlabs.org Link: http://lkml.kernel.org/r/1410527779-8133-2-git-send-email-atomlin@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/powerpc/mm/fault.c3
-rw-r--r--arch/x86/mm/fault.c3
-rw-r--r--include/linux/sched.h2
-rw-r--r--init/main.c1
-rw-r--r--kernel/fork.c12
-rw-r--r--kernel/trace/trace_stack.c4
6 files changed, 15 insertions, 10 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c
index 51ab9e7e6c39..35d0760c3fa4 100644
--- a/arch/powerpc/mm/fault.c
+++ b/arch/powerpc/mm/fault.c
@@ -30,7 +30,6 @@
30#include <linux/kprobes.h> 30#include <linux/kprobes.h>
31#include <linux/kdebug.h> 31#include <linux/kdebug.h>
32#include <linux/perf_event.h> 32#include <linux/perf_event.h>
33#include <linux/magic.h>
34#include <linux/ratelimit.h> 33#include <linux/ratelimit.h>
35#include <linux/context_tracking.h> 34#include <linux/context_tracking.h>
36 35
@@ -538,7 +537,7 @@ void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig)
538 regs->nip); 537 regs->nip);
539 538
540 stackend = end_of_stack(current); 539 stackend = end_of_stack(current);
541 if (current != &init_task && *stackend != STACK_END_MAGIC) 540 if (*stackend != STACK_END_MAGIC)
542 printk(KERN_ALERT "Thread overran stack, or stack corrupted\n"); 541 printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
543 542
544 die("Kernel access of bad area", regs, sig); 543 die("Kernel access of bad area", regs, sig);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index a24194681513..bc23a7043c65 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -3,7 +3,6 @@
3 * Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs. 3 * Copyright (C) 2001, 2002 Andi Kleen, SuSE Labs.
4 * Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar 4 * Copyright (C) 2008-2009, Red Hat Inc., Ingo Molnar
5 */ 5 */
6#include <linux/magic.h> /* STACK_END_MAGIC */
7#include <linux/sched.h> /* test_thread_flag(), ... */ 6#include <linux/sched.h> /* test_thread_flag(), ... */
8#include <linux/kdebug.h> /* oops_begin/end, ... */ 7#include <linux/kdebug.h> /* oops_begin/end, ... */
9#include <linux/module.h> /* search_exception_table */ 8#include <linux/module.h> /* search_exception_table */
@@ -710,7 +709,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
710 show_fault_oops(regs, error_code, address); 709 show_fault_oops(regs, error_code, address);
711 710
712 stackend = end_of_stack(tsk); 711 stackend = end_of_stack(tsk);
713 if (tsk != &init_task && *stackend != STACK_END_MAGIC) 712 if (*stackend != STACK_END_MAGIC)
714 printk(KERN_EMERG "Thread overran stack, or stack corrupted\n"); 713 printk(KERN_EMERG "Thread overran stack, or stack corrupted\n");
715 714
716 tsk->thread.cr2 = address; 715 tsk->thread.cr2 = address;
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 82ff3d6efb19..118dca7d5a28 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -57,6 +57,7 @@ struct sched_param {
57#include <linux/llist.h> 57#include <linux/llist.h>
58#include <linux/uidgid.h> 58#include <linux/uidgid.h>
59#include <linux/gfp.h> 59#include <linux/gfp.h>
60#include <linux/magic.h>
60 61
61#include <asm/processor.h> 62#include <asm/processor.h>
62 63
@@ -2638,6 +2639,7 @@ static inline unsigned long stack_not_used(struct task_struct *p)
2638 return (unsigned long)n - (unsigned long)end_of_stack(p); 2639 return (unsigned long)n - (unsigned long)end_of_stack(p);
2639} 2640}
2640#endif 2641#endif
2642extern void set_task_stack_end_magic(struct task_struct *tsk);
2641 2643
2642/* set thread flags in other task's structures 2644/* set thread flags in other task's structures
2643 * - see asm/thread_info.h for TIF_xxxx flags available 2645 * - see asm/thread_info.h for TIF_xxxx flags available
diff --git a/init/main.c b/init/main.c
index bb1aed928f21..5fc3fc7bd475 100644
--- a/init/main.c
+++ b/init/main.c
@@ -508,6 +508,7 @@ asmlinkage __visible void __init start_kernel(void)
508 * lockdep hash: 508 * lockdep hash:
509 */ 509 */
510 lockdep_init(); 510 lockdep_init();
511 set_task_stack_end_magic(&init_task);
511 smp_setup_processor_id(); 512 smp_setup_processor_id();
512 debug_objects_early_init(); 513 debug_objects_early_init();
513 514
diff --git a/kernel/fork.c b/kernel/fork.c
index 9387ae8ab048..ad64248c4b18 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -294,11 +294,18 @@ int __weak arch_dup_task_struct(struct task_struct *dst,
294 return 0; 294 return 0;
295} 295}
296 296
297void set_task_stack_end_magic(struct task_struct *tsk)
298{
299 unsigned long *stackend;
300
301 stackend = end_of_stack(tsk);
302 *stackend = STACK_END_MAGIC; /* for overflow detection */
303}
304
297static struct task_struct *dup_task_struct(struct task_struct *orig) 305static struct task_struct *dup_task_struct(struct task_struct *orig)
298{ 306{
299 struct task_struct *tsk; 307 struct task_struct *tsk;
300 struct thread_info *ti; 308 struct thread_info *ti;
301 unsigned long *stackend;
302 int node = tsk_fork_get_node(orig); 309 int node = tsk_fork_get_node(orig);
303 int err; 310 int err;
304 311
@@ -328,8 +335,7 @@ static struct task_struct *dup_task_struct(struct task_struct *orig)
328 setup_thread_stack(tsk, orig); 335 setup_thread_stack(tsk, orig);
329 clear_user_return_notifier(tsk); 336 clear_user_return_notifier(tsk);
330 clear_tsk_need_resched(tsk); 337 clear_tsk_need_resched(tsk);
331 stackend = end_of_stack(tsk); 338 set_task_stack_end_magic(tsk);
332 *stackend = STACK_END_MAGIC; /* for overflow detection */
333 339
334#ifdef CONFIG_CC_STACKPROTECTOR 340#ifdef CONFIG_CC_STACKPROTECTOR
335 tsk->stack_canary = get_random_int(); 341 tsk->stack_canary = get_random_int();
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index 8a4e5cb66a4c..1636e41828c2 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -13,7 +13,6 @@
13#include <linux/sysctl.h> 13#include <linux/sysctl.h>
14#include <linux/init.h> 14#include <linux/init.h>
15#include <linux/fs.h> 15#include <linux/fs.h>
16#include <linux/magic.h>
17 16
18#include <asm/setup.h> 17#include <asm/setup.h>
19 18
@@ -171,8 +170,7 @@ check_stack(unsigned long ip, unsigned long *stack)
171 i++; 170 i++;
172 } 171 }
173 172
174 if ((current != &init_task && 173 if (*end_of_stack(current) != STACK_END_MAGIC) {
175 *(end_of_stack(current)) != STACK_END_MAGIC)) {
176 print_max_stack(); 174 print_max_stack();
177 BUG(); 175 BUG();
178 } 176 }