]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - arch/s390/kernel/compat_signal.c
Merge branch 'process_vm' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux
[karo-tx-linux.git] / arch / s390 / kernel / compat_signal.c
index a9a285b8c4ad3ccdfafcaf2b1412de4900e2b219..4f68c81d3ffaafb7ee1db39e7c63375e0d08422b 100644 (file)
@@ -141,7 +141,8 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
                        break;
                case __SI_FAULT >> 16:
                        err |= __get_user(tmp, &from->si_addr);
-                       to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
+                       to->si_addr = (void __force __user *)
+                               (u64) (tmp & PSW32_ADDR_INSN);
                        break;
                case __SI_POLL >> 16:
                        err |= __get_user(to->si_band, &from->si_band);
@@ -213,16 +214,8 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
                ret = get_user(sa_handler, &act->sa_handler);
                ret |= __copy_from_user(&set32, &act->sa_mask,
                                        sizeof(compat_sigset_t));
-               switch (_NSIG_WORDS) {
-               case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]
-                               | (((long)set32.sig[7]) << 32);
-               case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]
-                               | (((long)set32.sig[5]) << 32);
-               case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]
-                               | (((long)set32.sig[3]) << 32);
-               case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]
-                               | (((long)set32.sig[1]) << 32);
-               }
+               new_ka.sa.sa_mask.sig[0] =
+                       set32.sig[0] | (((long)set32.sig[1]) << 32);
                ret |= __get_user(new_ka.sa.sa_flags, &act->sa_flags);
                
                if (ret)
@@ -233,20 +226,8 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
        if (!ret && oact) {
-               switch (_NSIG_WORDS) {
-               case 4:
-                       set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);
-                       set32.sig[6] = old_ka.sa.sa_mask.sig[3];
-               case 3:
-                       set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);
-                       set32.sig[4] = old_ka.sa.sa_mask.sig[2];
-               case 2:
-                       set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);
-                       set32.sig[2] = old_ka.sa.sa_mask.sig[1];
-               case 1:
-                       set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
-                       set32.sig[0] = old_ka.sa.sa_mask.sig[0];
-               }
+               set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);
+               set32.sig[0] = old_ka.sa.sa_mask.sig[0];
                ret = put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler);
                ret |= __copy_to_user(&oact->sa_mask, &set32,
                                      sizeof(compat_sigset_t));
@@ -300,9 +281,10 @@ static int save_sigregs32(struct pt_regs *regs, _sigregs32 __user *sregs)
        _s390_regs_common32 regs32;
        int err, i;
 
-       regs32.psw.mask = PSW32_MASK_MERGE(psw32_user_bits,
-                                          (__u32)(regs->psw.mask >> 32));
-       regs32.psw.addr = PSW32_ADDR_AMODE31 | (__u32) regs->psw.addr;
+       regs32.psw.mask = psw32_user_bits |
+               ((__u32)(regs->psw.mask >> 32) & PSW32_MASK_USER);
+       regs32.psw.addr = (__u32) regs->psw.addr |
+               (__u32)(regs->psw.mask & PSW_MASK_BA);
        for (i = 0; i < NUM_GPRS; i++)
                regs32.gprs[i] = (__u32) regs->gprs[i];
        save_access_regs(current->thread.acrs);
@@ -327,8 +309,9 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
        err = __copy_from_user(&regs32, &sregs->regs, sizeof(regs32));
        if (err)
                return err;
-       regs->psw.mask = PSW_MASK_MERGE(regs->psw.mask,
-                                       (__u64)regs32.psw.mask << 32);
+       regs->psw.mask = (regs->psw.mask & ~PSW_MASK_USER) |
+               (__u64)(regs32.psw.mask & PSW32_MASK_USER) << 32 |
+               (__u64)(regs32.psw.addr & PSW32_ADDR_AMODE);
        regs->psw.addr = (__u64)(regs32.psw.addr & PSW32_ADDR_INSN);
        for (i = 0; i < NUM_GPRS; i++)
                regs->gprs[i] = (__u64) regs32.gprs[i];
@@ -342,7 +325,7 @@ static int restore_sigregs32(struct pt_regs *regs,_sigregs32 __user *sregs)
                return err;
 
        restore_fp_regs(&current->thread.fp_regs);
-       regs->svcnr = 0;        /* disable syscall checks */
+       clear_thread_flag(TIF_SYSCALL); /* No longer in a system call */
        return 0;
 }
 
@@ -496,11 +479,11 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
        /* Set up to return from userspace.  If provided, use a stub
           already in userspace.  */
        if (ka->sa.sa_flags & SA_RESTORER) {
-               regs->gprs[14] = (__u64) ka->sa.sa_restorer;
+               regs->gprs[14] = (__u64) ka->sa.sa_restorer | PSW32_ADDR_AMODE;
        } else {
-               regs->gprs[14] = (__u64) frame->retcode;
+               regs->gprs[14] = (__u64) frame->retcode | PSW32_ADDR_AMODE;
                if (__put_user(S390_SYSCALL_OPCODE | __NR_sigreturn,
-                              (u16 __user *)(frame->retcode)))
+                              (u16 __force __user *)(frame->retcode)))
                        goto give_sigsegv;
         }
 
@@ -509,11 +492,12 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
                goto give_sigsegv;
 
        /* Set up registers for signal handler */
-       regs->gprs[15] = (__u64) frame;
-       regs->psw.addr = (__u64) ka->sa.sa_handler;
+       regs->gprs[15] = (__force __u64) frame;
+       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
+       regs->psw.addr = (__force __u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
-       regs->gprs[3] = (__u64) &frame->sc;
+       regs->gprs[3] = (__force __u64) &frame->sc;
 
        /* We forgot to include these in the sigcontext.
           To avoid breaking binary compatibility, they are passed as args. */
@@ -521,7 +505,7 @@ static int setup_frame32(int sig, struct k_sigaction *ka,
        regs->gprs[5] = current->thread.prot_addr;
 
        /* Place signal number on stack to allow backtrace from handler.  */
-       if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
+       if (__put_user(regs->gprs[2], (int __force __user *) &frame->signo))
                goto give_sigsegv;
        return 0;
 
@@ -564,20 +548,21 @@ static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
        } else {
                regs->gprs[14] = (__u64) frame->retcode;
                err |= __put_user(S390_SYSCALL_OPCODE | __NR_rt_sigreturn,
-                                 (u16 __user *)(frame->retcode));
+                                 (u16 __force __user *)(frame->retcode));
        }
 
        /* Set up backchain. */
-       if (__put_user(regs->gprs[15], (unsigned int __user *) frame))
+       if (__put_user(regs->gprs[15], (unsigned int __force __user *) frame))
                goto give_sigsegv;
 
        /* Set up registers for signal handler */
-       regs->gprs[15] = (__u64) frame;
+       regs->gprs[15] = (__force __u64) frame;
+       regs->psw.mask |= PSW_MASK_BA;          /* force amode 31 */
        regs->psw.addr = (__u64) ka->sa.sa_handler;
 
        regs->gprs[2] = map_signal(sig);
-       regs->gprs[3] = (__u64) &frame->info;
-       regs->gprs[4] = (__u64) &frame->uc;
+       regs->gprs[3] = (__force __u64) &frame->info;
+       regs->gprs[4] = (__force __u64) &frame->uc;
        return 0;
 
 give_sigsegv: