aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2009-01-19 06:36:09 -0500
committerIngo Molnar <mingo@elte.hu>2009-01-19 06:36:09 -0500
commit7890ba8c87604ca4c2c73f7de846bf5305d743e4 (patch)
treef3f920c09b8de694b1bc1d4b878cfd2b0b98c913 /arch
parent99937d6455cea95405ac681c86a857d0fcd530bd (diff)
parentb2b062b8163391c42b3219d466ca1ac9742b9c7b (diff)
Merge branch 'stackprotector' into core/percpu
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/Kconfig23
-rw-r--r--arch/x86/Kconfig.debug1
-rw-r--r--arch/x86/Makefile2
-rw-r--r--arch/x86/include/asm/pda.h4
-rw-r--r--arch/x86/include/asm/stackprotector.h39
-rw-r--r--arch/x86/include/asm/system.h6
-rw-r--r--arch/x86/kernel/Makefile1
-rw-r--r--arch/x86/kernel/process_64.c13
-rw-r--r--arch/x86/mm/fault.c7
9 files changed, 78 insertions, 18 deletions
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 73f7fe8fd4d1..ef27aed6ff74 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1340,13 +1340,17 @@ config SECCOMP
1340 1340
1341 If unsure, say Y. Only embedded should say N here. 1341 If unsure, say Y. Only embedded should say N here.
1342 1342
1343config CC_STACKPROTECTOR_ALL
1344 bool
1345
1343config CC_STACKPROTECTOR 1346config CC_STACKPROTECTOR
1344 bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" 1347 bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)"
1345 depends on X86_64 && EXPERIMENTAL && BROKEN 1348 depends on X86_64
1349 select CC_STACKPROTECTOR_ALL
1346 help 1350 help
1347 This option turns on the -fstack-protector GCC feature. This 1351 This option turns on the -fstack-protector GCC feature. This
1348 feature puts, at the beginning of critical functions, a canary 1352 feature puts, at the beginning of functions, a canary value on
1349 value on the stack just before the return address, and validates 1353 the stack just before the return address, and validates
1350 the value just before actually returning. Stack based buffer 1354 the value just before actually returning. Stack based buffer
1351 overflows (that need to overwrite this return address) now also 1355 overflows (that need to overwrite this return address) now also
1352 overwrite the canary, which gets detected and the attack is then 1356 overwrite the canary, which gets detected and the attack is then
@@ -1354,15 +1358,8 @@ config CC_STACKPROTECTOR
1354 1358
1355 This feature requires gcc version 4.2 or above, or a distribution 1359 This feature requires gcc version 4.2 or above, or a distribution
1356 gcc with the feature backported. Older versions are automatically 1360 gcc with the feature backported. Older versions are automatically
1357 detected and for those versions, this configuration option is ignored. 1361 detected and for those versions, this configuration option is
1358 1362 ignored. (and a warning is printed during bootup)
1359config CC_STACKPROTECTOR_ALL
1360 bool "Use stack-protector for all functions"
1361 depends on CC_STACKPROTECTOR
1362 help
1363 Normally, GCC only inserts the canary value protection for
1364 functions that use large-ish on-stack buffers. By enabling
1365 this option, GCC will be asked to do this for ALL functions.
1366 1363
1367source kernel/Kconfig.hz 1364source kernel/Kconfig.hz
1368 1365
diff --git a/arch/x86/Kconfig.debug b/arch/x86/Kconfig.debug
index 10d6cc3fd052..28f111461ca8 100644
--- a/arch/x86/Kconfig.debug
+++ b/arch/x86/Kconfig.debug
@@ -117,6 +117,7 @@ config DEBUG_RODATA
117config DEBUG_RODATA_TEST 117config DEBUG_RODATA_TEST
118 bool "Testcase for the DEBUG_RODATA feature" 118 bool "Testcase for the DEBUG_RODATA feature"
119 depends on DEBUG_RODATA 119 depends on DEBUG_RODATA
120 default y
120 help 121 help
121 This option enables a testcase for the DEBUG_RODATA 122 This option enables a testcase for the DEBUG_RODATA
122 feature as well as for the change_page_attr() infrastructure. 123 feature as well as for the change_page_attr() infrastructure.
diff --git a/arch/x86/Makefile b/arch/x86/Makefile
index d1a47adb5aec..cacee981d166 100644
--- a/arch/x86/Makefile
+++ b/arch/x86/Makefile
@@ -73,7 +73,7 @@ else
73 73
74 stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh 74 stackp := $(CONFIG_SHELL) $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh
75 stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \ 75 stackp-$(CONFIG_CC_STACKPROTECTOR) := $(shell $(stackp) \
76 "$(CC)" -fstack-protector ) 76 "$(CC)" "-fstack-protector -DGCC_HAS_SP" )
77 stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \ 77 stackp-$(CONFIG_CC_STACKPROTECTOR_ALL) += $(shell $(stackp) \
78 "$(CC)" -fstack-protector-all ) 78 "$(CC)" -fstack-protector-all )
79 79
diff --git a/arch/x86/include/asm/pda.h b/arch/x86/include/asm/pda.h
index c31ca048a901..5976cd803e9a 100644
--- a/arch/x86/include/asm/pda.h
+++ b/arch/x86/include/asm/pda.h
@@ -17,11 +17,9 @@ struct x8664_pda {
17 unsigned long unused4; 17 unsigned long unused4;
18 int unused5; 18 int unused5;
19 unsigned int unused6; /* 36 was cpunumber */ 19 unsigned int unused6; /* 36 was cpunumber */
20#ifdef CONFIG_CC_STACKPROTECTOR
21 unsigned long stack_canary; /* 40 stack canary value */ 20 unsigned long stack_canary; /* 40 stack canary value */
22 /* gcc-ABI: this canary MUST be at 21 /* gcc-ABI: this canary MUST be at
23 offset 40!!! */ 22 offset 40!!! */
24#endif
25 short in_bootmem; /* pda lives in bootmem */ 23 short in_bootmem; /* pda lives in bootmem */
26} ____cacheline_aligned_in_smp; 24} ____cacheline_aligned_in_smp;
27 25
@@ -42,4 +40,6 @@ extern void pda_init(int);
42 40
43#endif 41#endif
44 42
43#define refresh_stack_canary() write_pda(stack_canary, current->stack_canary)
44
45#endif /* _ASM_X86_PDA_H */ 45#endif /* _ASM_X86_PDA_H */
diff --git a/arch/x86/include/asm/stackprotector.h b/arch/x86/include/asm/stackprotector.h
new file mode 100644
index 000000000000..c7f0d10bae7b
--- /dev/null
+++ b/arch/x86/include/asm/stackprotector.h
@@ -0,0 +1,39 @@
1#ifndef _ASM_STACKPROTECTOR_H
2#define _ASM_STACKPROTECTOR_H 1
3
4#include <asm/tsc.h>
5#include <asm/pda.h>
6
7/*
8 * Initialize the stackprotector canary value.
9 *
10 * NOTE: this must only be called from functions that never return,
11 * and it must always be inlined.
12 */
13static __always_inline void boot_init_stack_canary(void)
14{
15 u64 canary;
16 u64 tsc;
17
18 /*
19 * If we're the non-boot CPU, nothing set the PDA stack
20 * canary up for us - and if we are the boot CPU we have
21 * a 0 stack canary. This is a good place for updating
22 * it, as we wont ever return from this function (so the
23 * invalid canaries already on the stack wont ever
24 * trigger).
25 *
26 * We both use the random pool and the current TSC as a source
27 * of randomness. The TSC only matters for very early init,
28 * there it already has some randomness on most systems. Later
29 * on during the bootup the random pool has true entropy too.
30 */
31 get_random_bytes(&canary, sizeof(canary));
32 tsc = __native_read_tsc();
33 canary += tsc + (tsc << 32UL);
34
35 current->stack_canary = canary;
36 write_pda(stack_canary, canary);
37}
38
39#endif
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index d1dc27dba36d..8cadfe9b1194 100644
--- a/arch/x86/include/asm/system.h
+++ b/arch/x86/include/asm/system.h
@@ -95,6 +95,8 @@ do { \
95 ".globl thread_return\n" \ 95 ".globl thread_return\n" \
96 "thread_return:\n\t" \ 96 "thread_return:\n\t" \
97 "movq "__percpu_arg([current_task])",%%rsi\n\t" \ 97 "movq "__percpu_arg([current_task])",%%rsi\n\t" \
98 "movq %P[task_canary](%%rsi),%%r8\n\t" \
99 "movq %%r8,%%gs:%P[pda_canary]\n\t" \
98 "movq %P[thread_info](%%rsi),%%r8\n\t" \ 100 "movq %P[thread_info](%%rsi),%%r8\n\t" \
99 LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \ 101 LOCK_PREFIX "btr %[tif_fork],%P[ti_flags](%%r8)\n\t" \
100 "movq %%rax,%%rdi\n\t" \ 102 "movq %%rax,%%rdi\n\t" \
@@ -106,7 +108,9 @@ do { \
106 [ti_flags] "i" (offsetof(struct thread_info, flags)), \ 108 [ti_flags] "i" (offsetof(struct thread_info, flags)), \
107 [tif_fork] "i" (TIF_FORK), \ 109 [tif_fork] "i" (TIF_FORK), \
108 [thread_info] "i" (offsetof(struct task_struct, stack)), \ 110 [thread_info] "i" (offsetof(struct task_struct, stack)), \
109 [current_task] "m" (per_cpu_var(current_task)) \ 111 [task_canary] "i" (offsetof(struct task_struct, stack_canary)),\
112 [current_task] "m" (per_cpu_var(current_task)), \
113 [pda_canary] "i" (offsetof(struct x8664_pda, stack_canary))\
110 : "memory", "cc" __EXTRA_CLOBBER) 114 : "memory", "cc" __EXTRA_CLOBBER)
111#endif 115#endif
112 116
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile
index d364df03c1d6..eb074530c7d3 100644
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -23,6 +23,7 @@ nostackp := $(call cc-option, -fno-stack-protector)
23CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp) 23CFLAGS_vsyscall_64.o := $(PROFILING) -g0 $(nostackp)
24CFLAGS_hpet.o := $(nostackp) 24CFLAGS_hpet.o := $(nostackp)
25CFLAGS_tsc.o := $(nostackp) 25CFLAGS_tsc.o := $(nostackp)
26CFLAGS_paravirt.o := $(nostackp)
26 27
27obj-y := process_$(BITS).o signal.o entry_$(BITS).o 28obj-y := process_$(BITS).o signal.o entry_$(BITS).o
28obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o 29obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 4523ff88a69d..aa89eabf09e0 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -16,6 +16,7 @@
16 16
17#include <stdarg.h> 17#include <stdarg.h>
18 18
19#include <linux/stackprotector.h>
19#include <linux/cpu.h> 20#include <linux/cpu.h>
20#include <linux/errno.h> 21#include <linux/errno.h>
21#include <linux/sched.h> 22#include <linux/sched.h>
@@ -117,6 +118,17 @@ static inline void play_dead(void)
117void cpu_idle(void) 118void cpu_idle(void)
118{ 119{
119 current_thread_info()->status |= TS_POLLING; 120 current_thread_info()->status |= TS_POLLING;
121
122 /*
123 * If we're the non-boot CPU, nothing set the PDA stack
124 * canary up for us - and if we are the boot CPU we have
125 * a 0 stack canary. This is a good place for updating
126 * it, as we wont ever return from this function (so the
127 * invalid canaries already on the stack wont ever
128 * trigger):
129 */
130 boot_init_stack_canary();
131
120 /* endless idle loop with no priority at all */ 132 /* endless idle loop with no priority at all */
121 while (1) { 133 while (1) {
122 tick_nohz_stop_sched_tick(1); 134 tick_nohz_stop_sched_tick(1);
@@ -627,7 +639,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
627 (unsigned long)task_stack_page(next_p) + 639 (unsigned long)task_stack_page(next_p) +
628 THREAD_SIZE - KERNEL_STACK_OFFSET); 640 THREAD_SIZE - KERNEL_STACK_OFFSET);
629#ifdef CONFIG_CC_STACKPROTECTOR 641#ifdef CONFIG_CC_STACKPROTECTOR
630 write_pda(stack_canary, next_p->stack_canary);
631 /* 642 /*
632 * Build time only check to make sure the stack_canary is at 643 * Build time only check to make sure the stack_canary is at
633 * offset 40 in the pda; this is a gcc ABI requirement 644 * offset 40 in the pda; this is a gcc ABI requirement
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 90dfae511a41..37242c405f16 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -26,6 +26,7 @@
26#include <linux/kprobes.h> 26#include <linux/kprobes.h>
27#include <linux/uaccess.h> 27#include <linux/uaccess.h>
28#include <linux/kdebug.h> 28#include <linux/kdebug.h>
29#include <linux/magic.h>
29 30
30#include <asm/system.h> 31#include <asm/system.h>
31#include <asm/desc.h> 32#include <asm/desc.h>
@@ -589,6 +590,8 @@ void __kprobes do_page_fault(struct pt_regs *regs, unsigned long error_code)
589 unsigned long address; 590 unsigned long address;
590 int write, si_code; 591 int write, si_code;
591 int fault; 592 int fault;
593 unsigned long *stackend;
594
592#ifdef CONFIG_X86_64 595#ifdef CONFIG_X86_64
593 unsigned long flags; 596 unsigned long flags;
594 int sig; 597 int sig;
@@ -841,6 +844,10 @@ no_context:
841 844
842 show_fault_oops(regs, error_code, address); 845 show_fault_oops(regs, error_code, address);
843 846
847 stackend = end_of_stack(tsk);
848 if (*stackend != STACK_END_MAGIC)
849 printk(KERN_ALERT "Thread overran stack, or stack corrupted\n");
850
844 tsk->thread.cr2 = address; 851 tsk->thread.cr2 = address;
845 tsk->thread.trap_no = 14; 852 tsk->thread.trap_no = 14;
846 tsk->thread.error_code = error_code; 853 tsk->thread.error_code = error_code;