aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/include/asm/system.h
diff options
context:
space:
mode:
authorTejun Heo <tj@kernel.org>2009-02-09 08:17:40 -0500
committerIngo Molnar <mingo@elte.hu>2009-02-09 18:42:01 -0500
commit60a5317ff0f42dd313094b88f809f63041568b08 (patch)
tree307dfd9715fbc9ff83c3c3ae3b0e8f03888083f2 /arch/x86/include/asm/system.h
parentccbeed3a05908d201b47b6c3dd1a373138bba566 (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.h21
1 files changed, 21 insertions, 0 deletions
diff --git a/arch/x86/include/asm/system.h b/arch/x86/include/asm/system.h
index 79b98e5b96f..2692ee8ef03 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)