Alexander Bluhm <alexander.bl...@gmx.net> wrote: > 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?
I am not confident about the db_print_loc_and_inst() change. To me it seems trap should recognize that the call has failed, and the fault-pc should not be the destination, but be rewinded to the caller. After all that that is where the fault happened. > > 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 */ >