History

x86/kasan: Print original address on #GP

Make #GP exceptions caused by out-of-bounds KASAN shadow accesses easier to understand by computing the address of the original access and printing that. More details are in the comments in the patch. This turns an error like this: kasan: CONFIG_KASAN_INLINE enabled kasan: GPF could be caused by NULL-ptr deref or user memory access general protection fault, probably for non-canonical address 0xe017577ddf75b7dd: 0000 [#1] PREEMPT SMP KASAN PTI into this: general protection fault, probably for non-canonical address 0xe017577ddf75b7dd: 0000 [#1] PREEMPT SMP KASAN PTI KASAN: maybe wild-memory-access in range [0x00badbeefbadbee8-0x00badbeefbadbeef] The hook is placed in architecture-independent code, but is currently only wired up to the X86 exception handler because I'm not sufficiently familiar with the address space layout and exception handling mechanisms on other architectures.

Jann Horn committed 6 years ago

Commit 2f004ee1 parent aa49f204 files · +48 −21Browse files

Unified · Split

4 files
  1. arch/x86/kernel/dumpstack.c +2 −0
  2. arch/x86/mm/kasan_init_64.c +0 −21
  3. include/linux/kasan.h +6 −0
  4. mm/kasan/report.c +40 −0
arch/x86/kernel/dumpstack.c+2−0
@@ -427,6 +427,8 @@ void die_addr(const char *str, struct pt_regs *regs, long err, long gp_addr) · 426 unmodified lines
427 int sig = SIGSEGV;427 int sig = SIGSEGV;
428 428
429 __die_header(str, regs, err);429 __die_header(str, regs, err);
430 if (gp_addr)
431 kasan_non_canonical_hook(gp_addr);
430 if (__die_body(str, regs, err))432 if (__die_body(str, regs, err))
431 sig = 0;433 sig = 0;
432 oops_end(flags, regs, sig);434 oops_end(flags, regs, sig);
arch/x86/mm/kasan_init_64.c+0−21
@@ -288,23 +288,6 @@ static void __init kasan_shallow_populate_pgds(void *start, void *end) · 287 unmodified lines
288 } while (pgd++, addr = next, addr != (unsigned long)end);288 } while (pgd++, addr = next, addr != (unsigned long)end);
289}289}
290 290
291#ifdef CONFIG_KASAN_INLINE
292static int kasan_die_handler(struct notifier_block *self,
293 unsigned long val,
294 void *data)
295{
296 if (val == DIE_GPF) {
297 pr_emerg("CONFIG_KASAN_INLINE enabled\n");
298 pr_emerg("GPF could be caused by NULL-ptr deref or user memory access\n");
299 }
300 return NOTIFY_OK;
301}
302
303static struct notifier_block kasan_die_notifier = {
304 .notifier_call = kasan_die_handler,
305};
306#endif
307
308void __init kasan_early_init(void)291void __init kasan_early_init(void)
309{292{
310 int i;293 int i;
@@ -341,10 +324,6 @@ void __init kasan_init(void) · 30 unmodified lines
341 int i;324 int i;
342 void *shadow_cpu_entry_begin, *shadow_cpu_entry_end;325 void *shadow_cpu_entry_begin, *shadow_cpu_entry_end;
343 326
344#ifdef CONFIG_KASAN_INLINE
345 register_die_notifier(&kasan_die_notifier);
346#endif
347
348 memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt));327 memcpy(early_top_pgt, init_top_pgt, sizeof(early_top_pgt));
349 328
350 /*329 /*
include/linux/kasan.h+6−0
@@ -228,4 +228,10 @@ static inline void kasan_release_vmalloc(unsigned long start, · 227 unmodified lines
228 unsigned long free_region_end) {}228 unsigned long free_region_end) {}
229#endif229#endif
230 230
231#ifdef CONFIG_KASAN_INLINE
232void kasan_non_canonical_hook(unsigned long addr);
233#else /* CONFIG_KASAN_INLINE */
234static inline void kasan_non_canonical_hook(unsigned long addr) { }
235#endif /* CONFIG_KASAN_INLINE */
236
231#endif /* LINUX_KASAN_H */237#endif /* LINUX_KASAN_H */
mm/kasan/report.c+40−0
@@ -512,3 +512,43 @@ void __kasan_report(unsigned long addr, size_t size, bool is_write, unsigned lon · 511 unmodified lines
512 512
513 end_report(&flags);513 end_report(&flags);
514}514}
515
516#ifdef CONFIG_KASAN_INLINE
517/*
518 * With CONFIG_KASAN_INLINE, accesses to bogus pointers (outside the high
519 * canonical half of the address space) cause out-of-bounds shadow memory reads
520 * before the actual access. For addresses in the low canonical half of the
521 * address space, as well as most non-canonical addresses, that out-of-bounds
522 * shadow memory access lands in the non-canonical part of the address space.
523 * Help the user figure out what the original bogus pointer was.
524 */
525void kasan_non_canonical_hook(unsigned long addr)
526{
527 unsigned long orig_addr;
528 const char *bug_type;
529
530 if (addr < KASAN_SHADOW_OFFSET)
531 return;
532
533 orig_addr = (addr - KASAN_SHADOW_OFFSET) << KASAN_SHADOW_SCALE_SHIFT;
534 /*
535 * For faults near the shadow address for NULL, we can be fairly certain
536 * that this is a KASAN shadow memory access.
537 * For faults that correspond to shadow for low canonical addresses, we
538 * can still be pretty sure - that shadow region is a fairly narrow
539 * chunk of the non-canonical address space.
540 * But faults that look like shadow for non-canonical addresses are a
541 * really large chunk of the address space. In that case, we still
542 * print the decoded address, but make it clear that this is not
543 * necessarily what's actually going on.
544 */
545 if (orig_addr < PAGE_SIZE)
546 bug_type = "null-ptr-deref";
547 else if (orig_addr < TASK_SIZE)
548 bug_type = "probably user-memory-access";
549 else
550 bug_type = "maybe wild-memory-access";
551 pr_alert("KASAN: %s in range [0x%016lx-0x%016lx]\n", bug_type,
552 orig_addr, orig_addr + KASAN_SHADOW_MASK);
553}
554#endif