Live-Patching Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks
@ 2020-07-17 14:04 Josh Poimboeuf
  2020-07-17 14:04 ` [PATCH 1/2] x86/unwind/orc: Fix ORC " Josh Poimboeuf
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Josh Poimboeuf @ 2020-07-17 14:04 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, live-patching, Peter Zijlstra, Wang ShaoBo

A couple of reliable unwinder fixes for newly forked tasks, which were
reported by Wang ShaoBo.

Josh Poimboeuf (2):
  x86/unwind/orc: Fix ORC for newly forked tasks
  x86/stacktrace: Fix reliable check for empty user task stacks

 arch/x86/kernel/stacktrace.c | 5 -----
 arch/x86/kernel/unwind_orc.c | 8 ++++++--
 2 files changed, 6 insertions(+), 7 deletions(-)

-- 
2.25.4


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

* [PATCH 1/2] x86/unwind/orc: Fix ORC for newly forked tasks
  2020-07-17 14:04 [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Josh Poimboeuf
@ 2020-07-17 14:04 ` Josh Poimboeuf
  2020-07-17 14:04 ` [PATCH 2/2] x86/stacktrace: Fix reliable check for empty user task stacks Josh Poimboeuf
  2020-07-20 11:06 ` [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Wangshaobo (bobo)
  2 siblings, 0 replies; 4+ messages in thread
From: Josh Poimboeuf @ 2020-07-17 14:04 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, live-patching, Peter Zijlstra, Wang ShaoBo

The ORC unwinder fails to unwind newly forked tasks which haven't yet
run on the CPU.  It correctly reads the 'ret_from_fork' instruction
pointer from the stack, but it incorrectly interprets that value as a
call stack address rather than a "signal" one, so the address gets
incorrectly decremented in the call to orc_find(), resulting in bad ORC
data.

Fix it by forcing 'ret_from_fork' frames to be signal frames.

Reported-by: Wang ShaoBo <bobo.shaobowang@huawei.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/unwind_orc.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/unwind_orc.c b/arch/x86/kernel/unwind_orc.c
index 7f969b2d240f..ec88bbe08a32 100644
--- a/arch/x86/kernel/unwind_orc.c
+++ b/arch/x86/kernel/unwind_orc.c
@@ -440,8 +440,11 @@ bool unwind_next_frame(struct unwind_state *state)
 	/*
 	 * Find the orc_entry associated with the text address.
 	 *
-	 * Decrement call return addresses by one so they work for sibling
-	 * calls and calls to noreturn functions.
+	 * For a call frame (as opposed to a signal frame), state->ip points to
+	 * the instruction after the call.  That instruction's stack layout
+	 * could be different from the call instruction's layout, for example
+	 * if the call was to a noreturn function.  So get the ORC data for the
+	 * call instruction itself.
 	 */
 	orc = orc_find(state->signal ? state->ip : state->ip - 1);
 	if (!orc) {
@@ -662,6 +665,7 @@ void __unwind_start(struct unwind_state *state, struct task_struct *task,
 		state->sp = task->thread.sp;
 		state->bp = READ_ONCE_NOCHECK(frame->bp);
 		state->ip = READ_ONCE_NOCHECK(frame->ret_addr);
+		state->signal = (void *)state->ip == ret_from_fork;
 	}
 
 	if (get_stack_info((unsigned long *)state->sp, state->task,
-- 
2.25.4


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

* [PATCH 2/2] x86/stacktrace: Fix reliable check for empty user task stacks
  2020-07-17 14:04 [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Josh Poimboeuf
  2020-07-17 14:04 ` [PATCH 1/2] x86/unwind/orc: Fix ORC " Josh Poimboeuf
@ 2020-07-17 14:04 ` Josh Poimboeuf
  2020-07-20 11:06 ` [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Wangshaobo (bobo)
  2 siblings, 0 replies; 4+ messages in thread
From: Josh Poimboeuf @ 2020-07-17 14:04 UTC (permalink / raw)
  To: x86; +Cc: linux-kernel, live-patching, Peter Zijlstra, Wang ShaoBo

If a user task's stack is empty, or if it only has user regs, ORC
reports it as a reliable empty stack.  But arch_stack_walk_reliable()
incorrectly treats it as unreliable.

That happens because the only success path for user tasks is inside the
loop, which only iterates on non-empty stacks.  Generally, a user task
must end in a user regs frame, but an empty stack is an exception to
that rule.

Thanks to commit 71c95825289f ("x86/unwind/orc: Fix error handling in
__unwind_start()"), unwind_start() now sets state->error appropriately.
So now for both ORC and FP unwinders, unwind_done() and !unwind_error()
always means the end of the stack was successfully reached.  So the
success path for kthreads is no longer needed -- it can also be used for
empty user tasks.

Reported-by: Wang ShaoBo <bobo.shaobowang@huawei.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
---
 arch/x86/kernel/stacktrace.c | 5 -----
 1 file changed, 5 deletions(-)

diff --git a/arch/x86/kernel/stacktrace.c b/arch/x86/kernel/stacktrace.c
index 6ad43fc44556..2fd698e28e4d 100644
--- a/arch/x86/kernel/stacktrace.c
+++ b/arch/x86/kernel/stacktrace.c
@@ -58,7 +58,6 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
 			 * or a page fault), which can make frame pointers
 			 * unreliable.
 			 */
-
 			if (IS_ENABLED(CONFIG_FRAME_POINTER))
 				return -EINVAL;
 		}
@@ -81,10 +80,6 @@ int arch_stack_walk_reliable(stack_trace_consume_fn consume_entry,
 	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)))
-		return -EINVAL;
-
 	return 0;
 }
 
-- 
2.25.4


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

* Re: [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks
  2020-07-17 14:04 [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Josh Poimboeuf
  2020-07-17 14:04 ` [PATCH 1/2] x86/unwind/orc: Fix ORC " Josh Poimboeuf
  2020-07-17 14:04 ` [PATCH 2/2] x86/stacktrace: Fix reliable check for empty user task stacks Josh Poimboeuf
@ 2020-07-20 11:06 ` Wangshaobo (bobo)
  2 siblings, 0 replies; 4+ messages in thread
From: Wangshaobo (bobo) @ 2020-07-20 11:06 UTC (permalink / raw)
  To: Josh Poimboeuf, x86; +Cc: linux-kernel, live-patching, Peter Zijlstra

Tested-by: Wang ShaoBo <bobo.shaobowang@huawei.com>

在 2020/7/17 22:04, Josh Poimboeuf 写道:
> A couple of reliable unwinder fixes for newly forked tasks, which were
> reported by Wang ShaoBo.
>
> Josh Poimboeuf (2):
>    x86/unwind/orc: Fix ORC for newly forked tasks
>    x86/stacktrace: Fix reliable check for empty user task stacks
>
>   arch/x86/kernel/stacktrace.c | 5 -----
>   arch/x86/kernel/unwind_orc.c | 8 ++++++--
>   2 files changed, 6 insertions(+), 7 deletions(-)
>


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

end of thread, back to index

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-07-17 14:04 [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Josh Poimboeuf
2020-07-17 14:04 ` [PATCH 1/2] x86/unwind/orc: Fix ORC " Josh Poimboeuf
2020-07-17 14:04 ` [PATCH 2/2] x86/stacktrace: Fix reliable check for empty user task stacks Josh Poimboeuf
2020-07-20 11:06 ` [PATCH 0/2] x86/unwind: A couple of fixes for newly forked tasks Wangshaobo (bobo)

Live-Patching Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/live-patching/0 live-patching/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 live-patching live-patching/ https://lore.kernel.org/live-patching \
		live-patching@vger.kernel.org
	public-inbox-index live-patching

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.live-patching


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git