[MIPS] use compat_siginfo in rt_sigframe_n32
[sfrench/cifs-2.6.git] / arch / mips / kernel / signal_n32.c
index 57456e6a0c628e005b4be025f1ad5c28860947ad..eb7e05926ebe359592d8fb0bc7d01e545efe76b5 100644 (file)
@@ -19,7 +19,6 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/kernel.h>
 #include <linux/signal.h>
 #include <linux/errno.h>
 #include <linux/compat.h>
 #include <linux/bitops.h>
 
+#include <asm/abi.h>
 #include <asm/asm.h>
 #include <asm/cacheflush.h>
+#include <asm/compat-signal.h>
 #include <asm/sim.h>
 #include <asm/uaccess.h>
 #include <asm/ucontext.h>
@@ -47,7 +48,9 @@
 #define __NR_N32_rt_sigreturn          6211
 #define __NR_N32_restart_syscall       6214
 
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+extern int setup_sigcontext(struct pt_regs *, struct sigcontext __user *);
+extern int restore_sigcontext(struct pt_regs *, struct sigcontext __user *);
+
 
 /* IRIX compatible stack_t  */
 typedef struct sigaltstack32 {
@@ -61,7 +64,7 @@ struct ucontextn32 {
        s32                 uc_link;
        stack32_t           uc_stack;
        struct sigcontext   uc_mcontext;
-       sigset_t            uc_sigmask;   /* mask last for extensibility */
+       compat_sigset_t     uc_sigmask;   /* mask last for extensibility */
 };
 
 #if ICACHE_REFILLS_WORKAROUND_WAR == 0
@@ -69,7 +72,7 @@ struct ucontextn32 {
 struct rt_sigframe_n32 {
        u32 rs_ass[4];                  /* argument save space for o32 */
        u32 rs_code[2];                 /* signal trampoline */
-       struct siginfo rs_info;
+       struct compat_siginfo rs_info;
        struct ucontextn32 rs_uc;
 };
 
@@ -78,7 +81,7 @@ struct rt_sigframe_n32 {
 struct rt_sigframe_n32 {
        u32 rs_ass[4];                  /* argument save space for o32 */
        u32 rs_pad[2];
-       struct siginfo rs_info;
+       struct compat_siginfo rs_info;
        struct ucontextn32 rs_uc;
        u32 rs_code[8] ____cacheline_aligned;           /* signal trampoline */
 };
@@ -123,11 +126,12 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        sigset_t set;
        stack_t st;
        s32 sp;
+       int sig;
 
        frame = (struct rt_sigframe_n32 __user *) regs.regs[29];
        if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
-       if (__copy_from_user(&set, &frame->rs_uc.uc_sigmask, sizeof(set)))
+       if (__copy_conv_sigset_from_user(&set, &frame->rs_uc.uc_sigmask))
                goto badframe;
 
        sigdelsetmask(&set, ~_BLOCKABLE);
@@ -136,8 +140,11 @@ asmlinkage void sysn32_rt_sigreturn(nabi_no_regargs struct pt_regs regs)
        recalc_sigpending();
        spin_unlock_irq(&current->sighand->siglock);
 
-       if (restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext))
+       sig = restore_sigcontext(&regs, &frame->rs_uc.uc_mcontext);
+       if (sig < 0)
                goto badframe;
+       else if (sig)
+               force_sig(sig, current);
 
        /* The ucontext contains a stack32_t, so we must convert!  */
        if (__get_user(sp, &frame->rs_uc.uc_stack.ss_sp))
@@ -166,7 +173,7 @@ badframe:
        force_sig(SIGSEGV, current);
 }
 
-int setup_rt_frame_n32(struct k_sigaction * ka,
+static int setup_rt_frame_n32(struct k_sigaction * ka,
        struct pt_regs *regs, int signr, sigset_t *set, siginfo_t *info)
 {
        struct rt_sigframe_n32 __user *frame;
@@ -180,7 +187,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        install_sigtramp(frame->rs_code, __NR_N32_rt_sigreturn);
 
        /* Create siginfo.  */
-       err |= copy_siginfo_to_user(&frame->rs_info, info);
+       err |= copy_siginfo_to_user32(&frame->rs_info, info);
 
        /* Create the ucontext.  */
        err |= __put_user(0, &frame->rs_uc.uc_flags);
@@ -193,7 +200,7 @@ int setup_rt_frame_n32(struct k_sigaction * ka,
        err |= __put_user(current->sas_ss_size,
                          &frame->rs_uc.uc_stack.ss_size);
        err |= setup_sigcontext(regs, &frame->rs_uc.uc_mcontext);
-       err |= __copy_to_user(&frame->rs_uc.uc_sigmask, set, sizeof(*set));
+       err |= __copy_conv_sigset_to_user(&frame->rs_uc.uc_sigmask, set);
 
        if (err)
                goto give_sigsegv;
@@ -225,3 +232,8 @@ give_sigsegv:
        force_sigsegv(signr, current);
        return -EFAULT;
 }
+
+struct mips_abi mips_abi_n32 = {
+       .setup_rt_frame = setup_rt_frame_n32,
+       .restart        = __NR_N32_restart_syscall
+};