diff options
author | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-12-08 08:54:04 +0000 |
---|---|---|
committer | Martin Pieuchot <mpi@cvs.openbsd.org> | 2017-12-08 08:54:04 +0000 |
commit | bc0a7095a7574c1ea986bdc86b1dc02fe318adc2 (patch) | |
tree | 30d953c35bb116316d23584486002d1400014d9e | |
parent | 2c077aa06384742aa1fa2d4264b798806a255541 (diff) |
Disable SMAP temporarily to display userland traces.
ok visa@, deraadt@, mlarkin@, jasper@
-rw-r--r-- | sys/arch/amd64/amd64/db_trace.c | 46 | ||||
-rw-r--r-- | sys/arch/i386/i386/db_trace.c | 48 |
2 files changed, 65 insertions, 29 deletions
diff --git a/sys/arch/amd64/amd64/db_trace.c b/sys/arch/amd64/amd64/db_trace.c index 8783f4c22e9..f3234a70cb3 100644 --- a/sys/arch/amd64/amd64/db_trace.c +++ b/sys/arch/amd64/amd64/db_trace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_trace.c,v 1.36 2017/11/03 11:29:46 jasper Exp $ */ +/* $OpenBSD: db_trace.c,v 1.37 2017/12/08 08:54:03 mpi Exp $ */ /* $NetBSD: db_trace.c,v 1.1 2003/04/26 18:39:27 fvdl Exp $ */ /* @@ -169,9 +169,11 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, struct callframe *frame, *lastframe; unsigned long *argp, *arg0; db_addr_t callpc; + unsigned int cr4save = CR4_SMEP|CR4_SMAP; int is_trap = 0; boolean_t kernel_only = TRUE; boolean_t trace_proc = FALSE; + struct proc *p; { char *cp = modif; @@ -185,22 +187,30 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, } } + if (trace_proc) { + p = tfind((pid_t)addr); + if (p == NULL) { + (*pr) ("not found\n"); + return; + } + } + + cr4save = rcr4(); + if (cr4save & CR4_SMAP) + lcr4(cr4save & ~CR4_SMAP); + if (!have_addr) { frame = (struct callframe *)ddb_regs.tf_rbp; callpc = (db_addr_t)ddb_regs.tf_rip; + } else if (trace_proc) { + frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp; + callpc = (db_addr_t) + db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE); + frame = (struct callframe *)frame->f_frame; } else { - if (trace_proc) { - struct proc *p = tfind((pid_t)addr); - if (p == NULL) { - (*pr) ("not found\n"); - return; - } - frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp; - } else { - frame = (struct callframe *)addr; - } + frame = (struct callframe *)addr; callpc = (db_addr_t) - db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE); + db_get_value((db_addr_t)&frame->f_retaddr, 8, FALSE); frame = (struct callframe *)frame->f_frame; } @@ -212,8 +222,13 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, db_expr_t offset; Elf_Sym * sym; - sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); - db_symbol_values(sym, &name, NULL); + if (INKERNEL(frame)) { + sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + db_symbol_values(sym, &name, NULL); + } else { + sym = NULL; + name = NULL; + } if (lastframe == 0 && sym == NULL) { /* Symbol not found, peek at code */ @@ -332,6 +347,9 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, db_printsym(callpc, DB_STGY_XTRN, pr); (*pr)(":\n"); } + + if (cr4save & CR4_SMAP) + lcr4(cr4save); } void diff --git a/sys/arch/i386/i386/db_trace.c b/sys/arch/i386/i386/db_trace.c index 8d7156b60b7..0e5289f60ab 100644 --- a/sys/arch/i386/i386/db_trace.c +++ b/sys/arch/i386/i386/db_trace.c @@ -1,4 +1,4 @@ -/* $OpenBSD: db_trace.c,v 1.31 2017/11/03 11:29:46 jasper Exp $ */ +/* $OpenBSD: db_trace.c,v 1.32 2017/12/08 08:54:03 mpi Exp $ */ /* $NetBSD: db_trace.c,v 1.18 1996/05/03 19:42:01 christos Exp $ */ /* @@ -184,18 +184,17 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, struct callframe *frame, *lastframe; int *argp, *arg0; db_addr_t callpc; + unsigned int cr4save = CR4_SMEP|CR4_SMAP; int is_trap = 0; boolean_t kernel_only = TRUE; - boolean_t trace_thread = FALSE; boolean_t trace_proc = FALSE; + struct proc *p; { char *cp = modif; char c; while ((c = *cp++) != 0) { - if (c == 't') - trace_thread = TRUE; if (c == 'p') trace_proc = TRUE; if (c == 'u') @@ -206,24 +205,33 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, if (count == -1) count = 65535; - if (!have_addr) { - frame = (struct callframe *)ddb_regs.tf_ebp; - callpc = (db_addr_t)ddb_regs.tf_eip; - } else if (trace_thread) { - (*pr) ("%s: can't trace thread\n", __func__); - } else if (trace_proc) { - struct proc *p = tfind((pid_t)addr); + if (trace_proc) { + p = tfind((pid_t)addr); if (p == NULL) { (*pr) ("not found\n"); return; } + } + + if (curcpu()->ci_feature_sefflags_ebx & SEFF0EBX_SMAP) { + cr4save = rcr4(); + if (cr4save & CR4_SMAP) + lcr4(cr4save & ~CR4_SMAP); + } else { + cr4save = 0; + } + + if (!have_addr) { + frame = (struct callframe *)ddb_regs.tf_ebp; + callpc = (db_addr_t)ddb_regs.tf_eip; + } else if (trace_proc) { frame = (struct callframe *)p->p_addr->u_pcb.pcb_ebp; callpc = (db_addr_t) db_get_value((int)&frame->f_retaddr, 4, FALSE); } else { frame = (struct callframe *)addr; callpc = (db_addr_t) - db_get_value((int)&frame->f_retaddr, 4, FALSE); + db_get_value((int)&frame->f_retaddr, 4, FALSE); } lastframe = 0; @@ -233,8 +241,13 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, db_expr_t offset; Elf_Sym *sym; - sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); - db_symbol_values(sym, &name, NULL); + if (INKERNEL(frame)) { + sym = db_search_symbol(callpc, DB_STGY_ANY, &offset); + db_symbol_values(sym, &name, NULL); + } else { + sym = NULL; + name = NULL; + } if (lastframe == 0 && sym == NULL) { /* Symbol not found, peek at code */ @@ -306,8 +319,10 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, } } else if (INKERNEL(lastframe)) { /* switch from user to kernel */ - if (kernel_only) + if (kernel_only) { + (*pr)("end of kernel\n"); break; /* kernel stack only */ + } } else { /* in user */ if (frame <= lastframe) { @@ -323,6 +338,9 @@ db_stack_trace_print(db_expr_t addr, boolean_t have_addr, db_expr_t count, db_printsym(callpc, DB_STGY_XTRN, pr); (*pr)(":\n"); } + + if (cr4save & CR4_SMAP) + lcr4(cr4save); } void |