vserver 2.0 rc7
[linux-2.6.git] / arch / cris / arch-v10 / kernel / signal.c
index 6698054..85e0032 100644 (file)
@@ -125,7 +125,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 
        if (act) {
                old_sigset_t mask;
-               if (verify_area(VERIFY_READ, act, sizeof(*act)) ||
+               if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
                    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
                    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
                        return -EFAULT;
@@ -137,7 +137,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
        if (!ret && oact) {
-               if (verify_area(VERIFY_WRITE, oact, sizeof(*oact)) ||
+               if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
                    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
                    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
                        return -EFAULT;
@@ -180,6 +180,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc)
        unsigned int err = 0;
        unsigned long old_usp;
 
+        /* Always make any pending restarted system calls return -EINTR */
+       current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
        /* restore the regs from &sc->regs (same as sc, since regs is first)
         * (sc is already checked for VERIFY_READ since the sigframe was
         *  checked in sys_sigreturn previously)
@@ -228,7 +231,7 @@ asmlinkage int sys_sigreturn(long r10, long r11, long r12, long r13, long mof,
         if (((long)frame) & 3)
                 goto badframe;
 
-       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
        if (__get_user(set.sig[0], &frame->sc.oldmask)
            || (_NSIG_WORDS > 1
@@ -261,7 +264,6 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
 {
        struct rt_sigframe __user *frame = (struct rt_sigframe *)rdusp();
        sigset_t set;
-       stack_t st;
 
         /*
          * Since we stacked the signal on a dword boundary,
@@ -271,7 +273,7 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
         if (((long)frame) & 3)
                 goto badframe;
 
-       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
+       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
@@ -285,11 +287,8 @@ asmlinkage int sys_rt_sigreturn(long r10, long r11, long r12, long r13,
        if (restore_sigcontext(regs, &frame->uc.uc_mcontext))
                goto badframe;
 
-       if (__copy_from_user(&st, &frame->uc.uc_stack, sizeof(st)))
+       if (do_sigaltstack(&frame->uc.uc_stack, NULL, rdusp()) == -EFAULT)
                goto badframe;
-       /* It is more difficult to avoid calling this function than to
-          call it and ignore errors.  */
-       do_sigaltstack(&st, NULL, rdusp());
 
        return regs->r10;
 
@@ -385,9 +384,9 @@ static void setup_frame(int sig, struct k_sigaction *ka,
                /* trampoline - the desired return ip is the retcode itself */
                return_ip = (unsigned long)&frame->retcode;
                /* This is movu.w __NR_sigreturn, r9; break 13; */
-               err |= __put_user(0x9c5f,         (short *)(frame->retcode+0));
-               err |= __put_user(__NR_sigreturn, (short *)(frame->retcode+2));
-               err |= __put_user(0xe93d,         (short *)(frame->retcode+4));
+               err |= __put_user(0x9c5f,         (short __user*)(frame->retcode+0));
+               err |= __put_user(__NR_sigreturn, (short __user*)(frame->retcode+2));
+               err |= __put_user(0xe93d,         (short __user*)(frame->retcode+4));
        }
 
        if (err)
@@ -406,9 +405,7 @@ static void setup_frame(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_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -447,9 +444,9 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                /* trampoline - the desired return ip is the retcode itself */
                return_ip = (unsigned long)&frame->retcode;
                /* This is movu.w __NR_rt_sigreturn, r9; break 13; */
-               err |= __put_user(0x9c5f,            (short *)(frame->retcode+0));
-               err |= __put_user(__NR_rt_sigreturn, (short *)(frame->retcode+2));
-               err |= __put_user(0xe93d,            (short *)(frame->retcode+4));
+               err |= __put_user(0x9c5f,            (short __user*)(frame->retcode+0));
+               err |= __put_user(__NR_rt_sigreturn, (short __user*)(frame->retcode+2));
+               err |= __put_user(0xe93d,            (short __user*)(frame->retcode+4));
        }
 
        if (err)
@@ -472,9 +469,7 @@ static void setup_rt_frame(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);
 }
 
 /*
@@ -483,16 +478,14 @@ give_sigsegv:
 
 extern inline void
 handle_signal(int canrestart, unsigned long sig,
-             siginfo_t *info, sigset_t *oldset, struct pt_regs * regs)
+             siginfo_t *info, struct k_sigaction *ka,
+              sigset_t *oldset, struct pt_regs * regs)
 {
-       struct k_sigaction *ka = &current->sighand->action[sig-1];
-
        /* Are we from a system call? */
        if (canrestart) {
                /* If so, check system call restarting.. */
                switch (regs->r10) {
                        case -ERESTART_RESTARTBLOCK:
-                               current_thread_info()->restart_block.fn = do_no_restart_syscall;
                        case -ERESTARTNOHAND:
                                /* ERESTARTNOHAND means that the syscall should only be
                                   restarted if there was no handler for the signal, and since
@@ -549,6 +542,7 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
 {
        siginfo_t info;
        int signr;
+        struct k_sigaction ka;
 
        /*
         * We want the common case to go fast, which
@@ -562,10 +556,10 @@ int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs)
        if (!oldset)
                oldset = &current->blocked;
 
-       signr = get_signal_to_deliver(&info, regs, NULL);
+       signr = get_signal_to_deliver(&info, &ka, regs, NULL);
        if (signr > 0) {
                /* Whee!  Actually deliver the signal.  */
-               handle_signal(canrestart, signr, &info, oldset, regs);
+               handle_signal(canrestart, signr, &info, &ka, oldset, regs);
                return 1;
        }