Skip to content

Commit

Permalink
x86: fix fpu restore from sig return
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Suresh Siddha authored and Thomas Gleixner committed May 10, 2008
1 parent 0646153 commit fd3c3ed
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 3 deletions.
12 changes: 10 additions & 2 deletions arch/x86/kernel/i387.c
Original file line number Diff line number Diff line change
Expand Up @@ -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));
}
Expand All @@ -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 */
Expand All @@ -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
Expand Down
10 changes: 9 additions & 1 deletion include/asm-x86/i387.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit fd3c3ed

Please sign in to comment.