summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2019-02-26 09:16:04 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2019-03-04 10:08:28 -0800
commit00c42373d3970b354948ba3b24a34501b1a2505f (patch)
tree5f3361f5d7a8e39d4f3b3e3835fdb4fbcab02ed8 /arch
parent1c163f4c7b3f621efff9b28a47abb36f7378d783 (diff)
downloadlinux-00c42373d3970b354948ba3b24a34501b1a2505f.tar.bz2
x86-64: add warning for non-canonical user access address dereferences
This adds a warning (once) for any kernel dereference that has a user exception handler, but accesses a non-canonical address. It basically is a simpler - and more limited - version of commit 9da3f2b74054 ("x86/fault: BUG() when uaccess helpers fault on kernel addresses") that got reverted. Note that unlike that original commit, this only causes a warning, because there are real situations where we currently can do this (notably speculative argument fetching for uprobes etc). Also, unlike that original commit, this _only_ triggers for #GP accesses, so the cases of valid kernel pointers that cross into a non-mapped page aren't affected. The intent of this is two-fold: - the uprobe/tracing accesses really do need to be more careful. In particular, from a portability standpoint it's just wrong to think that "a pointer is a pointer", and use the same logic for any random pointer value you find on the stack. It may _work_ on x86-64, but it doesn't necessarily work on other architectures (where the same pointer value can be either a kernel pointer _or_ a user pointer, and you really need to be much more careful in how you try to access it) The warning can hopefully end up being a reminder that just any random pointer access won't do. - Kees in particular wanted a way to actually report invalid uses of wild pointers to user space accessors, instead of just silently failing them. Automated fuzzers want a way to get reports if the kernel ever uses invalid values that the fuzzer fed it. The non-canonical address range is a fair chunk of the address space, and with this you can teach syzkaller to feed in invalid pointer values and find cases where we do not properly validate user addresses (possibly due to bad uses of "set_fs()"). Acked-by: Kees Cook <keescook@chromium.org> Cc: Jann Horn <jannh@google.com> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Peter Zijlstra <peterz@infradead.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/mm/extable.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 856fa409c536..3c4568f8fb28 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -122,6 +122,7 @@ __visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
unsigned long error_code,
unsigned long fault_addr)
{
+ WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
regs->ip = ex_fixup_addr(fixup);
return true;
}