vserver 1.9.3
[linux-2.6.git] / arch / s390 / kernel / compat_signal.c
index e8c8b2f..f29bcb8 100644 (file)
@@ -118,10 +118,10 @@ int copy_siginfo_from_user32(siginfo_t *to, siginfo_t32 __user *from)
        err |= __get_user(to->si_errno, &from->si_errno);
        err |= __get_user(to->si_code, &from->si_code);
 
-       if (from->si_code < 0)
+       if (to->si_code < 0)
                err |= __copy_from_user(&to->_sifields._pad, &from->_sifields._pad, SI_PAD_SIZE);
        else {
-               switch (from->si_code >> 16) {
+               switch (to->si_code >> 16) {
                case __SI_RT >> 16: /* This is not generated by the kernel as of now.  */
                case __SI_MESGQ >> 16:
                        err |= __get_user(to->si_int, &from->si_int);
@@ -218,14 +218,17 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
                 struct old_sigaction32 __user *oact)
 {
         struct k_sigaction new_ka, old_ka;
+       unsigned long sa_handler, sa_restorer;
         int ret;
 
         if (act) {
                compat_old_sigset_t mask;
                if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
-                   __get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler) ||
-                   __get_user((unsigned long)new_ka.sa.sa_restorer, &act->sa_restorer))
+                   __get_user(sa_handler, &act->sa_handler) ||
+                   __get_user(sa_restorer, &act->sa_restorer))
                        return -EFAULT;
+               new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
+               new_ka.sa.sa_restorer = (void (*)(void)) sa_restorer;
                __get_user(new_ka.sa.sa_flags, &act->sa_flags);
                __get_user(mask, &act->sa_mask);
                siginitset(&new_ka.sa.sa_mask, mask);
@@ -234,9 +237,11 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
         ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
        if (!ret && oact) {
+               sa_handler = (unsigned long) old_ka.sa.sa_handler;
+               sa_restorer = (unsigned long) old_ka.sa.sa_restorer;
                if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
-                   __put_user((unsigned long)old_ka.sa.sa_handler, &oact->sa_handler) ||
-                   __put_user((unsigned long)old_ka.sa.sa_restorer, &oact->sa_restorer))
+                   __put_user(sa_handler, &oact->sa_handler) ||
+                   __put_user(sa_restorer, &oact->sa_restorer))
                        return -EFAULT;
                __put_user(old_ka.sa.sa_flags, &oact->sa_flags);
                __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
@@ -253,6 +258,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
           struct sigaction32 __user *oact,  size_t sigsetsize)
 {
        struct k_sigaction new_ka, old_ka;
+       unsigned long sa_handler;
        int ret;
        compat_sigset_t set32;
 
@@ -261,7 +267,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
                return -EINVAL;
 
        if (act) {
-               ret = get_user((unsigned long)new_ka.sa.sa_handler, &act->sa_handler);
+               ret = get_user(sa_handler, &act->sa_handler);
                ret |= __copy_from_user(&set32, &act->sa_mask,
                                        sizeof(compat_sigset_t));
                switch (_NSIG_WORDS) {
@@ -278,6 +284,7 @@ sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
                
                if (ret)
                        return -EFAULT;
+               new_ka.sa.sa_handler = (__sighandler_t) sa_handler;
        }
 
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
@@ -311,17 +318,19 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
                                                        struct pt_regs *regs)
 {
        stack_t kss, koss;
+       unsigned long ss_sp;
        int ret, err = 0;
        mm_segment_t old_fs = get_fs();
 
        if (uss) {
                if (!access_ok(VERIFY_READ, uss, sizeof(*uss)))
                        return -EFAULT;
-               err |= __get_user((unsigned long) kss.ss_sp, &uss->ss_sp);
+               err |= __get_user(ss_sp, &uss->ss_sp);
                err |= __get_user(kss.ss_size, &uss->ss_size);
                err |= __get_user(kss.ss_flags, &uss->ss_flags);
                if (err)
                        return -EFAULT;
+               kss.ss_sp = (void *) ss_sp;
        }
 
        set_fs (KERNEL_DS);
@@ -333,7 +342,8 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
        if (!ret && uoss) {
                if (!access_ok(VERIFY_WRITE, uoss, sizeof(*uoss)))
                        return -EFAULT;
-               err |= __put_user((unsigned long) koss.ss_sp, &uoss->ss_sp);
+               ss_sp = (unsigned long) koss.ss_sp;
+               err |= __put_user(ss_sp, &uoss->ss_sp);
                err |= __put_user(koss.ss_size, &uoss->ss_size);
                err |= __put_user(koss.ss_flags, &uoss->ss_flags);
                if (err)
@@ -552,9 +562,7 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -604,9 +612,7 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
        return;
 
 give_sigsegv:
-       if (sig == SIGSEGV)
-               ka->sa.sa_handler = SIG_DFL;
-       force_sig(SIGSEGV, current);
+       force_sigsegv(sig, current);
 }
 
 /*
@@ -614,20 +620,15 @@ give_sigsegv:
  */    
 
 void
-handle_signal32(unsigned long sig, siginfo_t *info, sigset_t *oldset,
-       struct pt_regs * regs)
+handle_signal32(unsigned long sig, struct k_sigaction *ka,
+               siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
-       struct k_sigaction *ka = &current->sighand->action[sig-1];
-
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
                setup_rt_frame32(sig, ka, info, oldset, regs);
        else
                setup_frame32(sig, ka, oldset, regs);
 
-       if (ka->sa.sa_flags & SA_ONESHOT)
-               ka->sa.sa_handler = SIG_DFL;
-
        if (!(ka->sa.sa_flags & SA_NODEFER)) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);