diff options
author | Dave Airlie <airlied@redhat.com> | 2017-10-03 09:35:04 +1000 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2017-10-03 09:35:04 +1000 |
commit | ebec44a2456fbe5fe18aae88f6010f6878f0cb4a (patch) | |
tree | 427734722bdf3e807333329f33a6dbd6e95ec747 /arch/x86/mm/extable.c | |
parent | 659333de48268550b5f09fcd45f76459d737b946 (diff) | |
parent | 9e66317d3c92ddaab330c125dfe9d06eee268aff (diff) | |
download | linux-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.c | 24 |
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) { |