]> git.hungrycats.org Git - linux/commitdiff
[PATCH] x86_64: Fix signal FPU leak on i386 and x86-64
authorAndi Kleen <ak@suse.de>
Tue, 11 Jan 2005 09:51:31 +0000 (01:51 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 11 Jan 2005 09:51:31 +0000 (01:51 -0800)
Found by Bodo Stroesser. Description from Bodo:

>>
On i386, if a signal handler is started, the kernel saves the fpu-state
of the interrupted routine in the sigcontext on the stack. Calling
unlazy_fpu() and setting current->used_math=0, the kernel supplies the
signal-handler with a cleared virtual fpu.
On sigreturn(), the old fpu-state of the interrupted routine is
restored.

If a process never used the fpu, it virtually has a cleared fpu.
If such a process is interrupted by a signal handler, no fpu-context is
saved and sigcontext->fpstate is set to NULL.

Assume, that the signal handler uses the fpu. Then, AFAICS, on sigreturn
current->used_math will be 1. Since sigcontext->fpstate still is NULL,
restore_sigcontext() doesn't call restore_i387(). Thus, no
clear_fpu() is done, current->used_math is not reset.

Now, the interrupted processes fpu no longer is cleared!
<<

Fix by AK. Just clear the FPU again when this happens.

patch for i386 and x86-64.

Signed-off-by: Andi Kleen <ak@suse.de>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/signal.c
arch/x86_64/ia32/ia32_signal.c
arch/x86_64/kernel/signal.c

index 51c4bfc53c938e40c186e99d36b7648ff967e5a9..f98146004f5e1dc999347bebf75713440d498dea 100644 (file)
@@ -190,6 +190,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, int *peax
                        if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
                                goto badframe;
                        err |= restore_i387(buf);
+               } else {
+                       struct task_struct *me = current;
+                       if (me->used_math) {
+                               clear_fpu(me);
+                               me->used_math = 0;
+                       }
                }
        }
 
index 16854c4faa64c799fa6eb6b980dacdfbee73b59d..7b78206dd90bc82afec7e53bda2d0bb288a64c63 100644 (file)
@@ -261,6 +261,12 @@ ia32_restore_sigcontext(struct pt_regs *regs, struct sigcontext_ia32 __user *sc,
                        if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
                                goto badframe;
                        err |= restore_i387_ia32(current, buf, 0);
+               } else {
+                       struct task_struct *me = current;
+                       if (me->used_math) {
+                               clear_fpu(me);
+                               me->used_math = 0;
+                       }
                }
        }
 
index df01c50b71777031754d39b1cf130f1860aabe63..ad3b240cdd9c77eacbef24669358d9f4aa8786ea 100644 (file)
@@ -125,6 +125,12 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc, unsigned
                        if (verify_area(VERIFY_READ, buf, sizeof(*buf)))
                                goto badframe;
                        err |= restore_i387(buf);
+               } else {
+                       struct task_struct *me = current;
+                       if (me->used_math) {
+                               clear_fpu(me);
+                               me->used_math = 0;
+                       }
                }
        }