[5.2 regression] copy_fpstate_to_sigframe() change causing crash in 32-bit process
From: Eric Biggers
Date: Tue Jun 04 2019 - 14:57:58 EST
On latest Linus' tree I'm getting a crash in a 32-bit Wine process.
I bisected it to the following commit:
Author: Sebastian Andrzej Siewior <bigeasy@xxxxxxxxxxxxx>
Date: Wed Apr 3 18:41:35 2019 +0200
x86/fpu: Don't save fxregs for ia32 frames in copy_fpstate_to_sigframe()
Reverting the commit by applying the following diff makes the problem go away.
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 5a8d118bc423e..ed16a24aab497 100644
@@ -157,6 +157,7 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)
int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
+ struct fpu *fpu = ¤t->thread.fpu;
struct task_struct *tsk = current;
int ia32_fxstate = (buf != buf_fx);
@@ -202,6 +203,10 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
+ /* Update the thread's fxstate to save the fsave header. */
+ if (ia32_fxstate)
/* Save the fsave header for the 32-bit frames. */
if ((ia32_fxstate || !use_fxsr()) && save_fsave_header(tsk, buf))
Apparently the problem is that save_fsave_header() assumes the registers have
been saved to fpu->state.fxsave, yet the code that does so was removed.
Note, bisection was not straightforward because there was another bug also
causing a crash temporarily introduced during the FPU code rework: commit
39ea9baffda9 ("x86/fpu: Remove fpu->initialized usage in __fpu__restore_sig()")
forgot to call fpstate_init() on the temporary 'state' buffer, so
XCOMP_BV_COMPACTED_FORMAT was never set, causing xrstors to fail. But that bug
went away in later commits.