From: Oleg Nesterov <oleg@redhat.com>
To: Jiri Olsa <olsajiri@gmail.com>
Cc: Tianyi Liu <i.pear@outlook.com>,
andrii.nakryiko@gmail.com, mhiramat@kernel.org, ajor@meta.com,
albancrequy@linux.microsoft.com, bpf@vger.kernel.org,
flaniel@linux.microsoft.com, linux-trace-kernel@vger.kernel.org,
linux@jordanrome.com, mathieu.desnoyers@efficios.com
Subject: Re: [PATCH v2] tracing/uprobe: Add missing PID filter for uretprobe
Date: Thu, 29 Aug 2024 17:20:33 +0200 [thread overview]
Message-ID: <20240829152032.GA23996@redhat.com> (raw)
In-Reply-To: <Zs8N-xP4jlPK2yjE@krava>
On 08/28, Jiri Olsa wrote:
>
> On Tue, Aug 27, 2024 at 10:19:26PM +0200, Oleg Nesterov wrote:
> > Hmm. Really? In this case these 2 different consumers will have the different
> > trace_event_call's, so
> >
> > // consumer for task 1019
> > uretprobe_dispatcher
> > uretprobe_perf_func
> > __uprobe_perf_func
> > perf_tp_event
> >
> > won't store the event because this_cpu_ptr(call->perf_events) should be
> > hlist_empty() on this CPU, the perf_event for task 1019 wasn't scheduled in
> > on this CPU...
>
> I'll double check on that,
Yes, please.
> but because there's no filter for uretprobe
> I think it will be stored under 1018 event
...
> I'm working on bpf selftests for above (uprobe and uprobe_multi paths)
Meanwhile, I decided to try to test this case too ;)
test.c:
#include <unistd.h>
int func(int i)
{
return i;
}
int main(void)
{
int i;
for (i = 0;; ++i) {
sleep(1);
func(i);
}
return 0;
}
run_probe.c:
#include "./include/uapi/linux/perf_event.h"
#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
// cat /sys/bus/event_source/devices/uprobe/type
#define UPROBE_TYPE 9
void run_probe(const char *file, unsigned offset, int pid)
{
struct perf_event_attr attr = {
.type = UPROBE_TYPE,
.config = 1, // ret-probe
.uprobe_path = (unsigned long)file,
.probe_offset = offset,
.size = sizeof(struct perf_event_attr),
};
int fd = syscall(__NR_perf_event_open, &attr, pid, 0, -1, 0);
assert(fd >= 0);
assert(ioctl(fd, PERF_EVENT_IOC_ENABLE, 0) == 0);
for (;;)
pause();
}
int main(int argc, const char *argv[])
{
int pid = atoi(argv[1]);
run_probe("./test", 0x536, pid);
return 0;
}
Now, with the kernel patch below applied, I do
$ ./test &
$ PID1=$!
$ ./test &
$ PID2=$!
$ ./run_probe $PID1 &
$ ./run_probe $PID2 &
and the kernel prints:
CHAIN
trace_uprobe: HANDLER pid=46 consumers_target=46 stored=1
trace_uprobe: HANDLER pid=46 consumers_target=45 stored=0
CHAIN
trace_uprobe: HANDLER pid=45 consumers_target=46 stored=0
trace_uprobe: HANDLER pid=45 consumers_target=45 stored=1
CHAIN
trace_uprobe: HANDLER pid=46 consumers_target=46 stored=1
trace_uprobe: HANDLER pid=46 consumers_target=45 stored=0
CHAIN
trace_uprobe: HANDLER pid=45 consumers_target=46 stored=0
trace_uprobe: HANDLER pid=45 consumers_target=45 stored=1
CHAIN
trace_uprobe: HANDLER pid=46 consumers_target=46 stored=1
trace_uprobe: HANDLER pid=46 consumers_target=45 stored=0
CHAIN
trace_uprobe: HANDLER pid=45 consumers_target=46 stored=0
trace_uprobe: HANDLER pid=45 consumers_target=45 stored=1
CHAIN
trace_uprobe: HANDLER pid=46 consumers_target=46 stored=1
trace_uprobe: HANDLER pid=46 consumers_target=45 stored=0
CHAIN
trace_uprobe: HANDLER pid=45 consumers_target=46 stored=0
trace_uprobe: HANDLER pid=45 consumers_target=45 stored=1
and so on.
As you can see, perf_trace_buf_submit/etc is never called for the "unfiltered"
consumer, so I still think that perf is fine wrt filtering. But I can be easily
wrong, please check.
Oleg.
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index acc73c1bc54c..14aa92a78d6d 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -2150,6 +2150,8 @@ handle_uretprobe_chain(struct return_instance *ri, struct pt_regs *regs)
struct uprobe *uprobe = ri->uprobe;
struct uprobe_consumer *uc;
+ pr_crit("CHAIN\n");
+
rcu_read_lock_trace();
list_for_each_entry_rcu(uc, &uprobe->consumers, cons_node, rcu_read_lock_trace_held()) {
if (uc->ret_handler)
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index f7443e996b1b..e4eaa0363742 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -1364,7 +1364,7 @@ static bool uprobe_perf_filter(struct uprobe_consumer *uc, struct mm_struct *mm)
return ret;
}
-static void __uprobe_perf_func(struct trace_uprobe *tu,
+static int __uprobe_perf_func(struct trace_uprobe *tu,
unsigned long func, struct pt_regs *regs,
struct uprobe_cpu_buffer **ucbp)
{
@@ -1375,6 +1375,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
void *data;
int size, esize;
int rctx;
+ int ret = 0;
#ifdef CONFIG_BPF_EVENTS
if (bpf_prog_array_valid(call)) {
@@ -1382,7 +1383,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
ret = bpf_prog_run_array_uprobe(call->prog_array, regs, bpf_prog_run);
if (!ret)
- return;
+ return -1;
}
#endif /* CONFIG_BPF_EVENTS */
@@ -1392,12 +1393,13 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
size = esize + ucb->dsize;
size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32);
if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
- return;
+ return -1;
preempt_disable();
head = this_cpu_ptr(call->perf_events);
if (hlist_empty(head))
goto out;
+ ret = 1;
entry = perf_trace_buf_alloc(size, NULL, &rctx);
if (!entry)
@@ -1421,6 +1423,7 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
head, NULL);
out:
preempt_enable();
+ return ret;
}
/* uprobe profile handler */
@@ -1439,7 +1442,15 @@ static void uretprobe_perf_func(struct trace_uprobe *tu, unsigned long func,
struct pt_regs *regs,
struct uprobe_cpu_buffer **ucbp)
{
- __uprobe_perf_func(tu, func, regs, ucbp);
+ struct trace_uprobe_filter *filter = tu->tp.event->filter;
+ struct perf_event *event = list_first_entry(&filter->perf_events,
+ struct perf_event, hw.tp_list);
+
+ int r = __uprobe_perf_func(tu, func, regs, ucbp);
+
+ pr_crit("HANDLER pid=%d consumers_target=%d stored=%d\n",
+ current->pid, event->hw.target ? event->hw.target->pid : -1, r);
+
}
int bpf_get_uprobe_info(const struct perf_event *event, u32 *fd_type,
next prev parent reply other threads:[~2024-08-29 15:20 UTC|newest]
Thread overview: 57+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-23 13:53 [PATCH v2] tracing/uprobe: Add missing PID filter for uretprobe Tianyi Liu
2024-08-23 17:44 ` Masami Hiramatsu
2024-08-23 19:07 ` Andrii Nakryiko
2024-08-24 5:49 ` Tianyi Liu
2024-08-24 17:27 ` Masami Hiramatsu
2024-08-25 17:14 ` Oleg Nesterov
2024-08-25 18:43 ` Oleg Nesterov
2024-08-25 22:40 ` Oleg Nesterov
2024-08-26 10:05 ` Jiri Olsa
2024-08-26 11:57 ` Oleg Nesterov
2024-08-26 12:24 ` Oleg Nesterov
2024-08-26 13:48 ` Jiri Olsa
2024-08-26 18:56 ` Oleg Nesterov
2024-08-26 21:25 ` Oleg Nesterov
2024-08-26 22:01 ` Jiri Olsa
2024-08-26 22:08 ` Andrii Nakryiko
2024-08-26 22:29 ` Oleg Nesterov
2024-08-27 13:07 ` Jiri Olsa
2024-08-27 13:45 ` Jiri Olsa
2024-08-27 16:45 ` Oleg Nesterov
2024-08-28 11:40 ` Jiri Olsa
2024-08-27 20:19 ` Oleg Nesterov
2024-08-28 11:46 ` Jiri Olsa
2024-08-29 15:20 ` Oleg Nesterov [this message]
2024-08-29 19:46 ` Jiri Olsa
2024-08-29 21:12 ` Oleg Nesterov
2024-08-29 23:22 ` Jiri Olsa
2024-08-27 6:27 ` Tianyi Liu
2024-08-27 10:08 ` Jiri Olsa
2024-08-27 10:20 ` Jiri Olsa
2024-08-27 10:54 ` Oleg Nesterov
2024-08-27 10:40 ` Oleg Nesterov
2024-08-27 13:32 ` Jiri Olsa
2024-08-27 14:26 ` Oleg Nesterov
2024-08-27 14:41 ` Jiri Olsa
2024-08-26 14:52 ` Tianyi Liu
2024-08-25 17:00 ` Oleg Nesterov
2024-08-30 10:12 ` Oleg Nesterov
2024-08-30 12:23 ` Oleg Nesterov
2024-08-30 13:34 ` Jiri Olsa
2024-08-30 15:51 ` Andrii Nakryiko
2024-09-02 9:11 ` Jiri Olsa
2024-09-03 18:09 ` Andrii Nakryiko
2024-09-03 18:11 ` Andrii Nakryiko
2024-09-03 19:15 ` Jiri Olsa
2024-09-01 19:22 ` Tianyi Liu
2024-09-01 23:26 ` Oleg Nesterov
2024-09-02 17:17 ` Oleg Nesterov
2024-09-03 14:33 ` Jiri Olsa
2024-09-06 10:43 ` Jiri Olsa
2024-09-06 19:18 ` Oleg Nesterov
2024-09-09 10:41 ` Jiri Olsa
2024-09-09 18:34 ` Oleg Nesterov
2024-09-10 8:45 ` Jiri Olsa
2024-09-07 19:19 ` Tianyi Liu
2024-09-08 13:15 ` Oleg Nesterov
2024-09-09 1:16 ` Andrii Nakryiko
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=20240829152032.GA23996@redhat.com \
--to=oleg@redhat.com \
--cc=ajor@meta.com \
--cc=albancrequy@linux.microsoft.com \
--cc=andrii.nakryiko@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=flaniel@linux.microsoft.com \
--cc=i.pear@outlook.com \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=linux@jordanrome.com \
--cc=mathieu.desnoyers@efficios.com \
--cc=mhiramat@kernel.org \
--cc=olsajiri@gmail.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.