diff options
author | Nicolas Pitre <nico@fluxnic.net> | 2010-06-07 21:50:33 -0400 |
---|---|---|
committer | Nicolas Pitre <nico@fluxnic.net> | 2010-06-14 21:31:01 -0400 |
commit | df0698be14c6683606d5df2d83e3ae40f85ed0d9 (patch) | |
tree | fa0a2c08509d88e74d7033fa922f1cdfef83290f /arch/arm/kernel | |
parent | c743f38013aeff58ef6252601e397b5ba281c633 (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.c | 3 | ||||
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 8 |
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 @@ | |||
40 | int main(void) | 40 | int 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 |