diff options
author | Filippo Arcidiacono <filippo.arcidiacono@st.com> | 2012-04-19 02:45:57 -0400 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2012-04-19 02:45:57 -0400 |
commit | 5d920bb929a99446062a48cf90867bbca57b8e77 (patch) | |
tree | fdadebe0b0fe8906ffd81ad9f726430d6428a8f5 /arch/sh | |
parent | 932e9f352b5d685725076f21b237f7c7d804b29c (diff) |
sh: initial stack protector support.
This implements basic -fstack-protector support, based on the early ARM
version in c743f38013aeff58ef6252601e397b5ba281c633. The SMP case is
limited to the initial canary value, while the UP case handles per-task
granularity (limited to 32-bit sh until a new enough sh64 compiler
manifests itself).
Signed-off-by: Filippo Arcidiacono <filippo.arcidiacono@st.com>
Reviewed-by: Carmelo Amoroso <carmelo.amoroso@st.com>
Signed-off-by: Stuart Menefy <stuart.menefy@st.com>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh')
-rw-r--r-- | arch/sh/Kconfig | 14 | ||||
-rw-r--r-- | arch/sh/Makefile | 4 | ||||
-rw-r--r-- | arch/sh/include/asm/stackprotector.h | 27 | ||||
-rw-r--r-- | arch/sh/kernel/process.c | 7 | ||||
-rw-r--r-- | arch/sh/kernel/process_32.c | 5 |
5 files changed, 57 insertions, 0 deletions
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig index ff9e033ce626..60ed3669979d 100644 --- a/arch/sh/Kconfig +++ b/arch/sh/Kconfig | |||
@@ -685,6 +685,20 @@ config SECCOMP | |||
685 | 685 | ||
686 | If unsure, say N. | 686 | If unsure, say N. |
687 | 687 | ||
688 | config CC_STACKPROTECTOR | ||
689 | bool "Enable -fstack-protector buffer overflow detection (EXPERIMENTAL)" | ||
690 | depends on SUPERH32 && EXPERIMENTAL | ||
691 | help | ||
692 | This option turns on the -fstack-protector GCC feature. This | ||
693 | feature puts, at the beginning of functions, a canary value on | ||
694 | the stack just before the return address, and validates | ||
695 | the value just before actually returning. Stack based buffer | ||
696 | overflows (that need to overwrite this return address) now also | ||
697 | overwrite the canary, which gets detected and the attack is then | ||
698 | neutralized via a kernel panic. | ||
699 | |||
700 | This feature requires gcc version 4.2 or above. | ||
701 | |||
688 | config SMP | 702 | config SMP |
689 | bool "Symmetric multi-processing support" | 703 | bool "Symmetric multi-processing support" |
690 | depends on SYS_SUPPORTS_SMP | 704 | depends on SYS_SUPPORTS_SMP |
diff --git a/arch/sh/Makefile b/arch/sh/Makefile index 3fc0f413777c..24875c8c1514 100644 --- a/arch/sh/Makefile +++ b/arch/sh/Makefile | |||
@@ -199,6 +199,10 @@ ifeq ($(CONFIG_DWARF_UNWINDER),y) | |||
199 | KBUILD_CFLAGS += -fasynchronous-unwind-tables | 199 | KBUILD_CFLAGS += -fasynchronous-unwind-tables |
200 | endif | 200 | endif |
201 | 201 | ||
202 | ifeq ($(CONFIG_CC_STACKPROTECTOR),y) | ||
203 | KBUILD_CFLAGS += -fstack-protector | ||
204 | endif | ||
205 | |||
202 | libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) | 206 | libs-$(CONFIG_SUPERH32) := arch/sh/lib/ $(libs-y) |
203 | libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) | 207 | libs-$(CONFIG_SUPERH64) := arch/sh/lib64/ $(libs-y) |
204 | 208 | ||
diff --git a/arch/sh/include/asm/stackprotector.h b/arch/sh/include/asm/stackprotector.h new file mode 100644 index 000000000000..d9df3a76847c --- /dev/null +++ b/arch/sh/include/asm/stackprotector.h | |||
@@ -0,0 +1,27 @@ | |||
1 | #ifndef __ASM_SH_STACKPROTECTOR_H | ||
2 | #define __ASM_SH_STACKPROTECTOR_H | ||
3 | |||
4 | #include <linux/random.h> | ||
5 | #include <linux/version.h> | ||
6 | |||
7 | extern unsigned long __stack_chk_guard; | ||
8 | |||
9 | /* | ||
10 | * Initialize the stackprotector canary value. | ||
11 | * | ||
12 | * NOTE: this must only be called from functions that never return, | ||
13 | * and it must always be inlined. | ||
14 | */ | ||
15 | static __always_inline void boot_init_stack_canary(void) | ||
16 | { | ||
17 | unsigned long canary; | ||
18 | |||
19 | /* Try to get a semi random initial value. */ | ||
20 | get_random_bytes(&canary, sizeof(canary)); | ||
21 | canary ^= LINUX_VERSION_CODE; | ||
22 | |||
23 | current->stack_canary = canary; | ||
24 | __stack_chk_guard = current->stack_canary; | ||
25 | } | ||
26 | |||
27 | #endif /* __ASM_SH_STACKPROTECTOR_H */ | ||
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index 325f98b1736d..f3f03e4c785d 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c | |||
@@ -2,10 +2,17 @@ | |||
2 | #include <linux/kernel.h> | 2 | #include <linux/kernel.h> |
3 | #include <linux/slab.h> | 3 | #include <linux/slab.h> |
4 | #include <linux/sched.h> | 4 | #include <linux/sched.h> |
5 | #include <linux/export.h> | ||
6 | #include <linux/stackprotector.h> | ||
5 | 7 | ||
6 | struct kmem_cache *task_xstate_cachep = NULL; | 8 | struct kmem_cache *task_xstate_cachep = NULL; |
7 | unsigned int xstate_size; | 9 | unsigned int xstate_size; |
8 | 10 | ||
11 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
12 | unsigned long __stack_chk_guard __read_mostly; | ||
13 | EXPORT_SYMBOL(__stack_chk_guard); | ||
14 | #endif | ||
15 | |||
9 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | 16 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
10 | { | 17 | { |
11 | *dst = *src; | 18 | *dst = *src; |
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 94273aaf78c1..f78cc421e665 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/ftrace.h> | 22 | #include <linux/ftrace.h> |
23 | #include <linux/hw_breakpoint.h> | 23 | #include <linux/hw_breakpoint.h> |
24 | #include <linux/prefetch.h> | 24 | #include <linux/prefetch.h> |
25 | #include <linux/stackprotector.h> | ||
25 | #include <asm/uaccess.h> | 26 | #include <asm/uaccess.h> |
26 | #include <asm/mmu_context.h> | 27 | #include <asm/mmu_context.h> |
27 | #include <asm/fpu.h> | 28 | #include <asm/fpu.h> |
@@ -220,6 +221,10 @@ __switch_to(struct task_struct *prev, struct task_struct *next) | |||
220 | { | 221 | { |
221 | struct thread_struct *next_t = &next->thread; | 222 | struct thread_struct *next_t = &next->thread; |
222 | 223 | ||
224 | #if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP) | ||
225 | __stack_chk_guard = next->stack_canary; | ||
226 | #endif | ||
227 | |||
223 | unlazy_fpu(prev, task_pt_regs(prev)); | 228 | unlazy_fpu(prev, task_pt_regs(prev)); |
224 | 229 | ||
225 | /* we're going to use this soon, after a few expensive things */ | 230 | /* we're going to use this soon, after a few expensive things */ |