Skip to content

Commit

Permalink
Revert "x86: signal: change type of paramter for sys_rt_sigreturn()"
Browse files Browse the repository at this point in the history
This reverts commit 4217458.

Justin Madru bisected this commit, it was causing weird Firefox
crashes.

The reason is that GCC mis-optimizes (re-uses) the on-stack parameters of
the calling frame, which corrupts the syscall return pt_regs state and
thus corrupts user-space register state.

So we go back to the slightly less clean but more optimization-safe
method of getting to pt_regs. Also add a comment to explain this.

Resolves: http://bugzilla.kernel.org/show_bug.cgi?id=12505

Reported-and-bisected-by: Justin Madru <jdm64@gawab.com>
Tested-by: Justin Madru <jdm64@gawab.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
  • Loading branch information
Ingo Molnar committed Jan 21, 2009
1 parent e0a9612 commit 552b8aa
Show file tree
Hide file tree
Showing 2 changed files with 10 additions and 3 deletions.
2 changes: 1 addition & 1 deletion arch/x86/include/asm/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ asmlinkage int sys_sigaction(int, const struct old_sigaction __user *,
struct old_sigaction __user *);
asmlinkage int sys_sigaltstack(unsigned long);
asmlinkage unsigned long sys_sigreturn(unsigned long);
asmlinkage int sys_rt_sigreturn(struct pt_regs);
asmlinkage int sys_rt_sigreturn(unsigned long);

/* kernel/ioport.c */
asmlinkage long sys_iopl(unsigned long);
Expand Down
11 changes: 9 additions & 2 deletions arch/x86/kernel/signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,9 +632,16 @@ static long do_rt_sigreturn(struct pt_regs *regs)
}

#ifdef CONFIG_X86_32
asmlinkage int sys_rt_sigreturn(struct pt_regs regs)
/*
* Note: do not pass in pt_regs directly as with tail-call optimization
* GCC will incorrectly stomp on the caller's frame and corrupt user-space
* register state:
*/
asmlinkage int sys_rt_sigreturn(unsigned long __unused)
{
return do_rt_sigreturn(&regs);
struct pt_regs *regs = (struct pt_regs *)&__unused;

return do_rt_sigreturn(regs);
}
#else /* !CONFIG_X86_32 */
asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
Expand Down

0 comments on commit 552b8aa

Please sign in to comment.