mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Shuai Xue <xueshuai@linux.alibaba.com>
To: palmer@dabbelt.com, pjw@kernel.org, aou@eecs.berkeley.edu
Cc: alex@ghiti.fr, linux-riscv@lists.infradead.org, oleg@redhat.com,
	rostedt@goodmis.org, mhiramat@kernel.org, mark.rutland@arm.com,
	peterz@infradead.org, mingo@redhat.com, acme@kernel.org,
	namhyung@kernel.org, alexander.shishkin@linux.intel.com,
	jolsa@kernel.org, irogers@google.com, adrian.hunter@intel.com,
	james.clark@linaro.org, jpoimboe@kernel.org, jikos@kernel.org,
	mbenes@suse.cz, pmladek@suse.com, joe.lawrence@redhat.com,
	shuah@kernel.org, mpdesouza@suse.com, martin@kaiser.cx,
	kmehltretter@gmail.com, oliver.yang@linux.alibaba.com,
	zhuo.song@linux.alibaba.com, xueshuai@linux.alibaba.com,
	jkchen@linux.alibaba.com, linux-kernel@vger.kernel.org,
	linux-trace-kernel@vger.kernel.org,
	linux-perf-users@vger.kernel.org, live-patching@vger.kernel.org,
	linux-kselftest@vger.kernel.org
Subject: [PATCH v7 03/10] riscv: ftrace: use the frame pointer as the function graph return-address cookie
Date: Tue, 10 Nov 2026 09:37:43 +0800	[thread overview]
Message-ID: <20261110013750.36800-4-xueshuai@linux.alibaba.com> (raw)
In-Reply-To: <20261110013750.36800-1-xueshuai@linux.alibaba.com>

The function graph tracer stamps every shadow-stack entry with a
cookie, ftrace_ret_stack::retp, which stack unwinders later pass to
ftrace_graph_ret_addr() to recover a return address that the tracer
replaced with return_to_handler.  The match is an exact pointer
comparison, so the producer and the consumer must agree on what the
cookie is.  On riscv they don't:

  * The dynamic ftrace path stores &arch_ftrace_regs(fregs)->ra, a
    slot inside the transient ftrace trampoline frame.  The frame is
    popped as soon as the callback returns, so the stored cookie is
    an address that no consumer can ever reproduce.  It has never
    matched anything since ftrace_graph_func() was introduced in
    v6.8.

  * The frame-pointer walker in walk_stackframe() passes &frame->ra,
    the ra slot of a live frame record.  That key matches the static
    mcount path, which passes the callee's ra-slot address, but not
    the dynamic path.

Since distro kernels only ever use the dynamic path, the net effect
is that the shadow stack is never consulted during unwinding:
whenever the function graph tracer is running, dump_stack(), perf
callchains and __get_wchan() report return_to_handler instead of the
real caller.

Switch the cookie to the architectural frame pointer, i.e. the
caller's frame-pointer value.  Every party can reproduce it from the
frame records themselves:

  * ftrace.c stores (void *)frame_pointer on both entry paths.  At
    ftrace entry the frame pointer is still the caller's, which is
    the value the callee later saves in its frame_record::fp.

  * walk_stackframe() passes that value, frame->fp, to
    ftrace_graph_ret_addr() instead of the ra-slot address.  The
    static mcount path has to switch too: its old cookie (the
    callee's ra-slot address) is exactly what the old walker key
    matched, so leaving it behind would regress the static path.

This is the convention arm64 already uses: (void *)frame_pointer
from ftrace.c, the saved fp from the unwinder.

function_get_true_parent_ip() keeps passing the entry stack pointer
as its key; that key is only reproducible on architectures whose
return address lives at the entry stack pointer (x86).  On riscv,
as on arm64, it keeps falling back to the raw parent ip.

Fixes: 35e61e8827ee8 ("riscv: ftrace: Make function graph use ftrace directly")
Suggested-by: Martin Kaiser <martin@kaiser.cx>
Cc: stable@vger.kernel.org
Signed-off-by: Shuai Xue <xueshuai@linux.alibaba.com>
---
 arch/riscv/kernel/ftrace.c     | 6 ++++--
 arch/riscv/kernel/stacktrace.c | 3 ++-
 2 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/arch/riscv/kernel/ftrace.c b/arch/riscv/kernel/ftrace.c
index be8b68514417..0facd824c911 100644
--- a/arch/riscv/kernel/ftrace.c
+++ b/arch/riscv/kernel/ftrace.c
@@ -245,7 +245,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 	 */
 	old = *parent;
 
-	if (!function_graph_enter(old, self_addr, frame_pointer, parent))
+	if (!function_graph_enter(old, self_addr, frame_pointer,
+				  (void *)frame_pointer))
 		*parent = return_hooker;
 }
 
@@ -267,7 +268,8 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
 	 */
 	old = *parent;
 
-	if (!function_graph_enter_regs(old, ip, frame_pointer, parent, fregs))
+	if (!function_graph_enter_regs(old, ip, frame_pointer,
+				       (void *)frame_pointer, fregs))
 		*parent = return_hooker;
 }
 #endif /* CONFIG_DYNAMIC_FTRACE */
diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c
index 28c5744889ba..a5abb705d43b 100644
--- a/arch/riscv/kernel/stacktrace.c
+++ b/arch/riscv/kernel/stacktrace.c
@@ -96,8 +96,9 @@ static __always_inline void __walk_stackframe(struct task_struct *task,
 		} else {
 			fp = READ_ONCE_TASK_STACK(task, frame->fp);
 			pc = READ_ONCE_TASK_STACK(task, frame->ra);
+			/* the cookie is the caller's frame pointer */
 			pc = ftrace_graph_ret_addr(task, &graph_idx, pc,
-						   &frame->ra);
+						   (void *)fp);
 			if (pc >= (unsigned long)handle_exception &&
 			    pc < (unsigned long)&ret_from_exception_end) {
 				if (unlikely(!fn(arg, pc)))
-- 
2.39.3


  parent reply	other threads:[~2026-11-10  1:38 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-14  9:26 [PATCH v6 0/7] riscv: Add reliable stack unwinding for livepatch Shuai Xue
2026-09-14  9:26 ` [PATCH v6 1/7] riscv: stacktrace: Add frame record metadata Shuai Xue
2026-09-14  9:26 ` [PATCH v6 2/7] riscv: stacktrace: disable KASAN and KCOV instrumentation for stacktrace.o Shuai Xue
2026-09-14  9:26 ` [PATCH v6 3/7] riscv: ftrace: always preserve s0 in dynamic ftrace register frame Shuai Xue
2026-09-14  9:26 ` [PATCH v6 4/7] riscv: stacktrace: introduce stack-bound tracking helpers Shuai Xue
2026-09-14  9:26 ` [PATCH v6 5/7] riscv: stacktrace: switch to frame-pointer based unwinder Shuai Xue
2026-10-09 18:59   ` Karl Mehltretter
2026-10-10  3:38     ` Shuai Xue
2026-10-13 20:18   ` Martin Kaiser
2026-10-14 13:09     ` Shuai Xue
2026-09-14  9:26 ` [PATCH v6 6/7] riscv: Kconfig: enable HAVE_RELIABLE_STACKTRACE and HAVE_LIVEPATCH Shuai Xue
2026-09-14  9:26 ` [PATCH v6 7/7] selftests/livepatch: Add RISC-V syscall wrapper prefix Shuai Xue
2026-09-29  7:28 ` [PATCH v6 0/7] riscv: Add reliable stack unwinding for livepatch Martin Kaiser
2026-10-08 11:42   ` Shuai Xue
2026-10-12  8:44     ` Martin Kaiser
2026-11-10  1:37 ` [PATCH v7 00/10] " Shuai Xue
2026-11-10  1:37   ` [PATCH v7 01/10] riscv: stacktrace: do not report the walker's own frame from arch_stack_walk() Shuai Xue
2026-11-10  1:37   ` [PATCH v7 02/10] riscv: Add KUnit test for stack trace start frames Shuai Xue
2026-11-10  1:37   ` Shuai Xue [this message]
2026-11-10  1:37   ` [PATCH v7 04/10] riscv: stacktrace: Add frame record metadata Shuai Xue
2026-11-10  1:37   ` [PATCH v7 05/10] riscv: stacktrace: disable KASAN and KCOV instrumentation for stacktrace.o Shuai Xue
2026-11-10  1:37   ` [PATCH v7 06/10] riscv: ftrace: always preserve s0 in dynamic ftrace register frame Shuai Xue
2026-11-10  1:37   ` [PATCH v7 07/10] riscv: stacktrace: introduce stack-bound tracking helpers Shuai Xue
2026-11-10  1:37   ` [PATCH v7 08/10] riscv: stacktrace: switch to frame-pointer based unwinder Shuai Xue
2026-11-10  1:37   ` [PATCH v7 09/10] riscv: Kconfig: enable HAVE_RELIABLE_STACKTRACE and HAVE_LIVEPATCH Shuai Xue
2026-11-10  1:37   ` [PATCH v7 10/10] selftests/livepatch: Add RISC-V syscall wrapper prefix Shuai Xue
2026-11-10  6:35   ` [PATCH v7 00/10] riscv: Add reliable stack unwinding for livepatch Karl Mehltretter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261110013750.36800-4-xueshuai@linux.alibaba.com \
    --to=xueshuai@linux.alibaba.com \
    --cc=acme@kernel.org \
    --cc=adrian.hunter@intel.com \
    --cc=alex@ghiti.fr \
    --cc=alexander.shishkin@linux.intel.com \
    --cc=aou@eecs.berkeley.edu \
    --cc=irogers@google.com \
    --cc=james.clark@linaro.org \
    --cc=jikos@kernel.org \
    --cc=jkchen@linux.alibaba.com \
    --cc=joe.lawrence@redhat.com \
    --cc=jolsa@kernel.org \
    --cc=jpoimboe@kernel.org \
    --cc=kmehltretter@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-kselftest@vger.kernel.org \
    --cc=linux-perf-users@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=linux-trace-kernel@vger.kernel.org \
    --cc=live-patching@vger.kernel.org \
    --cc=mark.rutland@arm.com \
    --cc=martin@kaiser.cx \
    --cc=mbenes@suse.cz \
    --cc=mhiramat@kernel.org \
    --cc=mingo@redhat.com \
    --cc=mpdesouza@suse.com \
    --cc=namhyung@kernel.org \
    --cc=oleg@redhat.com \
    --cc=oliver.yang@linux.alibaba.com \
    --cc=palmer@dabbelt.com \
    --cc=peterz@infradead.org \
    --cc=pjw@kernel.org \
    --cc=pmladek@suse.com \
    --cc=rostedt@goodmis.org \
    --cc=shuah@kernel.org \
    --cc=zhuo.song@linux.alibaba.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®