diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 602cdf8e070a14..1939e546beae87 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c @@ -406,8 +406,11 @@ static void dump_pagetable(unsigned long address) static int is_errata93(struct pt_regs *regs, unsigned long address) { #if defined(CONFIG_X86_64) && defined(CONFIG_CPU_SUP_AMD) - if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD - || boot_cpu_data.x86 != 0xf) + if (likely(boot_cpu_data.x86_vendor != X86_VENDOR_AMD + || boot_cpu_data.x86 != 0xf)) + return 0; + + if (user_mode(regs)) return 0; if (address != regs->ip) @@ -707,9 +710,6 @@ no_context(struct pt_regs *regs, unsigned long error_code, if (is_prefetch(regs, error_code, address)) return; - if (is_errata93(regs, address)) - return; - /* * Buggy firmware could access regions which might page fault, try to * recover from such faults. @@ -1202,6 +1202,19 @@ void do_user_addr_fault(struct pt_regs *regs, tsk = current; mm = tsk->mm; + if (unlikely((error_code & (X86_PF_USER | X86_PF_INSTR)) == X86_PF_INSTR)) { + /* + * Whoops, this is kernel mode code trying to execute from + * user memory. Unless this is AMD erratum #93, we are toast. + * Don't even try to look up the VMA. + */ + if (is_errata93(regs, address)) + return; + + bad_area_nosemaphore(regs, error_code, address); + return; + } + /* kprobes don't want to hook the spurious faults: */ if (unlikely(kprobe_page_fault(regs, X86_TRAP_PF))) return;