Add temporary workaround until proper register_ftrace_direct() api lands. This commit must be reverted during upcoming merge window. The hack functions don't have safety checks that ftrace api performs. Signed-off-by: Alexei Starovoitov <ast@xxxxxxxxxx> --- arch/x86/kernel/ftrace.c | 36 ++++++++++++++++++++++++++++++++++++ include/linux/bpf.h | 5 +++++ kernel/bpf/core.c | 30 ++++++++++++++++++++++++++++++ 3 files changed, 71 insertions(+) diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c index 024c3053dbba..0fd7643da92d 100644 --- a/arch/x86/kernel/ftrace.c +++ b/arch/x86/kernel/ftrace.c @@ -265,6 +265,42 @@ static int update_ftrace_func(unsigned long ip, void *new) return ret; } +/* + * There are no safety checks here. It's a temporary hack until proper + * register_ftrace_direct() api lands. These functions blindly rewrite kernel + * text. Proper register_ftrace_direct() should check that IP is one of allowed + * fentry points. unregister_ftrace_direct() and modify_ftrace_direct() should + * do similar checks. + */ +int arch_register_ftrace_hack(unsigned long ip, unsigned long addr) +{ + u8 *new; + int ret; + + ftrace_arch_code_modify_prepare(); + new = ftrace_call_replace(ip, addr); + ret = update_ftrace_func(ip, new); + ftrace_arch_code_modify_post_process(); + return ret; +} + +int arch_unregister_ftrace_hack(unsigned long ip, unsigned long addr) +{ + u8 *old; + int ret; + + ftrace_arch_code_modify_prepare(); + old = (void *)ftrace_nop_replace(); + ret = update_ftrace_func(ip, old); + ftrace_arch_code_modify_post_process(); + return ret; +} + +int arch_modify_ftrace_hack(unsigned long ip, unsigned long addr) +{ + return arch_register_ftrace_hack(ip, addr); +} + int ftrace_update_ftrace_func(ftrace_func_t func) { unsigned long ip = (unsigned long)(&ftrace_call); diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 7c7f518811a6..a8941f113298 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1157,4 +1157,9 @@ static inline u32 bpf_xdp_sock_convert_ctx_access(enum bpf_access_type type, } #endif /* CONFIG_INET */ +/* workaround */ +int register_ftrace_direct(unsigned long ip, unsigned long addr); +int unregister_ftrace_direct(unsigned long ip, unsigned long addr); +int modify_ftrace_direct(unsigned long ip, unsigned long addr); + #endif /* _LINUX_BPF_H */ diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index df82d5a42b23..1bacf70e6509 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -2140,6 +2140,36 @@ int __weak skb_copy_bits(const struct sk_buff *skb, int offset, void *to, return -EFAULT; } +int __weak arch_register_ftrace_hack(unsigned long ip, unsigned long addr) +{ + return -ENOTSUPP; +} + +int __weak register_ftrace_direct(unsigned long ip, unsigned long addr) +{ + return arch_register_ftrace_hack(ip, addr); +} + +int __weak arch_unregister_ftrace_hack(unsigned long ip, unsigned long addr) +{ + return -ENOTSUPP; +} + +int __weak unregister_ftrace_direct(unsigned long ip, unsigned long addr) +{ + return arch_unregister_ftrace_hack(ip, addr); +} + +int __weak arch_modify_ftrace_hack(unsigned long ip, unsigned long addr) +{ + return -ENOTSUPP; +} + +int __weak modify_ftrace_direct(unsigned long ip, unsigned long addr) +{ + return arch_modify_ftrace_hack(ip, addr); +} + DEFINE_STATIC_KEY_FALSE(bpf_stats_enabled_key); EXPORT_SYMBOL(bpf_stats_enabled_key); -- 2.23.0