From: Jiri Olsa <jolsa@redhat.com>
To: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Masami Hiramatsu <mhiramat@kernel.org>
Cc: netdev@vger.kernel.org, bpf@vger.kernel.org,
lkml <linux-kernel@vger.kernel.org>,
Martin KaFai Lau <kafai@fb.com>, Song Liu <songliubraving@fb.com>,
Yonghong Song <yhs@fb.com>,
John Fastabend <john.fastabend@gmail.com>,
KP Singh <kpsingh@chromium.org>,
Steven Rostedt <rostedt@goodmis.org>,
"Naveen N. Rao" <naveen.n.rao@linux.ibm.com>,
Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>,
"David S. Miller" <davem@davemloft.net>
Subject: [PATCH 05/13] kprobe: Allow to get traced function address for multi ftrace kprobes
Date: Tue, 4 Jan 2022 09:09:35 +0100 [thread overview]
Message-ID: <20220104080943.113249-6-jolsa@kernel.org> (raw)
In-Reply-To: <20220104080943.113249-1-jolsa@kernel.org>
The current bpf_get_func_ip_kprobe helper does not work properly,
when used in ebpf program triggered by the new multi kprobes.
We can't use kprobe's func_addr in bpf_get_func_ip_kprobe helper,
because there are multiple functions registered for single kprobe
object.
Adding new per cpu variable current_ftrace_multi_addr and extra
address in kretprobe_instance object to keep current traced function
address for each cpu for both kprobe handler and kretprobe trampoline.
The address value is set/passed as follows, for kprobe:
kprobe_ftrace_multi_handler
{
old = kprobe_ftrace_multi_addr_set(ip);
handler..
kprobe_ftrace_multi_addr_set(old);
}
For kretprobe:
kprobe_ftrace_multi_handler
{
old = kprobe_ftrace_multi_addr_set(ip);
...
pre_handler_kretprobe
{
ri->ftrace_multi_addr = kprobe_ftrace_multi_addr
}
...
kprobe_ftrace_multi_addr_set(old);
}
__kretprobe_trampoline_handler
{
prev_func_addr = kprobe_ftrace_multi_addr_set(ri->ftrace_multi_addr);
handler..
kprobe_ftrace_multi_addr_set(prev_func_addr);
}
Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
arch/x86/kernel/kprobes/ftrace.c | 3 +++
include/linux/kprobes.h | 26 ++++++++++++++++++++++++++
kernel/kprobes.c | 6 ++++++
kernel/trace/bpf_trace.c | 7 ++++++-
4 files changed, 41 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/kprobes/ftrace.c b/arch/x86/kernel/kprobes/ftrace.c
index ac4d256b89c6..8caaa58c3a64 100644
--- a/arch/x86/kernel/kprobes/ftrace.c
+++ b/arch/x86/kernel/kprobes/ftrace.c
@@ -72,6 +72,7 @@ NOKPROBE_SYMBOL(kprobe_ftrace_handler);
void kprobe_ftrace_multi_handler(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct ftrace_regs *fregs)
{
+ unsigned long old;
struct kprobe *p;
int bit;
@@ -79,8 +80,10 @@ void kprobe_ftrace_multi_handler(unsigned long ip, unsigned long parent_ip,
if (bit < 0)
return;
+ old = kprobe_ftrace_multi_addr_set(ip);
p = container_of(ops, struct kprobe, multi.ops);
ftrace_handler(p, ip, fregs);
+ kprobe_ftrace_multi_addr_set(old);
ftrace_test_recursion_unlock(bit);
}
diff --git a/include/linux/kprobes.h b/include/linux/kprobes.h
index a31da6202b5c..3f0522b9538b 100644
--- a/include/linux/kprobes.h
+++ b/include/linux/kprobes.h
@@ -191,6 +191,7 @@ struct kretprobe_instance {
struct kretprobe_holder *rph;
kprobe_opcode_t *ret_addr;
void *fp;
+ unsigned long ftrace_multi_addr;
char data[];
};
@@ -387,16 +388,37 @@ static inline void wait_for_kprobe_optimizer(void) { }
#endif /* CONFIG_OPTPROBES */
#ifdef CONFIG_KPROBES_ON_FTRACE
+DECLARE_PER_CPU(unsigned long, current_ftrace_multi_addr);
extern void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct ftrace_regs *fregs);
extern void kprobe_ftrace_multi_handler(unsigned long ip, unsigned long parent_ip,
struct ftrace_ops *ops, struct ftrace_regs *fregs);
extern int arch_prepare_kprobe_ftrace(struct kprobe *p);
+
+static inline unsigned long kprobe_ftrace_multi_addr(void)
+{
+ return __this_cpu_read(current_ftrace_multi_addr);
+}
+static inline unsigned long kprobe_ftrace_multi_addr_set(unsigned long addr)
+{
+ unsigned long old = __this_cpu_read(current_ftrace_multi_addr);
+
+ __this_cpu_write(current_ftrace_multi_addr, addr);
+ return old;
+}
#else
static inline int arch_prepare_kprobe_ftrace(struct kprobe *p)
{
return -EINVAL;
}
+static inline unsigned long kprobe_ftrace_multi_addr_set(unsigned long addr)
+{
+ return 0;
+}
+static inline unsigned long kprobe_ftrace_multi_addr(void)
+{
+ return 0;
+}
#endif /* CONFIG_KPROBES_ON_FTRACE */
/* Get the kprobe at this addr (if any) - called with preemption disabled */
@@ -514,6 +536,10 @@ static inline int kprobe_get_kallsym(unsigned int symnum, unsigned long *value,
{
return -ERANGE;
}
+static inline unsigned long kprobe_ftrace_multi_addr(void)
+{
+ return 0;
+}
#endif /* CONFIG_KPROBES */
static inline int disable_kretprobe(struct kretprobe *rp)
diff --git a/kernel/kprobes.c b/kernel/kprobes.c
index 04fc411ca30c..6ba249f3a0cb 100644
--- a/kernel/kprobes.c
+++ b/kernel/kprobes.c
@@ -1064,6 +1064,8 @@ static bool in_kretprobe_blacklist(void *addr)
}
#ifdef CONFIG_KPROBES_ON_FTRACE
+DEFINE_PER_CPU(unsigned long, current_ftrace_multi_addr);
+
static struct ftrace_ops kprobe_ftrace_ops __read_mostly = {
.func = kprobe_ftrace_handler,
.flags = FTRACE_OPS_FL_SAVE_REGS,
@@ -2106,11 +2108,14 @@ unsigned long __kretprobe_trampoline_handler(struct pt_regs *regs,
rp = get_kretprobe(ri);
if (rp && rp->handler) {
struct kprobe *prev = kprobe_running();
+ unsigned long prev_func_addr;
+ prev_func_addr = kprobe_ftrace_multi_addr_set(ri->ftrace_multi_addr);
__this_cpu_write(current_kprobe, &rp->kp);
ri->ret_addr = correct_ret_addr;
rp->handler(ri, regs);
__this_cpu_write(current_kprobe, prev);
+ kprobe_ftrace_multi_addr_set(prev_func_addr);
}
if (first == node)
break;
@@ -2161,6 +2166,7 @@ static int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
}
arch_prepare_kretprobe(ri, regs);
+ ri->ftrace_multi_addr = kprobe_ftrace_multi_addr();
__llist_add(&ri->llist, ¤t->kretprobe_instances);
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 25631253084a..39f4d476cfca 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -1026,7 +1026,12 @@ BPF_CALL_1(bpf_get_func_ip_kprobe, struct pt_regs *, regs)
{
struct kprobe *kp = kprobe_running();
- return kp ? (uintptr_t)kp->func_addr : 0;
+ if (!kp)
+ return 0;
+ if (kprobe_ftrace_multi(kp))
+ return (uintptr_t) kprobe_ftrace_multi_addr();
+ else
+ return (uintptr_t) kp->func_addr;
}
static const struct bpf_func_proto bpf_get_func_ip_proto_kprobe = {
--
2.33.1
next prev parent reply other threads:[~2022-01-04 8:10 UTC|newest]
Thread overview: 54+ messages / expand[flat|nested] mbox.gz Atom feed top
2022-01-04 8:09 [RFC 00/13] kprobe/bpf: Add support to attach multiple kprobes Jiri Olsa
2022-01-04 8:09 ` [PATCH 01/13] ftrace: Add ftrace_set_filter_ips function Jiri Olsa
2022-01-04 8:09 ` [PATCH 02/13] kprobe: Keep traced function address Jiri Olsa
2022-01-05 14:32 ` Masami Hiramatsu
2022-01-06 8:30 ` Jiri Olsa
2022-01-06 4:30 ` Andrii Nakryiko
2022-01-06 8:31 ` Jiri Olsa
2022-01-04 8:09 ` [PATCH 03/13] kprobe: Add support to register multiple ftrace kprobes Jiri Olsa
2022-01-05 15:00 ` Masami Hiramatsu
2022-01-04 8:09 ` [PATCH 04/13] kprobe: Add support to register multiple ftrace kretprobes Jiri Olsa
2022-01-04 8:09 ` Jiri Olsa [this message]
2022-01-06 4:30 ` [PATCH 05/13] kprobe: Allow to get traced function address for multi ftrace kprobes Andrii Nakryiko
2022-01-04 8:09 ` [PATCH 06/13] samples/kprobes: Add support for multi kprobe interface Jiri Olsa
2022-01-04 8:09 ` [PATCH 07/13] samples/kprobes: Add support for multi kretprobe interface Jiri Olsa
2022-01-04 8:09 ` [PATCH 08/13] bpf: Add kprobe link for attaching raw kprobes Jiri Olsa
2022-01-06 4:30 ` Andrii Nakryiko
2022-01-06 8:41 ` Jiri Olsa
2022-01-06 16:32 ` Alexei Starovoitov
2022-01-06 21:53 ` Andrii Nakryiko
2022-01-04 8:09 ` [PATCH 09/13] libbpf: Add libbpf__kallsyms_parse function Jiri Olsa
2022-01-04 8:09 ` [PATCH 10/13] libbpf: Add bpf_link_create support for multi kprobes Jiri Olsa
2022-01-04 8:09 ` [PATCH 11/13] libbpf: Add bpf_program__attach_kprobe_opts " Jiri Olsa
2022-01-04 8:09 ` [PATCH 12/13] selftest/bpf: Add raw kprobe attach test Jiri Olsa
2022-01-04 8:09 ` [PATCH 13/13] selftest/bpf: Add bpf_cookie test for raw_k[ret]probe Jiri Olsa
2022-01-04 18:53 ` [RFC 00/13] kprobe/bpf: Add support to attach multiple kprobes Alexei Starovoitov
2022-01-05 9:15 ` Jiri Olsa
2022-01-05 15:24 ` Masami Hiramatsu
2022-01-06 8:29 ` Jiri Olsa
2022-01-06 13:59 ` Masami Hiramatsu
2022-01-06 14:57 ` Jiri Olsa
2022-01-07 5:42 ` Masami Hiramatsu
2022-01-06 15:02 ` Steven Rostedt
2022-01-06 17:40 ` Alexei Starovoitov
2022-01-06 23:52 ` Masami Hiramatsu
2022-01-07 0:20 ` Alexei Starovoitov
2022-01-07 12:55 ` Masami Hiramatsu
2022-01-11 15:00 ` [RFC PATCH 0/6] fprobe: Introduce fprobe function entry/exit probe Masami Hiramatsu
2022-01-11 15:00 ` [RFC PATCH 1/6] fprobe: Add ftrace based probe APIs Masami Hiramatsu
2022-01-11 15:00 ` [RFC PATCH 2/6] rethook: Add a generic return hook Masami Hiramatsu
2022-01-11 15:00 ` [RFC PATCH 3/6] rethook: x86: Add rethook x86 implementation Masami Hiramatsu
2022-01-11 15:01 ` [RFC PATCH 4/6] fprobe: Add exit_handler support Masami Hiramatsu
2022-01-12 22:28 ` kernel test robot
2022-01-13 2:29 ` kernel test robot
2022-01-13 2:29 ` kernel test robot
2022-01-24 22:24 ` kernel test robot
2022-01-11 15:01 ` [RFC PATCH 5/6] fprobe: Add sample program for fprobe Masami Hiramatsu
2022-01-11 15:01 ` [RFC PATCH 6/6] bpf: Add kprobe link for attaching raw kprobes Masami Hiramatsu
2022-01-12 22:18 ` kernel test robot
2022-01-12 23:19 ` kernel test robot
2022-01-12 23:19 ` kernel test robot
2022-01-12 23:40 ` kernel test robot
2022-01-11 22:39 ` [RFC PATCH 0/6] fprobe: Introduce fprobe function entry/exit probe Alexei Starovoitov
2022-01-12 7:33 ` Masami Hiramatsu
2022-01-12 11:08 ` Masami Hiramatsu
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20220104080943.113249-6-jolsa@kernel.org \
--to=jolsa@redhat.com \
--cc=andrii@kernel.org \
--cc=anil.s.keshavamurthy@intel.com \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=davem@davemloft.net \
--cc=john.fastabend@gmail.com \
--cc=kafai@fb.com \
--cc=kpsingh@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mhiramat@kernel.org \
--cc=naveen.n.rao@linux.ibm.com \
--cc=netdev@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=songliubraving@fb.com \
--cc=yhs@fb.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.