arm64: Recover kretprobe modified return address in stacktrace
Since the kretprobe replaces the function return address with the kretprobe_trampoline on the stack, stack unwinder shows it instead of the correct return address. This checks whether the next return address is the __kretprobe_trampoline(), and if so, try to find the correct return address from the kretprobe instance list. For this purpose this adds 'kr_cur' loop cursor to memorize the current kretprobe instance. With this fix, now arm64 can enable CONFIG_ARCH_CORRECT_STACKTRACE_ON_KRETPROBE, and pass the kprobe self tests. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> Acked-by: Will Deacon <will@kernel.org> Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
This commit is contained in:
Родитель
fc6d647638
Коммит
cd9bc2c925
|
@ -11,6 +11,7 @@ config ARM64
|
||||||
select ACPI_PPTT if ACPI
|
select ACPI_PPTT if ACPI
|
||||||
select ARCH_HAS_DEBUG_WX
|
select ARCH_HAS_DEBUG_WX
|
||||||
select ARCH_BINFMT_ELF_STATE
|
select ARCH_BINFMT_ELF_STATE
|
||||||
|
select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
|
||||||
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
|
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
|
||||||
select ARCH_ENABLE_MEMORY_HOTPLUG
|
select ARCH_ENABLE_MEMORY_HOTPLUG
|
||||||
select ARCH_ENABLE_MEMORY_HOTREMOVE
|
select ARCH_ENABLE_MEMORY_HOTREMOVE
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <linux/sched.h>
|
#include <linux/sched.h>
|
||||||
#include <linux/sched/task_stack.h>
|
#include <linux/sched/task_stack.h>
|
||||||
#include <linux/types.h>
|
#include <linux/types.h>
|
||||||
|
#include <linux/llist.h>
|
||||||
|
|
||||||
#include <asm/memory.h>
|
#include <asm/memory.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
@ -59,6 +60,9 @@ struct stackframe {
|
||||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||||
int graph;
|
int graph;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_KRETPROBES
|
||||||
|
struct llist_node *kr_cur;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
|
extern int unwind_frame(struct task_struct *tsk, struct stackframe *frame);
|
||||||
|
|
|
@ -41,6 +41,9 @@ void start_backtrace(struct stackframe *frame, unsigned long fp,
|
||||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||||
frame->graph = 0;
|
frame->graph = 0;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef CONFIG_KRETPROBES
|
||||||
|
frame->kr_cur = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Prime the first unwind.
|
* Prime the first unwind.
|
||||||
|
@ -129,6 +132,10 @@ int notrace unwind_frame(struct task_struct *tsk, struct stackframe *frame)
|
||||||
frame->pc = ret_stack->ret;
|
frame->pc = ret_stack->ret;
|
||||||
}
|
}
|
||||||
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
#endif /* CONFIG_FUNCTION_GRAPH_TRACER */
|
||||||
|
#ifdef CONFIG_KRETPROBES
|
||||||
|
if (is_kretprobe_trampoline(frame->pc))
|
||||||
|
frame->pc = kretprobe_find_ret_addr(tsk, (void *)frame->fp, &frame->kr_cur);
|
||||||
|
#endif
|
||||||
|
|
||||||
frame->pc = ptrauth_strip_insn_pac(frame->pc);
|
frame->pc = ptrauth_strip_insn_pac(frame->pc);
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче