Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / s390 / kernel / compat_signal.c
index d05d65a..b4c815d 100644 (file)
@@ -1,8 +1,7 @@
 /*
- *  arch/s390/kernel/signal32.c
+ *  arch/s390/kernel/compat_signal.c
  *
- *  S390 version
- *    Copyright (C) 2000 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ *    Copyright (C) IBM Corp. 2000,2006
  *    Author(s): Denis Joseph Barrow (djbarrow@de.ibm.com,barrow_dj@yahoo.com)
  *               Gerhard Tonn (ton@de.ibm.com)                  
  *
@@ -52,8 +51,6 @@ typedef struct
        struct ucontext32 uc;
 } rt_sigframe32;
 
-asmlinkage int FASTCALL(do_signal(struct pt_regs *regs, sigset_t *oldset));
-
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
        int err;
@@ -143,7 +140,7 @@ 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 *)(u64) (tmp & PSW32_ADDR_INSN);
+                       to->si_addr = (void __user *)(u64) (tmp & PSW32_ADDR_INSN);
                        break;
                case __SI_POLL >> 16:
                        err |= __get_user(to->si_band, &from->si_band);
@@ -161,66 +158,6 @@ int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
        return err;
 }
 
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys32_sigsuspend(struct pt_regs * regs,int history0, int history1, old_sigset_t mask)
-{
-       sigset_t saveset;
-
-       mask &= _BLOCKABLE;
-       spin_lock_irq(&current->sighand->siglock);
-       saveset = current->blocked;
-       siginitset(&current->blocked, mask);
-       recalc_sigpending();
-       spin_unlock_irq(&current->sighand->siglock);
-       regs->gprs[2] = -EINTR;
-
-       while (1) {
-               set_current_state(TASK_INTERRUPTIBLE);
-               schedule();
-               if (do_signal(regs, &saveset))
-                       return -EINTR;
-       }
-}
-
-asmlinkage int
-sys32_rt_sigsuspend(struct pt_regs * regs, compat_sigset_t __user *unewset,
-                                                               size_t sigsetsize)
-{
-       sigset_t saveset, newset;
-       compat_sigset_t set32;
-
-       /* XXX: Don't preclude handling different sized sigset_t's.  */
-       if (sigsetsize != sizeof(sigset_t))
-               return -EINVAL;
-
-       if (copy_from_user(&set32, unewset, sizeof(set32)))
-               return -EFAULT;
-       switch (_NSIG_WORDS) {
-       case 4: newset.sig[3] = set32.sig[6] + (((long)set32.sig[7]) << 32);
-       case 3: newset.sig[2] = set32.sig[4] + (((long)set32.sig[5]) << 32);
-       case 2: newset.sig[1] = set32.sig[2] + (((long)set32.sig[3]) << 32);
-       case 1: newset.sig[0] = set32.sig[0] + (((long)set32.sig[1]) << 32);
-       }
-        sigdelsetmask(&newset, ~_BLOCKABLE);
-
-        spin_lock_irq(&current->sighand->siglock);
-        saveset = current->blocked;
-        current->blocked = newset;
-        recalc_sigpending();
-        spin_unlock_irq(&current->sighand->siglock);
-        regs->gprs[2] = -EINTR;
-
-        while (1) {
-                set_current_state(TASK_INTERRUPTIBLE);
-                schedule();
-                if (do_signal(regs, &saveset))
-                        return -EINTR;
-        }
-}
-
 asmlinkage long
 sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
                 struct old_sigaction32 __user *oact)
@@ -258,9 +195,6 @@ sys32_sigaction(int sig, const struct old_sigaction32 __user *act,
        return ret;
 }
 
-int
-do_sigaction(int sig, const struct k_sigaction *act, struct k_sigaction *oact);
-
 asmlinkage long
 sys32_rt_sigaction(int sig, const struct sigaction32 __user *act,
           struct sigaction32 __user *oact,  size_t sigsetsize)
@@ -338,7 +272,7 @@ sys32_sigaltstack(const stack_t32 __user *uss, stack_t32 __user *uoss,
                err |= __get_user(kss.ss_flags, &uss->ss_flags);
                if (err)
                        return -EFAULT;
-               kss.ss_sp = (void *) ss_sp;
+               kss.ss_sp = (void __user *) ss_sp;
        }
 
        set_fs (KERNEL_DS);
@@ -461,14 +395,12 @@ asmlinkage long sys32_rt_sigreturn(struct pt_regs *regs)
                goto badframe;
 
        err = __get_user(ss_sp, &frame->uc.uc_stack.ss_sp);
-       st.ss_sp = (void *) A((unsigned long)ss_sp);
+       st.ss_sp = compat_ptr(ss_sp);
        err |= __get_user(st.ss_size, &frame->uc.uc_stack.ss_size);
        err |= __get_user(st.ss_flags, &frame->uc.uc_stack.ss_flags);
        if (err)
                goto badframe; 
 
-       /* It is more difficult to avoid calling this function than to
-          call it and ignore errors.  */
        set_fs (KERNEL_DS);
        do_sigaltstack((stack_t __user *)&st, NULL, regs->gprs[15]);
        set_fs (old_fs);
@@ -498,7 +430,7 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs * regs, size_t frame_size)
 
        /* This is the X/Open sanctioned signal stack switching.  */
        if (ka->sa.sa_flags & SA_ONSTACK) {
-               if (! on_sig_stack(sp))
+               if (! sas_ss_flags(sp))
                        sp = current->sas_ss_sp + current->sas_ss_size;
        }
 
@@ -522,7 +454,7 @@ static inline int map_signal(int sig)
                return sig;
 }
 
-static void setup_frame32(int sig, struct k_sigaction *ka,
+static int setup_frame32(int sig, struct k_sigaction *ka,
                        sigset_t *set, struct pt_regs * regs)
 {
        sigframe32 __user *frame = get_sigframe(ka, regs, sizeof(sigframe32));
@@ -567,13 +499,14 @@ static void setup_frame32(int sig, struct k_sigaction *ka,
        /* Place signal number on stack to allow backtrace from handler.  */
        if (__put_user(regs->gprs[2], (int __user *) &frame->signo))
                goto give_sigsegv;
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
-static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
+static int setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
                           sigset_t *set, struct pt_regs * regs)
 {
        int err = 0;
@@ -617,32 +550,37 @@ static void setup_rt_frame32(int sig, struct k_sigaction *ka, siginfo_t *info,
        regs->gprs[2] = map_signal(sig);
        regs->gprs[3] = (__u64) &frame->info;
        regs->gprs[4] = (__u64) &frame->uc;
-       return;
+       return 0;
 
 give_sigsegv:
        force_sigsegv(sig, current);
+       return -EFAULT;
 }
 
 /*
  * OK, we're invoking a handler
  */    
 
-void
+int
 handle_signal32(unsigned long sig, struct k_sigaction *ka,
                siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
 {
+       int ret;
+
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
-               setup_rt_frame32(sig, ka, info, oldset, regs);
+               ret = setup_rt_frame32(sig, ka, info, oldset, regs);
        else
-               setup_frame32(sig, ka, oldset, regs);
+               ret = setup_frame32(sig, ka, oldset, regs);
 
-       if (!(ka->sa.sa_flags & SA_NODEFER)) {
+       if (ret == 0) {
                spin_lock_irq(&current->sighand->siglock);
                sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-               sigaddset(&current->blocked,sig);
+               if (!(ka->sa.sa_flags & SA_NODEFER))
+                       sigaddset(&current->blocked,sig);
                recalc_sigpending();
                spin_unlock_irq(&current->sighand->siglock);
        }
+       return ret;
 }