From 6398fab2c1d9b5705f54860fb54aad5be9d94622 Mon Sep 17 00:00:00 2001 From: maxv Date: Wed, 22 Aug 2018 17:25:02 +0000 Subject: [PATCH] Unwind the stack on error, to get the full path that led to the illegal access. Example of output: kASan: Unauthorized Access In 0xffffffff80e6219c: Addr 0xffffbb007a39fd03 [1 byte, read] #0 0xffffffff80e6219c in ras_purgeall #1 0xffffffff80e62330 in sys_rasctl #2 0xffffffff80265008 in syscall (I manually added a one-byte stack read overflow in rasctl to demonstrate.) --- sys/arch/amd64/amd64/asan.c | 62 +++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/sys/arch/amd64/amd64/asan.c b/sys/arch/amd64/amd64/asan.c index cf4ed7355360..1bef1fb50307 100644 --- a/sys/arch/amd64/amd64/asan.c +++ b/sys/arch/amd64/amd64/asan.c @@ -1,4 +1,4 @@ -/* $NetBSD: asan.c,v 1.4 2018/08/22 17:04:36 maxv Exp $ */ +/* $NetBSD: asan.c,v 1.5 2018/08/22 17:25:02 maxv Exp $ */ /* * Copyright (c) 2018 The NetBSD Foundation, Inc. @@ -30,7 +30,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: asan.c,v 1.4 2018/08/22 17:04:36 maxv Exp $"); +__KERNEL_RCSID(0, "$NetBSD: asan.c,v 1.5 2018/08/22 17:25:02 maxv Exp $"); #include #include @@ -40,6 +40,7 @@ __KERNEL_RCSID(0, "$NetBSD: asan.c,v 1.4 2018/08/22 17:04:36 maxv Exp $"); #include #include #include +#include #include #include @@ -248,12 +249,69 @@ kasan_init(void) /* -------------------------------------------------------------------------- */ +static inline bool +kasan_unwind_end(const char *name) +{ + if (!strcmp(name, "syscall") || + !strcmp(name, "handle_syscall") || + !strncmp(name, "Xintr", 5) || + !strncmp(name, "Xhandle", 7) || + !strncmp(name, "Xresume", 7) || + !strncmp(name, "Xstray", 6) || + !strncmp(name, "Xhold", 5) || + !strncmp(name, "Xrecurse", 8) || + !strcmp(name, "Xdoreti") || + !strncmp(name, "Xsoft", 5)) { + return true; + } + + return false; +} + +static void +kasan_unwind(void) +{ + uint64_t *rbp, rip; + const char *mod; + const char *sym; + size_t nsym; + int error; + + rbp = (uint64_t *)__builtin_frame_address(0); + nsym = 0; + + while (1) { + /* 8(%rbp) contains the saved %rip. */ + rip = *(rbp + 1); + + if (rip < KERNBASE) { + break; + } + error = ksyms_getname(&mod, &sym, (vaddr_t)rip, KSYMS_PROC); + if (error) { + break; + } + printf("#%zu %p in %s <%s>\n", nsym, (void *)rip, sym, mod); + if (kasan_unwind_end(sym)) { + break; + } + + rbp = (uint64_t *)*(rbp); + nsym++; + + if (nsym >= 15) { + break; + } + } +} + static void kasan_report(unsigned long addr, size_t size, bool write, unsigned long rip) { printf("kASan: Unauthorized Access In %p: Addr %p [%zu byte%s, %s]\n", (void *)rip, (void *)addr, size, (size > 1 ? "s" : ""), (write ? "write" : "read")); + kasan_unwind(); } /* -------------------------------------------------------------------------- */