Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/amd64/amd64 Unwind the stack on error, to get the f...



details:   https://anonhg.NetBSD.org/src/rev/ecb7f361c786
branches:  trunk
changeset: 834666:ecb7f361c786
user:      maxv <maxv%NetBSD.org@localhost>
date:      Wed Aug 22 17:25:02 2018 +0000

description:
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 <netbsd>
#1 0xffffffff80e62330 in sys_rasctl <netbsd>
#2 0xffffffff80265008 in syscall <netbsd>

(I manually added a one-byte stack read overflow in rasctl to demonstrate.)

diffstat:

 sys/arch/amd64/amd64/asan.c |  62 +++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 60 insertions(+), 2 deletions(-)

diffs (96 lines):

diff -r a8676bd54ffa -r ecb7f361c786 sys/arch/amd64/amd64/asan.c
--- a/sys/arch/amd64/amd64/asan.c       Wed Aug 22 17:04:36 2018 +0000
+++ b/sys/arch/amd64/amd64/asan.c       Wed Aug 22 17:25:02 2018 +0000
@@ -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 <sys/cdefs.h>
-__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 <sys/param.h>
 #include <sys/device.h>
@@ -40,6 +40,7 @@
 #include <sys/conf.h>
 #include <sys/systm.h>
 #include <sys/types.h>
+#include <sys/ksyms.h>
 #include <sys/asan.h>
 
 #include <uvm/uvm.h>
@@ -248,12 +249,69 @@
 
 /* -------------------------------------------------------------------------- */
 
+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();
 }
 
 /* -------------------------------------------------------------------------- */



Home | Main Index | Thread Index | Old Index