[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <c31660074f9c8fa51f35b490e0f20f82fedeae5b.1456524359.git.yu-cheng.yu@intel.com>
Date: Mon, 29 Feb 2016 09:42:02 -0800
From: Yu-cheng Yu <yu-cheng.yu@...el.com>
To: x86@...nel.org, "H. Peter Anvin" <hpa@...or.com>,
Thomas Gleixner <tglx@...utronix.de>,
Ingo Molnar <mingo@...hat.com>, linux-kernel@...r.kernel.org
Cc: Dave Hansen <dave.hansen@...ux.intel.com>,
Andy Lutomirski <luto@...nel.org>,
Borislav Petkov <bp@...e.de>,
Sai Praneeth Prakhya <sai.praneeth.prakhya@...el.com>,
"Ravi V. Shankar" <ravi.v.shankar@...el.com>,
Fenghua Yu <fenghua.yu@...el.com>,
Yu-cheng Yu <yu-cheng.yu@...el.com>
Subject: [PATCH v3 4/9] x86/xsaves: Introduce a new check that allows correct xstates copy from kernel to user directly
XSAVES is a kernel instruction and uses a compacted format. When
working with user space, the kernel should provide standard-format,
non-supervisor state data. We cannot do __copy_to_user() from a compacted-
format kernel xstate area to a signal frame.
Note that the path to copy_fpstate_to_sigframe() does currently check if
the thread has used FPU, but add a WARN_ONCE() there to detect any
potential mis-use.
Dave Hansen proposes this method to simplify copy xstate directly to user.
Signed-off-by: Fenghua Yu <fenghua.yu@...el.com>
Signed-off by: Yu-cheng Yu <yu-cheng.yu@...el.com>
---
arch/x86/kernel/fpu/signal.c | 41 ++++++++++++++++++++++++++++++++++++++++-
1 file changed, 40 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 0fbf60c..09945f1 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -130,6 +130,45 @@ static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf)
return err;
}
+static int may_copy_fpregs_to_sigframe(void)
+{
+ /*
+ * In signal handling path, the kernel already checks if
+ * FPU instructions have been used before it calls
+ * copy_fpstate_to_sigframe(). We check this here again
+ * to detect any potential mis-use and saving invalid
+ * register values directly to a signal frame.
+ */
+ WARN_ONCE(!current->thread.fpu.fpstate_active,
+ "direct FPU save with no math use\n");
+
+ /*
+ * In the case that we are using a compacted kernel
+ * xsave area, we can not copy the thread.fpu.state
+ * directly to userspace and *must* save it from the
+ * registers directly.
+ */
+ if (boot_cpu_has(X86_FEATURE_XSAVES))
+ return 1;
+
+ /*
+ * fpregs_active() means "Can I use the FPU hardware
+ * without taking a device-not-available exception?" This
+ * means that saving the registers directly will be
+ * cheaper than copying their contents out of
+ * thread.fpu.state.
+ *
+ * Note that fpregs_active() is inherently racy and may
+ * become false at any time. If this race happens, we
+ * will take a harmless device-not-available exception
+ * when we attempt the FPU save instruction.
+ */
+ if (fpregs_active())
+ return 1;
+
+ return 0;
+}
+
/*
* Save the fpu, extended register state to the user signal frame.
*
@@ -167,7 +206,7 @@ int copy_fpstate_to_sigframe(void __user *buf, void __user *buf_fx, int size)
sizeof(struct user_i387_ia32_struct), NULL,
(struct _fpstate_32 __user *) buf) ? -1 : 1;
- if (fpregs_active()) {
+ if (may_copy_fpregs_to_sigframe()) {
/* Save the live register state to the user directly. */
if (copy_fpregs_to_sigframe(buf_fx))
return -1;
--
1.9.1
Powered by blists - more mailing lists