diff options
author | Gregory Fong <gregory.0xf0@gmail.com> | 2013-06-12 13:08:54 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2013-07-01 09:10:48 -0400 |
commit | 36ecafc5ad17861e2bc1fb12af4cc97680e25942 (patch) | |
tree | 8b1094782049660b366b417119d34a5a519e0c95 /arch/mips | |
parent | 23df34155b29674465813b327647cd79722aa659 (diff) |
MIPS: initial stack protector support
Implements basic stack protector support based on ARM version in
c743f38013aeff58ef6252601e397b5ba281c633 , with Kconfig option,
constant canary value set at boot time, and script to check if
compiler actually supports stack protector.
Tested by creating a kernel module that writes past end of char[].
Signed-off-by: Gregory Fong <gregory.0xf0@gmail.com>
Cc: linux-mips@linux-mips.org
Cc: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Cc: Carmelo Amoroso <carmelo.amoroso@st.com>
Patchwork: https://patchwork.linux-mips.org/patch/5448/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r-- | arch/mips/Kconfig | 13 | ||||
-rw-r--r-- | arch/mips/Makefile | 4 | ||||
-rw-r--r-- | arch/mips/include/asm/stackprotector.h | 40 | ||||
-rw-r--r-- | arch/mips/kernel/process.c | 6 |
4 files changed, 63 insertions, 0 deletions
diff --git a/arch/mips/Kconfig b/arch/mips/Kconfig index 69bf31062ca4..6dbeb273afc6 100644 --- a/arch/mips/Kconfig +++ b/arch/mips/Kconfig | |||
@@ -2367,6 +2367,19 @@ config SECCOMP | |||
2367 | 2367 | ||
2368 | If unsure, say Y. Only embedded should say N here. | 2368 | If unsure, say Y. Only embedded should say N here. |
2369 | 2369 | ||
2370 | config CC_STACKPROTECTOR | ||
2371 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | ||
2372 | help | ||
2373 | This option turns on the -fstack-protector GCC feature. This | ||
2374 | feature puts, at the beginning of functions, a canary value on | ||
2375 | the stack just before the return address, and validates | ||
2376 | the value just before actually returning. Stack based buffer | ||
2377 | overflows (that need to overwrite this return address) now also | ||
2378 | overwrite the canary, which gets detected and the attack is then | ||
2379 | neutralized via a kernel panic. | ||
2380 | |||
2381 | This feature requires gcc version 4.2 or above. | ||
2382 | |||
2370 | config USE_OF | 2383 | config USE_OF |
2371 | bool | 2384 | bool |
2372 | select OF | 2385 | select OF |
diff --git a/arch/mips/Makefile b/arch/mips/Makefile index dd58a04ef4bc..37f9ef324f2f 100644 --- a/arch/mips/Makefile +++ b/arch/mips/Makefile | |||
@@ -227,6 +227,10 @@ KBUILD_CPPFLAGS += -DDATAOFFSET=$(if $(dataoffset-y),$(dataoffset-y),0) | |||
227 | 227 | ||
228 | LDFLAGS += -m $(ld-emul) | 228 | LDFLAGS += -m $(ld-emul) |
229 | 229 | ||
230 | ifdef CONFIG_CC_STACKPROTECTOR | ||
231 | KBUILD_CFLAGS += -fstack-protector | ||
232 | endif | ||
233 | |||
230 | ifdef CONFIG_MIPS | 234 | ifdef CONFIG_MIPS |
231 | CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ | 235 | CHECKFLAGS += $(shell $(CC) $(KBUILD_CFLAGS) -dM -E -x c /dev/null | \ |
232 | egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ | 236 | egrep -vw '__GNUC_(|MINOR_|PATCHLEVEL_)_' | \ |
diff --git a/arch/mips/include/asm/stackprotector.h b/arch/mips/include/asm/stackprotector.h new file mode 100644 index 000000000000..eb9b1035e926 --- /dev/null +++ b/arch/mips/include/asm/stackprotector.h | |||
@@ -0,0 +1,40 @@ | |||
1 | /* | ||
2 | * GCC stack protector support. | ||
3 | * | ||
4 | * (This is directly adopted from the ARM implementation) | ||
5 | * | ||
6 | * Stack protector works by putting predefined pattern at the start of | ||
7 | * the stack frame and verifying that it hasn't been overwritten when | ||
8 | * returning from the function. The pattern is called stack canary | ||
9 | * and gcc expects it to be defined by a global variable called | ||
10 | * "__stack_chk_guard" on MIPS. This unfortunately means that on SMP | ||
11 | * we cannot have a different canary value per task. | ||
12 | */ | ||
13 | |||
14 | #ifndef _ASM_STACKPROTECTOR_H | ||
15 | #define _ASM_STACKPROTECTOR_H 1 | ||
16 | |||
17 | #include <linux/random.h> | ||
18 | #include <linux/version.h> | ||
19 | |||
20 | extern unsigned long __stack_chk_guard; | ||
21 | |||
22 | /* | ||
23 | * Initialize the stackprotector canary value. | ||
24 | * | ||
25 | * NOTE: this must only be called from functions that never return, | ||
26 | * and it must always be inlined. | ||
27 | */ | ||
28 | static __always_inline void boot_init_stack_canary(void) | ||
29 | { | ||
30 | unsigned long canary; | ||
31 | |||
32 | /* Try to get a semi random initial value. */ | ||
33 | get_random_bytes(&canary, sizeof(canary)); | ||
34 | canary ^= LINUX_VERSION_CODE; | ||
35 | |||
36 | current->stack_canary = canary; | ||
37 | __stack_chk_guard = current->stack_canary; | ||
38 | } | ||
39 | |||
40 | #endif /* _ASM_STACKPROTECTOR_H */ | ||
diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index c6a041d9d05d..7d62894f7e23 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c | |||
@@ -201,6 +201,12 @@ int dump_task_fpu(struct task_struct *t, elf_fpregset_t *fpr) | |||
201 | return 1; | 201 | return 1; |
202 | } | 202 | } |
203 | 203 | ||
204 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
205 | #include <linux/stackprotector.h> | ||
206 | unsigned long __stack_chk_guard __read_mostly; | ||
207 | EXPORT_SYMBOL(__stack_chk_guard); | ||
208 | #endif | ||
209 | |||
204 | /* | 210 | /* |
205 | * | 211 | * |
206 | */ | 212 | */ |