Skip to content

Commit

Permalink
arm64: rethook: Replace kretprobe trampoline with rethook
Browse files Browse the repository at this point in the history
Replace the kretprobe's trampoline code with the rethook on arm64.
The rethook on arm64 is almost renamed from kretprobe trampoline
code. The mechanism is completely same.

Signed-off-by: Masami Hiramatsu <[email protected]>
  • Loading branch information
mhiramat authored and Kernel Patches Daemon committed Apr 11, 2022
1 parent 490d30f commit 52dfc80
Show file tree
Hide file tree
Showing 9 changed files with 41 additions and 27 deletions.
1 change: 1 addition & 0 deletions arch/arm64/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,7 @@ config ARM64
select HAVE_SYSCALL_TRACEPOINTS
select HAVE_KPROBES
select HAVE_KRETPROBES
select HAVE_RETHOOK
select HAVE_GENERIC_VDSO
select IOMMU_DMA if IOMMU_SUPPORT
select IRQ_DOMAIN
Expand Down
2 changes: 0 additions & 2 deletions arch/arm64/include/asm/kprobes.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,6 @@ void arch_remove_kprobe(struct kprobe *);
int kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr);
int kprobe_exceptions_notify(struct notifier_block *self,
unsigned long val, void *data);
void __kretprobe_trampoline(void);
void __kprobes *trampoline_probe_handler(struct pt_regs *regs);

#endif /* CONFIG_KPROBES */
#endif /* _ARM_KPROBES_H */
2 changes: 1 addition & 1 deletion arch/arm64/include/asm/stacktrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ struct stackframe {
DECLARE_BITMAP(stacks_done, __NR_STACK_TYPES);
unsigned long prev_fp;
enum stack_type prev_type;
#ifdef CONFIG_KRETPROBES
#if defined(CONFIG_RETHOOK)
struct llist_node *kr_cur;
#endif
};
Expand Down
1 change: 1 addition & 0 deletions arch/arm64/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ obj-$(CONFIG_ACPI_NUMA) += acpi_numa.o
obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o
obj-$(CONFIG_PARAVIRT) += paravirt.o
obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o
obj-$(CONFIG_RETHOOK) += rethook.o rethook_trampoline.o
obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o
obj-$(CONFIG_ELF_CORE) += elfcore.o
obj-$(CONFIG_KEXEC_CORE) += machine_kexec.o relocate_kernel.o \
Expand Down
1 change: 0 additions & 1 deletion arch/arm64/kernel/probes/Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KPROBES) += kprobes.o decode-insn.o \
kprobes_trampoline.o \
simulate-insn.o
obj-$(CONFIG_UPROBES) += uprobes.o decode-insn.o \
simulate-insn.o
15 changes: 0 additions & 15 deletions arch/arm64/kernel/probes/kprobes.c
Original file line number Diff line number Diff line change
Expand Up @@ -399,21 +399,6 @@ int __init arch_populate_kprobe_blacklist(void)
return ret;
}

void __kprobes __used *trampoline_probe_handler(struct pt_regs *regs)
{
return (void *)kretprobe_trampoline_handler(regs, (void *)regs->regs[29]);
}

void __kprobes arch_prepare_kretprobe(struct kretprobe_instance *ri,
struct pt_regs *regs)
{
ri->ret_addr = (kprobe_opcode_t *)regs->regs[30];
ri->fp = (void *)regs->regs[29];

/* replace return addr (x30) with trampoline */
regs->regs[30] = (long)&__kretprobe_trampoline;
}

int __kprobes arch_trampoline_kprobe(struct kprobe *p)
{
return 0;
Expand Down
28 changes: 28 additions & 0 deletions arch/arm64/kernel/rethook.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Generic return hook for arm64.
* Most of the code is copied from arch/arm64/kernel/probes/kprobes.c
*/

#include <linux/kprobes.h>
#include <linux/rethook.h>

/* This is called from arch_rethook_trampoline() */
unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs);

unsigned long __used arch_rethook_trampoline_callback(struct pt_regs *regs)
{
return rethook_trampoline_handler(regs, regs->regs[29]);
}
NOKPROBE_SYMBOL(arch_rethook_trampoline_callback);

int arch_rethook_prepare(struct rethook_node *rhn, struct pt_regs *regs, bool mcount)
{
rhn->ret_addr = regs->regs[30];
rhn->frame = regs->regs[29];

/* replace return addr (x30) with trampoline */
regs->regs[30] = (u64)arch_rethook_trampoline;
return 0;
}
NOKPROBE_SYMBOL(arch_rethook_prepare);
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* trampoline entry and return code for kretprobes.
* trampoline entry and return code for rethook.
* Renamed from arch/arm64/kernel/probes/kprobes_trampoline.S
*/

#include <linux/linkage.h>
Expand Down Expand Up @@ -61,7 +62,7 @@
ldp x28, x29, [sp, #S_X28]
.endm

SYM_CODE_START(__kretprobe_trampoline)
SYM_CODE_START(arch_rethook_trampoline)
sub sp, sp, #PT_REGS_SIZE

save_all_base_regs
Expand All @@ -70,7 +71,7 @@ SYM_CODE_START(__kretprobe_trampoline)
add x29, sp, #S_FP

mov x0, sp
bl trampoline_probe_handler
bl arch_rethook_trampoline_callback
/*
* Replace trampoline address in lr with actual orig_ret_addr return
* address.
Expand All @@ -83,4 +84,4 @@ SYM_CODE_START(__kretprobe_trampoline)
add sp, sp, #PT_REGS_SIZE
ret

SYM_CODE_END(__kretprobe_trampoline)
SYM_CODE_END(arch_rethook_trampoline)
9 changes: 5 additions & 4 deletions arch/arm64/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/export.h>
#include <linux/ftrace.h>
#include <linux/kprobes.h>
#include <linux/rethook.h>
#include <linux/sched.h>
#include <linux/sched/debug.h>
#include <linux/sched/task_stack.h>
Expand Down Expand Up @@ -38,7 +39,7 @@ static notrace void start_backtrace(struct stackframe *frame, unsigned long fp,
{
frame->fp = fp;
frame->pc = pc;
#ifdef CONFIG_KRETPROBES
#if defined(CONFIG_RETHOOK)
frame->kr_cur = NULL;
#endif

Expand Down Expand Up @@ -134,9 +135,9 @@ static int notrace unwind_frame(struct task_struct *tsk,
frame->pc = orig_pc;
}
#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);
#ifdef CONFIG_RETHOOK
if (is_rethook_trampoline(frame->pc))
frame->pc = rethook_find_ret_addr(tsk, frame->fp, &frame->kr_cur);
#endif

return 0;
Expand Down

0 comments on commit 52dfc80

Please sign in to comment.