]>
Commit | Line | Data |
---|---|---|
c5a9e72a PS |
1 | diff -uNr linux-2.6.16.orig/arch/x86_64/Kconfig linux-2.6.16/arch/x86_64/Kconfig |
2 | --- linux-2.6.16.orig/arch/x86_64/Kconfig 2006-08-27 09:02:03.754054500 +0200 | |
3 | +++ linux-2.6.16/arch/x86_64/Kconfig 2006-08-27 09:12:33.514413750 +0200 | |
4 | @@ -464,6 +464,30 @@ | |
5 | ||
6 | If unsure, say Y. Only embedded should say N here. | |
7 | ||
8 | +config CC_STACKPROTECTOR | |
9 | + bool "Enable -fstack-protector buffer overflow detection (EXPRIMENTAL)" | |
10 | + depends on EXPERIMENTAL | |
11 | + help | |
12 | + This option turns on the -fstack-protector GCC feature. This | |
13 | + feature puts, at the beginning of critical functions, a canary | |
14 | + value on the stack just before the return address, and validates | |
15 | + the value just before actually returning. Stack based buffer | |
16 | + overflows (that need to overwrite this return address) now also | |
17 | + overwrite the canary, which gets detected and the attack is then | |
18 | + neutralized via a kernel panic. | |
19 | + | |
20 | + This feature requires gcc version 4.2 or above, or a distribution | |
21 | + gcc with the feature backported. Older versions are automatically | |
22 | + detected and for those versions, this configuration option is ignored. | |
23 | + | |
24 | +config CC_STACKPROTECTOR_ALL | |
25 | + bool "Use stack-protector for all functions" | |
26 | + depends on CC_STACKPROTECTOR | |
27 | + help | |
28 | + Normally, GCC only inserts the canary value protection for | |
29 | + functions that use large-ish on-stack buffers. By enabling | |
30 | + this option, GCC will be asked to do this for ALL functions. | |
31 | + | |
32 | source kernel/Kconfig.hz | |
33 | ||
34 | endmenu | |
35 | diff -uNr linux-2.6.16.orig/arch/x86_64/kernel/process.c linux-2.6.16/arch/x86_64/kernel/process.c | |
36 | --- linux-2.6.16.orig/arch/x86_64/kernel/process.c 2006-08-27 09:02:03.798035250 +0200 | |
37 | +++ linux-2.6.16/arch/x86_64/kernel/process.c 2006-08-27 09:12:52.254211500 +0200 | |
38 | @@ -598,6 +598,14 @@ | |
39 | ||
40 | write_pda(kernelstack, | |
41 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); | |
42 | +#ifdef CONFIG_CC_STACKPROTECTOR | |
43 | + write_pda(stack_canary, next_p->stack_canary); | |
44 | + /* | |
45 | + * Build time only check to make sure the stack_canary is at | |
46 | + * offset 40 in the pda; this is a gcc ABI requirement | |
47 | + */ | |
48 | + BUILD_BUG_ON(offsetof(struct x8664_pda, stack_canary) != 40); | |
49 | +#endif | |
50 | ||
51 | /* | |
52 | * Now maybe reload the debug registers | |
53 | diff -uNr linux-2.6.16.orig/arch/x86_64/Makefile linux-2.6.16/arch/x86_64/Makefile | |
54 | --- linux-2.6.16.orig/arch/x86_64/Makefile 2006-03-20 06:53:29.000000000 +0100 | |
55 | +++ linux-2.6.16/arch/x86_64/Makefile 2006-08-27 09:13:17.898987000 +0200 | |
56 | @@ -29,6 +29,14 @@ | |
57 | ||
58 | cflags-$(CONFIG_MK8) += $(call cc-option,-march=k8) | |
59 | cflags-$(CONFIG_MPSC) += $(call cc-option,-march=nocona) | |
60 | + | |
61 | +stack-protector = $(shell $(CONFIG_SHELL) \ | |
62 | + $(srctree)/scripts/gcc-x86_64-has-stack-protector.sh $(1)) | |
63 | +cflags-$(CONFIG_CC_STACKPROTECTOR) += \ | |
64 | + $(call stack-protector, $(CC) -fstack-protector) | |
65 | +cflags-$(CONFIG_CC_STACKPROTECTOR_ALL) += \ | |
66 | + $(call stack-protector, $(CC) -fstack-protector-all) | |
67 | + | |
68 | CFLAGS += $(cflags-y) | |
69 | ||
70 | CFLAGS += -m64 | |
71 | diff -uNr linux-2.6.16.orig/include/asm-x86_64/pda.h linux-2.6.16/include/asm-x86_64/pda.h | |
72 | --- linux-2.6.16.orig/include/asm-x86_64/pda.h 2006-03-20 06:53:29.000000000 +0100 | |
73 | +++ linux-2.6.16/include/asm-x86_64/pda.h 2006-08-27 09:12:52.254211500 +0200 | |
74 | @@ -9,14 +9,16 @@ | |
75 | ||
76 | /* Per processor datastructure. %gs points to it while the kernel runs */ | |
77 | struct x8664_pda { | |
78 | - struct task_struct *pcurrent; /* Current process */ | |
79 | - unsigned long data_offset; /* Per cpu data offset from linker address */ | |
80 | - unsigned long kernelstack; /* top of kernel stack for current */ | |
81 | - unsigned long oldrsp; /* user rsp for system call */ | |
82 | -#if DEBUG_STKSZ > EXCEPTION_STKSZ | |
83 | - unsigned long debugstack; /* #DB/#BP stack. */ | |
84 | + struct task_struct *pcurrent; /* 0 */ /* Current process */ | |
85 | + unsigned long data_offset; /* 8 */ /* Per cpu data offset from linker address */ | |
86 | + unsigned long kernelstack; /* 16 */ /* top of kernel stack for current */ | |
87 | + unsigned long oldrsp; /* 24 */ /* user rsp for system call */ | |
88 | + unsigned long debugstack; /* 32 */ /* #DB/#BP stack. */ | |
89 | +#ifdef CONFIG_CC_STACKPROTECTOR | |
90 | + unsigned long stack_canary; /* 40 */ /* stack canary value */ | |
91 | + /* gcc-ABI: this canary MUST be at offset 40!!! */ | |
92 | #endif | |
93 | - int irqcount; /* Irq nesting counter. Starts with -1 */ | |
94 | + int irqcount; /* 48 */ /* Irq nesting counter. Starts with -1 */ | |
95 | int cpunumber; /* Logical CPU number */ | |
96 | char *irqstackptr; /* top of irqstack */ | |
97 | int nodenumber; /* number of current node */ | |
98 | diff -uNr linux-2.6.16.orig/include/linux/sched.h linux-2.6.16/include/linux/sched.h | |
99 | --- linux-2.6.16.orig/include/linux/sched.h 2006-08-27 09:02:04.285821750 +0200 | |
100 | +++ linux-2.6.16/include/linux/sched.h 2006-08-27 09:12:52.254211500 +0200 | |
101 | @@ -755,6 +755,11 @@ | |
102 | unsigned did_exec:1; | |
103 | pid_t pid; | |
104 | pid_t tgid; | |
105 | + | |
106 | +#ifdef CONFIG_CC_STACKPROTECTOR | |
107 | + /* Canary value for the -fstack-protector gcc feature */ | |
108 | + unsigned long stack_canary; | |
109 | +#endif | |
110 | /* | |
111 | * pointers to (original) parent process, youngest child, younger sibling, | |
112 | * older sibling, respectively. (p->father can be replaced with | |
113 | diff -uNr linux-2.6.16.orig/kernel/fork.c linux-2.6.16/kernel/fork.c | |
114 | --- linux-2.6.16.orig/kernel/fork.c 2006-08-27 09:02:04.097904000 +0200 | |
115 | +++ linux-2.6.16/kernel/fork.c 2006-08-27 09:12:52.254211500 +0200 | |
116 | @@ -45,6 +45,7 @@ | |
117 | #include <linux/acct.h> | |
118 | #include <linux/cn_proc.h> | |
119 | #include <linux/vs_context.h> | |
120 | +#include <linux/random.h> | |
121 | #include <linux/vs_network.h> | |
122 | #include <linux/vs_limit.h> | |
123 | #include <linux/vs_memory.h> | |
124 | @@ -184,6 +185,10 @@ | |
125 | tsk->thread_info = ti; | |
126 | setup_thread_stack(tsk, orig); | |
127 | ||
128 | +#ifdef CONFIG_CC_STACKPROTECTOR | |
129 | + tsk->stack_canary = get_random_int(); | |
130 | +#endif | |
131 | + | |
132 | /* One for us, one for whoever does the "release_task()" (usually parent) */ | |
133 | atomic_set(&tsk->usage,2); | |
134 | atomic_set(&tsk->fs_excl, 0); | |
135 | diff -uNr linux-2.6.16.orig/kernel/panic.c linux-2.6.16/kernel/panic.c | |
136 | --- linux-2.6.16.orig/kernel/panic.c 2006-03-20 06:53:29.000000000 +0100 | |
137 | +++ linux-2.6.16/kernel/panic.c 2006-08-27 09:13:06.200107500 +0200 | |
138 | @@ -174,3 +174,15 @@ | |
139 | tainted |= flag; | |
140 | } | |
141 | EXPORT_SYMBOL(add_taint); | |
142 | + | |
143 | +#ifdef CONFIG_CC_STACKPROTECTOR | |
144 | +/* | |
145 | + * Called when gcc's -fstack-protector feature is used, and | |
146 | + * gcc detects corruption of the on-stack canary value | |
147 | + */ | |
148 | +void __stack_chk_fail(void) | |
149 | +{ | |
150 | + panic("stack-protector: Kernel stack is corrupted"); | |
151 | +} | |
152 | +EXPORT_SYMBOL(__stack_chk_fail); | |
153 | +#endif | |
154 | diff -uNr linux-2.6.16.orig/scripts/gcc-x86_64-has-stack-protector.sh linux-2.6.16/scripts/gcc-x86_64-has-stack-protector.sh | |
155 | --- linux-2.6.16.orig/scripts/gcc-x86_64-has-stack-protector.sh 1970-01-01 01:00:00.000000000 +0100 | |
156 | +++ linux-2.6.16/scripts/gcc-x86_64-has-stack-protector.sh 2006-08-27 09:13:17.898987000 +0200 | |
157 | @@ -0,0 +1,6 @@ | |
158 | +#!/bin/sh | |
159 | + | |
160 | +echo "int foo(void) { char X[200]; return 3; }" | $1 -S -xc -c -O0 -mcmodel=kernel -fstack-protector - -o - | grep -q "%gs" | |
161 | +if [ "$?" -eq "0" ] ; then | |
162 | + echo $2 | |
163 | +fi |