diff options
author | Nicolas Pitre <nico@fluxnic.net> | 2010-05-24 23:55:42 -0400 |
---|---|---|
committer | Nicolas Pitre <nico@fluxnic.net> | 2010-06-14 21:31:00 -0400 |
commit | c743f38013aeff58ef6252601e397b5ba281c633 (patch) | |
tree | b364e1690aff8a0dd97a83d4cb17bcadcdb5bd19 /arch/arm | |
parent | cc92c28b2db5b406657ecc05235d4ca4e222ae34 (diff) |
ARM: initial stack protector (-fstack-protector) support
This is the very basic stuff without the changing canary upon
task switch yet. Just the Kconfig option and a constant canary
value initialized at boot time.
Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/Kconfig | 12 | ||||
-rw-r--r-- | arch/arm/Makefile | 4 | ||||
-rw-r--r-- | arch/arm/include/asm/stackprotector.h | 38 | ||||
-rw-r--r-- | arch/arm/kernel/process.c | 6 |
4 files changed, 60 insertions, 0 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 1f254bd6c937..f160b93691cd 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig | |||
@@ -1374,6 +1374,18 @@ config UACCESS_WITH_MEMCPY | |||
1374 | However, if the CPU data cache is using a write-allocate mode, | 1374 | However, if the CPU data cache is using a write-allocate mode, |
1375 | this option is unlikely to provide any performance gain. | 1375 | this option is unlikely to provide any performance gain. |
1376 | 1376 | ||
1377 | config CC_STACKPROTECTOR | ||
1378 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | ||
1379 | help | ||
1380 | This option turns on the -fstack-protector GCC feature. This | ||
1381 | feature puts, at the beginning of functions, a canary value on | ||
1382 | the stack just before the return address, and validates | ||
1383 | the value just before actually returning. Stack based buffer | ||
1384 | overflows (that need to overwrite this return address) now also | ||
1385 | overwrite the canary, which gets detected and the attack is then | ||
1386 | neutralized via a kernel panic. | ||
1387 | This feature requires gcc version 4.2 or above. | ||
1388 | |||
1377 | endmenu | 1389 | endmenu |
1378 | 1390 | ||
1379 | menu "Boot options" | 1391 | menu "Boot options" |
diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 64ba313724d2..ddf6da158ad8 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile | |||
@@ -34,6 +34,10 @@ ifeq ($(CONFIG_FRAME_POINTER),y) | |||
34 | KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog | 34 | KBUILD_CFLAGS +=-fno-omit-frame-pointer -mapcs -mno-sched-prolog |
35 | endif | 35 | endif |
36 | 36 | ||
37 | ifeq ($(CONFIG_CC_STACKPROTECTOR),y) | ||
38 | KBUILD_CFLAGS +=-fstack-protector | ||
39 | endif | ||
40 | |||
37 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) | 41 | ifeq ($(CONFIG_CPU_BIG_ENDIAN),y) |
38 | KBUILD_CPPFLAGS += -mbig-endian | 42 | KBUILD_CPPFLAGS += -mbig-endian |
39 | AS += -EB | 43 | AS += -EB |
diff --git a/arch/arm/include/asm/stackprotector.h b/arch/arm/include/asm/stackprotector.h new file mode 100644 index 000000000000..de003327be97 --- /dev/null +++ b/arch/arm/include/asm/stackprotector.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* | ||
2 | * GCC stack protector support. | ||
3 | * | ||
4 | * Stack protector works by putting predefined pattern at the start of | ||
5 | * the stack frame and verifying that it hasn't been overwritten when | ||
6 | * returning from the function. The pattern is called stack canary | ||
7 | * and gcc expects it to be defined by a global variable called | ||
8 | * "__stack_chk_guard" on ARM. This unfortunately means that on SMP | ||
9 | * we cannot have a different canary value per task. | ||
10 | */ | ||
11 | |||
12 | #ifndef _ASM_STACKPROTECTOR_H | ||
13 | #define _ASM_STACKPROTECTOR_H 1 | ||
14 | |||
15 | #include <linux/random.h> | ||
16 | #include <linux/version.h> | ||
17 | |||
18 | extern unsigned long __stack_chk_guard; | ||
19 | |||
20 | /* | ||
21 | * Initialize the stackprotector canary value. | ||
22 | * | ||
23 | * NOTE: this must only be called from functions that never return, | ||
24 | * and it must always be inlined. | ||
25 | */ | ||
26 | static __always_inline void boot_init_stack_canary(void) | ||
27 | { | ||
28 | unsigned long canary; | ||
29 | |||
30 | /* Try to get a semi random initial value. */ | ||
31 | get_random_bytes(&canary, sizeof(canary)); | ||
32 | canary ^= LINUX_VERSION_CODE; | ||
33 | |||
34 | current->stack_canary = canary; | ||
35 | __stack_chk_guard = current->stack_canary; | ||
36 | } | ||
37 | |||
38 | #endif /* _ASM_STACKPROTECTOR_H */ | ||
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 1c6eb7ed9642..090ac9459da1 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -37,6 +37,12 @@ | |||
37 | #include <asm/stacktrace.h> | 37 | #include <asm/stacktrace.h> |
38 | #include <asm/mach/time.h> | 38 | #include <asm/mach/time.h> |
39 | 39 | ||
40 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
41 | #include <linux/stackprotector.h> | ||
42 | unsigned long __stack_chk_guard __read_mostly; | ||
43 | EXPORT_SYMBOL(__stack_chk_guard); | ||
44 | #endif | ||
45 | |||
40 | static const char *processor_modes[] = { | 46 | static const char *processor_modes[] = { |
41 | "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , | 47 | "USER_26", "FIQ_26" , "IRQ_26" , "SVC_26" , "UK4_26" , "UK5_26" , "UK6_26" , "UK7_26" , |
42 | "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", | 48 | "UK8_26" , "UK9_26" , "UK10_26", "UK11_26", "UK12_26", "UK13_26", "UK14_26", "UK15_26", |