generic compat_sys_sigaltstack()
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 14 Dec 2012 19:47:53 +0000 (14:47 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Wed, 19 Dec 2012 23:07:41 +0000 (18:07 -0500)
Again, conditional on CONFIG_GENERIC_SIGALTSTACK

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
arch/x86/ia32/ia32_signal.c
arch/x86/ia32/ia32entry.S
arch/x86/include/asm/ia32.h
arch/x86/include/asm/sys_ia32.h
arch/x86/kernel/entry_64.S
arch/x86/kernel/signal.c
arch/x86/syscalls/syscall_32.tbl
arch/x86/syscalls/syscall_64.tbl
include/linux/compat.h
kernel/signal.c

index efc6a95..a866411 100644 (file)
@@ -136,52 +136,6 @@ asmlinkage long sys32_sigsuspend(int history0, int history1, old_sigset_t mask)
        return sigsuspend(&blocked);
 }
 
-asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
-                                 stack_ia32_t __user *uoss_ptr,
-                                 struct pt_regs *regs)
-{
-       stack_t uss, uoss;
-       int ret, err = 0;
-       mm_segment_t seg;
-
-       if (uss_ptr) {
-               u32 ptr;
-
-               memset(&uss, 0, sizeof(stack_t));
-               if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
-                       return -EFAULT;
-
-               get_user_try {
-                       get_user_ex(ptr, &uss_ptr->ss_sp);
-                       get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
-                       get_user_ex(uss.ss_size, &uss_ptr->ss_size);
-               } get_user_catch(err);
-
-               if (err)
-                       return -EFAULT;
-               uss.ss_sp = compat_ptr(ptr);
-       }
-       seg = get_fs();
-       set_fs(KERNEL_DS);
-       ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
-                            (stack_t __force __user *) &uoss, regs->sp);
-       set_fs(seg);
-       if (ret >= 0 && uoss_ptr)  {
-               if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
-                       return -EFAULT;
-
-               put_user_try {
-                       put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
-                       put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
-                       put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
-               } put_user_catch(err);
-
-               if (err)
-                       ret = -EFAULT;
-       }
-       return ret;
-}
-
 /*
  * Do a signal return; undo the signal stack.
  */
@@ -292,7 +246,6 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
        struct rt_sigframe_ia32 __user *frame;
        sigset_t set;
        unsigned int ax;
-       struct pt_regs tregs;
 
        frame = (struct rt_sigframe_ia32 __user *)(regs->sp - 4);
 
@@ -306,8 +259,7 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
        if (ia32_restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
                goto badframe;
 
-       tregs = *regs;
-       if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
+       if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
        return ax;
index 32e6f05..102ff7c 100644 (file)
@@ -464,7 +464,6 @@ GLOBAL(\label)
 
        PTREGSCALL stub32_rt_sigreturn, sys32_rt_sigreturn, %rdi
        PTREGSCALL stub32_sigreturn, sys32_sigreturn, %rdi
-       PTREGSCALL stub32_sigaltstack, sys32_sigaltstack, %rdx
        PTREGSCALL stub32_execve, compat_sys_execve, %rcx
        PTREGSCALL stub32_fork, sys_fork, %rdi
        PTREGSCALL stub32_vfork, sys_vfork, %rdi
index e623277..4c6da2e 100644 (file)
@@ -29,16 +29,10 @@ struct old_sigaction32 {
        unsigned int sa_restorer;       /* Another 32 bit pointer */
 };
 
-typedef struct sigaltstack_ia32 {
-       unsigned int    ss_sp;
-       int             ss_flags;
-       unsigned int    ss_size;
-} stack_ia32_t;
-
 struct ucontext_ia32 {
        unsigned int      uc_flags;
        unsigned int      uc_link;
-       stack_ia32_t      uc_stack;
+       compat_stack_t    uc_stack;
        struct sigcontext_ia32 uc_mcontext;
        compat_sigset_t   uc_sigmask;   /* mask last for extensibility */
 };
@@ -46,7 +40,7 @@ struct ucontext_ia32 {
 struct ucontext_x32 {
        unsigned int      uc_flags;
        unsigned int      uc_link;
-       stack_ia32_t      uc_stack;
+       compat_stack_t    uc_stack;
        unsigned int      uc__pad0;     /* needed for alignment */
        struct sigcontext uc_mcontext;  /* the 64-bit sigcontext type */
        compat_sigset_t   uc_sigmask;   /* mask last for extensibility */
index c76fae4..31f61f9 100644 (file)
@@ -69,8 +69,6 @@ asmlinkage long sys32_fallocate(int, int, unsigned,
 
 /* ia32/ia32_signal.c */
 asmlinkage long sys32_sigsuspend(int, int, old_sigset_t);
-asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *,
-                                 stack_ia32_t __user *, struct pt_regs *);
 asmlinkage long sys32_sigreturn(struct pt_regs *);
 asmlinkage long sys32_rt_sigreturn(struct pt_regs *);
 
index 6e46201..86d8119 100644 (file)
@@ -912,8 +912,6 @@ ENTRY(stub_rt_sigreturn)
 END(stub_rt_sigreturn)
 
 #ifdef CONFIG_X86_X32_ABI
-       PTREGSCALL stub_x32_sigaltstack, sys32_sigaltstack, %rdx
-
 ENTRY(stub_x32_rt_sigreturn)
        CFI_STARTPROC
        addq $8, %rsp
index 16d065c..b17ed37 100644 (file)
@@ -857,7 +857,6 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
        struct rt_sigframe_x32 __user *frame;
        sigset_t set;
        unsigned long ax;
-       struct pt_regs tregs;
 
        frame = (struct rt_sigframe_x32 __user *)(regs->sp - 8);
 
@@ -871,8 +870,7 @@ asmlinkage long sys32_x32_rt_sigreturn(struct pt_regs *regs)
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext, &ax))
                goto badframe;
 
-       tregs = *regs;
-       if (sys32_sigaltstack(&frame->uc.uc_stack, NULL, &tregs) == -EFAULT)
+       if (compat_restore_altstack(&frame->uc.uc_stack))
                goto badframe;
 
        return ax;
index 62c7b22..235226e 100644 (file)
 183    i386    getcwd                  sys_getcwd
 184    i386    capget                  sys_capget
 185    i386    capset                  sys_capset
-186    i386    sigaltstack             sys_sigaltstack                 stub32_sigaltstack
+186    i386    sigaltstack             sys_sigaltstack                 compat_sys_sigaltstack
 187    i386    sendfile                sys_sendfile                    sys32_sendfile
 188    i386    getpmsg
 189    i386    putpmsg
index 6ffa7f9..c68cbe7 100644 (file)
 522    x32     rt_sigpending           sys32_rt_sigpending
 523    x32     rt_sigtimedwait         compat_sys_rt_sigtimedwait
 524    x32     rt_sigqueueinfo         sys32_rt_sigqueueinfo
-525    x32     sigaltstack             stub_x32_sigaltstack
+525    x32     sigaltstack             compat_sys_sigaltstack
 526    x32     timer_create            compat_sys_timer_create
 527    x32     mq_notify               compat_sys_mq_notify
 528    x32     kexec_load              compat_sys_kexec_load
index 62bb76f..cb5637e 100644 (file)
 #ifndef compat_user_stack_pointer
 #define compat_user_stack_pointer() current_user_stack_pointer()
 #endif
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+#ifndef compat_sigaltstack     /* we'll need that for MIPS */
+typedef struct compat_sigaltstack {
+       compat_uptr_t                   ss_sp;
+       int                             ss_flags;
+       compat_size_t                   ss_size;
+} compat_stack_t;
+#endif
+#endif
+
 #define compat_jiffies_to_clock_t(x)   \
                (((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
@@ -632,6 +642,12 @@ asmlinkage ssize_t compat_sys_process_vm_writev(compat_pid_t pid,
 
 asmlinkage long compat_sys_sendfile(int out_fd, int in_fd,
                                    compat_off_t __user *offset, compat_size_t count);
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
+                                      compat_stack_t __user *uoss_ptr);
+
+int compat_restore_altstack(const compat_stack_t __user *uss);
+#endif
 
 #else
 
index f05f4c4..aee85bd 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/nsproxy.h>
 #include <linux/user_namespace.h>
 #include <linux/uprobes.h>
+#include <linux/compat.h>
 #define CREATE_TRACE_POINTS
 #include <trace/events/signal.h>
 
@@ -3116,6 +3117,50 @@ int restore_altstack(const stack_t __user *uss)
        return err == -EFAULT ? err : 0;
 }
 
+#ifdef CONFIG_COMPAT
+#ifdef CONFIG_GENERIC_SIGALTSTACK
+asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
+                                      compat_stack_t __user *uoss_ptr)
+{
+       stack_t uss, uoss;
+       int ret;
+       mm_segment_t seg;
+
+       if (uss_ptr) {
+               compat_stack_t uss32;
+
+               memset(&uss, 0, sizeof(stack_t));
+               if (copy_from_user(&uss32, uss_ptr, sizeof(compat_stack_t)))
+                       return -EFAULT;
+               uss.ss_sp = compat_ptr(uss32.ss_sp);
+               uss.ss_flags = uss32.ss_flags;
+               uss.ss_size = uss32.ss_size;
+       }
+       seg = get_fs();
+       set_fs(KERNEL_DS);
+       ret = do_sigaltstack((stack_t __force __user *) (uss_ptr ? &uss : NULL),
+                            (stack_t __force __user *) &uoss,
+                            compat_user_stack_pointer());
+       set_fs(seg);
+       if (ret >= 0 && uoss_ptr)  {
+               if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(compat_stack_t)) ||
+                   __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
+                   __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
+                   __put_user(uoss.ss_size, &uoss_ptr->ss_size))
+                       ret = -EFAULT;
+       }
+       return ret;
+}
+
+int compat_restore_altstack(const compat_stack_t __user *uss)
+{
+       int err = compat_sys_sigaltstack(uss, NULL);
+       /* squash all but -EFAULT for now */
+       return err == -EFAULT ? err : 0;
+}
+#endif
+#endif
+
 #ifdef __ARCH_WANT_SYS_SIGPENDING
 
 /**