diff options
author | Tejun Heo <tj@kernel.org> | 2009-02-09 08:17:40 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 18:42:01 -0500 |
commit | 60a5317ff0f42dd313094b88f809f63041568b08 (patch) | |
tree | 307dfd9715fbc9ff83c3c3ae3b0e8f03888083f2 /arch/x86/include/asm/system.h | |
parent | ccbeed3a05908d201b47b6c3dd1a373138bba566 (diff) |
x86: implement x86_32 stack protector
Impact: stack protector for x86_32
Implement stack protector for x86_32. GDT entry 28 is used for it.
It's set to point to stack_canary-20 and have the length of 24 bytes.
CONFIG_CC_STACKPROTECTOR turns off CONFIG_X86_32_LAZY_GS and sets %gs
to the stack canary segment on entry. As %gs is otherwise unused by
the kernel, the canary can be anywhere. It's defined as a percpu
variable.
x86_32 exception handlers take register frame on stack directly as
struct pt_regs. With -fstack-protector turned on, gcc copies the
whole structure after the stack canary and (of course) doesn't copy
back on return thus losing all changed. For now, -fno-stack-protector
is added to all files which contain those functions. We definitely
need something better.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/include/asm/system.h')
-rw-r--r-- | arch/x86/include/asm/system.h | 21 |
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h index 79b98e5b96f4..2692ee8ef031 100644 --- a/arch/x86/include/asm/system.h +++ b/arch/x86/include/asm/system.h | |||
@@ -23,6 +23,22 @@ struct task_struct *__switch_to(struct task_struct *prev, | |||
23 | 23 | ||
24 | #ifdef CONFIG_X86_32 | 24 | #ifdef CONFIG_X86_32 |
25 | 25 | ||
26 | #ifdef CONFIG_CC_STACKPROTECTOR | ||
27 | #define __switch_canary \ | ||
28 | "movl "__percpu_arg([current_task])",%%ebx\n\t" \ | ||
29 | "movl %P[task_canary](%%ebx),%%ebx\n\t" \ | ||
30 | "movl %%ebx,"__percpu_arg([stack_canary])"\n\t" | ||
31 | #define __switch_canary_oparam \ | ||
32 | , [stack_canary] "=m" (per_cpu_var(stack_canary)) | ||
33 | #define __switch_canary_iparam \ | ||
34 | , [current_task] "m" (per_cpu_var(current_task)) \ | ||
35 | , [task_canary] "i" (offsetof(struct task_struct, stack_canary)) | ||
36 | #else /* CC_STACKPROTECTOR */ | ||
37 | #define __switch_canary | ||
38 | #define __switch_canary_oparam | ||
39 | #define __switch_canary_iparam | ||
40 | #endif /* CC_STACKPROTECTOR */ | ||
41 | |||
26 | /* | 42 | /* |
27 | * Saving eflags is important. It switches not only IOPL between tasks, | 43 | * Saving eflags is important. It switches not only IOPL between tasks, |
28 | * it also protects other tasks from NT leaking through sysenter etc. | 44 | * it also protects other tasks from NT leaking through sysenter etc. |
@@ -46,6 +62,7 @@ do { \ | |||
46 | "pushl %[next_ip]\n\t" /* restore EIP */ \ | 62 | "pushl %[next_ip]\n\t" /* restore EIP */ \ |
47 | "jmp __switch_to\n" /* regparm call */ \ | 63 | "jmp __switch_to\n" /* regparm call */ \ |
48 | "1:\t" \ | 64 | "1:\t" \ |
65 | __switch_canary \ | ||
49 | "popl %%ebp\n\t" /* restore EBP */ \ | 66 | "popl %%ebp\n\t" /* restore EBP */ \ |
50 | "popfl\n" /* restore flags */ \ | 67 | "popfl\n" /* restore flags */ \ |
51 | \ | 68 | \ |
@@ -58,6 +75,8 @@ do { \ | |||
58 | "=b" (ebx), "=c" (ecx), "=d" (edx), \ | 75 | "=b" (ebx), "=c" (ecx), "=d" (edx), \ |
59 | "=S" (esi), "=D" (edi) \ | 76 | "=S" (esi), "=D" (edi) \ |
60 | \ | 77 | \ |
78 | __switch_canary_oparam \ | ||
79 | \ | ||
61 | /* input parameters: */ \ | 80 | /* input parameters: */ \ |
62 | : [next_sp] "m" (next->thread.sp), \ | 81 | : [next_sp] "m" (next->thread.sp), \ |
63 | [next_ip] "m" (next->thread.ip), \ | 82 | [next_ip] "m" (next->thread.ip), \ |
@@ -66,6 +85,8 @@ do { \ | |||
66 | [prev] "a" (prev), \ | 85 | [prev] "a" (prev), \ |
67 | [next] "d" (next) \ | 86 | [next] "d" (next) \ |
68 | \ | 87 | \ |
88 | __switch_canary_iparam \ | ||
89 | \ | ||
69 | : /* reloaded segment registers */ \ | 90 | : /* reloaded segment registers */ \ |
70 | "memory"); \ | 91 | "memory"); \ |
71 | } while (0) | 92 | } while (0) |