lists.openwall.net | lists / announce owl-users owl-dev john-users john-dev passwdqc-users yescrypt popa3d-users / oss-security kernel-hardening musl sabotage tlsify passwords / crypt-dev xvendor / Bugtraq Full-Disclosure linux-kernel linux-netdev linux-ext4 linux-hardening linux-cve-announce PHC | |
Open Source and information security mailing list archives
| ||
|
Date: Wed, 10 Jun 2020 20:12:54 +0800 From: YuanJunQing <yuanjunqing66@....com> To: tsbogend@...ha.franken.de Cc: yszhou4tech@...il.com, linux-mips@...r.kernel.org, linux-kernel@...r.kernel.org, liulichao@...ngson.cn, YuanJunQing <yuanjunqing66@....com> Subject: [PATCH] mips/ftrace: Fix stack backtrace in unwind_stack_by_address() Calling the unwind_stack_by_address() function for stack backtrace will fail, when we use "echo function: stacktrace > set_ftrace_filter". The stack backtrace as follows: <...>-3102 [001] ...2 63.557737: <stack trace> => 0 => 0 => 0 => 0 => 0 => 0 => 0 => 0 => <idle>-0 [000] .N.2 63.558793: <stack trace> The reason is that when performing stack backtrace, the "ftrace_call" and "ftrace_graph_call" global symbols in ftrace_caller() are treated as functions. If CONFIG_FUNCTION_GRAPH_TRACER is defined, the value in the "ra" register is the address of ftrace_graph_call when the stack backtrace back to ftrace_caller(). ”ftrace_graph_call“ is a global symbol, and the value of "ofs" is set to zero when the kallsyms_lookup_size_offset() is called. Otherwise, the value in the "ra" register is the address of ftrace_call+8. "ftrace_call" is the global symbol, and return one when the get_frame_info() is called. Signed-off-by: YuanJunQing <yuanjunqing66@....com> --- arch/mips/kernel/process.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/arch/mips/kernel/process.c b/arch/mips/kernel/process.c index b2a797557825..ac4fe79bc5bc 100644 --- a/arch/mips/kernel/process.c +++ b/arch/mips/kernel/process.c @@ -53,6 +53,8 @@ #include <asm/inst.h> #include <asm/stacktrace.h> #include <asm/irq_regs.h> +#include <linux/ftrace.h> +#include <generated/asm-offsets.h> #ifdef CONFIG_HOTPLUG_CPU void arch_cpu_idle_dead(void) @@ -569,6 +571,13 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, * Return ra if an exception occurred at the first instruction */ if (unlikely(ofs == 0)) { +#ifdef CONFIG_FUNCTION_GRAPH_TRACER + extern void ftrace_graph_call(void); + if ((pc == (unsigned long)ftrace_graph_call)) { + pc = ((unsigned long *)(*sp))[PT_R31/sizeof(long)]; + *sp += PT_SIZE; + } else +#endif pc = *ra; *ra = 0; return pc; @@ -583,16 +592,23 @@ unsigned long notrace unwind_stack_by_address(unsigned long stack_page, if (*sp < low || *sp + info.frame_size > high) return 0; - if (leaf) + if (leaf) { /* * For some extreme cases, get_frame_info() can * consider wrongly a nested function as a leaf * one. In that cases avoid to return always the * same value. */ +#ifdef CONFIG_DYNAMIC_FTRACE + if (info.func == (void *)ftrace_call) { + pc = ((unsigned long *)(*sp))[PT_R31/sizeof(long)]; + info.frame_size = PT_SIZE; + } else +#endif pc = pc != *ra ? *ra : 0; - else + } else { pc = ((unsigned long *)(*sp))[info.pc_offset]; + } *sp += info.frame_size; *ra = 0; -- 2.17.1
Powered by blists - more mailing lists