x86/nmi: Fix NMI uaccess race against CR3 switching
A NMI can hit in the middle of context switching or in the middle of switch_mm_irqs_off(). In either case, CR3 might not match current->mm, which could cause copy_from_user_nmi() and friends to read the wrong memory. Fix it by adding a new nmi_uaccess_okay() helper and checking it in copy_from_user_nmi() and in __copy_from_user_nmi()'s callers. Signed-off-by: Andy Lutomirski <luto@kernel.org> Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Reviewed-by: Rik van Riel <riel@surriel.com> Cc: Nadav Amit <nadav.amit@gmail.com> Cc: Borislav Petkov <bp@alien8.de> Cc: Jann Horn <jannh@google.com> Cc: Peter Zijlstra <peterz@infradead.org> Cc: stable@vger.kernel.org Link: https://lkml.kernel.org/r/dd956eba16646fd0b15c3c0741269dfd84452dac.1535557289.git.luto@kernel.org
This commit is contained in:

committed by
Thomas Gleixner

parent
829fe4aa9a
commit
4012e77a90
@@ -7,6 +7,8 @@
|
||||
#include <linux/uaccess.h>
|
||||
#include <linux/export.h>
|
||||
|
||||
#include <asm/tlbflush.h>
|
||||
|
||||
/*
|
||||
* We rely on the nested NMI work to allow atomic faults from the NMI path; the
|
||||
* nested NMI paths are careful to preserve CR2.
|
||||
@@ -19,6 +21,9 @@ copy_from_user_nmi(void *to, const void __user *from, unsigned long n)
|
||||
if (__range_not_ok(from, n, TASK_SIZE))
|
||||
return n;
|
||||
|
||||
if (!nmi_uaccess_okay())
|
||||
return n;
|
||||
|
||||
/*
|
||||
* Even though this function is typically called from NMI/IRQ context
|
||||
* disable pagefaults so that its behaviour is consistent even when
|
||||
|
Reference in New Issue
Block a user