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>
This commit is contained in:
parent
ce28b9864b
commit
5d119b2c9a
2 changed files with 7 additions and 5 deletions
|
@ -453,6 +453,7 @@ ENTRY(stub_execve)
|
|||
CFI_REGISTER rip, r11
|
||||
SAVE_REST
|
||||
FIXUP_TOP_OF_STACK %r11
|
||||
movq %rsp, %rcx
|
||||
call sys_execve
|
||||
RESTORE_TOP_OF_STACK %r11
|
||||
movq %rax,RAX(%rsp)
|
||||
|
@ -1036,15 +1037,16 @@ ENDPROC(child_rip)
|
|||
* rdi: name, rsi: argv, rdx: envp
|
||||
*
|
||||
* We want to fallback into:
|
||||
* extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs regs)
|
||||
* extern long sys_execve(char *name, char **argv,char **envp, struct pt_regs *regs)
|
||||
*
|
||||
* do_sys_execve asm fallback arguments:
|
||||
* rdi: name, rsi: argv, rdx: envp, fake frame on the stack
|
||||
* rdi: name, rsi: argv, rdx: envp, rcx: fake frame on the stack
|
||||
*/
|
||||
ENTRY(kernel_execve)
|
||||
CFI_STARTPROC
|
||||
FAKE_STACK_FRAME $0
|
||||
SAVE_ALL
|
||||
movq %rsp,%rcx
|
||||
call sys_execve
|
||||
movq %rax, RAX(%rsp)
|
||||
RESTORE_REST
|
||||
|
|
|
@ -730,16 +730,16 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
|
|||
*/
|
||||
asmlinkage
|
||||
long sys_execve(char __user *name, char __user * __user *argv,
|
||||
char __user * __user *envp, struct pt_regs regs)
|
||||
char __user * __user *envp, struct pt_regs *regs)
|
||||
{
|
||||
long error;
|
||||
char * filename;
|
||||
|
||||
filename = getname(name);
|
||||
error = PTR_ERR(filename);
|
||||
if (IS_ERR(filename))
|
||||
if (IS_ERR(filename))
|
||||
return error;
|
||||
error = do_execve(filename, argv, envp, ®s);
|
||||
error = do_execve(filename, argv, envp, regs);
|
||||
putname(filename);
|
||||
return error;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue