On Thu, Dec 19, 2019 at 06:25:06PM -0800, Philip Guenther wrote: > For this part, should we reuse the 'faultstr' logic seen later to set the > panic string and do something like, say...
That makes sense. I need another workaround for the stack trace after calling the NULL function. This time I tested with SMEP/SMAP and ddb.panic=0/1. I get nice traces in all cases. ok? bluhm 1. SMEP, ddb.panic=0 attempt to execute user address 0x0 in supervisor mode fatal page fault in supervisor mode trap type 6 code 10 rip 0 cs 8 rflags 10286 cr2 0 cpl 0 rsp ffff80001feee048 gsbase 0xffff80001fb5aff0 kgsbase 0x0 panic: trap type 6, code=10, pc=0 Starting stack trace... panic(ffffffff81c5759e) at panic+0x11b kerntrap(ffff80001feedf90) at kerntrap+0x114 alltraps_kern_meltdown() at alltraps_kern_meltdown+0x7b 0(ffff80001feee458,4,8975d881000,ffff80001feee488,ffff8000ffff58c0,ffff80001feee458) at 0 kern_sysctl(ffff80001feee454,5,8975d881000,ffff80001feee488,0,0) at kern_sysctl+0x18e sys_sysctl(ffff8000ffff58c0,ffff80001feee4f0,ffff80001feee550) at sys_sysctl+0x186 syscall(ffff80001feee5c0) at syscall+0x389 Xsyscall() at Xsyscall+0x128 end of kernel end trace frame: 0x7f7ffffbb490, count: 249 End of stack trace. 2. SMEP, ddb.panic=1 attempt to execute user address 0x0 in supervisor mode kernel: page fault trap, code=0 Stopped at 0 ddb{3}> show panic kernel page fault attempt to execute user address 0x0 in supervisor mode 0(ffff8000004cf190,0,17,ffff80001feee7b8,0,23bcd315000) at 0 sysctl_file(ffff80001feee788,4,23bcd315000,ffff80001feee7b8,ffff8000ffff0018) a t sysctl_file+0x75c end trace frame: 0xffff80001feee760, count: 0 ddb{3}> trace 0(ffff8000004cf190,0,17,ffff80001feee7b8,0,23bcd315000) at 0 sysctl_file(ffff80001feee788,4,23bcd315000,ffff80001feee7b8,ffff8000ffff0018) a t sysctl_file+0x75c kern_sysctl(ffff80001feee784,5,23bcd315000,ffff80001feee7b8,0,0) at kern_sysctl +0x18e sys_sysctl(ffff8000ffff0018,ffff80001feee820,ffff80001feee880) at sys_sysctl+0x 186 syscall(ffff80001feee8f0) at syscall+0x389 Xsyscall() at Xsyscall+0x128 end of kernel end trace frame: 0x7f7fffffacd0, count: -5 ddb{3}> 3. SMAP, ddb.panic=0 attempt to access user address 0x2af5846a000 in supervisor mode fatal page fault in supervisor mode trap type 6 code 3 rip ffffffff812d1c75 cs 8 rflags 10202 cr2 2af5846a000 cpl 0 rsp ffff80001feee4e8 gsbase 0xffff80001fb63ff0 kgsbase 0x0 panic: trap type 6, code=3, pc=ffffffff812d1c75 Starting stack trace... panic(ffffffff81c59b90) at panic+0x11b kerntrap(ffff80001feee430) at kerntrap+0x114 alltraps_kern_meltdown() at alltraps_kern_meltdown+0x7b memcpy() at memcpy+0x15 kern_sysctl(ffff80001feee8f4,5,2af5846a000,ffff80001feee928,0,0) at kern_sysctl+0x18e sys_sysctl(ffff8000ffff1650,ffff80001feee990,ffff80001feee9f0) at sys_sysctl+0x186 syscall(ffff80001feeea60) at syscall+0x389 Xsyscall() at Xsyscall+0x128 end of kernel end trace frame: 0x7f7ffffd7d00, count: 249 End of stack trace. 4. SMAP, ddb.panic=1 attempt to access user address 0x3e88d674000 in supervisor mode kernel: page fault trap, code=0 Stopped at memcpy+0x15: repe movsq (%rsi),%es:(%rdi) ddb{1}> show panic kernel page fault attempt to access user address 0x3e88d674000 in supervisor mode memcpy() at memcpy+0x15 end trace frame: 0xffff80001feee7f0, count: 0 ddb{1}> trace memcpy() at memcpy+0x15 kern_sysctl(ffff80001feee814,5,3e88d674000,ffff80001feee848,0,0) at kern_sysctl +0x18e sys_sysctl(ffff8000ffff1650,ffff80001feee8b0,ffff80001feee910) at sys_sysctl+0x 186 syscall(ffff80001feee980) at syscall+0x389 Xsyscall() at Xsyscall+0x128 end of kernel end trace frame: 0x7f7ffffd9bf0, count: -5 ddb{1}> Index: arch/amd64/amd64/db_trace.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/db_trace.c,v retrieving revision 1.47 diff -u -p -r1.47 db_trace.c --- arch/amd64/amd64/db_trace.c 10 Nov 2019 10:03:33 -0000 1.47 +++ arch/amd64/amd64/db_trace.c 20 Dec 2019 16:15:46 -0000 @@ -150,7 +150,7 @@ db_stack_trace_print(db_expr_t addr, int name = NULL; } - if (lastframe == 0 && sym == NULL) { + if (lastframe == 0 && sym == NULL && callpc != 0) { /* Symbol not found, peek at code */ unsigned long instr = db_get_value(callpc, 8, 0); Index: arch/amd64/amd64/trap.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/arch/amd64/amd64/trap.c,v retrieving revision 1.77 diff -u -p -r1.77 trap.c --- arch/amd64/amd64/trap.c 6 Sep 2019 12:22:01 -0000 1.77 +++ arch/amd64/amd64/trap.c 20 Dec 2019 17:16:18 -0000 @@ -77,6 +77,7 @@ #include <sys/signal.h> #include <sys/syscall.h> #include <sys/syscall_mi.h> +#include <sys/stdarg.h> #include <uvm/uvm_extern.h> @@ -132,6 +133,24 @@ static inline void verify_smap(const cha static inline void debug_trap(struct trapframe *_frame, struct proc *_p, long _type); +static inline int +fault(const char *format, ...) +{ + static char faultbuf[512]; + va_list ap; + + /* + * Save the fault info for DDB and retain the kernel lock to keep + * faultbuf from being overwritten by another CPU. + */ + va_start(ap, format); + vsnprintf(faultbuf, sizeof faultbuf, format, ap); + va_end(ap); + printf("%s\n", faultbuf); + faultstr = faultbuf; + return 0; +} + /* * pageflttrap(frame, usermode): page fault handler * Returns non-zero if the fault was handled (possibly by generating @@ -160,16 +179,14 @@ pageflttrap(struct trapframe *frame, int KERNEL_LOCK(); if (!usermode) { - extern struct vm_map *kernel_map; - /* This will only trigger if SMEP is enabled */ if (cr2 <= VM_MAXUSER_ADDRESS && frame->tf_err & PGEX_I) - panic("attempt to execute user address %p " + return fault("attempt to execute user address %p " "in supervisor mode", (void *)cr2); /* This will only trigger if SMAP is enabled */ if (pcb->pcb_onfault == NULL && cr2 <= VM_MAXUSER_ADDRESS && frame->tf_err & PGEX_P) - panic("attempt to access user address %p " + return fault("attempt to access user address %p " "in supervisor mode", (void *)cr2); /* @@ -211,18 +228,9 @@ pageflttrap(struct trapframe *frame, int frame->tf_rip = (u_int64_t)pcb->pcb_onfault; return 1; } else { - /* - * Bad memory access in the kernel; save the fault - * info for DDB and retain the kernel lock to keep - * faultbuf from being overwritten by another CPU. - */ - static char faultbuf[512]; - snprintf(faultbuf, sizeof faultbuf, - "uvm_fault(%p, 0x%llx, 0, %d) -> %x", + /* bad memory access in the kernel */ + return fault("uvm_fault(%p, 0x%llx, 0, %d) -> %x", map, cr2, ftype, error); - printf("%s\n", faultbuf); - faultstr = faultbuf; - return 0; } } else { union sigval sv; @@ -395,7 +403,7 @@ trap_print(struct trapframe *frame, int printf(" in %s mode\n", KERNELMODE(frame->tf_cs, frame->tf_rflags) ? "supervisor" : "user"); printf("trap type %d code %llx rip %llx cs %llx rflags %llx cr2 " - " %llx cpl %x rsp %llx\n", + "%llx cpl %x rsp %llx\n", type, frame->tf_err, frame->tf_rip, frame->tf_cs, frame->tf_rflags, rcr2(), curcpu()->ci_ilevel, frame->tf_rsp); printf("gsbase %p kgsbase %p\n", Index: ddb/db_examine.c =================================================================== RCS file: /data/mirror/openbsd/cvs/src/sys/ddb/db_examine.c,v retrieving revision 1.26 diff -u -p -r1.26 db_examine.c --- ddb/db_examine.c 7 Nov 2019 13:16:25 -0000 1.26 +++ ddb/db_examine.c 20 Dec 2019 17:20:36 -0000 @@ -288,8 +288,10 @@ void db_print_loc_and_inst(vaddr_t loc) { db_printsym(loc, DB_STGY_PROC, db_printf); - db_printf(":\t"); - (void) db_disasm(loc, 0); + if (loc != 0) { + db_printf(":\t"); + db_disasm(loc, 0); + } } /* local copy is needed here so that we can trace strlcpy() in libkern */