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/kernel/head_32.S | |
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/kernel/head_32.S')
-rw-r--r-- | arch/x86/kernel/head_32.S | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 24c0e5cd71e3..924e31615fb6 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <asm/asm-offsets.h> | 19 | #include <asm/asm-offsets.h> |
20 | #include <asm/setup.h> | 20 | #include <asm/setup.h> |
21 | #include <asm/processor-flags.h> | 21 | #include <asm/processor-flags.h> |
22 | #include <asm/percpu.h> | ||
22 | 23 | ||
23 | /* Physical address */ | 24 | /* Physical address */ |
24 | #define pa(X) ((X) - __PAGE_OFFSET) | 25 | #define pa(X) ((X) - __PAGE_OFFSET) |
@@ -437,8 +438,25 @@ is386: movl $2,%ecx # set MP | |||
437 | movl $(__KERNEL_PERCPU), %eax | 438 | movl $(__KERNEL_PERCPU), %eax |
438 | movl %eax,%fs # set this cpu's percpu | 439 | movl %eax,%fs # set this cpu's percpu |
439 | 440 | ||
440 | xorl %eax,%eax # Clear GS and LDT | 441 | #ifdef CONFIG_CC_STACKPROTECTOR |
442 | /* | ||
443 | * The linker can't handle this by relocation. Manually set | ||
444 | * base address in stack canary segment descriptor. | ||
445 | */ | ||
446 | cmpb $0,ready | ||
447 | jne 1f | ||
448 | movl $per_cpu__gdt_page,%eax | ||
449 | movl $per_cpu__stack_canary,%ecx | ||
450 | movw %cx, 8 * GDT_ENTRY_STACK_CANARY + 2(%eax) | ||
451 | shrl $16, %ecx | ||
452 | movb %cl, 8 * GDT_ENTRY_STACK_CANARY + 4(%eax) | ||
453 | movb %ch, 8 * GDT_ENTRY_STACK_CANARY + 7(%eax) | ||
454 | 1: | ||
455 | #endif | ||
456 | movl $(__KERNEL_STACK_CANARY),%eax | ||
441 | movl %eax,%gs | 457 | movl %eax,%gs |
458 | |||
459 | xorl %eax,%eax # Clear LDT | ||
442 | lldt %ax | 460 | lldt %ax |
443 | 461 | ||
444 | cld # gcc2 wants the direction flag cleared at all times | 462 | cld # gcc2 wants the direction flag cleared at all times |