summaryrefslogtreecommitdiff
path: root/arch/x86/mm/extable.c
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2017-10-03 09:35:04 +1000
committerDave Airlie <airlied@redhat.com>2017-10-03 09:35:04 +1000
commitebec44a2456fbe5fe18aae88f6010f6878f0cb4a (patch)
tree427734722bdf3e807333329f33a6dbd6e95ec747 /arch/x86/mm/extable.c
parent659333de48268550b5f09fcd45f76459d737b946 (diff)
parent9e66317d3c92ddaab330c125dfe9d06eee268aff (diff)
downloadlinux-ebec44a2456fbe5fe18aae88f6010f6878f0cb4a.tar.gz
linux-ebec44a2456fbe5fe18aae88f6010f6878f0cb4a.tar.bz2
linux-ebec44a2456fbe5fe18aae88f6010f6878f0cb4a.zip
BackMerge tag 'v4.14-rc3' into drm-next
Linux 4.14-rc3 Requested by Daniel for the tracing build fix in fixes.
Diffstat (limited to 'arch/x86/mm/extable.c')
-rw-r--r--arch/x86/mm/extable.c24
1 files changed, 24 insertions, 0 deletions
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index c076f710de4c..c3521e2be396 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -2,6 +2,7 @@
#include <linux/uaccess.h>
#include <linux/sched/debug.h>
+#include <asm/fpu/internal.h>
#include <asm/traps.h>
#include <asm/kdebug.h>
@@ -78,6 +79,29 @@ bool ex_handler_refcount(const struct exception_table_entry *fixup,
}
EXPORT_SYMBOL_GPL(ex_handler_refcount);
+/*
+ * Handler for when we fail to restore a task's FPU state. We should never get
+ * here because the FPU state of a task using the FPU (task->thread.fpu.state)
+ * should always be valid. However, past bugs have allowed userspace to set
+ * reserved bits in the XSAVE area using PTRACE_SETREGSET or sys_rt_sigreturn().
+ * These caused XRSTOR to fail when switching to the task, leaking the FPU
+ * registers of the task previously executing on the CPU. Mitigate this class
+ * of vulnerability by restoring from the initial state (essentially, zeroing
+ * out all the FPU registers) if we can't restore from the task's FPU state.
+ */
+bool ex_handler_fprestore(const struct exception_table_entry *fixup,
+ struct pt_regs *regs, int trapnr)
+{
+ regs->ip = ex_fixup_addr(fixup);
+
+ WARN_ONCE(1, "Bad FPU state detected at %pB, reinitializing FPU registers.",
+ (void *)instruction_pointer(regs));
+
+ __copy_kernel_to_fpregs(&init_fpstate, -1);
+ return true;
+}
+EXPORT_SYMBOL_GPL(ex_handler_fprestore);
+
bool ex_handler_ext(const struct exception_table_entry *fixup,
struct pt_regs *regs, int trapnr)
{