Commit c5cada67 authored by Ingo Molnar's avatar Ingo Molnar Committed by Linus Torvalds

[PATCH] tailcall prevention in sys_wait4() and sys_waitid()

A hack to prevent the compiler from generatin tailcalls in these two
functions.

With CONFIG_REGPARM=y, the tailcalled code ends up stomping on the
syscall's argument frame which corrupts userspace's registers.
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 74a82aa9
...@@ -5,6 +5,10 @@ ...@@ -5,6 +5,10 @@
#define FASTCALL(x) x __attribute__((regparm(3))) #define FASTCALL(x) x __attribute__((regparm(3)))
#define fastcall __attribute__((regparm(3))) #define fastcall __attribute__((regparm(3)))
#ifdef CONFIG_REGPARM
# define prevent_tail_call(ret) __asm__ ("" : "=r" (ret) : "0" (ret))
#endif
#ifdef CONFIG_X86_ALIGNMENT_16 #ifdef CONFIG_X86_ALIGNMENT_16
#define __ALIGN .align 16,0x90 #define __ALIGN .align 16,0x90
#define __ALIGN_STR ".align 16,0x90" #define __ALIGN_STR ".align 16,0x90"
......
...@@ -14,6 +14,10 @@ ...@@ -14,6 +14,10 @@
#define asmlinkage CPP_ASMLINKAGE #define asmlinkage CPP_ASMLINKAGE
#endif #endif
#ifndef prevent_tail_call
# define prevent_tail_call(ret) do { } while (0)
#endif
#ifndef __ALIGN #ifndef __ALIGN
#define __ALIGN .align 4,0x90 #define __ALIGN .align 4,0x90
#define __ALIGN_STR ".align 4,0x90" #define __ALIGN_STR ".align 4,0x90"
......
...@@ -1376,6 +1376,8 @@ asmlinkage long sys_waitid(int which, pid_t pid, ...@@ -1376,6 +1376,8 @@ asmlinkage long sys_waitid(int which, pid_t pid,
struct siginfo __user *infop, int options, struct siginfo __user *infop, int options,
struct rusage __user *ru) struct rusage __user *ru)
{ {
long ret;
if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED)) if (options & ~(WNOHANG|WNOWAIT|WEXITED|WSTOPPED|WCONTINUED))
return -EINVAL; return -EINVAL;
if (!(options & (WEXITED|WSTOPPED|WCONTINUED))) if (!(options & (WEXITED|WSTOPPED|WCONTINUED)))
...@@ -1398,15 +1400,25 @@ asmlinkage long sys_waitid(int which, pid_t pid, ...@@ -1398,15 +1400,25 @@ asmlinkage long sys_waitid(int which, pid_t pid,
return -EINVAL; return -EINVAL;
} }
return do_wait(pid, options, infop, NULL, ru); ret = do_wait(pid, options, infop, NULL, ru);
/* avoid REGPARM breakage on x86: */
prevent_tail_call(ret);
return ret;
} }
asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr, asmlinkage long sys_wait4(pid_t pid, int __user *stat_addr,
int options, struct rusage __user *ru) int options, struct rusage __user *ru)
{ {
long ret;
if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL)) if (options & ~(WNOHANG|WUNTRACED|__WNOTHREAD|__WCLONE|__WALL))
return -EINVAL; return -EINVAL;
return do_wait(pid, options | WEXITED, NULL, stat_addr, ru); ret = do_wait(pid, options | WEXITED, NULL, stat_addr, ru);
/* avoid REGPARM breakage on x86: */
prevent_tail_call(ret);
return ret;
} }
#ifdef __ARCH_WANT_SYS_WAITPID #ifdef __ARCH_WANT_SYS_WAITPID
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment