We currently leak FPU state across execve() boundaries on eagerfpu systems:

        $ /host/home/mingo/dump-xmm-regs-exec
        # XMM state before execve():
        XMM0 : 000000000000dede
        XMM1 : 000000000000dedf
        XMM2 : 000000000000dee0
        XMM3 : 000000000000dee1
        XMM4 : 000000000000dee2
        XMM5 : 000000000000dee3
        XMM6 : 000000000000dee4
        XMM7 : 000000000000dee5
        XMM8 : 000000000000dee6
        XMM9 : 000000000000dee7
        XMM10: 000000000000dee8
        XMM11: 000000000000dee9
        XMM12: 000000000000deea
        XMM13: 000000000000deeb
        XMM14: 000000000000deec
        XMM15: 000000000000deed

        # XMM state after execve(), in the new task context:
        XMM0 : 0000000000000000
        XMM1 : 2f2f2f2f2f2f2f2f
        XMM2 : 0000000000000000
        XMM3 : 0000000000000000
        XMM4 : 00000000000000ff
        XMM5 : 00000000ff000000
        XMM6 : 000000000000dee4
        XMM7 : 000000000000dee5
        XMM8 : 0000000000000000
        XMM9 : 0000000000000000
        XMM10: 0000000000000000
        XMM11: 0000000000000000
        XMM12: 0000000000000000
        XMM13: 000000000000deeb
        XMM14: 000000000000deec
        XMM15: 000000000000deed

The reason is that fpu__clear() does not clear out the state properly.

Fix it.

Cc: Andy Lutomirski <l...@amacapital.net>
Cc: Borislav Petkov <b...@alien8.de>
Cc: Dave Hansen <dave.han...@linux.intel.com>
Cc: Fenghua Yu <fenghua...@intel.com>
Cc: H. Peter Anvin <h...@zytor.com>
Cc: Linus Torvalds <torva...@linux-foundation.org>
Cc: Oleg Nesterov <o...@redhat.com>
Cc: Thomas Gleixner <t...@linutronix.de>
Signed-off-by: Ingo Molnar <mi...@kernel.org>
---
 arch/x86/kernel/fpu/core.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/fpu/core.c b/arch/x86/kernel/fpu/core.c
index 45ef4e51928b..33c9a43b000e 100644
--- a/arch/x86/kernel/fpu/core.c
+++ b/arch/x86/kernel/fpu/core.c
@@ -348,6 +348,10 @@ void fpu__restore(void)
 }
 EXPORT_SYMBOL_GPL(fpu__restore);
 
+/*
+ * Called by sys_execve() to clear the FPU fpregs, so that FPU state
+ * of the previous binary does not leak over into the exec()ed binary:
+ */
 void fpu__clear(struct task_struct *tsk)
 {
        struct fpu *fpu = &tsk->thread.fpu;
@@ -361,8 +365,8 @@ void fpu__clear(struct task_struct *tsk)
                 if (!fpu->fpstate_active) {
                        fpu__activate_curr(fpu);
                        user_fpu_begin();
-                       restore_init_xstate();
                }
+               restore_init_xstate();
        }
 }
 
-- 
2.1.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to