Call fixup_vdso_exception() to attempt to fixup exceptions in vDSO code before generating a signal for userspace faults. This allows vDSO functions to utilize exception fixup to report unhandled exceptions directly to userspace for specific flows in lieu of generating a signal.
Suggested-by: Andy Lutomirski <l...@amacapital.net> Cc: Andy Lutomirski <l...@amacapital.net> Cc: Jarkko Sakkinen <jarkko.sakki...@linux.intel.com> Cc: Dave Hansen <dave.han...@linux.intel.com> Cc: Josh Triplett <j...@joshtriplett.org> Signed-off-by: Sean Christopherson <sean.j.christopher...@intel.com> --- arch/x86/kernel/traps.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 9b7c4ca8f0a7..106a6cc20ad6 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -61,6 +61,7 @@ #include <asm/mpx.h> #include <asm/vm86.h> #include <asm/umip.h> +#include <asm/vdso.h> #ifdef CONFIG_X86_64 #include <asm/x86_init.h> @@ -223,6 +224,10 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, const char *str, tsk->thread.error_code = error_code; tsk->thread.trap_nr = trapnr; + if (user_mode(regs) && + fixup_vdso_exception(regs, trapnr, error_code, 0)) + return 0; + return -1; } @@ -563,6 +568,9 @@ do_general_protection(struct pt_regs *regs, long error_code) tsk->thread.error_code = error_code; tsk->thread.trap_nr = X86_TRAP_GP; + if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0)) + return; + show_signal(tsk, SIGSEGV, "", desc, regs, error_code); force_sig(SIGSEGV, tsk); @@ -854,6 +862,9 @@ static void math_error(struct pt_regs *regs, int error_code, int trapnr) if (!si_code) return; + if (fixup_vdso_exception(regs, trapnr, error_code, 0)) + return; + force_sig_fault(SIGFPE, si_code, (void __user *)uprobe_get_trap_addr(regs), task); } -- 2.19.2