diff options
| author | Jani Nikula <jani.nikula@intel.com> | 2017-10-18 12:37:31 +0300 |
|---|---|---|
| committer | Jani Nikula <jani.nikula@intel.com> | 2017-10-18 12:37:31 +0300 |
| commit | 526b96c4f8dceb0104e267c61e5a3b22c538570c (patch) | |
| tree | 8825258c4f678f5ad9fddc0afaf72d640458481a /arch/x86/mm/extable.c | |
| parent | cb8d50dfb341e9615c8d203a3e6513dae9ff901d (diff) | |
| parent | 40d86701a625eed9e644281b9af228d6a52d8ed9 (diff) | |
Merge drm-upstream/drm-next into drm-intel-next-queued
Needed for timer_setup() and drm_dev_{get,put}() conversions in i915.
Signed-off-by: Jani Nikula <jani.nikula@intel.com>
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) { |
