x86: fix fpu restore from sig return
authorSuresh Siddha <suresh.b.siddha@intel.com>
Wed, 7 May 2008 19:09:52 +0000 (12:09 -0700)
committerThomas Gleixner <tglx@linutronix.de>
Sat, 10 May 2008 17:31:45 +0000 (19:31 +0200)
If the task never used fpu, initialize the fpu before restoring the FP
state from the signal handler context. This will allocate the fpu
state, if the task never needed it before.

Reported-and-bisected-by: Eric Sesterhenn <snakebyte@gmx.de>
Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Tested-by: Eric Sesterhenn <snakebyte@gmx.de>
Cc: Frederik Deweerdt <deweerdt@free.fr>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
arch/x86/kernel/i387.c
include/asm-x86/i387.h

index db6839b53195e1a83d9186a76bf9a05562fc39e6..e03cc952f233db9a2d77a1592798a96cf68a0674 100644 (file)
@@ -450,7 +450,6 @@ static inline int restore_i387_fsave(struct _fpstate_ia32 __user *buf)
 {
        struct task_struct *tsk = current;
 
-       clear_fpu(tsk);
        return __copy_from_user(&tsk->thread.xstate->fsave, buf,
                                sizeof(struct i387_fsave_struct));
 }
@@ -461,7 +460,6 @@ static int restore_i387_fxsave(struct _fpstate_ia32 __user *buf)
        struct user_i387_ia32_struct env;
        int err;
 
-       clear_fpu(tsk);
        err = __copy_from_user(&tsk->thread.xstate->fxsave, &buf->_fxsr_env[0],
                               sizeof(struct i387_fxsave_struct));
        /* mxcsr reserved bits must be masked to zero for security reasons */
@@ -478,6 +476,16 @@ int restore_i387_ia32(struct _fpstate_ia32 __user *buf)
        int err;
 
        if (HAVE_HWFP) {
+               struct task_struct *tsk = current;
+
+               clear_fpu(tsk);
+
+               if (!used_math()) {
+                       err = init_fpu(tsk);
+                       if (err)
+                               return err;
+               }
+
                if (cpu_has_fxsr)
                        err = restore_i387_fxsave(buf);
                else
index da2adb45f6e3949476ac0a4d2c1aa1cbb2024986..6b722d315936705605850bdd43141064bae9f71f 100644 (file)
@@ -175,7 +175,15 @@ static inline int save_i387(struct _fpstate __user *buf)
  */
 static inline int restore_i387(struct _fpstate __user *buf)
 {
-       set_used_math();
+       struct task_struct *tsk = current;
+       int err;
+
+       if (!used_math()) {
+               err = init_fpu(tsk);
+               if (err)
+                       return err;
+       }
+
        if (!(task_thread_info(current)->status & TS_USEDFPU)) {
                clts();
                task_thread_info(current)->status |= TS_USEDFPU;