All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test
@ 2024-08-29 19:45 Jiri Olsa
  2024-08-29 19:45 ` [PATCH bpf-next 1/2] selftests/bpf: Add child argument to spawn_child function Jiri Olsa
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Jiri Olsa @ 2024-08-29 19:45 UTC (permalink / raw)
  To: Oleg Nesterov, Peter Zijlstra, Andrii Nakryiko, Tianyi Liu,
	Masami Hiramatsu
  Cc: bpf, Steven Rostedt, linux-kernel, linux-trace-kernel

hi,
in response to [1] patch, I'm adding bpf selftest that confirms the
change fixes problem for bpf programs trigered by return uprobe created
over perf event.

Oleg pointed out other issues with uprobe_multi pid filter,
I plan to send another patchset for that.

thanks,
jirka


[1] https://lore.kernel.org/linux-trace-kernel/ME0P300MB0416034322B9915ECD3888649D882@ME0P300MB0416.AUSP300.PROD.OUTLOOK.COM/
---
Jiri Olsa (2):
      selftests/bpf: Add child argument to spawn_child function
      selftests/bpf: Add uprobe pid filter test for multiple processes

 tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c  | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------------------
 tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c |  61 ++++++++++++++++++++++++++++++
 2 files changed, 203 insertions(+), 46 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c

^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH bpf-next 1/2] selftests/bpf: Add child argument to spawn_child function
  2024-08-29 19:45 [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Jiri Olsa
@ 2024-08-29 19:45 ` Jiri Olsa
  2024-08-29 19:45 ` [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes Jiri Olsa
  2024-08-30 17:08 ` [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Stanislav Fomichev
  2 siblings, 0 replies; 5+ messages in thread
From: Jiri Olsa @ 2024-08-29 19:45 UTC (permalink / raw)
  To: Oleg Nesterov, Peter Zijlstra, Andrii Nakryiko, Tianyi Liu,
	Masami Hiramatsu
  Cc: bpf, Steven Rostedt, linux-kernel, linux-trace-kernel

Adding child argument to spawn_child function to allow
to create multiple children in following change.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../bpf/prog_tests/uprobe_multi_test.c        | 85 +++++++++----------
 1 file changed, 39 insertions(+), 46 deletions(-)

diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
index acb62675ff65..250eb47c68f9 100644
--- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
@@ -68,29 +68,27 @@ static void kick_child(struct child *child)
 	fflush(NULL);
 }
 
-static struct child *spawn_child(void)
+static int spawn_child(struct child *child)
 {
-	static struct child child;
-	int err;
-	int c;
+	int err, c;
 
 	/* pipe to notify child to execute the trigger functions */
-	if (pipe(child.go))
-		return NULL;
+	if (pipe(child->go))
+		return -1;
 
-	child.pid = child.tid = fork();
-	if (child.pid < 0) {
-		release_child(&child);
+	child->pid = child->tid = fork();
+	if (child->pid < 0) {
+		release_child(child);
 		errno = EINVAL;
-		return NULL;
+		return -1;
 	}
 
 	/* child */
-	if (child.pid == 0) {
-		close(child.go[1]);
+	if (child->pid == 0) {
+		close(child->go[1]);
 
 		/* wait for parent's kick */
-		err = read(child.go[0], &c, 1);
+		err = read(child->go[0], &c, 1);
 		if (err != 1)
 			exit(err);
 
@@ -102,7 +100,7 @@ static struct child *spawn_child(void)
 		exit(errno);
 	}
 
-	return &child;
+	return 0;
 }
 
 static void *child_thread(void *ctx)
@@ -131,39 +129,38 @@ static void *child_thread(void *ctx)
 	pthread_exit(&err);
 }
 
-static struct child *spawn_thread(void)
+static int spawn_thread(struct child *child)
 {
-	static struct child child;
 	int c, err;
 
 	/* pipe to notify child to execute the trigger functions */
-	if (pipe(child.go))
-		return NULL;
+	if (pipe(child->go))
+		return -1;
 	/* pipe to notify parent that child thread is ready */
-	if (pipe(child.c2p)) {
-		close(child.go[0]);
-		close(child.go[1]);
-		return NULL;
+	if (pipe(child->c2p)) {
+		close(child->go[0]);
+		close(child->go[1]);
+		return -1;
 	}
 
-	child.pid = getpid();
+	child->pid = getpid();
 
-	err = pthread_create(&child.thread, NULL, child_thread, &child);
+	err = pthread_create(&child->thread, NULL, child_thread, child);
 	if (err) {
 		err = -errno;
-		close(child.go[0]);
-		close(child.go[1]);
-		close(child.c2p[0]);
-		close(child.c2p[1]);
+		close(child->go[0]);
+		close(child->go[1]);
+		close(child->c2p[0]);
+		close(child->c2p[1]);
 		errno = -err;
-		return NULL;
+		return -1;
 	}
 
-	err = read(child.c2p[0], &c, 1);
+	err = read(child->c2p[0], &c, 1);
 	if (!ASSERT_EQ(err, 1, "child_thread_ready"))
-		return NULL;
+		return -1;
 
-	return &child;
+	return 0;
 }
 
 static void uprobe_multi_test_run(struct uprobe_multi *skel, struct child *child)
@@ -304,24 +301,22 @@ __test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_mul
 static void
 test_attach_api(const char *binary, const char *pattern, struct bpf_uprobe_multi_opts *opts)
 {
-	struct child *child;
+	static struct child child;
 
 	/* no pid filter */
 	__test_attach_api(binary, pattern, opts, NULL);
 
 	/* pid filter */
-	child = spawn_child();
-	if (!ASSERT_OK_PTR(child, "spawn_child"))
+	if (!ASSERT_OK(spawn_child(&child), "spawn_child"))
 		return;
 
-	__test_attach_api(binary, pattern, opts, child);
+	__test_attach_api(binary, pattern, opts, &child);
 
 	/* pid filter (thread) */
-	child = spawn_thread();
-	if (!ASSERT_OK_PTR(child, "spawn_thread"))
+	if (!ASSERT_OK(spawn_thread(&child), "spawn_thread"))
 		return;
 
-	__test_attach_api(binary, pattern, opts, child);
+	__test_attach_api(binary, pattern, opts, &child);
 }
 
 static void test_attach_api_pattern(void)
@@ -712,24 +707,22 @@ static void __test_link_api(struct child *child)
 
 static void test_link_api(void)
 {
-	struct child *child;
+	static struct child child;
 
 	/* no pid filter */
 	__test_link_api(NULL);
 
 	/* pid filter */
-	child = spawn_child();
-	if (!ASSERT_OK_PTR(child, "spawn_child"))
+	if (!ASSERT_OK(spawn_child(&child), "spawn_child"))
 		return;
 
-	__test_link_api(child);
+	__test_link_api(&child);
 
 	/* pid filter (thread) */
-	child = spawn_thread();
-	if (!ASSERT_OK_PTR(child, "spawn_thread"))
+	if (!ASSERT_OK(spawn_thread(&child), "spawn_thread"))
 		return;
 
-	__test_link_api(child);
+	__test_link_api(&child);
 }
 
 static struct bpf_program *
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes
  2024-08-29 19:45 [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Jiri Olsa
  2024-08-29 19:45 ` [PATCH bpf-next 1/2] selftests/bpf: Add child argument to spawn_child function Jiri Olsa
@ 2024-08-29 19:45 ` Jiri Olsa
  2024-08-30 20:51   ` Andrii Nakryiko
  2024-08-30 17:08 ` [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Stanislav Fomichev
  2 siblings, 1 reply; 5+ messages in thread
From: Jiri Olsa @ 2024-08-29 19:45 UTC (permalink / raw)
  To: Oleg Nesterov, Peter Zijlstra, Andrii Nakryiko, Tianyi Liu,
	Masami Hiramatsu
  Cc: bpf, Steven Rostedt, linux-kernel, linux-trace-kernel

The idea is to create and monitor 3 uprobes, each trigered in separate
process and make sure the bpf program gets executed just for the proper
PID specified via pid filter.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
---
 .../bpf/prog_tests/uprobe_multi_test.c        | 103 ++++++++++++++++++
 .../bpf/progs/uprobe_multi_pid_filter.c       |  61 +++++++++++
 2 files changed, 164 insertions(+)
 create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c

diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
index 250eb47c68f9..59c460675af9 100644
--- a/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c
@@ -7,6 +7,7 @@
 #include "uprobe_multi_bench.skel.h"
 #include "uprobe_multi_usdt.skel.h"
 #include "uprobe_multi_consumers.skel.h"
+#include "uprobe_multi_pid_filter.skel.h"
 #include "bpf/libbpf_internal.h"
 #include "testing_helpers.h"
 #include "../sdt.h"
@@ -935,6 +936,106 @@ static void test_consumers(void)
 	uprobe_multi_consumers__destroy(skel);
 }
 
+typedef struct bpf_link *(create_link_t)(struct uprobe_multi_pid_filter *, int, int, bool);
+
+static struct bpf_program *uprobe_program(struct uprobe_multi_pid_filter *skel, int idx)
+{
+	switch (idx) {
+	case 0: return skel->progs.uprobe_0;
+	case 1: return skel->progs.uprobe_1;
+	case 2: return skel->progs.uprobe_2;
+	}
+	return NULL;
+}
+
+static struct bpf_link *create_link_uprobe(struct uprobe_multi_pid_filter *skel,
+					   int idx, int pid, bool retprobe)
+{
+	LIBBPF_OPTS(bpf_uprobe_opts, opts,
+		.retprobe  = retprobe,
+		.func_name = "uprobe_multi_func_1",
+	);
+
+	return bpf_program__attach_uprobe_opts(uprobe_program(skel, idx), pid,
+					       "/proc/self/exe", 0, &opts);
+}
+
+static struct bpf_program *uprobe_multi_program(struct uprobe_multi_pid_filter *skel, int idx)
+{
+	switch (idx) {
+	case 0: return skel->progs.uprobe_multi_0;
+	case 1: return skel->progs.uprobe_multi_1;
+	case 2: return skel->progs.uprobe_multi_2;
+	}
+	return NULL;
+}
+
+static struct bpf_link *create_link_uprobe_multi(struct uprobe_multi_pid_filter *skel,
+						 int idx, int pid, bool retprobe)
+{
+	LIBBPF_OPTS(bpf_uprobe_multi_opts, opts, .retprobe = retprobe);
+
+	return bpf_program__attach_uprobe_multi(uprobe_multi_program(skel, idx), pid,
+						"/proc/self/exe", "uprobe_multi_func_1", &opts);
+}
+
+#define TASKS 3
+
+static void run_pid_filter(struct uprobe_multi_pid_filter *skel,
+			   create_link_t create_link, bool retprobe)
+{
+	struct bpf_link *link[TASKS] = {};
+	struct child child[TASKS] = {};
+	int i;
+
+	printf("%s retprobe %d\n", create_link == create_link_uprobe ? "uprobe" : "uprobe_multi",
+		retprobe);
+
+	memset(skel->bss->test, 0, sizeof(skel->bss->test));
+
+	for (i = 0; i < TASKS; i++) {
+		if (!ASSERT_OK(spawn_child(&child[i]), "spawn_child"))
+			goto cleanup;
+		skel->bss->pids[i] = child[i].pid;
+	}
+
+	for (i = 0; i < TASKS; i++) {
+		link[i] = create_link(skel, i, child[i].pid, retprobe);
+		if (!ASSERT_OK_PTR(link[i], "create_link"))
+			goto cleanup;
+	}
+
+	for (i = 0; i < TASKS; i++)
+		kick_child(&child[i]);
+
+	for (i = 0; i < TASKS; i++) {
+		ASSERT_EQ(skel->bss->test[i][0], 1, "pid");
+		ASSERT_EQ(skel->bss->test[i][1], 0, "unknown");
+	}
+
+cleanup:
+	for (i = 0; i < TASKS; i++)
+		bpf_link__destroy(link[i]);
+	for (i = 0; i < TASKS; i++)
+		release_child(&child[i]);
+}
+
+static void test_pid_filter_process(void)
+{
+	struct uprobe_multi_pid_filter *skel;
+
+	skel = uprobe_multi_pid_filter__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "uprobe_multi_pid_filter__open_and_load"))
+		return;
+
+	run_pid_filter(skel, create_link_uprobe, false);
+	run_pid_filter(skel, create_link_uprobe, true);
+	run_pid_filter(skel, create_link_uprobe_multi, false);
+	run_pid_filter(skel, create_link_uprobe_multi, true);
+
+	uprobe_multi_pid_filter__destroy(skel);
+}
+
 static void test_bench_attach_uprobe(void)
 {
 	long attach_start_ns = 0, attach_end_ns = 0;
@@ -1027,4 +1128,6 @@ void test_uprobe_multi_test(void)
 		test_attach_uprobe_fails();
 	if (test__start_subtest("consumers"))
 		test_consumers();
+	if (test__start_subtest("filter_process"))
+		test_pid_filter_process();
 }
diff --git a/tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c b/tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c
new file mode 100644
index 000000000000..260d46406e47
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c
@@ -0,0 +1,61 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+
+char _license[] SEC("license") = "GPL";
+
+__u32 pids[3];
+__u32 test[3][2];
+
+static void update_pid(int idx)
+{
+	__u32 pid = bpf_get_current_pid_tgid() >> 32;
+
+	if (pid == pids[idx])
+		test[idx][0]++;
+	else
+		test[idx][1]++;
+}
+
+SEC("uprobe.multi")
+int uprobe_multi_0(struct pt_regs *ctx)
+{
+	update_pid(0);
+	return 0;
+}
+
+SEC("uprobe.multi")
+int uprobe_multi_1(struct pt_regs *ctx)
+{
+	update_pid(1);
+	return 0;
+}
+
+SEC("uprobe.multi")
+int uprobe_multi_2(struct pt_regs *ctx)
+{
+	update_pid(2);
+	return 0;
+}
+
+SEC("uprobe")
+int uprobe_0(struct pt_regs *ctx)
+{
+	update_pid(0);
+	return 0;
+}
+
+SEC("uprobe")
+int uprobe_1(struct pt_regs *ctx)
+{
+	update_pid(1);
+	return 0;
+}
+
+SEC("uprobe")
+int uprobe_2(struct pt_regs *ctx)
+{
+	update_pid(2);
+	return 0;
+}
-- 
2.46.0


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test
  2024-08-29 19:45 [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Jiri Olsa
  2024-08-29 19:45 ` [PATCH bpf-next 1/2] selftests/bpf: Add child argument to spawn_child function Jiri Olsa
  2024-08-29 19:45 ` [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes Jiri Olsa
@ 2024-08-30 17:08 ` Stanislav Fomichev
  2 siblings, 0 replies; 5+ messages in thread
From: Stanislav Fomichev @ 2024-08-30 17:08 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Oleg Nesterov, Peter Zijlstra, Andrii Nakryiko, Tianyi Liu,
	Masami Hiramatsu, bpf, Steven Rostedt, linux-kernel,
	linux-trace-kernel

On 08/29, Jiri Olsa wrote:
> hi,
> in response to [1] patch, I'm adding bpf selftest that confirms the
> change fixes problem for bpf programs trigered by return uprobe created
> over perf event.
> 
> Oleg pointed out other issues with uprobe_multi pid filter,
> I plan to send another patchset for that.

Not sure whether Oleg or Andrii plan to take a look, but LGTM:

Acked-by: Stanislav Fomichev <sdf@fomichev.me>

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes
  2024-08-29 19:45 ` [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes Jiri Olsa
@ 2024-08-30 20:51   ` Andrii Nakryiko
  0 siblings, 0 replies; 5+ messages in thread
From: Andrii Nakryiko @ 2024-08-30 20:51 UTC (permalink / raw)
  To: Jiri Olsa
  Cc: Oleg Nesterov, Peter Zijlstra, Andrii Nakryiko, Tianyi Liu,
	Masami Hiramatsu, bpf, Steven Rostedt, linux-kernel,
	linux-trace-kernel

On Thu, Aug 29, 2024 at 12:45 PM Jiri Olsa <jolsa@kernel.org> wrote:
>
> The idea is to create and monitor 3 uprobes, each trigered in separate

typo: triggered

> process and make sure the bpf program gets executed just for the proper
> PID specified via pid filter.
>
> Signed-off-by: Jiri Olsa <jolsa@kernel.org>
> ---
>  .../bpf/prog_tests/uprobe_multi_test.c        | 103 ++++++++++++++++++
>  .../bpf/progs/uprobe_multi_pid_filter.c       |  61 +++++++++++
>  2 files changed, 164 insertions(+)
>  create mode 100644 tools/testing/selftests/bpf/progs/uprobe_multi_pid_filter.c
>

It's good to have a test, thanks for adding it! But we should couple
it with the fix in multi-uprobe and land together, right? I'm not
exactly sure why we can't just use task->signal-based check, but let's
try to converge on something and fix it.

pw-bot: cr

[...]

> +#define TASKS 3
> +
> +static void run_pid_filter(struct uprobe_multi_pid_filter *skel,
> +                          create_link_t create_link, bool retprobe)
> +{
> +       struct bpf_link *link[TASKS] = {};
> +       struct child child[TASKS] = {};
> +       int i;
> +
> +       printf("%s retprobe %d\n", create_link == create_link_uprobe ? "uprobe" : "uprobe_multi",
> +               retprobe);

leftovers

> +
> +       memset(skel->bss->test, 0, sizeof(skel->bss->test));
> +
> +       for (i = 0; i < TASKS; i++) {
> +               if (!ASSERT_OK(spawn_child(&child[i]), "spawn_child"))
> +                       goto cleanup;
> +               skel->bss->pids[i] = child[i].pid;
> +       }

[...]

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-08-30 20:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-08-29 19:45 [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Jiri Olsa
2024-08-29 19:45 ` [PATCH bpf-next 1/2] selftests/bpf: Add child argument to spawn_child function Jiri Olsa
2024-08-29 19:45 ` [PATCH bpf-next 2/2] selftests/bpf: Add uprobe pid filter test for multiple processes Jiri Olsa
2024-08-30 20:51   ` Andrii Nakryiko
2024-08-30 17:08 ` [PATCH bpf-next 0/2] selftests/bpf: Add uprobe pid filter test Stanislav Fomichev

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.