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 */
> 

Reply via email to