diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-02-26 06:55:57 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-02-26 06:55:57 -0500 |
commit | 5d119b2c9a490e2d647eae134211b32a18a04c7d (patch) | |
tree | 37f40ec2e3ae4ad793d6c4c40f253e4266895d09 /arch | |
parent | ce28b9864b853803320c3f1d8de1b81aa4120b14 (diff) |
x86: fix execve with -fstack-protect
pointed out by pageexec@freemail.hu:
> what happens here is that gcc treats the argument area as owned by the
> callee, not the caller and is allowed to do certain tricks. for ssp it
> will make a copy of the struct passed by value into the local variable
> area and pass *its* address down, and it won't copy it back into the
> original instance stored in the argument area.
>
> so once sys_execve returns, the pt_regs passed by value hasn't at all
> changed and its default content will cause a nice double fault (FWIW,
> this part took me the longest to debug, being down with cold didn't
> help it either ;).
To fix this we pass in pt_regs by pointer.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/x86/kernel/entry_64.S | 6 | ||||
-rw-r--r-- | arch/x86/kernel/process_64.c | 6 |
2 files changed, 7 insertions, 5 deletions
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S index 2ad9a1bc6a73..c20c9e7e08dd 100644 --- a/arch/x86/kernel/entry_64.S +++ b/arch/x86/kernel/entry_64.S | |||
@@ -453,6 +453,7 @@ ENTRY(stub_execve) | |||
453 | CFI_REGISTER rip, r11 | 453 | CFI_REGISTER rip, r11 |
454 | SAVE_REST | 454 | SAVE_REST |
455 | FIXUP_TOP_OF_STACK %r11 | 455 | FIXUP_TOP_OF_STACK %r11 |
456 | movq %rsp, %rcx | ||
456 | call sys_execve | 457 | call sys_execve |
457 | RESTORE_TOP_OF_STACK %r11 | 458 | RESTORE_TOP_OF_STACK %r11 |
458 | movq %rax,RAX(%rsp) | 459 | movq %rax,RAX(%rsp) |
@@ -1036,15 +1037,16 @@ ENDPROC(child_rip) | |||
1036 | * rdi: name, rsi: argv, rdx: envp | 1037 | * rdi: name, rsi: argv, rdx: envp |
1037 | * | 1038 | * |
1038 | * We want to fallback into: | 1039 | * We want to fallback into: |
1039 | * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs) | 1040 | * extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs *regs) |
1040 | * | 1041 | * |
1041 | * do_sys_execve asm fallback arguments: | 1042 | * do_sys_execve asm fallback arguments: |
1042 | * rdi: name, rsi: argv, rdx: envp, fake frame on the stack | 1043 | * rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack |
1043 | */ | 1044 | */ |
1044 | ENTRY(kernel_execve) | 1045 | ENTRY(kernel_execve) |
1045 | CFI_STARTPROC | 1046 | CFI_STARTPROC |
1046 | FAKE_STACK_FRAME $0 | 1047 | FAKE_STACK_FRAME $0 |
1047 | SAVE_ALL | 1048 | SAVE_ALL |
1049 | movq %rsp,%rcx | ||
1048 | call sys_execve | 1050 | call sys_execve |
1049 | movq %rax, RAX(%rsp) | 1051 | movq %rax, RAX(%rsp) |
1050 | RESTORE_REST | 1052 | RESTORE_REST |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index b0cc8f0136d8..43f287744f9f 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -730,16 +730,16 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
730 | */ | 730 | */ |
731 | asmlinkage | 731 | asmlinkage |
732 | long sys_execve(char __user *name, char __user * __user *argv, | 732 | long sys_execve(char __user *name, char __user * __user *argv, |
733 | char __user * __user *envp, struct pt_regs regs) | 733 | char __user * __user *envp, struct pt_regs *regs) |
734 | { | 734 | { |
735 | long error; | 735 | long error; |
736 | char * filename; | 736 | char * filename; |
737 | 737 | ||
738 | filename = getname(name); | 738 | filename = getname(name); |
739 | error = PTR_ERR(filename); | 739 | error = PTR_ERR(filename); |
740 | if (IS_ERR(filename)) | 740 | if (IS_ERR(filename)) |
741 | return error; | 741 | return error; |
742 | error = do_execve(filename, argv, envp, ®s); | 742 | error = do_execve(filename, argv, envp, regs); |
743 | putname(filename); | 743 | putname(filename); |
744 | return error; | 744 | return error; |
745 | } | 745 | } |