]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
s390/ftrace: Fix return address recovery of traced function
authorSumanth Korikkar <sumanthk@linux.ibm.com>
Mon, 24 Feb 2025 11:27:04 +0000 (12:27 +0100)
committerVasily Gorbik <gor@linux.ibm.com>
Tue, 4 Mar 2025 16:15:19 +0000 (17:15 +0100)
When fgraph is enabled the traced function return address is replaced with
trampoline return_to_handler(). The original return address of the traced
function is saved in per task return stack along with a stack pointer for
reliable stack unwinding via function_graph_enter_regs().

During stack unwinding e.g. for livepatching, ftrace_graph_ret_addr()
identifies the original return address of the traced function with the
saved stack pointer.

With a recent change, the stack pointers passed to ftrace_graph_ret_addr()
and function_graph_enter_regs() do not match anymore, and therefore the
original return address is not found.

Pass the correct stack pointer to function_graph_enter_regs() to fix this.

Fixes: 7495e179b478 ("s390/tracing: Enable HAVE_FTRACE_GRAPH_FUNC")
Reviewed-by: Heiko Carstens <hca@linux.ibm.com>
Signed-off-by: Sumanth Korikkar <sumanthk@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
arch/s390/kernel/ftrace.c

index 63ba6306632ef39a806c00e919d55ddc5ea81a5c..e540b022ceb23e2c74bfa6b8c12d7483193b551a 100644 (file)
@@ -266,12 +266,13 @@ void ftrace_graph_func(unsigned long ip, unsigned long parent_ip,
                       struct ftrace_ops *op, struct ftrace_regs *fregs)
 {
        unsigned long *parent = &arch_ftrace_regs(fregs)->regs.gprs[14];
+       unsigned long sp = arch_ftrace_regs(fregs)->regs.gprs[15];
 
        if (unlikely(ftrace_graph_is_dead()))
                return;
        if (unlikely(atomic_read(&current->tracing_graph_pause)))
                return;
-       if (!function_graph_enter_regs(*parent, ip, 0, parent, fregs))
+       if (!function_graph_enter_regs(*parent, ip, 0, (unsigned long *)sp, fregs))
                *parent = (unsigned long)&return_to_handler;
 }