Message ID | 164304060913.1680787.1167309209346264268.stgit@devnote2 (mailing list archive) |
---|---|
State | Superseded |
Delegated to: | BPF |
Headers | show |
Series | fprobe: Introduce fprobe function entry/exit probe | expand |
Context | Check | Description |
---|---|---|
netdev/tree_selection | success | Not a local patch |
Hi Masami, I love your patch! Yet something to improve: [auto build test ERROR on rostedt-trace/for-next] [also build test ERROR on tip/x86/core linus/master v5.17-rc1 next-20220124] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Masami-Hiramatsu/fprobe-Introduce-fprobe-function-entry-exit-probe/20220125-001253 base: https://git.kernel.org/pub/scm/linux/kernel/git/rostedt/linux-trace.git for-next config: i386-tinyconfig (https://download.01.org/0day-ci/archive/20220125/202201250509.MSbKNePn-lkp@intel.com/config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/6366c7f830e71242dd9538fbdb09acdccea6e786 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Masami-Hiramatsu/fprobe-Introduce-fprobe-function-entry-exit-probe/20220125-001253 git checkout 6366c7f830e71242dd9538fbdb09acdccea6e786 # save the config file to linux build tree mkdir build_dir make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash arch/x86/kernel/ If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): In file included from arch/x86/kernel/process.c:48: arch/x86/include/asm/unwind.h: In function 'unwind_recover_kretprobe': >> arch/x86/include/asm/unwind.h:113:17: error: 'struct unwind_state' has no member named 'kr_cur' 113 | &state->kr_cur); | ^~ arch/x86/kernel/process.c: At top level: arch/x86/kernel/process.c:887:13: warning: no previous prototype for 'arch_post_acpi_subsys_init' [-Wmissing-prototypes] 887 | void __init arch_post_acpi_subsys_init(void) | ^~~~~~~~~~~~~~~~~~~~~~~~~~ -- In file included from arch/x86/kernel/unwind_guess.c:7: arch/x86/include/asm/unwind.h: In function 'unwind_recover_kretprobe': >> arch/x86/include/asm/unwind.h:113:17: error: 'struct unwind_state' has no member named 'kr_cur' 113 | &state->kr_cur); | ^~ vim +113 arch/x86/include/asm/unwind.h 106 107 static inline 108 unsigned long unwind_recover_kretprobe(struct unwind_state *state, 109 unsigned long addr, unsigned long *addr_p) 110 { 111 if (IS_ENABLED(CONFIG_RETHOOK) && is_rethook_trampoline(addr)) 112 return rethook_find_ret_addr(state->task, (unsigned long)addr_p, > 113 &state->kr_cur); 114 #ifdef CONFIG_KRETPROBES 115 return is_kretprobe_trampoline(addr) ? 116 kretprobe_find_ret_addr(state->task, addr_p, &state->kr_cur) : 117 addr; 118 #else 119 return addr; 120 #endif 121 } 122 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Tue, 25 Jan 2022 01:10:09 +0900 Masami Hiramatsu <mhiramat@kernel.org> wrote: > Add rethook for x86 implementation. Most of the code > has been copied from kretprobes on x86. > > Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> > --- > Changes in v4: > - fix stack backtrace as same as kretprobe does. > --- > arch/x86/Kconfig | 1 > arch/x86/include/asm/unwind.h | 4 + > arch/x86/kernel/Makefile | 1 > arch/x86/kernel/rethook.c | 115 +++++++++++++++++++++++++++++++++++++++++ > 4 files changed, 121 insertions(+) > create mode 100644 arch/x86/kernel/rethook.c > > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig > index 5c2ccb85f2ef..0a7d48a63787 100644 > --- a/arch/x86/Kconfig > +++ b/arch/x86/Kconfig > @@ -219,6 +219,7 @@ config X86 > select HAVE_KPROBES_ON_FTRACE > select HAVE_FUNCTION_ERROR_INJECTION > select HAVE_KRETPROBES > + select HAVE_RETHOOK > select HAVE_KVM > select HAVE_LIVEPATCH if X86_64 > select HAVE_MIXED_BREAKPOINTS_REGS > diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h > index 2a1f8734416d..9fe5f73f22f1 100644 > --- a/arch/x86/include/asm/unwind.h > +++ b/arch/x86/include/asm/unwind.h > @@ -5,6 +5,7 @@ > #include <linux/sched.h> > #include <linux/ftrace.h> > #include <linux/kprobes.h> > +#include <linux/rethook.h> > #include <asm/ptrace.h> > #include <asm/stacktrace.h> > > @@ -107,6 +108,9 @@ static inline > unsigned long unwind_recover_kretprobe(struct unwind_state *state, > unsigned long addr, unsigned long *addr_p) > { > + if (IS_ENABLED(CONFIG_RETHOOK) && is_rethook_trampoline(addr)) > + return rethook_find_ret_addr(state->task, (unsigned long)addr_p, > + &state->kr_cur); Hm, I found that this doesn't work since state->kr_cur is not defined when CONFIG_KRETPROBES=n. Even if I define it with CONFIG_RETHOOK=y, if both CONFIG_RETHOOK and CONFIG_KRETPROBES are 'n', the compiler caused a build error. So I decided to use #ifdef here in the next version. Thank you,
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 5c2ccb85f2ef..0a7d48a63787 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -219,6 +219,7 @@ config X86 select HAVE_KPROBES_ON_FTRACE select HAVE_FUNCTION_ERROR_INJECTION select HAVE_KRETPROBES + select HAVE_RETHOOK select HAVE_KVM select HAVE_LIVEPATCH if X86_64 select HAVE_MIXED_BREAKPOINTS_REGS diff --git a/arch/x86/include/asm/unwind.h b/arch/x86/include/asm/unwind.h index 2a1f8734416d..9fe5f73f22f1 100644 --- a/arch/x86/include/asm/unwind.h +++ b/arch/x86/include/asm/unwind.h @@ -5,6 +5,7 @@ #include <linux/sched.h> #include <linux/ftrace.h> #include <linux/kprobes.h> +#include <linux/rethook.h> #include <asm/ptrace.h> #include <asm/stacktrace.h> @@ -107,6 +108,9 @@ static inline unsigned long unwind_recover_kretprobe(struct unwind_state *state, unsigned long addr, unsigned long *addr_p) { + if (IS_ENABLED(CONFIG_RETHOOK) && is_rethook_trampoline(addr)) + return rethook_find_ret_addr(state->task, (unsigned long)addr_p, + &state->kr_cur); #ifdef CONFIG_KRETPROBES return is_kretprobe_trampoline(addr) ? kretprobe_find_ret_addr(state->task, addr_p, &state->kr_cur) : diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 2ff3e600f426..66593d8c4d74 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -106,6 +106,7 @@ obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o obj-$(CONFIG_FTRACE_SYSCALLS) += ftrace.o obj-$(CONFIG_X86_TSC) += trace_clock.o obj-$(CONFIG_TRACING) += trace.o +obj-$(CONFIG_RETHOOK) += rethook.o obj-$(CONFIG_CRASH_CORE) += crash_core_$(BITS).o obj-$(CONFIG_KEXEC_CORE) += machine_kexec_$(BITS).o obj-$(CONFIG_KEXEC_CORE) += relocate_kernel_$(BITS).o crash.o diff --git a/arch/x86/kernel/rethook.c b/arch/x86/kernel/rethook.c new file mode 100644 index 000000000000..f2f3b9526e43 --- /dev/null +++ b/arch/x86/kernel/rethook.c @@ -0,0 +1,115 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * x86 implementation of rethook. Mostly copied from arch/x86/kernel/kprobes/core.c. + */ +#include <linux/bug.h> +#include <linux/rethook.h> +#include <linux/kprobes.h> + +#include "kprobes/common.h" + +/* + * Called from arch_rethook_trampoline + */ +__used __visible void arch_rethook_trampoline_callback(struct pt_regs *regs) +{ + unsigned long *frame_pointer; + + /* fixup registers */ + regs->cs = __KERNEL_CS; +#ifdef CONFIG_X86_32 + regs->gs = 0; +#endif + regs->ip = (unsigned long)&arch_rethook_trampoline; + regs->orig_ax = ~0UL; + regs->sp += sizeof(long); + frame_pointer = ®s->sp + 1; + + /* + * The return address at 'frame_pointer' is recovered by the + * arch_rethook_fixup_return() which called from this + * rethook_trampoline_handler(). + */ + rethook_trampoline_handler(regs, (unsigned long)frame_pointer); + + /* + * Copy FLAGS to 'pt_regs::sp' so that arch_rethook_trapmoline() + * can do RET right after POPF. + */ + regs->sp = regs->flags; +} +NOKPROBE_SYMBOL(arch_rethook_trampoline_callback); + +/* + * When a target function returns, this code saves registers and calls + * arch_rethook_trampoline_callback(), which calls the rethook handler. + */ +asm( + ".text\n" + ".global arch_rethook_trampoline\n" + ".type arch_rethook_trampoline, @function\n" + "arch_rethook_trampoline:\n" +#ifdef CONFIG_X86_64 + /* Push a fake return address to tell the unwinder it's a kretprobe. */ + " pushq $arch_rethook_trampoline\n" + UNWIND_HINT_FUNC + /* Save the 'sp - 8', this will be fixed later. */ + " pushq %rsp\n" + " pushfq\n" + SAVE_REGS_STRING + " movq %rsp, %rdi\n" + " call arch_rethook_trampoline_callback\n" + RESTORE_REGS_STRING + /* In the callback function, 'regs->flags' is copied to 'regs->sp'. */ + " addq $8, %rsp\n" + " popfq\n" +#else + /* Push a fake return address to tell the unwinder it's a kretprobe. */ + " pushl $arch_rethook_trampoline\n" + UNWIND_HINT_FUNC + /* Save the 'sp - 4', this will be fixed later. */ + " pushl %esp\n" + " pushfl\n" + SAVE_REGS_STRING + " movl %esp, %eax\n" + " call arch_rethook_trampoline_callback\n" + RESTORE_REGS_STRING + /* In the callback function, 'regs->flags' is copied to 'regs->sp'. */ + " addl $4, %esp\n" + " popfl\n" +#endif + " ret\n" + ".size arch_rethook_trampoline, .-arch_rethook_trampoline\n" +); +NOKPROBE_SYMBOL(arch_rethook_trampoline); +/* + * arch_rethook_trampoline() skips updating frame pointer. The frame pointer + * saved in arch_rethook_trampoline_callback() points to the real caller + * function's frame pointer. Thus the arch_rethook_trampoline() doesn't have + * a standard stack frame with CONFIG_FRAME_POINTER=y. + * Let's mark it non-standard function. Anyway, FP unwinder can correctly + * unwind without the hint. + */ +STACK_FRAME_NON_STANDARD_FP(arch_rethook_trampoline); + +/* This is called from rethook_trampoline_handler(). */ +void arch_rethook_fixup_return(struct pt_regs *regs, + unsigned long correct_ret_addr) +{ + unsigned long *frame_pointer = ®s->sp + 1; + + /* Replace fake return address with real one. */ + *frame_pointer = correct_ret_addr; +} + +void arch_rethook_prepare(struct rethook_node *rh, struct pt_regs *regs) +{ + unsigned long *stack = (unsigned long *)regs->sp; + + rh->ret_addr = stack[0]; + rh->frame = regs->sp; + + /* Replace the return addr with trampoline addr */ + stack[0] = (unsigned long) arch_rethook_trampoline; +} +NOKPROBE_SYMBOL(arch_rethook_prepare);
Add rethook for x86 implementation. Most of the code has been copied from kretprobes on x86. Signed-off-by: Masami Hiramatsu <mhiramat@kernel.org> --- Changes in v4: - fix stack backtrace as same as kretprobe does. --- arch/x86/Kconfig | 1 arch/x86/include/asm/unwind.h | 4 + arch/x86/kernel/Makefile | 1 arch/x86/kernel/rethook.c | 115 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+) create mode 100644 arch/x86/kernel/rethook.c