linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs
@ 2018-05-14 14:06 Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 2/6] x86/stacktrace: make clear the success paths Jiri Slaby
                   ` (4 more replies)
  0 siblings, 5 replies; 9+ messages in thread
From: Jiri Slaby @ 2018-05-14 14:06 UTC (permalink / raw)
  To: mingo
  Cc: linux-kernel, Jiri Slaby, Thomas Gleixner, H. Peter Anvin, x86,
	Josh Poimboeuf

Josh pointed out, that there is no way a frame can be after user regs.
So remove the last unwind and the check.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/stacktrace.c | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 093f2ea5dd56..8948b7d9c064 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -113,15 +113,6 @@ __save_stack_trace_reliable(struct stack_trace *trace,
 			if (!user_mode(regs))
 				return -EINVAL;
 
-			/*
-			 * The last frame contains the user mode syscall
-			 * pt_regs.  Skip it and finish the unwind.
-			 */
-			unwind_next_frame(&state);
-			if (!unwind_done(&state)) {
-				STACKTRACE_DUMP_ONCE(task);
-				return -EINVAL;
-			}
 			break;
 		}
 
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 2/6] x86/stacktrace: make clear the success paths
  2018-05-14 14:06 [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs Jiri Slaby
@ 2018-05-14 14:06 ` Jiri Slaby
  2018-05-14 15:03   ` Josh Poimboeuf
  2018-05-14 14:06 ` [PATCH v2 3/6] x86/stacktrace: remove STACKTRACE_DUMP_ONCE from __save_stack_trace_reliable Jiri Slaby
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2018-05-14 14:06 UTC (permalink / raw)
  To: mingo
  Cc: linux-kernel, Jiri Slaby, Thomas Gleixner, H. Peter Anvin, x86,
	Josh Poimboeuf

Make clear which path is for user tasks and for kthreads and idle
tasks. This will allow easier plug-in of ORC unwinder in the next
patches.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/stacktrace.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 8948b7d9c064..3a4602c2324f 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -104,16 +104,18 @@ __save_stack_trace_reliable(struct stack_trace *trace,
 
 		regs = unwind_get_entry_regs(&state, NULL);
 		if (regs) {
+			/* Success path for user tasks */
+			if (user_mode(regs))
+				goto success;
+
 			/*
 			 * Kernel mode registers on the stack indicate an
 			 * in-kernel interrupt or exception (e.g., preemption
 			 * or a page fault), which can make frame pointers
 			 * unreliable.
 			 */
-			if (!user_mode(regs))
-				return -EINVAL;
 
-			break;
+			return -EINVAL;
 		}
 
 		addr = unwind_get_return_address(&state);
@@ -138,6 +140,11 @@ __save_stack_trace_reliable(struct stack_trace *trace,
 		return -EINVAL;
 	}
 
+	/* Success path for non-user tasks, i.e. kthreads and idle tasks */
+	if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
+		return -EINVAL;
+
+success:
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 3/6] x86/stacktrace: remove STACKTRACE_DUMP_ONCE from __save_stack_trace_reliable
  2018-05-14 14:06 [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 2/6] x86/stacktrace: make clear the success paths Jiri Slaby
@ 2018-05-14 14:06 ` Jiri Slaby
  2018-05-14 15:04   ` Josh Poimboeuf
  2018-05-14 14:06 ` [PATCH v2 4/6] x86/stacktrace: do not fail for ORC with regs on stack Jiri Slaby
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2018-05-14 14:06 UTC (permalink / raw)
  To: mingo
  Cc: linux-kernel, Jiri Slaby, Thomas Gleixner, H. Peter Anvin, x86,
	Josh Poimboeuf

The stack unwinding can sometimes fail yet. Especially with the
generated debug info. So do not yell at users -- live patching (the only
user of this interface) will inform the user about the failure
gracefully.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/stacktrace.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 3a4602c2324f..e0169b128523 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -125,20 +125,16 @@ __save_stack_trace_reliable(struct stack_trace *trace,
 		 * generated code which __kernel_text_address() doesn't know
 		 * about.
 		 */
-		if (!addr) {
-			STACKTRACE_DUMP_ONCE(task);
+		if (!addr)
 			return -EINVAL;
-		}
 
 		if (save_stack_address(trace, addr, false))
 			return -EINVAL;
 	}
 
 	/* Check for stack corruption */
-	if (unwind_error(&state)) {
-		STACKTRACE_DUMP_ONCE(task);
+	if (unwind_error(&state))
 		return -EINVAL;
-	}
 
 	/* Success path for non-user tasks, i.e. kthreads and idle tasks */
 	if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 4/6] x86/stacktrace: do not fail for ORC with regs on stack
  2018-05-14 14:06 [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 2/6] x86/stacktrace: make clear the success paths Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 3/6] x86/stacktrace: remove STACKTRACE_DUMP_ONCE from __save_stack_trace_reliable Jiri Slaby
@ 2018-05-14 14:06 ` Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 5/6] x86/unwind/orc: Detect the end of the stack Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 6/6] x86/stacktrace: orc, mark it as reliable Jiri Slaby
  4 siblings, 0 replies; 9+ messages in thread
From: Jiri Slaby @ 2018-05-14 14:06 UTC (permalink / raw)
  To: mingo
  Cc: linux-kernel, Jiri Slaby, Thomas Gleixner, H. Peter Anvin, x86,
	Josh Poimboeuf

save_stack_trace_reliable now returns "non reliable" when there are
kernel pt_regs on stack. This means an interrupt or exception happened
somewhere down the route. It is a problem for the frame pointer
unwinder, because the frame might not have been set up yet when the irq
happened, so the unwinder might fail to unwind from the interrupted
function.

With ORC, this is not a problem, as ORC has out-of-band data. We can
find ORC data even for the IP in the interrupted function and always
unwind one level up reliably.

So lift the check to apply only when CONFIG_FRAME_POINTER is enabled.

[v2]
- rewrite the code in favor of Josh's suggestions

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/stacktrace.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index e0169b128523..32983bf642d1 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -115,7 +115,8 @@ __save_stack_trace_reliable(struct stack_trace *trace,
 			 * unreliable.
 			 */
 
-			return -EINVAL;
+			if (IS_ENABLED(CONFIG_FRAME_POINTER))
+				return -EINVAL;
 		}
 
 		addr = unwind_get_return_address(&state);
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 5/6] x86/unwind/orc: Detect the end of the stack
  2018-05-14 14:06 [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs Jiri Slaby
                   ` (2 preceding siblings ...)
  2018-05-14 14:06 ` [PATCH v2 4/6] x86/stacktrace: do not fail for ORC with regs on stack Jiri Slaby
@ 2018-05-14 14:06 ` Jiri Slaby
  2018-05-14 14:06 ` [PATCH v2 6/6] x86/stacktrace: orc, mark it as reliable Jiri Slaby
  4 siblings, 0 replies; 9+ messages in thread
From: Jiri Slaby @ 2018-05-14 14:06 UTC (permalink / raw)
  To: mingo; +Cc: linux-kernel, Josh Poimboeuf, Jiri Slaby

From: Josh Poimboeuf <jpoimboe@redhat.com>

The existing UNWIND_HINT_EMPTY annotations happen to be good indicators
of where entry code calls into C code for the first time.  So also use
them to mark the end of the stack for the ORC unwinder.

Use that information to set unwind->error if the ORC unwinder doesn't
unwind all the way to the end.  This will be needed for enabling
HAVE_RELIABLE_STACKTRACE for the ORC unwinder so we can use it with the
livepatch consistency model.

Thanks to Jiri Slaby for teaching the ORCs about the unwind hints.

[v2] this patch is new in v2

Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/x86/entry/entry_64.S                      |  1 +
 arch/x86/include/asm/orc_types.h               |  2 +
 arch/x86/include/asm/unwind_hints.h            | 16 +++++---
 arch/x86/kernel/unwind_orc.c                   | 52 +++++++++++++++-----------
 tools/objtool/arch/x86/include/asm/orc_types.h |  2 +
 tools/objtool/check.c                          |  1 +
 tools/objtool/check.h                          |  2 +-
 tools/objtool/orc_dump.c                       |  3 +-
 tools/objtool/orc_gen.c                        |  2 +
 9 files changed, 52 insertions(+), 29 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 49109c991f87..5acdb7946d69 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -410,6 +410,7 @@ SYM_CODE_START(ret_from_fork)
 
 1:
 	/* kernel thread */
+	UNWIND_HINT_EMPTY
 	movq	%r12, %rdi
 	CALL_NOSPEC %rbx
 	/*
diff --git a/arch/x86/include/asm/orc_types.h b/arch/x86/include/asm/orc_types.h
index 9c9dc579bd7d..46f516dd80ce 100644
--- a/arch/x86/include/asm/orc_types.h
+++ b/arch/x86/include/asm/orc_types.h
@@ -88,6 +88,7 @@ struct orc_entry {
 	unsigned	sp_reg:4;
 	unsigned	bp_reg:4;
 	unsigned	type:2;
+	unsigned	end:1;
 } __packed;
 
 /*
@@ -101,6 +102,7 @@ struct unwind_hint {
 	s16		sp_offset;
 	u8		sp_reg;
 	u8		type;
+	u8		end;
 };
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/x86/include/asm/unwind_hints.h b/arch/x86/include/asm/unwind_hints.h
index bae46fc6b9de..0bcdb1279361 100644
--- a/arch/x86/include/asm/unwind_hints.h
+++ b/arch/x86/include/asm/unwind_hints.h
@@ -26,7 +26,7 @@
  * the debuginfo as necessary.  It will also warn if it sees any
  * inconsistencies.
  */
-.macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL
+.macro UNWIND_HINT sp_reg=ORC_REG_SP sp_offset=0 type=ORC_TYPE_CALL end=0
 #ifdef CONFIG_STACK_VALIDATION
 .Lunwind_hint_ip_\@:
 	.pushsection .discard.unwind_hints
@@ -35,12 +35,14 @@
 		.short \sp_offset
 		.byte \sp_reg
 		.byte \type
+		.byte \end
+		.balign 4
 	.popsection
 #endif
 .endm
 
 .macro UNWIND_HINT_EMPTY
-	UNWIND_HINT sp_reg=ORC_REG_UNDEFINED
+	UNWIND_HINT sp_reg=ORC_REG_UNDEFINED end=1
 .endm
 
 .macro UNWIND_HINT_REGS base=%rsp offset=0 indirect=0 extra=1 iret=0
@@ -86,19 +88,21 @@
 
 #else /* !__ASSEMBLY__ */
 
-#define UNWIND_HINT(sp_reg, sp_offset, type)			\
+#define UNWIND_HINT(sp_reg, sp_offset, type, end)		\
 	"987: \n\t"						\
 	".pushsection .discard.unwind_hints\n\t"		\
 	/* struct unwind_hint */				\
 	".long 987b - .\n\t"					\
-	".short " __stringify(sp_offset) "\n\t"		\
+	".short " __stringify(sp_offset) "\n\t"			\
 	".byte " __stringify(sp_reg) "\n\t"			\
 	".byte " __stringify(type) "\n\t"			\
+	".byte " __stringify(end) "\n\t"			\
+	".balign 4 \n\t"					\
 	".popsection\n\t"
 
-#define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE)
+#define UNWIND_HINT_SAVE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_SAVE, 0)
 
-#define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE)
+#define UNWIND_HINT_RESTORE UNWIND_HINT(0, 0, UNWIND_HINT_TYPE_RESTORE, 0)
 
 #endif /* __ASSEMBLY__ */
 
diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index feb28fee6cea..26038eacf74a 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -198,7 +198,7 @@ static int orc_sort_cmp(const void *_a, const void *_b)
 	 * whitelisted .o files which didn't get objtool generation.
 	 */
 	orc_a = cur_orc_table + (a - cur_orc_ip_table);
-	return orc_a->sp_reg == ORC_REG_UNDEFINED ? -1 : 1;
+	return orc_a->sp_reg == ORC_REG_UNDEFINED && !orc_a->end ? -1 : 1;
 }
 
 #ifdef CONFIG_MODULES
@@ -352,7 +352,7 @@ static bool deref_stack_iret_regs(struct unwind_state *state, unsigned long addr
 
 bool unwind_next_frame(struct unwind_state *state)
 {
-	unsigned long ip_p, sp, orig_ip, prev_sp = state->sp;
+	unsigned long ip_p, sp, orig_ip = state->ip, prev_sp = state->sp;
 	enum stack_type prev_type = state->stack_info.type;
 	struct orc_entry *orc;
 	bool indirect = false;
@@ -363,9 +363,9 @@ bool unwind_next_frame(struct unwind_state *state)
 	/* Don't let modules unload while we're reading their ORC data. */
 	preempt_disable();
 
-	/* Have we reached the end? */
+	/* End-of-stack check for user tasks: */
 	if (state->regs && user_mode(state->regs))
-		goto done;
+		goto the_end;
 
 	/*
 	 * Find the orc_entry associated with the text address.
@@ -374,9 +374,16 @@ bool unwind_next_frame(struct unwind_state *state)
 	 * calls and calls to noreturn functions.
 	 */
 	orc = orc_find(state->signal ? state->ip : state->ip - 1);
-	if (!orc || orc->sp_reg == ORC_REG_UNDEFINED)
-		goto done;
-	orig_ip = state->ip;
+	if (!orc)
+		goto err;
+
+	/* End-of-stack check for kernel threads: */
+	if (orc->sp_reg == ORC_REG_UNDEFINED) {
+		if (!orc->end)
+			goto err;
+
+		goto the_end;
+	}
 
 	/* Find the previous frame's stack: */
 	switch (orc->sp_reg) {
@@ -402,7 +409,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		if (!state->regs || !state->full_regs) {
 			orc_warn("missing regs for base reg R10 at ip %pB\n",
 				 (void *)state->ip);
-			goto done;
+			goto err;
 		}
 		sp = state->regs->r10;
 		break;
@@ -411,7 +418,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		if (!state->regs || !state->full_regs) {
 			orc_warn("missing regs for base reg R13 at ip %pB\n",
 				 (void *)state->ip);
-			goto done;
+			goto err;
 		}
 		sp = state->regs->r13;
 		break;
@@ -420,7 +427,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		if (!state->regs || !state->full_regs) {
 			orc_warn("missing regs for base reg DI at ip %pB\n",
 				 (void *)state->ip);
-			goto done;
+			goto err;
 		}
 		sp = state->regs->di;
 		break;
@@ -429,7 +436,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		if (!state->regs || !state->full_regs) {
 			orc_warn("missing regs for base reg DX at ip %pB\n",
 				 (void *)state->ip);
-			goto done;
+			goto err;
 		}
 		sp = state->regs->dx;
 		break;
@@ -437,12 +444,12 @@ bool unwind_next_frame(struct unwind_state *state)
 	default:
 		orc_warn("unknown SP base reg %d for ip %pB\n",
 			 orc->sp_reg, (void *)state->ip);
-		goto done;
+		goto err;
 	}
 
 	if (indirect) {
 		if (!deref_stack_reg(state, sp, &sp))
-			goto done;
+			goto err;
 	}
 
 	/* Find IP, SP and possibly regs: */
@@ -451,7 +458,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		ip_p = sp - sizeof(long);
 
 		if (!deref_stack_reg(state, ip_p, &state->ip))
-			goto done;
+			goto err;
 
 		state->ip = ftrace_graph_ret_addr(state->task, &state->graph_idx,
 						  state->ip, (void *)ip_p);
@@ -465,7 +472,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		if (!deref_stack_regs(state, sp, &state->ip, &state->sp)) {
 			orc_warn("can't dereference registers at %p for ip %pB\n",
 				 (void *)sp, (void *)orig_ip);
-			goto done;
+			goto err;
 		}
 
 		state->regs = (struct pt_regs *)sp;
@@ -477,7 +484,7 @@ bool unwind_next_frame(struct unwind_state *state)
 		if (!deref_stack_iret_regs(state, sp, &state->ip, &state->sp)) {
 			orc_warn("can't dereference iret registers at %p for ip %pB\n",
 				 (void *)sp, (void *)orig_ip);
-			goto done;
+			goto err;
 		}
 
 		state->regs = (void *)sp - IRET_FRAME_OFFSET;
@@ -500,18 +507,18 @@ bool unwind_next_frame(struct unwind_state *state)
 
 	case ORC_REG_PREV_SP:
 		if (!deref_stack_reg(state, sp + orc->bp_offset, &state->bp))
-			goto done;
+			goto err;
 		break;
 
 	case ORC_REG_BP:
 		if (!deref_stack_reg(state, state->bp + orc->bp_offset, &state->bp))
-			goto done;
+			goto err;
 		break;
 
 	default:
 		orc_warn("unknown BP base reg %d for ip %pB\n",
 			 orc->bp_reg, (void *)orig_ip);
-		goto done;
+		goto err;
 	}
 
 	/* Prevent a recursive loop due to bad ORC data: */
@@ -520,13 +527,16 @@ bool unwind_next_frame(struct unwind_state *state)
 	    state->sp <= prev_sp) {
 		orc_warn("stack going in the wrong direction? ip=%pB\n",
 			 (void *)orig_ip);
-		goto done;
+		goto err;
 	}
 
 	preempt_enable();
 	return true;
 
-done:
+err:
+	state->error = true;
+
+the_end:
 	preempt_enable();
 	state->stack_info.type = STACK_TYPE_UNKNOWN;
 	return false;
diff --git a/tools/objtool/arch/x86/include/asm/orc_types.h b/tools/objtool/arch/x86/include/asm/orc_types.h
index 9c9dc579bd7d..46f516dd80ce 100644
--- a/tools/objtool/arch/x86/include/asm/orc_types.h
+++ b/tools/objtool/arch/x86/include/asm/orc_types.h
@@ -88,6 +88,7 @@ struct orc_entry {
 	unsigned	sp_reg:4;
 	unsigned	bp_reg:4;
 	unsigned	type:2;
+	unsigned	end:1;
 } __packed;
 
 /*
@@ -101,6 +102,7 @@ struct unwind_hint {
 	s16		sp_offset;
 	u8		sp_reg;
 	u8		type;
+	u8		end;
 };
 #endif /* __ASSEMBLY__ */
 
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index 5409f6f6c48d..fef15cea9f1e 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -1109,6 +1109,7 @@ static int read_unwind_hints(struct objtool_file *file)
 
 		cfa->offset = hint->sp_offset;
 		insn->state.type = hint->type;
+		insn->state.end = hint->end;
 	}
 
 	return 0;
diff --git a/tools/objtool/check.h b/tools/objtool/check.h
index c6b68fcb926f..95700a2bcb7c 100644
--- a/tools/objtool/check.h
+++ b/tools/objtool/check.h
@@ -31,7 +31,7 @@ struct insn_state {
 	int stack_size;
 	unsigned char type;
 	bool bp_scratch;
-	bool drap;
+	bool drap, end;
 	int drap_reg, drap_offset;
 	struct cfi_reg vals[CFI_NUM_REGS];
 };
diff --git a/tools/objtool/orc_dump.c b/tools/objtool/orc_dump.c
index c3343820916a..faa444270ee3 100644
--- a/tools/objtool/orc_dump.c
+++ b/tools/objtool/orc_dump.c
@@ -203,7 +203,8 @@ int orc_dump(const char *_objname)
 
 		print_reg(orc[i].bp_reg, orc[i].bp_offset);
 
-		printf(" type:%s\n", orc_type_name(orc[i].type));
+		printf(" type:%s end:%d\n",
+		       orc_type_name(orc[i].type), orc[i].end);
 	}
 
 	elf_end(elf);
diff --git a/tools/objtool/orc_gen.c b/tools/objtool/orc_gen.c
index 18384d9be4e1..3f98dcfbc177 100644
--- a/tools/objtool/orc_gen.c
+++ b/tools/objtool/orc_gen.c
@@ -31,6 +31,8 @@ int create_orc(struct objtool_file *file)
 		struct cfi_reg *cfa = &insn->state.cfa;
 		struct cfi_reg *bp = &insn->state.regs[CFI_BP];
 
+		orc->end = insn->state.end;
+
 		if (cfa->base == CFI_UNDEFINED) {
 			orc->sp_reg = ORC_REG_UNDEFINED;
 			continue;
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* [PATCH v2 6/6] x86/stacktrace: orc, mark it as reliable
  2018-05-14 14:06 [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs Jiri Slaby
                   ` (3 preceding siblings ...)
  2018-05-14 14:06 ` [PATCH v2 5/6] x86/unwind/orc: Detect the end of the stack Jiri Slaby
@ 2018-05-14 14:06 ` Jiri Slaby
  2018-05-14 15:07   ` Josh Poimboeuf
  4 siblings, 1 reply; 9+ messages in thread
From: Jiri Slaby @ 2018-05-14 14:06 UTC (permalink / raw)
  To: mingo
  Cc: linux-kernel, Jiri Slaby, Josh Poimboeuf, Thomas Gleixner,
	H. Peter Anvin, x86

In SUSE, we need a reliable stack unwinder for kernel live patching, but
we do not want to enable frame pointers for performance reasons. So
after the previous patches to make the ORC reliable, mark ORC as a
reliable stack unwinder on x86.

Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: x86@kernel.org
---
 arch/x86/Kconfig | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 47e7f582f86a..e4199fbcc7f2 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -181,7 +181,7 @@ config X86
 	select HAVE_PERF_USER_STACK_DUMP
 	select HAVE_RCU_TABLE_FREE
 	select HAVE_REGS_AND_STACK_ACCESS_API
-	select HAVE_RELIABLE_STACKTRACE		if X86_64 && UNWINDER_FRAME_POINTER && STACK_VALIDATION
+	select HAVE_RELIABLE_STACKTRACE		if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION
 	select HAVE_STACK_VALIDATION		if X86_64
 	select HAVE_SYSCALL_TRACEPOINTS
 	select HAVE_UNSTABLE_SCHED_CLOCK
-- 
2.16.3

^ permalink raw reply related	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 2/6] x86/stacktrace: make clear the success paths
  2018-05-14 14:06 ` [PATCH v2 2/6] x86/stacktrace: make clear the success paths Jiri Slaby
@ 2018-05-14 15:03   ` Josh Poimboeuf
  0 siblings, 0 replies; 9+ messages in thread
From: Josh Poimboeuf @ 2018-05-14 15:03 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: mingo, linux-kernel, Thomas Gleixner, H. Peter Anvin, x86

On Mon, May 14, 2018 at 04:06:49PM +0200, Jiri Slaby wrote:
> Make clear which path is for user tasks and for kthreads and idle
> tasks. This will allow easier plug-in of ORC unwinder in the next
> patches.
> 
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> ---
>  arch/x86/kernel/stacktrace.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
> index 8948b7d9c064..3a4602c2324f 100644
> --- a/arch/x86/kernel/stacktrace.c
> +++ b/arch/x86/kernel/stacktrace.c
> @@ -104,16 +104,18 @@ __save_stack_trace_reliable(struct stack_trace *trace,
>  
>  		regs = unwind_get_entry_regs(&state, NULL);
>  		if (regs) {
> +			/* Success path for user tasks */
> +			if (user_mode(regs))
> +				goto success;
> +
>  			/*
>  			 * Kernel mode registers on the stack indicate an
>  			 * in-kernel interrupt or exception (e.g., preemption
>  			 * or a page fault), which can make frame pointers
>  			 * unreliable.
>  			 */
> -			if (!user_mode(regs))
> -				return -EINVAL;
>  
> -			break;
> +			return -EINVAL;
>  		}
>  
>  		addr = unwind_get_return_address(&state);
> @@ -138,6 +140,11 @@ __save_stack_trace_reliable(struct stack_trace *trace,
>  		return -EINVAL;
>  	}
>  
> +	/* Success path for non-user tasks, i.e. kthreads and idle tasks */
> +	if (!(task->flags & (PF_KTHREAD | PF_IDLE)))
> +		return -EINVAL;
> +
> +success:
>  	if (trace->nr_entries < trace->max_entries)
>  		trace->entries[trace->nr_entries++] = ULONG_MAX;
>  
> -- 
> 2.16.3
> 

The unwind_error() check is now getting skipped on the user mode
success path.  It would probably be safer to check it at the very top of
the loop so that it always gets checked.

Also the subject can be "clarified" a bit:

  x86/stacktrace: Clarify the reliable success paths

-- 
Josh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 3/6] x86/stacktrace: remove STACKTRACE_DUMP_ONCE from __save_stack_trace_reliable
  2018-05-14 14:06 ` [PATCH v2 3/6] x86/stacktrace: remove STACKTRACE_DUMP_ONCE from __save_stack_trace_reliable Jiri Slaby
@ 2018-05-14 15:04   ` Josh Poimboeuf
  0 siblings, 0 replies; 9+ messages in thread
From: Josh Poimboeuf @ 2018-05-14 15:04 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: mingo, linux-kernel, Thomas Gleixner, H. Peter Anvin, x86

On Mon, May 14, 2018 at 04:06:50PM +0200, Jiri Slaby wrote:
> The stack unwinding can sometimes fail yet. Especially with the
> generated debug info. So do not yell at users -- live patching (the only
> user of this interface) will inform the user about the failure
> gracefully.
> 
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> ---
>  arch/x86/kernel/stacktrace.c | 8 ++------
>  1 file changed, 2 insertions(+), 6 deletions(-)
> 
> diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
> index 3a4602c2324f..e0169b128523 100644
> --- a/arch/x86/kernel/stacktrace.c
> +++ b/arch/x86/kernel/stacktrace.c
> @@ -125,20 +125,16 @@ __save_stack_trace_reliable(struct stack_trace *trace,
>  		 * generated code which __kernel_text_address() doesn't know
>  		 * about.
>  		 */
> -		if (!addr) {
> -			STACKTRACE_DUMP_ONCE(task);
> +		if (!addr)
>  			return -EINVAL;
> -		}
>  
>  		if (save_stack_address(trace, addr, false))
>  			return -EINVAL;
>  	}
>  
>  	/* Check for stack corruption */
> -	if (unwind_error(&state)) {
> -		STACKTRACE_DUMP_ONCE(task);
> +	if (unwind_error(&state))
>  		return -EINVAL;
> -	}
>  
>  	/* Success path for non-user tasks, i.e. kthreads and idle tasks */
>  	if (!(task->flags & (PF_KTHREAD | PF_IDLE)))

The STACKTRACE_DUMP_ONCE macro itself can also be removed.

Also the subject is a bit long, how about

  x86/stacktrace: Remove STACKTRACE_DUMP_ONCE

-- 
Josh

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: [PATCH v2 6/6] x86/stacktrace: orc, mark it as reliable
  2018-05-14 14:06 ` [PATCH v2 6/6] x86/stacktrace: orc, mark it as reliable Jiri Slaby
@ 2018-05-14 15:07   ` Josh Poimboeuf
  0 siblings, 0 replies; 9+ messages in thread
From: Josh Poimboeuf @ 2018-05-14 15:07 UTC (permalink / raw)
  To: Jiri Slaby; +Cc: mingo, linux-kernel, Thomas Gleixner, H. Peter Anvin, x86

On Mon, May 14, 2018 at 04:06:53PM +0200, Jiri Slaby wrote:
> In SUSE, we need a reliable stack unwinder for kernel live patching, but
> we do not want to enable frame pointers for performance reasons. So
> after the previous patches to make the ORC reliable, mark ORC as a
> reliable stack unwinder on x86.
> 
> Signed-off-by: Jiri Slaby <jslaby@suse.cz>
> Cc: Josh Poimboeuf <jpoimboe@redhat.com>
> Cc: Thomas Gleixner <tglx@linutronix.de>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: "H. Peter Anvin" <hpa@zytor.com>
> Cc: x86@kernel.org
> ---
>  arch/x86/Kconfig | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> index 47e7f582f86a..e4199fbcc7f2 100644
> --- a/arch/x86/Kconfig
> +++ b/arch/x86/Kconfig
> @@ -181,7 +181,7 @@ config X86
>  	select HAVE_PERF_USER_STACK_DUMP
>  	select HAVE_RCU_TABLE_FREE
>  	select HAVE_REGS_AND_STACK_ACCESS_API
> -	select HAVE_RELIABLE_STACKTRACE		if X86_64 && UNWINDER_FRAME_POINTER && STACK_VALIDATION
> +	select HAVE_RELIABLE_STACKTRACE		if X86_64 && (UNWINDER_FRAME_POINTER || UNWINDER_ORC) && STACK_VALIDATION
>  	select HAVE_STACK_VALIDATION		if X86_64
>  	select HAVE_SYSCALL_TRACEPOINTS
>  	select HAVE_UNSTABLE_SCHED_CLOCK

Maybe clarify the subject here as well:

  x86/stacktrace: Enable HAVE_RELIABLE_STACKTRACE for the ORC unwinder

-- 
Josh

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2018-05-14 15:08 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-05-14 14:06 [PATCH v2 1/6] x86/stacktrace: do not unwind after user regs Jiri Slaby
2018-05-14 14:06 ` [PATCH v2 2/6] x86/stacktrace: make clear the success paths Jiri Slaby
2018-05-14 15:03   ` Josh Poimboeuf
2018-05-14 14:06 ` [PATCH v2 3/6] x86/stacktrace: remove STACKTRACE_DUMP_ONCE from __save_stack_trace_reliable Jiri Slaby
2018-05-14 15:04   ` Josh Poimboeuf
2018-05-14 14:06 ` [PATCH v2 4/6] x86/stacktrace: do not fail for ORC with regs on stack Jiri Slaby
2018-05-14 14:06 ` [PATCH v2 5/6] x86/unwind/orc: Detect the end of the stack Jiri Slaby
2018-05-14 14:06 ` [PATCH v2 6/6] x86/stacktrace: orc, mark it as reliable Jiri Slaby
2018-05-14 15:07   ` Josh Poimboeuf

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).