This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / arch / i386 / kernel / signal.c
index 14fd069..ab606b5 100644 (file)
@@ -93,7 +93,7 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 
        if (act) {
                old_sigset_t mask;
-               if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
+               if (verify_area(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;
@@ -105,7 +105,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 (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
+               if (verify_area(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;
@@ -187,14 +187,14 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
                struct _fpstate __user * buf;
                err |= __get_user(buf, &sc->fpstate);
                if (buf) {
-                       if (!access_ok(VERIFY_READ, buf, sizeof(*buf)))
+                       if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
                                goto badframe;
                        err |= restore_i387(buf);
                } else {
                        struct task_struct *me = current;
-                       if (used_math()) {
+                       if (me->used_math) {
                                clear_fpu(me);
-                               clear_used_math();
+                               me->used_math = 0;
                        }
                }
        }
@@ -213,7 +213,7 @@ asmlinkage int sys_sigreturn(unsigned long __unused)
        sigset_t set;
        int eax;
 
-       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
        if (__get_user(set.sig[0], &frame->sc.oldmask)
            || (_NSIG_WORDS > 1
@@ -243,7 +243,7 @@ asmlinkage int sys_rt_sigreturn(unsigned long __unused)
        sigset_t set;
        int eax;
 
-       if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+       if (verify_area(VERIFY_READ, frame, sizeof(*frame)))
                goto badframe;
        if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
                goto badframe;
@@ -276,6 +276,7 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
                 struct pt_regs *regs, unsigned long mask)
 {
        int tmp, err = 0;
+       unsigned long eflags;
 
        tmp = 0;
        __asm__("movl %%gs,%0" : "=r"(tmp): "0"(tmp));
@@ -297,7 +298,16 @@ setup_sigcontext(struct sigcontext __user *sc, struct _fpstate __user *fpstate,
        err |= __put_user(current->thread.error_code, &sc->err);
        err |= __put_user(regs->eip, &sc->eip);
        err |= __put_user(regs->xcs, (unsigned int __user *)&sc->cs);
-       err |= __put_user(regs->eflags, &sc->eflags);
+
+       /*
+        * Iff TF was set because the program is being single-stepped by a
+        * debugger, don't save that information on the signal stack.. We
+        * don't want debugging to change state.
+        */
+       eflags = regs->eflags;
+       if (current->ptrace & PT_DTRACE)
+               eflags &= ~TF_MASK;
+       err |= __put_user(eflags, &sc->eflags);
        err |= __put_user(regs->esp, &sc->esp_at_signal);
        err |= __put_user(regs->xss, (unsigned int __user *)&sc->ss);
 
@@ -365,20 +375,20 @@ static void setup_frame(int sig, struct k_sigaction *ka,
                ? current_thread_info()->exec_domain->signal_invmap[sig]
                : sig;
 
-       err = __put_user(usig, &frame->sig);
+       err |= __put_user(usig, &frame->sig);
        if (err)
                goto give_sigsegv;
 
-       err = setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
+       err |= setup_sigcontext(&frame->sc, &frame->fpstate, regs, set->sig[0]);
        if (err)
                goto give_sigsegv;
 
        if (_NSIG_WORDS > 1) {
-               err = __copy_to_user(&frame->extramask, &set->sig[1],
+               err |= __copy_to_user(&frame->extramask, &set->sig[1],
                                      sizeof(frame->extramask));
-               if (err)
-                       goto give_sigsegv;
        }
+       if (err)
+               goto give_sigsegv;
 
        restorer = current->mm->context.vdso + (long)&__kernel_sigreturn;
        if (ka->sa.sa_flags & SA_RESTORER)
@@ -420,9 +430,11 @@ static void setup_frame(int sig, struct k_sigaction *ka,
         * The tracer may want to single-step inside the
         * handler too.
         */
-       regs->eflags &= ~TF_MASK;
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
+       if (regs->eflags & TF_MASK) {
+               regs->eflags &= ~TF_MASK;
+               if (current->ptrace & PT_DTRACE)
+                       ptrace_notify(SIGTRAP);
+       }
 
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -478,6 +490,7 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
        restorer = current->mm->context.vdso + (long)&__kernel_rt_sigreturn;
        if (ka->sa.sa_flags & SA_RESTORER)
                restorer = ka->sa.sa_restorer;
+
        err |= __put_user(restorer, &frame->pretcode);
         
        /*
@@ -513,9 +526,11 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
         * The tracer may want to single-step inside the
         * handler too.
         */
-       regs->eflags &= ~TF_MASK;
-       if (test_thread_flag(TIF_SINGLESTEP))
-               ptrace_notify(SIGTRAP);
+       if (regs->eflags & TF_MASK) {
+               regs->eflags &= ~TF_MASK;
+               if (current->ptrace & PT_DTRACE)
+                       ptrace_notify(SIGTRAP);
+       }
 
 #if DEBUG_SIG
        printk("SIG deliver (%s:%d): sp=%p pc=%p ra=%p\n",
@@ -557,16 +572,6 @@ handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka,
                }
        }
 
-       /*
-        * If TF is set due to a debugger (PT_DTRACE), clear the TF flag so
-        * that register information in the sigcontext is correct.
-        */
-       if (unlikely(regs->eflags & TF_MASK)
-           && likely(current->ptrace & PT_DTRACE)) {
-               current->ptrace &= ~PT_DTRACE;
-               regs->eflags &= ~TF_MASK;
-       }
-
        /* Set up the stack frame */
        if (ka->sa.sa_flags & SA_SIGINFO)
                setup_rt_frame(sig, ka, info, oldset, regs);
@@ -618,7 +623,7 @@ int fastcall do_signal(struct pt_regs *regs, sigset_t *oldset)
                 * inside the kernel.
                 */
                if (unlikely(current->thread.debugreg[7])) {
-                       loaddebug(&current->thread, 7);
+                       __asm__("movl %0,%%db7" : : "r" (current->thread.debugreg[7]));
                }
 
                /* Whee!  Actually deliver the signal.  */