aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorNicolas Pitre <nico@fluxnic.net>2010-06-07 21:50:33 -0400
committerNicolas Pitre <nico@fluxnic.net>2010-06-14 21:31:01 -0400
commitdf0698be14c6683606d5df2d83e3ae40f85ed0d9 (patch)
treefa0a2c08509d88e74d7033fa922f1cdfef83290f /arch/arm/kernel
parentc743f38013aeff58ef6252601e397b5ba281c633 (diff)
ARM: stack protector: change the canary value per task
A new random value for the canary is stored in the task struct whenever a new task is forked. This is meant to allow for different canary values per task. On ARM, GCC expects the canary value to be found in a global variable called __stack_chk_guard. So this variable has to be updated with the value stored in the task struct whenever a task switch occurs. Because the variable GCC expects is global, this cannot work on SMP unfortunately. So, on SMP, the same initial canary value is kept throughout, making this feature a bit less effective although it is still useful. One way to overcome this GCC limitation would be to locate the __stack_chk_guard variable into a memory page of its own for each CPU, and then use TLB locking to have each CPU see its own page at the same virtual address for each of them. Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/asm-offsets.c3
-rw-r--r--arch/arm/kernel/entry-armv.S8
2 files changed, 11 insertions, 0 deletions
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 883511522fca..85f2a019f77b 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -40,6 +40,9 @@
40int main(void) 40int main(void)
41{ 41{
42 DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm)); 42 DEFINE(TSK_ACTIVE_MM, offsetof(struct task_struct, active_mm));
43#ifdef CONFIG_CC_STACKPROTECTOR
44 DEFINE(TSK_STACK_CANARY, offsetof(struct task_struct, stack_canary));
45#endif
43 BLANK(); 46 BLANK();
44 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); 47 DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
45 DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); 48 DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 7ee48e7f8f31..2d14081b26b1 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -745,6 +745,11 @@ ENTRY(__switch_to)
745 mov r4, #0xffff0fff 745 mov r4, #0xffff0fff
746 str r3, [r4, #-15] @ TLS val at 0xffff0ff0 746 str r3, [r4, #-15] @ TLS val at 0xffff0ff0
747#endif 747#endif
748#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
749 ldr r7, [r2, #TI_TASK]
750 ldr r8, =__stack_chk_guard
751 ldr r7, [r7, #TSK_STACK_CANARY]
752#endif
748#ifdef CONFIG_MMU 753#ifdef CONFIG_MMU
749 mcr p15, 0, r6, c3, c0, 0 @ Set domain register 754 mcr p15, 0, r6, c3, c0, 0 @ Set domain register
750#endif 755#endif
@@ -753,6 +758,9 @@ ENTRY(__switch_to)
753 ldr r0, =thread_notify_head 758 ldr r0, =thread_notify_head
754 mov r1, #THREAD_NOTIFY_SWITCH 759 mov r1, #THREAD_NOTIFY_SWITCH
755 bl atomic_notifier_call_chain 760 bl atomic_notifier_call_chain
761#if defined(CONFIG_CC_STACKPROTECTOR) && !defined(CONFIG_SMP)
762 str r7, [r8]
763#endif
756 THUMB( mov ip, r4 ) 764 THUMB( mov ip, r4 )
757 mov r0, r5 765 mov r0, r5
758 ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously 766 ARM( ldmia r4, {r4 - sl, fp, sp, pc} ) @ Load all regs saved previously