Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d119b2c authored by Ingo Molnar's avatar Ingo Molnar
Browse files

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: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
parent ce28b986
Loading
Loading
Loading
Loading
+4 −2
Original line number Diff line number Diff line
@@ -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
+3 −3
Original line number Diff line number Diff line
@@ -730,7 +730,7 @@ __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;
@@ -739,7 +739,7 @@ long sys_execve(char __user *name, char __user * __user *argv,
	error = PTR_ERR(filename);
	if (IS_ERR(filename))
		return error;
	error = do_execve(filename, argv, envp, &regs); 
	error = do_execve(filename, argv, envp, regs);
	putname(filename);
	return error;
}