This commit was manufactured by cvs2svn to create tag
[linux-2.6.git] / arch / i386 / kernel / signal.c
index 1e8b41c..ab606b5 100644 (file)
@@ -192,9 +192,9 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
                        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;
                        }
                }
        }
@@ -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,22 +375,22 @@ 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 = &__kernel_sigreturn;
+       restorer = current->mm->context.vdso + (long)&__kernel_sigreturn;
        if (ka->sa.sa_flags & SA_RESTORER)
                restorer = ka->sa.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",
@@ -475,9 +487,10 @@ static void setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
                goto give_sigsegv;
 
        /* Set up to return from userspace.  */
-       restorer = &__kernel_rt_sigreturn;
+       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",