summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Pieuchot <mpi@cvs.openbsd.org>2017-12-08 08:54:04 +0000
committerMartin Pieuchot <mpi@cvs.openbsd.org>2017-12-08 08:54:04 +0000
commitbc0a7095a7574c1ea986bdc86b1dc02fe318adc2 (patch)
tree30d953c35bb116316d23584486002d1400014d9e
parent2c077aa06384742aa1fa2d4264b798806a255541 (diff)
Disable SMAP temporarily to display userland traces.
ok visa@, deraadt@, mlarkin@, jasper@
-rw-r--r--sys/arch/amd64/amd64/db_trace.c46
-rw-r--r--sys/arch/i386/i386/db_trace.c48
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