On Mon, Dec 04, 2017 at 12:24:00PM +0100, Martin Pieuchot wrote:
> 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?
>
This looks ok to me.
-ml
> 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
>