Since SMAP is enabled ddb(4)'s 'trace /u' and 'trace /p' for a userland
processes result, as expected, in page faults.

Diff below disable SMAP for the duration of the command.  This allows us
to see any possible frame corruption.

ok?

Index: arch/amd64/amd64/db_trace.c
===================================================================
RCS file: /cvs/src/sys/arch/amd64/amd64/db_trace.c,v
retrieving revision 1.36
diff -u -p -r1.36 db_trace.c
--- arch/amd64/amd64/db_trace.c 3 Nov 2017 11:29:46 -0000       1.36
+++ arch/amd64/amd64/db_trace.c 4 Dec 2017 10:42:42 -0000
@@ -169,6 +169,7 @@ db_stack_trace_print(db_expr_t addr, boo
        struct callframe *frame, *lastframe;
        unsigned long   *argp, *arg0;
        db_addr_t       callpc;
+       unsigned int    cr4save;
        int             is_trap = 0;
        boolean_t       kernel_only = TRUE;
        boolean_t       trace_proc = FALSE;
@@ -185,6 +186,10 @@ db_stack_trace_print(db_expr_t addr, boo
                }
        }
 
+       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;
@@ -193,7 +198,7 @@ db_stack_trace_print(db_expr_t addr, boo
                        struct proc *p = tfind((pid_t)addr);
                        if (p == NULL) {
                                (*pr) ("not found\n");
-                               return;
+                               goto out;
                        }
                        frame = (struct callframe *)p->p_addr->u_pcb.pcb_rbp;
                } else {
@@ -212,8 +217,13 @@ db_stack_trace_print(db_expr_t addr, boo
                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 +342,9 @@ db_stack_trace_print(db_expr_t addr, boo
                db_printsym(callpc, DB_STGY_XTRN, pr);
                (*pr)(":\n");
        }
+
+out:
+       lcr4(cr4save);
 }
 
 void
Index: arch/i386/i386/db_trace.c
===================================================================
RCS file: /cvs/src/sys/arch/i386/i386/db_trace.c,v
retrieving revision 1.31
diff -u -p -r1.31 db_trace.c
--- arch/i386/i386/db_trace.c   3 Nov 2017 11:29:46 -0000       1.31
+++ arch/i386/i386/db_trace.c   4 Dec 2017 11:18:38 -0000
@@ -184,9 +184,9 @@ db_stack_trace_print(db_expr_t addr, boo
        struct callframe *frame, *lastframe;
        int             *argp, *arg0;
        db_addr_t       callpc;
+       unsigned int    cr4save;
        int             is_trap = 0;
        boolean_t       kernel_only = TRUE;
-       boolean_t       trace_thread = FALSE;
        boolean_t       trace_proc = FALSE;
 
        {
@@ -194,8 +194,6 @@ db_stack_trace_print(db_expr_t addr, boo
                char c;
 
                while ((c = *cp++) != 0) {
-                       if (c == 't')
-                               trace_thread = TRUE;
                        if (c == 'p')
                                trace_proc = TRUE;
                        if (c == 'u')
@@ -206,16 +204,18 @@ db_stack_trace_print(db_expr_t addr, boo
        if (count == -1)
                count = 65535;
 
+       cr4save = rcr4();
+       if (cr4save & CR4_SMAP)
+               lcr4(cr4save & ~CR4_SMAP);
+
        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 (p == NULL) {
                        (*pr) ("not found\n");
-                       return;
+                       goto out;
                }
                frame = (struct callframe *)p->p_addr->u_pcb.pcb_ebp;
                callpc = (db_addr_t)
@@ -233,8 +233,13 @@ db_stack_trace_print(db_expr_t addr, boo
                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 +311,10 @@ db_stack_trace_print(db_expr_t addr, boo
                        }
                } 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 +330,9 @@ db_stack_trace_print(db_expr_t addr, boo
                db_printsym(callpc, DB_STGY_XTRN, pr);
                (*pr)(":\n");
        }
+
+out:
+       lcr4(cr4save);
 }
 
 void

Reply via email to