Skip to content

Commit 03c81ea

Browse files
amlutosuryasaimadhu
authored andcommitted
x86/fault: Improve kernel-executing-user-memory handling
Right now, the case of the kernel trying to execute from user memory is treated more or less just like the kernel getting a page fault on a user access. In the failure path, it checks for erratum #93, tries to otherwise fix up the error, and then oopses. If it manages to jump to the user address space, with or without SMEP, it should not try to resolve the page fault. This is an error, pure and simple. Rearrange the code so that this case is caught early, check for erratum #93, and bail out. [ bp: Massage commit message. ] Signed-off-by: Andy Lutomirski <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Link: https://lkml.kernel.org/r/ab8719c7afb8bd501c4eee0e36493150fbbe5f6a.1612924255.git.luto@kernel.org
1 parent 56e62cd commit 03c81ea

File tree

1 file changed

+18
-3
lines changed

1 file changed

+18
-3
lines changed

arch/x86/mm/fault.c

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -447,6 +447,9 @@ static int is_errata93(struct pt_regs *regs, unsigned long address)
447447
|| boot_cpu_data.x86 != 0xf)
448448
return 0;
449449

450+
if (user_mode(regs))
451+
return 0;
452+
450453
if (address != regs->ip)
451454
return 0;
452455

@@ -744,9 +747,6 @@ no_context(struct pt_regs *regs, unsigned long error_code,
744747
if (is_prefetch(regs, error_code, address))
745748
return;
746749

747-
if (is_errata93(regs, address))
748-
return;
749-
750750
/*
751751
* Buggy firmware could access regions which might page fault, try to
752752
* recover from such faults.
@@ -1239,6 +1239,21 @@ void do_user_addr_fault(struct pt_regs *regs,
12391239
tsk = current;
12401240
mm = tsk->mm;
12411241

1242+
if (unlikely((error_code & (X86_PF_USER | X86_PF_INSTR)) == X86_PF_INSTR)) {
1243+
/*
1244+
* Whoops, this is kernel mode code trying to execute from
1245+
* user memory. Unless this is AMD erratum #93, which
1246+
* corrupts RIP such that it looks like a user address,
1247+
* this is unrecoverable. Don't even try to look up the
1248+
* VMA.
1249+
*/
1250+
if (is_errata93(regs, address))
1251+
return;
1252+
1253+
bad_area_nosemaphore(regs, error_code, address);
1254+
return;
1255+
}
1256+
12421257
/* kprobes don't want to hook the spurious faults: */
12431258
if (unlikely(kprobe_page_fault(regs, X86_TRAP_PF)))
12441259
return;

0 commit comments

Comments
 (0)