aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-02-26 06:55:57 -0500
committerIngo Molnar <mingo@elte.hu>2008-02-26 06:55:57 -0500
commit5d119b2c9a490e2d647eae134211b32a18a04c7d (patch)
tree37f40ec2e3ae4ad793d6c4c40f253e4266895d09 /arch
parentce28b9864b853803320c3f1d8de1b81aa4120b14 (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.S6
-rw-r--r--arch/x86/kernel/process_64.c6
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 */
1044ENTRY(kernel_execve) 1045ENTRY(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 */
731asmlinkage 731asmlinkage
732long sys_execve(char __user *name, char __user * __user *argv, 732long 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, &regs); 742 error = do_execve(filename, argv, envp, regs);
743 putname(filename); 743 putname(filename);
744 return error; 744 return error;
745} 745}