Skip to content

Commit

Permalink
x86/fault: Improve kernel-executing-user-memory handling
Browse files Browse the repository at this point in the history
Right now we treat the case of the kernel trying to execute from user
memory more or less just like the kernel getting a page fault on a user
access.  In the failure path, we check for erratum torvalds#93, try to otherwise
fix up the error, and then oops.

If we manage to jump to the user address space, with or without SMEP, we
should not try to resolve the page fault.  This is an error, pure and
simple.  Rearrange the code so that we catch this case early, check for
erratum torvalds#93, and bail out.

Cc: Dave Hansen <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Andy Lutomirski <[email protected]>
  • Loading branch information
amluto committed Feb 10, 2021
1 parent a3fb5f1 commit 79b73a4
Showing 1 changed file with 18 additions and 3 deletions.
21 changes: 18 additions & 3 deletions arch/x86/mm/fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -447,6 +447,9 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
|| boot_cpu_data.x86 != 0xf)
return 0;

if (user_mode(regs))
return 0;

if (address != regs->ip)
return 0;

Expand Down Expand Up @@ -744,9 +747,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.
Expand Down Expand Up @@ -1239,6 +1239,21 @@ 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, which
* corrupts RIP such that it looks like a user address,
* this is unrecoverable. 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;
Expand Down

0 comments on commit 79b73a4

Please sign in to comment.