linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH bpf-next v2 0/3] libbpf: allow users to set kprobe/uprobe attach mode
@ 2023-02-20  8:47 menglong8.dong
  2023-02-20  8:47 ` [PATCH bpf-next v2 1/3] libbpf: add support " menglong8.dong
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: menglong8.dong @ 2023-02-20  8:47 UTC (permalink / raw)
  To: andrii.nakryiko, alan.maguire
  Cc: ast, daniel, andrii, martin.lau, song, yhs, john.fastabend,
	kpsingh, sdf, haoluo, jolsa, bpf, linux-kernel, Menglong Dong

From: Menglong Dong <imagedong@tencent.com>

By default, libbpf will attach the kprobe/uprobe eBPF program in the
latest mode that supported by kernel. In this series, we add the support
to let users manually attach kprobe/uprobe in legacy/perf/link mode in
the 1th patch.

And in the 2th patch, we split the testing 'attach_probe' into multi
subtests, as Andrii suggested.

In the 3th patch, we add the testings for loading kprobe/uprobe in
different mode.

Changes since v1:
- some small changes in the 1th patch, as Andrii suggested
- split 'attach_probe' into multi subtests

Menglong Dong (3):
  libbpf: add support to set kprobe/uprobe attach mode
  selftests/bpf: split test_attach_probe into multi subtests
  selftests/bpf: add test for legacy/perf kprobe/uprobe attach mode

 tools/lib/bpf/libbpf.c                        |  42 ++-
 tools/lib/bpf/libbpf.h                        |  31 +-
 .../selftests/bpf/prog_tests/attach_probe.c   | 283 ++++++++++++------
 .../bpf/progs/test_attach_kprobe_sleepable.c  |  23 ++
 .../selftests/bpf/progs/test_attach_probe.c   |  45 +--
 .../bpf/progs/test_attach_probe_manual.c      |  53 ++++
 6 files changed, 337 insertions(+), 140 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
 create mode 100644 tools/testing/selftests/bpf/progs/test_attach_probe_manual.c

-- 
2.39.0


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

* [PATCH bpf-next v2 1/3] libbpf: add support to set kprobe/uprobe attach mode
  2023-02-20  8:47 [PATCH bpf-next v2 0/3] libbpf: allow users to set kprobe/uprobe attach mode menglong8.dong
@ 2023-02-20  8:47 ` menglong8.dong
  2023-02-20  8:47 ` [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests menglong8.dong
  2023-02-20  8:47 ` [PATCH bpf-next v2 3/3] selftests/bpf: add test for legacy/perf kprobe/uprobe attach mode menglong8.dong
  2 siblings, 0 replies; 6+ messages in thread
From: menglong8.dong @ 2023-02-20  8:47 UTC (permalink / raw)
  To: andrii.nakryiko, alan.maguire
  Cc: ast, daniel, andrii, martin.lau, song, yhs, john.fastabend,
	kpsingh, sdf, haoluo, jolsa, bpf, linux-kernel, Menglong Dong

From: Menglong Dong <imagedong@tencent.com>

By default, libbpf will attach the kprobe/uprobe eBPF program in the
latest mode that supported by kernel. In this patch, we add the support
to let users manually attach kprobe/uprobe in legacy or perf mode.

There are 3 mode that supported by the kernel to attach kprobe/uprobe:

  LEGACY: create perf event in legacy way and don't use bpf_link
  PERF: create perf event with perf_event_open() and don't use bpf_link
  LINK: create perf event with perf_event_open() and use bpf_link

Users now can manually choose the mode with
bpf_program__attach_uprobe_opts()/bpf_program__attach_kprobe_opts().

Link: https://lore.kernel.org/bpf/20230113093427.1666466-1-imagedong@tencent.com/
Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
v2:
- rename no_link to force_ioctl_attach
- rename probe_mode to probe_attach_mode
- add more doc for probe_attach_mode
- return -ENOTSUP when necessray in bpf_program__attach_uprobe_opts and
  bpf_program__attach_kprobe_opts
---
 tools/lib/bpf/libbpf.c | 42 +++++++++++++++++++++++++++++++++++++++++-
 tools/lib/bpf/libbpf.h | 31 ++++++++++++++++++++++++++++---
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index 35a698eb825d..724ee5fab839 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -9747,7 +9747,7 @@ struct bpf_link *bpf_program__attach_perf_event_opts(const struct bpf_program *p
 	link->link.dealloc = &bpf_link_perf_dealloc;
 	link->perf_event_fd = pfd;
 
-	if (kernel_supports(prog->obj, FEAT_PERF_LINK)) {
+	if (kernel_supports(prog->obj, FEAT_PERF_LINK) && !opts->force_ioctl_attach) {
 		DECLARE_LIBBPF_OPTS(bpf_link_create_opts, link_opts,
 			.perf_event.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0));
 
@@ -10106,6 +10106,7 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog,
 				const struct bpf_kprobe_opts *opts)
 {
 	DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
+	enum probe_attach_mode attach_mode;
 	char errmsg[STRERR_BUFSIZE];
 	char *legacy_probe = NULL;
 	struct bpf_link *link;
@@ -10116,11 +10117,30 @@ bpf_program__attach_kprobe_opts(const struct bpf_program *prog,
 	if (!OPTS_VALID(opts, bpf_kprobe_opts))
 		return libbpf_err_ptr(-EINVAL);
 
+	attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT);
 	retprobe = OPTS_GET(opts, retprobe, false);
 	offset = OPTS_GET(opts, offset, 0);
 	pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
 
 	legacy = determine_kprobe_perf_type() < 0;
+	switch (attach_mode) {
+	case PROBE_ATTACH_MODE_LEGACY:
+		legacy = true;
+		pe_opts.force_ioctl_attach = true;
+		break;
+	case PROBE_ATTACH_MODE_PERF:
+		if (legacy)
+			return libbpf_err_ptr(-ENOTSUP);
+		pe_opts.force_ioctl_attach = true;
+		break;
+	case PROBE_ATTACH_MODE_LINK:
+		if (!kernel_supports(prog->obj, FEAT_PERF_LINK))
+			return libbpf_err_ptr(-ENOTSUP);
+		break;
+	default:
+		break;
+	}
+
 	if (!legacy) {
 		pfd = perf_event_open_probe(false /* uprobe */, retprobe,
 					    func_name, offset,
@@ -10774,6 +10794,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
 {
 	DECLARE_LIBBPF_OPTS(bpf_perf_event_opts, pe_opts);
 	char errmsg[STRERR_BUFSIZE], *legacy_probe = NULL;
+	enum probe_attach_mode attach_mode;
 	char full_binary_path[PATH_MAX];
 	struct bpf_link *link;
 	size_t ref_ctr_off;
@@ -10784,6 +10805,7 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
 	if (!OPTS_VALID(opts, bpf_uprobe_opts))
 		return libbpf_err_ptr(-EINVAL);
 
+	attach_mode = OPTS_GET(opts, attach_mode, PROBE_ATTACH_MODE_DEFAULT);
 	retprobe = OPTS_GET(opts, retprobe, false);
 	ref_ctr_off = OPTS_GET(opts, ref_ctr_offset, 0);
 	pe_opts.bpf_cookie = OPTS_GET(opts, bpf_cookie, 0);
@@ -10812,6 +10834,24 @@ bpf_program__attach_uprobe_opts(const struct bpf_program *prog, pid_t pid,
 	}
 
 	legacy = determine_uprobe_perf_type() < 0;
+	switch (attach_mode) {
+	case PROBE_ATTACH_MODE_LEGACY:
+		legacy = true;
+		pe_opts.force_ioctl_attach = true;
+		break;
+	case PROBE_ATTACH_MODE_PERF:
+		if (legacy)
+			return libbpf_err_ptr(-ENOTSUP);
+		pe_opts.force_ioctl_attach = true;
+		break;
+	case PROBE_ATTACH_MODE_LINK:
+		if (!kernel_supports(prog->obj, FEAT_PERF_LINK))
+			return libbpf_err_ptr(-ENOTSUP);
+		break;
+	default:
+		break;
+	}
+
 	if (!legacy) {
 		pfd = perf_event_open_probe(true /* uprobe */, retprobe, binary_path,
 					    func_offset, pid, ref_ctr_off);
diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h
index 2efd80f6f7b9..ef8f68da42f9 100644
--- a/tools/lib/bpf/libbpf.h
+++ b/tools/lib/bpf/libbpf.h
@@ -451,8 +451,11 @@ struct bpf_perf_event_opts {
 	size_t sz;
 	/* custom user-provided value fetchable through bpf_get_attach_cookie() */
 	__u64 bpf_cookie;
+	/* don't use bpf_link when attach eBPF program */
+	bool force_ioctl_attach;
+	size_t :0;
 };
-#define bpf_perf_event_opts__last_field bpf_cookie
+#define bpf_perf_event_opts__last_field force_ioctl_attach
 
 LIBBPF_API struct bpf_link *
 bpf_program__attach_perf_event(const struct bpf_program *prog, int pfd);
@@ -461,6 +464,24 @@ LIBBPF_API struct bpf_link *
 bpf_program__attach_perf_event_opts(const struct bpf_program *prog, int pfd,
 				    const struct bpf_perf_event_opts *opts);
 
+
+/**
+ * enum probe_attach_mode - the mode to attach kprobe/uprobe
+ *
+ * force libbpf to attach kprobe/uprobe in specific mode, -ENOTSUP will
+ * be returned if it is not supported by the kernel.
+ */
+enum probe_attach_mode {
+	/* attach probe in latest supported mode by kernel */
+	PROBE_ATTACH_MODE_DEFAULT = 0,
+	/* attach probe in legacy mode */
+	PROBE_ATTACH_MODE_LEGACY,
+	/* create perf event with perf_event_open() syscall */
+	PROBE_ATTACH_MODE_PERF,
+	/* attach probe with bpf_link */
+	PROBE_ATTACH_MODE_LINK,
+};
+
 struct bpf_kprobe_opts {
 	/* size of this struct, for forward/backward compatiblity */
 	size_t sz;
@@ -470,9 +491,11 @@ struct bpf_kprobe_opts {
 	size_t offset;
 	/* kprobe is return probe */
 	bool retprobe;
+	/* kprobe attach mode */
+	enum probe_attach_mode attach_mode;
 	size_t :0;
 };
-#define bpf_kprobe_opts__last_field retprobe
+#define bpf_kprobe_opts__last_field attach_mode
 
 LIBBPF_API struct bpf_link *
 bpf_program__attach_kprobe(const struct bpf_program *prog, bool retprobe,
@@ -570,9 +593,11 @@ struct bpf_uprobe_opts {
 	 * binary_path.
 	 */
 	const char *func_name;
+	/* uprobe attach mode */
+	enum probe_attach_mode attach_mode;
 	size_t :0;
 };
-#define bpf_uprobe_opts__last_field func_name
+#define bpf_uprobe_opts__last_field attach_mode
 
 /**
  * @brief **bpf_program__attach_uprobe()** attaches a BPF program
-- 
2.39.0


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

* [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests
  2023-02-20  8:47 [PATCH bpf-next v2 0/3] libbpf: allow users to set kprobe/uprobe attach mode menglong8.dong
  2023-02-20  8:47 ` [PATCH bpf-next v2 1/3] libbpf: add support " menglong8.dong
@ 2023-02-20  8:47 ` menglong8.dong
  2023-02-20 11:40   ` Alan Maguire
  2023-02-20  8:47 ` [PATCH bpf-next v2 3/3] selftests/bpf: add test for legacy/perf kprobe/uprobe attach mode menglong8.dong
  2 siblings, 1 reply; 6+ messages in thread
From: menglong8.dong @ 2023-02-20  8:47 UTC (permalink / raw)
  To: andrii.nakryiko, alan.maguire
  Cc: ast, daniel, andrii, martin.lau, song, yhs, john.fastabend,
	kpsingh, sdf, haoluo, jolsa, bpf, linux-kernel, Menglong Dong

From: Menglong Dong <imagedong@tencent.com>

In order to adapt to the older kernel, now we split the "attach_probe"
testing into multi subtests:

  manual // manual attach tests for kprobe/uprobe
  auto // auto-attach tests for kprobe and uprobe
  kprobe-sleepable // kprobe sleepable test
  uprobe-lib // uprobe tests for library function by name
  uprobe-sleepabel // uprobe sleepable test
  uprobe-ref_ctr // uprobe ref_ctr test

As sleepable kprobe needs to set BPF_F_SLEEPABLE flag before loading,
we need to move it to a stand alone skel file, in case of it is not
supported by kernel and make the whole loading fail.

Therefore, we can only enable part of the subtests for older kernel.

Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 .../selftests/bpf/prog_tests/attach_probe.c   | 268 +++++++++++-------
 .../bpf/progs/test_attach_kprobe_sleepable.c  |  23 ++
 .../selftests/bpf/progs/test_attach_probe.c   |  23 +-
 3 files changed, 208 insertions(+), 106 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c

diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
index 56374c8b5436..9824a5eb8595 100644
--- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
+++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
@@ -1,5 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <test_progs.h>
+#include "test_attach_kprobe_sleepable.skel.h"
 #include "test_attach_probe.skel.h"
 
 /* this is how USDT semaphore is actually defined, except volatile modifier */
@@ -23,110 +24,63 @@ static noinline void trigger_func3(void)
 	asm volatile ("");
 }
 
+/* attach point for ref_ctr */
+static noinline void trigger_func4(void)
+{
+	asm volatile ("");
+}
+
 static char test_data[] = "test_data";
 
-void test_attach_probe(void)
+/* manual attach kprobe/kretprobe/uprobe/uretprobe testings */
+static void test_attach_probe_manual(struct test_attach_probe *skel)
 {
 	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
 	struct bpf_link *kprobe_link, *kretprobe_link;
 	struct bpf_link *uprobe_link, *uretprobe_link;
-	struct test_attach_probe* skel;
-	ssize_t uprobe_offset, ref_ctr_offset;
-	struct bpf_link *uprobe_err_link;
-	FILE *devnull;
-	bool legacy;
-
-	/* Check if new-style kprobe/uprobe API is supported.
-	 * Kernels that support new FD-based kprobe and uprobe BPF attachment
-	 * through perf_event_open() syscall expose
-	 * /sys/bus/event_source/devices/kprobe/type and
-	 * /sys/bus/event_source/devices/uprobe/type files, respectively. They
-	 * contain magic numbers that are passed as "type" field of
-	 * perf_event_attr. Lack of such file in the system indicates legacy
-	 * kernel with old-style kprobe/uprobe attach interface through
-	 * creating per-probe event through tracefs. For such cases
-	 * ref_ctr_offset feature is not supported, so we don't test it.
-	 */
-	legacy = access("/sys/bus/event_source/devices/kprobe/type", F_OK) != 0;
+	ssize_t uprobe_offset;
 
 	uprobe_offset = get_uprobe_offset(&trigger_func);
 	if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset"))
 		return;
 
-	ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
-	if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
-		return;
-
-	skel = test_attach_probe__open();
-	if (!ASSERT_OK_PTR(skel, "skel_open"))
-		return;
-
-	/* sleepable kprobe test case needs flags set before loading */
-	if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
-		BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
-		goto cleanup;
-
-	if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
-		goto cleanup;
-	if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
-		goto cleanup;
-
 	/* manual-attach kprobe/kretprobe */
 	kprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kprobe,
 						 false /* retprobe */,
 						 SYS_NANOSLEEP_KPROBE_NAME);
 	if (!ASSERT_OK_PTR(kprobe_link, "attach_kprobe"))
-		goto cleanup;
+		return;
 	skel->links.handle_kprobe = kprobe_link;
 
 	kretprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kretprobe,
 						    true /* retprobe */,
 						    SYS_NANOSLEEP_KPROBE_NAME);
 	if (!ASSERT_OK_PTR(kretprobe_link, "attach_kretprobe"))
-		goto cleanup;
+		return;
 	skel->links.handle_kretprobe = kretprobe_link;
 
-	/* auto-attachable kprobe and kretprobe */
-	skel->links.handle_kprobe_auto = bpf_program__attach(skel->progs.handle_kprobe_auto);
-	ASSERT_OK_PTR(skel->links.handle_kprobe_auto, "attach_kprobe_auto");
-
-	skel->links.handle_kretprobe_auto = bpf_program__attach(skel->progs.handle_kretprobe_auto);
-	ASSERT_OK_PTR(skel->links.handle_kretprobe_auto, "attach_kretprobe_auto");
-
-	if (!legacy)
-		ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
-
+	/* manual-attach uprobe/uretprobe */
+	uprobe_opts.ref_ctr_offset = 0;
 	uprobe_opts.retprobe = false;
-	uprobe_opts.ref_ctr_offset = legacy ? 0 : ref_ctr_offset;
 	uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe,
 						      0 /* self pid */,
 						      "/proc/self/exe",
 						      uprobe_offset,
 						      &uprobe_opts);
 	if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe"))
-		goto cleanup;
+		return;
 	skel->links.handle_uprobe = uprobe_link;
 
-	if (!legacy)
-		ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
-
-	/* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
 	uprobe_opts.retprobe = true;
-	uprobe_opts.ref_ctr_offset = legacy ? 0 : ref_ctr_offset;
 	uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe,
 							 -1 /* any pid */,
 							 "/proc/self/exe",
 							 uprobe_offset, &uprobe_opts);
 	if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe"))
-		goto cleanup;
+		return;
 	skel->links.handle_uretprobe = uretprobe_link;
 
-	/* verify auto-attach fails for old-style uprobe definition */
-	uprobe_err_link = bpf_program__attach(skel->progs.handle_uprobe_byname);
-	if (!ASSERT_EQ(libbpf_get_error(uprobe_err_link), -EOPNOTSUPP,
-		       "auto-attach should fail for old-style name"))
-		goto cleanup;
-
+	/* attach uprobe by function name manually */
 	uprobe_opts.func_name = "trigger_func2";
 	uprobe_opts.retprobe = false;
 	uprobe_opts.ref_ctr_offset = 0;
@@ -136,13 +90,62 @@ void test_attach_probe(void)
 							"/proc/self/exe",
 							0, &uprobe_opts);
 	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname, "attach_uprobe_byname"))
-		goto cleanup;
+		return;
+
+	/* trigger & validate kprobe && kretprobe */
+	usleep(1);
+
+	/* trigger & validate uprobe & uretprobe */
+	trigger_func();
+
+	/* trigger & validate uprobe attached by name */
+	trigger_func2();
+
+	ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
+	ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
+	ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
+	ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
+	ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
+}
+
+static void test_attach_probe_auto(struct test_attach_probe *skel)
+{
+	struct bpf_link *uprobe_err_link;
+
+	/* auto-attachable kprobe and kretprobe */
+	skel->links.handle_kprobe_auto = bpf_program__attach(skel->progs.handle_kprobe_auto);
+	ASSERT_OK_PTR(skel->links.handle_kprobe_auto, "attach_kprobe_auto");
+
+	skel->links.handle_kretprobe_auto = bpf_program__attach(skel->progs.handle_kretprobe_auto);
+	ASSERT_OK_PTR(skel->links.handle_kretprobe_auto, "attach_kretprobe_auto");
+
+	/* verify auto-attach fails for old-style uprobe definition */
+	uprobe_err_link = bpf_program__attach(skel->progs.handle_uprobe_byname);
+	if (!ASSERT_EQ(libbpf_get_error(uprobe_err_link), -EOPNOTSUPP,
+		       "auto-attach should fail for old-style name"))
+		return;
 
 	/* verify auto-attach works */
 	skel->links.handle_uretprobe_byname =
 			bpf_program__attach(skel->progs.handle_uretprobe_byname);
 	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname, "attach_uretprobe_byname"))
-		goto cleanup;
+		return;
+
+	/* trigger & validate kprobe && kretprobe */
+	usleep(1);
+
+	/* trigger & validate uprobe attached by name */
+	trigger_func2();
+
+	ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
+	ASSERT_EQ(skel->bss->kretprobe2_res, 22, "check_kretprobe_auto_res");
+	ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
+}
+
+static void test_uprobe_lib(struct test_attach_probe *skel)
+{
+	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
+	FILE *devnull;
 
 	/* test attach by name for a library function, using the library
 	 * as the binary argument. libc.so.6 will be resolved via dlopen()/dlinfo().
@@ -155,7 +158,7 @@ void test_attach_probe(void)
 							"libc.so.6",
 							0, &uprobe_opts);
 	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname2, "attach_uprobe_byname2"))
-		goto cleanup;
+		return;
 
 	uprobe_opts.func_name = "fclose";
 	uprobe_opts.retprobe = true;
@@ -165,62 +168,137 @@ void test_attach_probe(void)
 							"libc.so.6",
 							0, &uprobe_opts);
 	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname2, "attach_uretprobe_byname2"))
+		return;
+
+	/* trigger & validate shared library u[ret]probes attached by name */
+	devnull = fopen("/dev/null", "r");
+	fclose(devnull);
+
+	ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
+	ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
+}
+
+static void test_uporbe_ref_ctr(struct test_attach_probe *skel)
+{
+	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
+	struct bpf_link *uprobe_link, *uretprobe_link;
+	ssize_t uprobe_offset, ref_ctr_offset;
+
+	uprobe_offset = get_uprobe_offset(&trigger_func4);
+	if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset_ref_ctr"))
+		return;
+
+	ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
+	if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
+		return;
+
+	ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
+
+	uprobe_opts.retprobe = false;
+	uprobe_opts.ref_ctr_offset = ref_ctr_offset;
+	uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe_ref_ctr,
+						      0 /* self pid */,
+						      "/proc/self/exe",
+						      uprobe_offset,
+						      &uprobe_opts);
+	if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe_ref_ctr"))
+		return;
+	skel->links.handle_uprobe_ref_ctr = uprobe_link;
+
+	ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
+
+	/* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
+	uprobe_opts.retprobe = true;
+	uprobe_opts.ref_ctr_offset = ref_ctr_offset;
+	uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe_ref_ctr,
+							 -1 /* any pid */,
+							 "/proc/self/exe",
+							 uprobe_offset, &uprobe_opts);
+	if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe_ref_ctr"))
+		return;
+	skel->links.handle_uretprobe_ref_ctr = uretprobe_link;
+}
+
+static void test_kprobe_sleepable(void)
+{
+	struct test_attach_kprobe_sleepable *skel;
+
+	skel = test_attach_kprobe_sleepable__open();
+	if (!ASSERT_OK_PTR(skel, "skel_kprobe_sleepable_open"))
+		return;
+
+	/* sleepable kprobe test case needs flags set before loading */
+	if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
+		BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
+		goto cleanup;
+
+	if (!ASSERT_OK(test_attach_kprobe_sleepable__load(skel),
+		       "skel_kprobe_sleepable_load"))
 		goto cleanup;
 
 	/* sleepable kprobes should not attach successfully */
 	skel->links.handle_kprobe_sleepable = bpf_program__attach(skel->progs.handle_kprobe_sleepable);
-	if (!ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable"))
-		goto cleanup;
+	ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable");
+
+cleanup:
+	test_attach_kprobe_sleepable__destroy(skel);
+}
 
+static void test_uprobe_sleepable(struct test_attach_probe *skel)
+{
 	/* test sleepable uprobe and uretprobe variants */
 	skel->links.handle_uprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uprobe_byname3_sleepable);
 	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3_sleepable, "attach_uprobe_byname3_sleepable"))
-		goto cleanup;
+		return;
 
 	skel->links.handle_uprobe_byname3 = bpf_program__attach(skel->progs.handle_uprobe_byname3);
 	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3, "attach_uprobe_byname3"))
-		goto cleanup;
+		return;
 
 	skel->links.handle_uretprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uretprobe_byname3_sleepable);
 	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3_sleepable, "attach_uretprobe_byname3_sleepable"))
-		goto cleanup;
+		return;
 
 	skel->links.handle_uretprobe_byname3 = bpf_program__attach(skel->progs.handle_uretprobe_byname3);
 	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3, "attach_uretprobe_byname3"))
-		goto cleanup;
+		return;
 
 	skel->bss->user_ptr = test_data;
 
-	/* trigger & validate kprobe && kretprobe */
-	usleep(1);
-
-	/* trigger & validate shared library u[ret]probes attached by name */
-	devnull = fopen("/dev/null", "r");
-	fclose(devnull);
-
-	/* trigger & validate uprobe & uretprobe */
-	trigger_func();
-
-	/* trigger & validate uprobe attached by name */
-	trigger_func2();
-
 	/* trigger & validate sleepable uprobe attached by name */
 	trigger_func3();
 
-	ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
-	ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
-	ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
-	ASSERT_EQ(skel->bss->kretprobe2_res, 22, "check_kretprobe_auto_res");
-	ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
-	ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
-	ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
-	ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
-	ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
-	ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
 	ASSERT_EQ(skel->bss->uprobe_byname3_sleepable_res, 9, "check_uprobe_byname3_sleepable_res");
 	ASSERT_EQ(skel->bss->uprobe_byname3_res, 10, "check_uprobe_byname3_res");
 	ASSERT_EQ(skel->bss->uretprobe_byname3_sleepable_res, 11, "check_uretprobe_byname3_sleepable_res");
 	ASSERT_EQ(skel->bss->uretprobe_byname3_res, 12, "check_uretprobe_byname3_res");
+}
+
+void test_attach_probe(void)
+{
+	struct test_attach_probe *skel;
+
+	skel = test_attach_probe__open();
+	if (!ASSERT_OK_PTR(skel, "skel_open"))
+		return;
+
+	if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
+		goto cleanup;
+	if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
+		goto cleanup;
+
+	if (test__start_subtest("manual"))
+		test_attach_probe_manual(skel);
+	if (test__start_subtest("auto"))
+		test_attach_probe_auto(skel);
+	if (test__start_subtest("kprobe-sleepable"))
+		test_kprobe_sleepable();
+	if (test__start_subtest("uprobe-lib"))
+		test_uprobe_lib(skel);
+	if (test__start_subtest("uprobe-sleepable"))
+		test_uprobe_sleepable(skel);
+	if (test__start_subtest("uprobe-ref_ctr"))
+		test_uporbe_ref_ctr(skel);
 
 cleanup:
 	test_attach_probe__destroy(skel);
diff --git a/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c b/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
new file mode 100644
index 000000000000..f548b7446218
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017 Facebook
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include "bpf_misc.h"
+
+int kprobe_res = 0;
+
+/**
+ * This program will be manually made sleepable on the userspace side
+ * and should thus be unattachable.
+ */
+SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
+int handle_kprobe_sleepable(struct pt_regs *ctx)
+{
+	kprobe_res = 1;
+	return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_attach_probe.c b/tools/testing/selftests/bpf/progs/test_attach_probe.c
index 3b5dc34d23e9..9e1e7163bb67 100644
--- a/tools/testing/selftests/bpf/progs/test_attach_probe.c
+++ b/tools/testing/selftests/bpf/progs/test_attach_probe.c
@@ -37,17 +37,6 @@ int BPF_KSYSCALL(handle_kprobe_auto, struct __kernel_timespec *req, struct __ker
 	return 0;
 }
 
-/**
- * This program will be manually made sleepable on the userspace side
- * and should thus be unattachable.
- */
-SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
-int handle_kprobe_sleepable(struct pt_regs *ctx)
-{
-	kprobe_res = 2;
-	return 0;
-}
-
 SEC("kretprobe")
 int handle_kretprobe(struct pt_regs *ctx)
 {
@@ -76,6 +65,18 @@ int handle_uretprobe(struct pt_regs *ctx)
 	return 0;
 }
 
+SEC("uprobe")
+int handle_uprobe_ref_ctr(struct pt_regs *ctx)
+{
+	return 0;
+}
+
+SEC("uretprobe")
+int handle_uretprobe_ref_ctr(struct pt_regs *ctx)
+{
+	return 0;
+}
+
 SEC("uprobe")
 int handle_uprobe_byname(struct pt_regs *ctx)
 {
-- 
2.39.0


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

* [PATCH bpf-next v2 3/3] selftests/bpf: add test for legacy/perf kprobe/uprobe attach mode
  2023-02-20  8:47 [PATCH bpf-next v2 0/3] libbpf: allow users to set kprobe/uprobe attach mode menglong8.dong
  2023-02-20  8:47 ` [PATCH bpf-next v2 1/3] libbpf: add support " menglong8.dong
  2023-02-20  8:47 ` [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests menglong8.dong
@ 2023-02-20  8:47 ` menglong8.dong
  2 siblings, 0 replies; 6+ messages in thread
From: menglong8.dong @ 2023-02-20  8:47 UTC (permalink / raw)
  To: andrii.nakryiko, alan.maguire
  Cc: ast, daniel, andrii, martin.lau, song, yhs, john.fastabend,
	kpsingh, sdf, haoluo, jolsa, bpf, linux-kernel, Menglong Dong

From: Menglong Dong <imagedong@tencent.com>

Add the testing for kprobe/uprobe attaching in default, legacy, perf and
link mode. And the testing passed:

./test_progs -t attach_probe
$5/1     attach_probe/manual-default:OK
$5/2     attach_probe/manual-legacy:OK
$5/3     attach_probe/manual-perf:OK
$5/4     attach_probe/manual-link:OK
$5/5     attach_probe/auto:OK
$5/6     attach_probe/kprobe-sleepable:OK
$5/7     attach_probe/uprobe-lib:OK
$5/8     attach_probe/uprobe-sleepable:OK
$5/9     attach_probe/uprobe-ref_ctr:OK
$5       attach_probe:OK
Summary: 1/9 PASSED, 0 SKIPPED, 0 FAILED

Signed-off-by: Menglong Dong <imagedong@tencent.com>
---
 .../selftests/bpf/prog_tests/attach_probe.c   | 54 ++++++++++++++-----
 .../selftests/bpf/progs/test_attach_probe.c   | 32 -----------
 .../bpf/progs/test_attach_probe_manual.c      | 53 ++++++++++++++++++
 3 files changed, 93 insertions(+), 46 deletions(-)
 create mode 100644 tools/testing/selftests/bpf/progs/test_attach_probe_manual.c

diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
index 9824a5eb8595..54868af49b5e 100644
--- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
+++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
@@ -1,6 +1,7 @@
 // SPDX-License-Identifier: GPL-2.0
 #include <test_progs.h>
 #include "test_attach_kprobe_sleepable.skel.h"
+#include "test_attach_probe_manual.skel.h"
 #include "test_attach_probe.skel.h"
 
 /* this is how USDT semaphore is actually defined, except volatile modifier */
@@ -33,33 +34,48 @@ static noinline void trigger_func4(void)
 static char test_data[] = "test_data";
 
 /* manual attach kprobe/kretprobe/uprobe/uretprobe testings */
-static void test_attach_probe_manual(struct test_attach_probe *skel)
+static void test_attach_probe_manual(enum probe_attach_mode attach_mode)
 {
 	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
+	DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, kprobe_opts);
 	struct bpf_link *kprobe_link, *kretprobe_link;
 	struct bpf_link *uprobe_link, *uretprobe_link;
+	struct test_attach_probe_manual *skel;
 	ssize_t uprobe_offset;
 
+	skel = test_attach_probe_manual__open();
+	if (!ASSERT_OK_PTR(skel, "skel_kprobe_manual_open"))
+		return;
+
+	if (!ASSERT_OK(test_attach_probe_manual__load(skel), "skel_manual_load"))
+		goto cleanup;
+	if (!ASSERT_OK_PTR(skel->bss, "manual_check_bss"))
+		goto cleanup;
+
 	uprobe_offset = get_uprobe_offset(&trigger_func);
 	if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset"))
-		return;
+		goto cleanup;
 
 	/* manual-attach kprobe/kretprobe */
-	kprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kprobe,
-						 false /* retprobe */,
-						 SYS_NANOSLEEP_KPROBE_NAME);
+	kprobe_opts.attach_mode = attach_mode;
+	kprobe_opts.retprobe = false;
+	kprobe_link = bpf_program__attach_kprobe_opts(skel->progs.handle_kprobe,
+						      SYS_NANOSLEEP_KPROBE_NAME,
+						      &kprobe_opts);
 	if (!ASSERT_OK_PTR(kprobe_link, "attach_kprobe"))
-		return;
+		goto cleanup;
 	skel->links.handle_kprobe = kprobe_link;
 
-	kretprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kretprobe,
-						    true /* retprobe */,
-						    SYS_NANOSLEEP_KPROBE_NAME);
+	kprobe_opts.retprobe = true;
+	kretprobe_link = bpf_program__attach_kprobe_opts(skel->progs.handle_kretprobe,
+							 SYS_NANOSLEEP_KPROBE_NAME,
+							 &kprobe_opts);
 	if (!ASSERT_OK_PTR(kretprobe_link, "attach_kretprobe"))
-		return;
+		goto cleanup;
 	skel->links.handle_kretprobe = kretprobe_link;
 
 	/* manual-attach uprobe/uretprobe */
+	uprobe_opts.attach_mode = attach_mode;
 	uprobe_opts.ref_ctr_offset = 0;
 	uprobe_opts.retprobe = false;
 	uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe,
@@ -68,7 +84,7 @@ static void test_attach_probe_manual(struct test_attach_probe *skel)
 						      uprobe_offset,
 						      &uprobe_opts);
 	if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe"))
-		return;
+		goto cleanup;
 	skel->links.handle_uprobe = uprobe_link;
 
 	uprobe_opts.retprobe = true;
@@ -77,7 +93,7 @@ static void test_attach_probe_manual(struct test_attach_probe *skel)
 							 "/proc/self/exe",
 							 uprobe_offset, &uprobe_opts);
 	if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe"))
-		return;
+		goto cleanup;
 	skel->links.handle_uretprobe = uretprobe_link;
 
 	/* attach uprobe by function name manually */
@@ -106,6 +122,9 @@ static void test_attach_probe_manual(struct test_attach_probe *skel)
 	ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
 	ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
 	ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
+
+cleanup:
+	test_attach_probe_manual__destroy(skel);
 }
 
 static void test_attach_probe_auto(struct test_attach_probe *skel)
@@ -287,8 +306,15 @@ void test_attach_probe(void)
 	if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
 		goto cleanup;
 
-	if (test__start_subtest("manual"))
-		test_attach_probe_manual(skel);
+	if (test__start_subtest("manual-default"))
+		test_attach_probe_manual(PROBE_ATTACH_MODE_DEFAULT);
+	if (test__start_subtest("manual-legacy"))
+		test_attach_probe_manual(PROBE_ATTACH_MODE_LEGACY);
+	if (test__start_subtest("manual-perf"))
+		test_attach_probe_manual(PROBE_ATTACH_MODE_PERF);
+	if (test__start_subtest("manual-link"))
+		test_attach_probe_manual(PROBE_ATTACH_MODE_LINK);
+
 	if (test__start_subtest("auto"))
 		test_attach_probe_auto(skel);
 	if (test__start_subtest("kprobe-sleepable"))
diff --git a/tools/testing/selftests/bpf/progs/test_attach_probe.c b/tools/testing/selftests/bpf/progs/test_attach_probe.c
index 9e1e7163bb67..68466a6ad18c 100644
--- a/tools/testing/selftests/bpf/progs/test_attach_probe.c
+++ b/tools/testing/selftests/bpf/progs/test_attach_probe.c
@@ -7,12 +7,8 @@
 #include <bpf/bpf_core_read.h>
 #include "bpf_misc.h"
 
-int kprobe_res = 0;
 int kprobe2_res = 0;
-int kretprobe_res = 0;
 int kretprobe2_res = 0;
-int uprobe_res = 0;
-int uretprobe_res = 0;
 int uprobe_byname_res = 0;
 int uretprobe_byname_res = 0;
 int uprobe_byname2_res = 0;
@@ -23,13 +19,6 @@ int uretprobe_byname3_sleepable_res = 0;
 int uretprobe_byname3_res = 0;
 void *user_ptr = 0;
 
-SEC("kprobe")
-int handle_kprobe(struct pt_regs *ctx)
-{
-	kprobe_res = 1;
-	return 0;
-}
-
 SEC("ksyscall/nanosleep")
 int BPF_KSYSCALL(handle_kprobe_auto, struct __kernel_timespec *req, struct __kernel_timespec *rem)
 {
@@ -37,13 +26,6 @@ int BPF_KSYSCALL(handle_kprobe_auto, struct __kernel_timespec *req, struct __ker
 	return 0;
 }
 
-SEC("kretprobe")
-int handle_kretprobe(struct pt_regs *ctx)
-{
-	kretprobe_res = 2;
-	return 0;
-}
-
 SEC("kretsyscall/nanosleep")
 int BPF_KRETPROBE(handle_kretprobe_auto, int ret)
 {
@@ -51,20 +33,6 @@ int BPF_KRETPROBE(handle_kretprobe_auto, int ret)
 	return ret;
 }
 
-SEC("uprobe")
-int handle_uprobe(struct pt_regs *ctx)
-{
-	uprobe_res = 3;
-	return 0;
-}
-
-SEC("uretprobe")
-int handle_uretprobe(struct pt_regs *ctx)
-{
-	uretprobe_res = 4;
-	return 0;
-}
-
 SEC("uprobe")
 int handle_uprobe_ref_ctr(struct pt_regs *ctx)
 {
diff --git a/tools/testing/selftests/bpf/progs/test_attach_probe_manual.c b/tools/testing/selftests/bpf/progs/test_attach_probe_manual.c
new file mode 100644
index 000000000000..7f08bce94596
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_attach_probe_manual.c
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2017 Facebook
+
+#include "vmlinux.h"
+#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_tracing.h>
+#include <bpf/bpf_core_read.h>
+#include "bpf_misc.h"
+
+int kprobe_res = 0;
+int kretprobe_res = 0;
+int uprobe_res = 0;
+int uretprobe_res = 0;
+int uprobe_byname_res = 0;
+void *user_ptr = 0;
+
+SEC("kprobe")
+int handle_kprobe(struct pt_regs *ctx)
+{
+	kprobe_res = 1;
+	return 0;
+}
+
+SEC("kretprobe")
+int handle_kretprobe(struct pt_regs *ctx)
+{
+	kretprobe_res = 2;
+	return 0;
+}
+
+SEC("uprobe")
+int handle_uprobe(struct pt_regs *ctx)
+{
+	uprobe_res = 3;
+	return 0;
+}
+
+SEC("uretprobe")
+int handle_uretprobe(struct pt_regs *ctx)
+{
+	uretprobe_res = 4;
+	return 0;
+}
+
+SEC("uprobe")
+int handle_uprobe_byname(struct pt_regs *ctx)
+{
+	uprobe_byname_res = 5;
+	return 0;
+}
+
+
+char _license[] SEC("license") = "GPL";
-- 
2.39.0


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

* Re: [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests
  2023-02-20  8:47 ` [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests menglong8.dong
@ 2023-02-20 11:40   ` Alan Maguire
  2023-02-21  2:19     ` Menglong Dong
  0 siblings, 1 reply; 6+ messages in thread
From: Alan Maguire @ 2023-02-20 11:40 UTC (permalink / raw)
  To: menglong8.dong, andrii.nakryiko
  Cc: ast, daniel, andrii, martin.lau, song, yhs, john.fastabend,
	kpsingh, sdf, haoluo, jolsa, bpf, linux-kernel, Menglong Dong

On 20/02/2023 08:47, menglong8.dong@gmail.com wrote:
> From: Menglong Dong <imagedong@tencent.com>
> 
> In order to adapt to the older kernel, now we split the "attach_probe"
> testing into multi subtests:
> 
>   manual // manual attach tests for kprobe/uprobe
>   auto // auto-attach tests for kprobe and uprobe
>   kprobe-sleepable // kprobe sleepable test
>   uprobe-lib // uprobe tests for library function by name
>   uprobe-sleepabel // uprobe sleepable test
>   uprobe-ref_ctr // uprobe ref_ctr test
> 
> As sleepable kprobe needs to set BPF_F_SLEEPABLE flag before loading,
> we need to move it to a stand alone skel file, in case of it is not
> supported by kernel and make the whole loading fail.
> 
> Therefore, we can only enable part of the subtests for older kernel.
> 
> Signed-off-by: Menglong Dong <imagedong@tencent.com>

this is great work! One small typo in the ref counter subtest function
name below, but for the series:

Reviewed-by: Alan Maguire <alan.maguire@oracle.com>

> ---
>  .../selftests/bpf/prog_tests/attach_probe.c   | 268 +++++++++++-------
>  .../bpf/progs/test_attach_kprobe_sleepable.c  |  23 ++
>  .../selftests/bpf/progs/test_attach_probe.c   |  23 +-
>  3 files changed, 208 insertions(+), 106 deletions(-)
>  create mode 100644 tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
> 
> diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> index 56374c8b5436..9824a5eb8595 100644
> --- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> +++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> @@ -1,5 +1,6 @@
>  // SPDX-License-Identifier: GPL-2.0
>  #include <test_progs.h>
> +#include "test_attach_kprobe_sleepable.skel.h"
>  #include "test_attach_probe.skel.h"
>  
>  /* this is how USDT semaphore is actually defined, except volatile modifier */
> @@ -23,110 +24,63 @@ static noinline void trigger_func3(void)
>  	asm volatile ("");
>  }
>  
> +/* attach point for ref_ctr */
> +static noinline void trigger_func4(void)
> +{
> +	asm volatile ("");
> +}
> +
>  static char test_data[] = "test_data";
>  
> -void test_attach_probe(void)
> +/* manual attach kprobe/kretprobe/uprobe/uretprobe testings */
> +static void test_attach_probe_manual(struct test_attach_probe *skel)
>  {
>  	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
>  	struct bpf_link *kprobe_link, *kretprobe_link;
>  	struct bpf_link *uprobe_link, *uretprobe_link;
> -	struct test_attach_probe* skel;
> -	ssize_t uprobe_offset, ref_ctr_offset;
> -	struct bpf_link *uprobe_err_link;
> -	FILE *devnull;
> -	bool legacy;
> -
> -	/* Check if new-style kprobe/uprobe API is supported.
> -	 * Kernels that support new FD-based kprobe and uprobe BPF attachment
> -	 * through perf_event_open() syscall expose
> -	 * /sys/bus/event_source/devices/kprobe/type and
> -	 * /sys/bus/event_source/devices/uprobe/type files, respectively. They
> -	 * contain magic numbers that are passed as "type" field of
> -	 * perf_event_attr. Lack of such file in the system indicates legacy
> -	 * kernel with old-style kprobe/uprobe attach interface through
> -	 * creating per-probe event through tracefs. For such cases
> -	 * ref_ctr_offset feature is not supported, so we don't test it.
> -	 */
> -	legacy = access("/sys/bus/event_source/devices/kprobe/type", F_OK) != 0;
> +	ssize_t uprobe_offset;
>  
>  	uprobe_offset = get_uprobe_offset(&trigger_func);
>  	if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset"))
>  		return;
>  
> -	ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
> -	if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
> -		return;
> -
> -	skel = test_attach_probe__open();
> -	if (!ASSERT_OK_PTR(skel, "skel_open"))
> -		return;
> -
> -	/* sleepable kprobe test case needs flags set before loading */
> -	if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
> -		BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
> -		goto cleanup;
> -
> -	if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
> -		goto cleanup;
> -	if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
> -		goto cleanup;
> -
>  	/* manual-attach kprobe/kretprobe */
>  	kprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kprobe,
>  						 false /* retprobe */,
>  						 SYS_NANOSLEEP_KPROBE_NAME);
>  	if (!ASSERT_OK_PTR(kprobe_link, "attach_kprobe"))
> -		goto cleanup;
> +		return;
>  	skel->links.handle_kprobe = kprobe_link;
>  
>  	kretprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kretprobe,
>  						    true /* retprobe */,
>  						    SYS_NANOSLEEP_KPROBE_NAME);
>  	if (!ASSERT_OK_PTR(kretprobe_link, "attach_kretprobe"))
> -		goto cleanup;
> +		return;
>  	skel->links.handle_kretprobe = kretprobe_link;
>  
> -	/* auto-attachable kprobe and kretprobe */
> -	skel->links.handle_kprobe_auto = bpf_program__attach(skel->progs.handle_kprobe_auto);
> -	ASSERT_OK_PTR(skel->links.handle_kprobe_auto, "attach_kprobe_auto");
> -
> -	skel->links.handle_kretprobe_auto = bpf_program__attach(skel->progs.handle_kretprobe_auto);
> -	ASSERT_OK_PTR(skel->links.handle_kretprobe_auto, "attach_kretprobe_auto");
> -
> -	if (!legacy)
> -		ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
> -
> +	/* manual-attach uprobe/uretprobe */
> +	uprobe_opts.ref_ctr_offset = 0;
>  	uprobe_opts.retprobe = false;
> -	uprobe_opts.ref_ctr_offset = legacy ? 0 : ref_ctr_offset;
>  	uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe,
>  						      0 /* self pid */,
>  						      "/proc/self/exe",
>  						      uprobe_offset,
>  						      &uprobe_opts);
>  	if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe"))
> -		goto cleanup;
> +		return;
>  	skel->links.handle_uprobe = uprobe_link;
>  
> -	if (!legacy)
> -		ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
> -
> -	/* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
>  	uprobe_opts.retprobe = true;
> -	uprobe_opts.ref_ctr_offset = legacy ? 0 : ref_ctr_offset;
>  	uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe,
>  							 -1 /* any pid */,
>  							 "/proc/self/exe",
>  							 uprobe_offset, &uprobe_opts);
>  	if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe"))
> -		goto cleanup;
> +		return;
>  	skel->links.handle_uretprobe = uretprobe_link;
>  
> -	/* verify auto-attach fails for old-style uprobe definition */
> -	uprobe_err_link = bpf_program__attach(skel->progs.handle_uprobe_byname);
> -	if (!ASSERT_EQ(libbpf_get_error(uprobe_err_link), -EOPNOTSUPP,
> -		       "auto-attach should fail for old-style name"))
> -		goto cleanup;
> -
> +	/* attach uprobe by function name manually */
>  	uprobe_opts.func_name = "trigger_func2";
>  	uprobe_opts.retprobe = false;
>  	uprobe_opts.ref_ctr_offset = 0;
> @@ -136,13 +90,62 @@ void test_attach_probe(void)
>  							"/proc/self/exe",
>  							0, &uprobe_opts);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname, "attach_uprobe_byname"))
> -		goto cleanup;
> +		return;
> +
> +	/* trigger & validate kprobe && kretprobe */
> +	usleep(1);
> +
> +	/* trigger & validate uprobe & uretprobe */
> +	trigger_func();
> +
> +	/* trigger & validate uprobe attached by name */
> +	trigger_func2();
> +
> +	ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
> +	ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
> +	ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
> +	ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
> +	ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
> +}
> +
> +static void test_attach_probe_auto(struct test_attach_probe *skel)
> +{
> +	struct bpf_link *uprobe_err_link;
> +
> +	/* auto-attachable kprobe and kretprobe */
> +	skel->links.handle_kprobe_auto = bpf_program__attach(skel->progs.handle_kprobe_auto);
> +	ASSERT_OK_PTR(skel->links.handle_kprobe_auto, "attach_kprobe_auto");
> +
> +	skel->links.handle_kretprobe_auto = bpf_program__attach(skel->progs.handle_kretprobe_auto);
> +	ASSERT_OK_PTR(skel->links.handle_kretprobe_auto, "attach_kretprobe_auto");
> +
> +	/* verify auto-attach fails for old-style uprobe definition */
> +	uprobe_err_link = bpf_program__attach(skel->progs.handle_uprobe_byname);
> +	if (!ASSERT_EQ(libbpf_get_error(uprobe_err_link), -EOPNOTSUPP,
> +		       "auto-attach should fail for old-style name"))
> +		return;
>  
>  	/* verify auto-attach works */
>  	skel->links.handle_uretprobe_byname =
>  			bpf_program__attach(skel->progs.handle_uretprobe_byname);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname, "attach_uretprobe_byname"))
> -		goto cleanup;
> +		return;
> +
> +	/* trigger & validate kprobe && kretprobe */
> +	usleep(1);
> +
> +	/* trigger & validate uprobe attached by name */
> +	trigger_func2();
> +
> +	ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
> +	ASSERT_EQ(skel->bss->kretprobe2_res, 22, "check_kretprobe_auto_res");
> +	ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
> +}
> +
> +static void test_uprobe_lib(struct test_attach_probe *skel)
> +{
> +	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
> +	FILE *devnull;
>  
>  	/* test attach by name for a library function, using the library
>  	 * as the binary argument. libc.so.6 will be resolved via dlopen()/dlinfo().
> @@ -155,7 +158,7 @@ void test_attach_probe(void)
>  							"libc.so.6",
>  							0, &uprobe_opts);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname2, "attach_uprobe_byname2"))
> -		goto cleanup;
> +		return;
>  
>  	uprobe_opts.func_name = "fclose";
>  	uprobe_opts.retprobe = true;
> @@ -165,62 +168,137 @@ void test_attach_probe(void)
>  							"libc.so.6",
>  							0, &uprobe_opts);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname2, "attach_uretprobe_byname2"))
> +		return;
> +
> +	/* trigger & validate shared library u[ret]probes attached by name */
> +	devnull = fopen("/dev/null", "r");
> +	fclose(devnull);
> +
> +	ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
> +	ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
> +}
> +
> +static void test_uporbe_ref_ctr(struct test_attach_probe *skel)

typo, should be test_uprobe_ref_ctr

> +{
> +	DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
> +	struct bpf_link *uprobe_link, *uretprobe_link;
> +	ssize_t uprobe_offset, ref_ctr_offset;
> +
> +	uprobe_offset = get_uprobe_offset(&trigger_func4);
> +	if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset_ref_ctr"))
> +		return;
> +
> +	ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
> +	if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
> +		return;
> +
> +	ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
> +
> +	uprobe_opts.retprobe = false;
> +	uprobe_opts.ref_ctr_offset = ref_ctr_offset;
> +	uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe_ref_ctr,
> +						      0 /* self pid */,
> +						      "/proc/self/exe",
> +						      uprobe_offset,
> +						      &uprobe_opts);
> +	if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe_ref_ctr"))
> +		return;
> +	skel->links.handle_uprobe_ref_ctr = uprobe_link;
> +
> +	ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
> +
> +	/* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
> +	uprobe_opts.retprobe = true;
> +	uprobe_opts.ref_ctr_offset = ref_ctr_offset;
> +	uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe_ref_ctr,
> +							 -1 /* any pid */,
> +							 "/proc/self/exe",
> +							 uprobe_offset, &uprobe_opts);
> +	if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe_ref_ctr"))
> +		return;
> +	skel->links.handle_uretprobe_ref_ctr = uretprobe_link;
> +}
> +
> +static void test_kprobe_sleepable(void)
> +{
> +	struct test_attach_kprobe_sleepable *skel;
> +
> +	skel = test_attach_kprobe_sleepable__open();
> +	if (!ASSERT_OK_PTR(skel, "skel_kprobe_sleepable_open"))
> +		return;
> +
> +	/* sleepable kprobe test case needs flags set before loading */
> +	if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
> +		BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
> +		goto cleanup;
> +
> +	if (!ASSERT_OK(test_attach_kprobe_sleepable__load(skel),
> +		       "skel_kprobe_sleepable_load"))
>  		goto cleanup;
>  
>  	/* sleepable kprobes should not attach successfully */
>  	skel->links.handle_kprobe_sleepable = bpf_program__attach(skel->progs.handle_kprobe_sleepable);
> -	if (!ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable"))
> -		goto cleanup;
> +	ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable");
> +
> +cleanup:
> +	test_attach_kprobe_sleepable__destroy(skel);
> +}
>  
> +static void test_uprobe_sleepable(struct test_attach_probe *skel)
> +{
>  	/* test sleepable uprobe and uretprobe variants */
>  	skel->links.handle_uprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uprobe_byname3_sleepable);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3_sleepable, "attach_uprobe_byname3_sleepable"))
> -		goto cleanup;
> +		return;
>  
>  	skel->links.handle_uprobe_byname3 = bpf_program__attach(skel->progs.handle_uprobe_byname3);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3, "attach_uprobe_byname3"))
> -		goto cleanup;
> +		return;
>  
>  	skel->links.handle_uretprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uretprobe_byname3_sleepable);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3_sleepable, "attach_uretprobe_byname3_sleepable"))
> -		goto cleanup;
> +		return;
>  
>  	skel->links.handle_uretprobe_byname3 = bpf_program__attach(skel->progs.handle_uretprobe_byname3);
>  	if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3, "attach_uretprobe_byname3"))
> -		goto cleanup;
> +		return;
>  
>  	skel->bss->user_ptr = test_data;
>  
> -	/* trigger & validate kprobe && kretprobe */
> -	usleep(1);
> -
> -	/* trigger & validate shared library u[ret]probes attached by name */
> -	devnull = fopen("/dev/null", "r");
> -	fclose(devnull);
> -
> -	/* trigger & validate uprobe & uretprobe */
> -	trigger_func();
> -
> -	/* trigger & validate uprobe attached by name */
> -	trigger_func2();
> -
>  	/* trigger & validate sleepable uprobe attached by name */
>  	trigger_func3();
>  
> -	ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
> -	ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
> -	ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
> -	ASSERT_EQ(skel->bss->kretprobe2_res, 22, "check_kretprobe_auto_res");
> -	ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
> -	ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
> -	ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
> -	ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
> -	ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
> -	ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
>  	ASSERT_EQ(skel->bss->uprobe_byname3_sleepable_res, 9, "check_uprobe_byname3_sleepable_res");
>  	ASSERT_EQ(skel->bss->uprobe_byname3_res, 10, "check_uprobe_byname3_res");
>  	ASSERT_EQ(skel->bss->uretprobe_byname3_sleepable_res, 11, "check_uretprobe_byname3_sleepable_res");
>  	ASSERT_EQ(skel->bss->uretprobe_byname3_res, 12, "check_uretprobe_byname3_res");
> +}
> +
> +void test_attach_probe(void)
> +{
> +	struct test_attach_probe *skel;
> +
> +	skel = test_attach_probe__open();
> +	if (!ASSERT_OK_PTR(skel, "skel_open"))
> +		return;
> +
> +	if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
> +		goto cleanup;
> +	if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
> +		goto cleanup;
> +
> +	if (test__start_subtest("manual"))
> +		test_attach_probe_manual(skel);
> +	if (test__start_subtest("auto"))
> +		test_attach_probe_auto(skel);
> +	if (test__start_subtest("kprobe-sleepable"))
> +		test_kprobe_sleepable();
> +	if (test__start_subtest("uprobe-lib"))
> +		test_uprobe_lib(skel);
> +	if (test__start_subtest("uprobe-sleepable"))
> +		test_uprobe_sleepable(skel);
> +	if (test__start_subtest("uprobe-ref_ctr"))
> +		test_uporbe_ref_ctr(skel);

...and here.

>  
>  cleanup:
>  	test_attach_probe__destroy(skel);
> diff --git a/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c b/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
> new file mode 100644
> index 000000000000..f548b7446218
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
> @@ -0,0 +1,23 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (c) 2017 Facebook
> +
> +#include "vmlinux.h"
> +#include <bpf/bpf_helpers.h>
> +#include <bpf/bpf_tracing.h>
> +#include <bpf/bpf_core_read.h>
> +#include "bpf_misc.h"
> +
> +int kprobe_res = 0;
> +
> +/**
> + * This program will be manually made sleepable on the userspace side
> + * and should thus be unattachable.
> + */
> +SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
> +int handle_kprobe_sleepable(struct pt_regs *ctx)
> +{
> +	kprobe_res = 1;
> +	return 0;
> +}
> +
> +char _license[] SEC("license") = "GPL";
> diff --git a/tools/testing/selftests/bpf/progs/test_attach_probe.c b/tools/testing/selftests/bpf/progs/test_attach_probe.c
> index 3b5dc34d23e9..9e1e7163bb67 100644
> --- a/tools/testing/selftests/bpf/progs/test_attach_probe.c
> +++ b/tools/testing/selftests/bpf/progs/test_attach_probe.c
> @@ -37,17 +37,6 @@ int BPF_KSYSCALL(handle_kprobe_auto, struct __kernel_timespec *req, struct __ker
>  	return 0;
>  }
>  
> -/**
> - * This program will be manually made sleepable on the userspace side
> - * and should thus be unattachable.
> - */
> -SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
> -int handle_kprobe_sleepable(struct pt_regs *ctx)
> -{
> -	kprobe_res = 2;
> -	return 0;
> -}
> -
>  SEC("kretprobe")
>  int handle_kretprobe(struct pt_regs *ctx)
>  {
> @@ -76,6 +65,18 @@ int handle_uretprobe(struct pt_regs *ctx)
>  	return 0;
>  }
>  
> +SEC("uprobe")
> +int handle_uprobe_ref_ctr(struct pt_regs *ctx)
> +{
> +	return 0;
> +}
> +
> +SEC("uretprobe")
> +int handle_uretprobe_ref_ctr(struct pt_regs *ctx)
> +{
> +	return 0;
> +}
> +
>  SEC("uprobe")
>  int handle_uprobe_byname(struct pt_regs *ctx)
>  {
> 

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

* Re: [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests
  2023-02-20 11:40   ` Alan Maguire
@ 2023-02-21  2:19     ` Menglong Dong
  0 siblings, 0 replies; 6+ messages in thread
From: Menglong Dong @ 2023-02-21  2:19 UTC (permalink / raw)
  To: Alan Maguire
  Cc: andrii.nakryiko, ast, daniel, andrii, martin.lau, song, yhs,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, bpf, linux-kernel,
	Menglong Dong

On Mon, Feb 20, 2023 at 7:40 PM Alan Maguire <alan.maguire@oracle.com> wrote:
>
> On 20/02/2023 08:47, menglong8.dong@gmail.com wrote:
> > From: Menglong Dong <imagedong@tencent.com>
> >
> > In order to adapt to the older kernel, now we split the "attach_probe"
> > testing into multi subtests:
> >
> >   manual // manual attach tests for kprobe/uprobe
> >   auto // auto-attach tests for kprobe and uprobe
> >   kprobe-sleepable // kprobe sleepable test
> >   uprobe-lib // uprobe tests for library function by name
> >   uprobe-sleepabel // uprobe sleepable test
> >   uprobe-ref_ctr // uprobe ref_ctr test
> >
> > As sleepable kprobe needs to set BPF_F_SLEEPABLE flag before loading,
> > we need to move it to a stand alone skel file, in case of it is not
> > supported by kernel and make the whole loading fail.
> >
> > Therefore, we can only enable part of the subtests for older kernel.
> >
> > Signed-off-by: Menglong Dong <imagedong@tencent.com>
>
> this is great work! One small typo in the ref counter subtest function
> name below, but for the series:
>
> Reviewed-by: Alan Maguire <alan.maguire@oracle.com>
>
> > ---
> >  .../selftests/bpf/prog_tests/attach_probe.c   | 268 +++++++++++-------
> >  .../bpf/progs/test_attach_kprobe_sleepable.c  |  23 ++
> >  .../selftests/bpf/progs/test_attach_probe.c   |  23 +-
> >  3 files changed, 208 insertions(+), 106 deletions(-)
> >  create mode 100644 tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> > index 56374c8b5436..9824a5eb8595 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> > @@ -1,5 +1,6 @@
> >  // SPDX-License-Identifier: GPL-2.0
> >  #include <test_progs.h>
> > +#include "test_attach_kprobe_sleepable.skel.h"
> >  #include "test_attach_probe.skel.h"
> >
> >  /* this is how USDT semaphore is actually defined, except volatile modifier */
> > @@ -23,110 +24,63 @@ static noinline void trigger_func3(void)
> >       asm volatile ("");
> >  }
> >
> > +/* attach point for ref_ctr */
> > +static noinline void trigger_func4(void)
> > +{
> > +     asm volatile ("");
> > +}
> > +
> >  static char test_data[] = "test_data";
> >
> > -void test_attach_probe(void)
> > +/* manual attach kprobe/kretprobe/uprobe/uretprobe testings */
> > +static void test_attach_probe_manual(struct test_attach_probe *skel)
> >  {
> >       DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
> >       struct bpf_link *kprobe_link, *kretprobe_link;
> >       struct bpf_link *uprobe_link, *uretprobe_link;
> > -     struct test_attach_probe* skel;
> > -     ssize_t uprobe_offset, ref_ctr_offset;
> > -     struct bpf_link *uprobe_err_link;
> > -     FILE *devnull;
> > -     bool legacy;
> > -
> > -     /* Check if new-style kprobe/uprobe API is supported.
> > -      * Kernels that support new FD-based kprobe and uprobe BPF attachment
> > -      * through perf_event_open() syscall expose
> > -      * /sys/bus/event_source/devices/kprobe/type and
> > -      * /sys/bus/event_source/devices/uprobe/type files, respectively. They
> > -      * contain magic numbers that are passed as "type" field of
> > -      * perf_event_attr. Lack of such file in the system indicates legacy
> > -      * kernel with old-style kprobe/uprobe attach interface through
> > -      * creating per-probe event through tracefs. For such cases
> > -      * ref_ctr_offset feature is not supported, so we don't test it.
> > -      */
> > -     legacy = access("/sys/bus/event_source/devices/kprobe/type", F_OK) != 0;
> > +     ssize_t uprobe_offset;
> >
> >       uprobe_offset = get_uprobe_offset(&trigger_func);
> >       if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset"))
> >               return;
> >
> > -     ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
> > -     if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
> > -             return;
> > -
> > -     skel = test_attach_probe__open();
> > -     if (!ASSERT_OK_PTR(skel, "skel_open"))
> > -             return;
> > -
> > -     /* sleepable kprobe test case needs flags set before loading */
> > -     if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
> > -             BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
> > -             goto cleanup;
> > -
> > -     if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
> > -             goto cleanup;
> > -     if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
> > -             goto cleanup;
> > -
> >       /* manual-attach kprobe/kretprobe */
> >       kprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kprobe,
> >                                                false /* retprobe */,
> >                                                SYS_NANOSLEEP_KPROBE_NAME);
> >       if (!ASSERT_OK_PTR(kprobe_link, "attach_kprobe"))
> > -             goto cleanup;
> > +             return;
> >       skel->links.handle_kprobe = kprobe_link;
> >
> >       kretprobe_link = bpf_program__attach_kprobe(skel->progs.handle_kretprobe,
> >                                                   true /* retprobe */,
> >                                                   SYS_NANOSLEEP_KPROBE_NAME);
> >       if (!ASSERT_OK_PTR(kretprobe_link, "attach_kretprobe"))
> > -             goto cleanup;
> > +             return;
> >       skel->links.handle_kretprobe = kretprobe_link;
> >
> > -     /* auto-attachable kprobe and kretprobe */
> > -     skel->links.handle_kprobe_auto = bpf_program__attach(skel->progs.handle_kprobe_auto);
> > -     ASSERT_OK_PTR(skel->links.handle_kprobe_auto, "attach_kprobe_auto");
> > -
> > -     skel->links.handle_kretprobe_auto = bpf_program__attach(skel->progs.handle_kretprobe_auto);
> > -     ASSERT_OK_PTR(skel->links.handle_kretprobe_auto, "attach_kretprobe_auto");
> > -
> > -     if (!legacy)
> > -             ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
> > -
> > +     /* manual-attach uprobe/uretprobe */
> > +     uprobe_opts.ref_ctr_offset = 0;
> >       uprobe_opts.retprobe = false;
> > -     uprobe_opts.ref_ctr_offset = legacy ? 0 : ref_ctr_offset;
> >       uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe,
> >                                                     0 /* self pid */,
> >                                                     "/proc/self/exe",
> >                                                     uprobe_offset,
> >                                                     &uprobe_opts);
> >       if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe"))
> > -             goto cleanup;
> > +             return;
> >       skel->links.handle_uprobe = uprobe_link;
> >
> > -     if (!legacy)
> > -             ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
> > -
> > -     /* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
> >       uprobe_opts.retprobe = true;
> > -     uprobe_opts.ref_ctr_offset = legacy ? 0 : ref_ctr_offset;
> >       uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe,
> >                                                        -1 /* any pid */,
> >                                                        "/proc/self/exe",
> >                                                        uprobe_offset, &uprobe_opts);
> >       if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe"))
> > -             goto cleanup;
> > +             return;
> >       skel->links.handle_uretprobe = uretprobe_link;
> >
> > -     /* verify auto-attach fails for old-style uprobe definition */
> > -     uprobe_err_link = bpf_program__attach(skel->progs.handle_uprobe_byname);
> > -     if (!ASSERT_EQ(libbpf_get_error(uprobe_err_link), -EOPNOTSUPP,
> > -                    "auto-attach should fail for old-style name"))
> > -             goto cleanup;
> > -
> > +     /* attach uprobe by function name manually */
> >       uprobe_opts.func_name = "trigger_func2";
> >       uprobe_opts.retprobe = false;
> >       uprobe_opts.ref_ctr_offset = 0;
> > @@ -136,13 +90,62 @@ void test_attach_probe(void)
> >                                                       "/proc/self/exe",
> >                                                       0, &uprobe_opts);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname, "attach_uprobe_byname"))
> > -             goto cleanup;
> > +             return;
> > +
> > +     /* trigger & validate kprobe && kretprobe */
> > +     usleep(1);
> > +
> > +     /* trigger & validate uprobe & uretprobe */
> > +     trigger_func();
> > +
> > +     /* trigger & validate uprobe attached by name */
> > +     trigger_func2();
> > +
> > +     ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
> > +     ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
> > +     ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
> > +     ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
> > +     ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
> > +}
> > +
> > +static void test_attach_probe_auto(struct test_attach_probe *skel)
> > +{
> > +     struct bpf_link *uprobe_err_link;
> > +
> > +     /* auto-attachable kprobe and kretprobe */
> > +     skel->links.handle_kprobe_auto = bpf_program__attach(skel->progs.handle_kprobe_auto);
> > +     ASSERT_OK_PTR(skel->links.handle_kprobe_auto, "attach_kprobe_auto");
> > +
> > +     skel->links.handle_kretprobe_auto = bpf_program__attach(skel->progs.handle_kretprobe_auto);
> > +     ASSERT_OK_PTR(skel->links.handle_kretprobe_auto, "attach_kretprobe_auto");
> > +
> > +     /* verify auto-attach fails for old-style uprobe definition */
> > +     uprobe_err_link = bpf_program__attach(skel->progs.handle_uprobe_byname);
> > +     if (!ASSERT_EQ(libbpf_get_error(uprobe_err_link), -EOPNOTSUPP,
> > +                    "auto-attach should fail for old-style name"))
> > +             return;
> >
> >       /* verify auto-attach works */
> >       skel->links.handle_uretprobe_byname =
> >                       bpf_program__attach(skel->progs.handle_uretprobe_byname);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname, "attach_uretprobe_byname"))
> > -             goto cleanup;
> > +             return;
> > +
> > +     /* trigger & validate kprobe && kretprobe */
> > +     usleep(1);
> > +
> > +     /* trigger & validate uprobe attached by name */
> > +     trigger_func2();
> > +
> > +     ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
> > +     ASSERT_EQ(skel->bss->kretprobe2_res, 22, "check_kretprobe_auto_res");
> > +     ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
> > +}
> > +
> > +static void test_uprobe_lib(struct test_attach_probe *skel)
> > +{
> > +     DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
> > +     FILE *devnull;
> >
> >       /* test attach by name for a library function, using the library
> >        * as the binary argument. libc.so.6 will be resolved via dlopen()/dlinfo().
> > @@ -155,7 +158,7 @@ void test_attach_probe(void)
> >                                                       "libc.so.6",
> >                                                       0, &uprobe_opts);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname2, "attach_uprobe_byname2"))
> > -             goto cleanup;
> > +             return;
> >
> >       uprobe_opts.func_name = "fclose";
> >       uprobe_opts.retprobe = true;
> > @@ -165,62 +168,137 @@ void test_attach_probe(void)
> >                                                       "libc.so.6",
> >                                                       0, &uprobe_opts);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname2, "attach_uretprobe_byname2"))
> > +             return;
> > +
> > +     /* trigger & validate shared library u[ret]probes attached by name */
> > +     devnull = fopen("/dev/null", "r");
> > +     fclose(devnull);
> > +
> > +     ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
> > +     ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
> > +}
> > +
> > +static void test_uporbe_ref_ctr(struct test_attach_probe *skel)
>
> typo, should be test_uprobe_ref_ctr
>

Oops......Thanks! I'll send the v3 with your viewed-by tag and
fix the typo.

Thanks!
Menglong Dong

> > +{
> > +     DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
> > +     struct bpf_link *uprobe_link, *uretprobe_link;
> > +     ssize_t uprobe_offset, ref_ctr_offset;
> > +
> > +     uprobe_offset = get_uprobe_offset(&trigger_func4);
> > +     if (!ASSERT_GE(uprobe_offset, 0, "uprobe_offset_ref_ctr"))
> > +             return;
> > +
> > +     ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
> > +     if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
> > +             return;
> > +
> > +     ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
> > +
> > +     uprobe_opts.retprobe = false;
> > +     uprobe_opts.ref_ctr_offset = ref_ctr_offset;
> > +     uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe_ref_ctr,
> > +                                                   0 /* self pid */,
> > +                                                   "/proc/self/exe",
> > +                                                   uprobe_offset,
> > +                                                   &uprobe_opts);
> > +     if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe_ref_ctr"))
> > +             return;
> > +     skel->links.handle_uprobe_ref_ctr = uprobe_link;
> > +
> > +     ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
> > +
> > +     /* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
> > +     uprobe_opts.retprobe = true;
> > +     uprobe_opts.ref_ctr_offset = ref_ctr_offset;
> > +     uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe_ref_ctr,
> > +                                                      -1 /* any pid */,
> > +                                                      "/proc/self/exe",
> > +                                                      uprobe_offset, &uprobe_opts);
> > +     if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe_ref_ctr"))
> > +             return;
> > +     skel->links.handle_uretprobe_ref_ctr = uretprobe_link;
> > +}
> > +
> > +static void test_kprobe_sleepable(void)
> > +{
> > +     struct test_attach_kprobe_sleepable *skel;
> > +
> > +     skel = test_attach_kprobe_sleepable__open();
> > +     if (!ASSERT_OK_PTR(skel, "skel_kprobe_sleepable_open"))
> > +             return;
> > +
> > +     /* sleepable kprobe test case needs flags set before loading */
> > +     if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
> > +             BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
> > +             goto cleanup;
> > +
> > +     if (!ASSERT_OK(test_attach_kprobe_sleepable__load(skel),
> > +                    "skel_kprobe_sleepable_load"))
> >               goto cleanup;
> >
> >       /* sleepable kprobes should not attach successfully */
> >       skel->links.handle_kprobe_sleepable = bpf_program__attach(skel->progs.handle_kprobe_sleepable);
> > -     if (!ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable"))
> > -             goto cleanup;
> > +     ASSERT_ERR_PTR(skel->links.handle_kprobe_sleepable, "attach_kprobe_sleepable");
> > +
> > +cleanup:
> > +     test_attach_kprobe_sleepable__destroy(skel);
> > +}
> >
> > +static void test_uprobe_sleepable(struct test_attach_probe *skel)
> > +{
> >       /* test sleepable uprobe and uretprobe variants */
> >       skel->links.handle_uprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uprobe_byname3_sleepable);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3_sleepable, "attach_uprobe_byname3_sleepable"))
> > -             goto cleanup;
> > +             return;
> >
> >       skel->links.handle_uprobe_byname3 = bpf_program__attach(skel->progs.handle_uprobe_byname3);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uprobe_byname3, "attach_uprobe_byname3"))
> > -             goto cleanup;
> > +             return;
> >
> >       skel->links.handle_uretprobe_byname3_sleepable = bpf_program__attach(skel->progs.handle_uretprobe_byname3_sleepable);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3_sleepable, "attach_uretprobe_byname3_sleepable"))
> > -             goto cleanup;
> > +             return;
> >
> >       skel->links.handle_uretprobe_byname3 = bpf_program__attach(skel->progs.handle_uretprobe_byname3);
> >       if (!ASSERT_OK_PTR(skel->links.handle_uretprobe_byname3, "attach_uretprobe_byname3"))
> > -             goto cleanup;
> > +             return;
> >
> >       skel->bss->user_ptr = test_data;
> >
> > -     /* trigger & validate kprobe && kretprobe */
> > -     usleep(1);
> > -
> > -     /* trigger & validate shared library u[ret]probes attached by name */
> > -     devnull = fopen("/dev/null", "r");
> > -     fclose(devnull);
> > -
> > -     /* trigger & validate uprobe & uretprobe */
> > -     trigger_func();
> > -
> > -     /* trigger & validate uprobe attached by name */
> > -     trigger_func2();
> > -
> >       /* trigger & validate sleepable uprobe attached by name */
> >       trigger_func3();
> >
> > -     ASSERT_EQ(skel->bss->kprobe_res, 1, "check_kprobe_res");
> > -     ASSERT_EQ(skel->bss->kprobe2_res, 11, "check_kprobe_auto_res");
> > -     ASSERT_EQ(skel->bss->kretprobe_res, 2, "check_kretprobe_res");
> > -     ASSERT_EQ(skel->bss->kretprobe2_res, 22, "check_kretprobe_auto_res");
> > -     ASSERT_EQ(skel->bss->uprobe_res, 3, "check_uprobe_res");
> > -     ASSERT_EQ(skel->bss->uretprobe_res, 4, "check_uretprobe_res");
> > -     ASSERT_EQ(skel->bss->uprobe_byname_res, 5, "check_uprobe_byname_res");
> > -     ASSERT_EQ(skel->bss->uretprobe_byname_res, 6, "check_uretprobe_byname_res");
> > -     ASSERT_EQ(skel->bss->uprobe_byname2_res, 7, "check_uprobe_byname2_res");
> > -     ASSERT_EQ(skel->bss->uretprobe_byname2_res, 8, "check_uretprobe_byname2_res");
> >       ASSERT_EQ(skel->bss->uprobe_byname3_sleepable_res, 9, "check_uprobe_byname3_sleepable_res");
> >       ASSERT_EQ(skel->bss->uprobe_byname3_res, 10, "check_uprobe_byname3_res");
> >       ASSERT_EQ(skel->bss->uretprobe_byname3_sleepable_res, 11, "check_uretprobe_byname3_sleepable_res");
> >       ASSERT_EQ(skel->bss->uretprobe_byname3_res, 12, "check_uretprobe_byname3_res");
> > +}
> > +
> > +void test_attach_probe(void)
> > +{
> > +     struct test_attach_probe *skel;
> > +
> > +     skel = test_attach_probe__open();
> > +     if (!ASSERT_OK_PTR(skel, "skel_open"))
> > +             return;
> > +
> > +     if (!ASSERT_OK(test_attach_probe__load(skel), "skel_load"))
> > +             goto cleanup;
> > +     if (!ASSERT_OK_PTR(skel->bss, "check_bss"))
> > +             goto cleanup;
> > +
> > +     if (test__start_subtest("manual"))
> > +             test_attach_probe_manual(skel);
> > +     if (test__start_subtest("auto"))
> > +             test_attach_probe_auto(skel);
> > +     if (test__start_subtest("kprobe-sleepable"))
> > +             test_kprobe_sleepable();
> > +     if (test__start_subtest("uprobe-lib"))
> > +             test_uprobe_lib(skel);
> > +     if (test__start_subtest("uprobe-sleepable"))
> > +             test_uprobe_sleepable(skel);
> > +     if (test__start_subtest("uprobe-ref_ctr"))
> > +             test_uporbe_ref_ctr(skel);
>
> ...and here.
>
> >
> >  cleanup:
> >       test_attach_probe__destroy(skel);
> > diff --git a/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c b/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
> > new file mode 100644
> > index 000000000000..f548b7446218
> > --- /dev/null
> > +++ b/tools/testing/selftests/bpf/progs/test_attach_kprobe_sleepable.c
> > @@ -0,0 +1,23 @@
> > +// SPDX-License-Identifier: GPL-2.0
> > +// Copyright (c) 2017 Facebook
> > +
> > +#include "vmlinux.h"
> > +#include <bpf/bpf_helpers.h>
> > +#include <bpf/bpf_tracing.h>
> > +#include <bpf/bpf_core_read.h>
> > +#include "bpf_misc.h"
> > +
> > +int kprobe_res = 0;
> > +
> > +/**
> > + * This program will be manually made sleepable on the userspace side
> > + * and should thus be unattachable.
> > + */
> > +SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
> > +int handle_kprobe_sleepable(struct pt_regs *ctx)
> > +{
> > +     kprobe_res = 1;
> > +     return 0;
> > +}
> > +
> > +char _license[] SEC("license") = "GPL";
> > diff --git a/tools/testing/selftests/bpf/progs/test_attach_probe.c b/tools/testing/selftests/bpf/progs/test_attach_probe.c
> > index 3b5dc34d23e9..9e1e7163bb67 100644
> > --- a/tools/testing/selftests/bpf/progs/test_attach_probe.c
> > +++ b/tools/testing/selftests/bpf/progs/test_attach_probe.c
> > @@ -37,17 +37,6 @@ int BPF_KSYSCALL(handle_kprobe_auto, struct __kernel_timespec *req, struct __ker
> >       return 0;
> >  }
> >
> > -/**
> > - * This program will be manually made sleepable on the userspace side
> > - * and should thus be unattachable.
> > - */
> > -SEC("kprobe/" SYS_PREFIX "sys_nanosleep")
> > -int handle_kprobe_sleepable(struct pt_regs *ctx)
> > -{
> > -     kprobe_res = 2;
> > -     return 0;
> > -}
> > -
> >  SEC("kretprobe")
> >  int handle_kretprobe(struct pt_regs *ctx)
> >  {
> > @@ -76,6 +65,18 @@ int handle_uretprobe(struct pt_regs *ctx)
> >       return 0;
> >  }
> >
> > +SEC("uprobe")
> > +int handle_uprobe_ref_ctr(struct pt_regs *ctx)
> > +{
> > +     return 0;
> > +}
> > +
> > +SEC("uretprobe")
> > +int handle_uretprobe_ref_ctr(struct pt_regs *ctx)
> > +{
> > +     return 0;
> > +}
> > +
> >  SEC("uprobe")
> >  int handle_uprobe_byname(struct pt_regs *ctx)
> >  {
> >

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

end of thread, other threads:[~2023-02-21  2:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-20  8:47 [PATCH bpf-next v2 0/3] libbpf: allow users to set kprobe/uprobe attach mode menglong8.dong
2023-02-20  8:47 ` [PATCH bpf-next v2 1/3] libbpf: add support " menglong8.dong
2023-02-20  8:47 ` [PATCH bpf-next v2 2/3] selftests/bpf: split test_attach_probe into multi subtests menglong8.dong
2023-02-20 11:40   ` Alan Maguire
2023-02-21  2:19     ` Menglong Dong
2023-02-20  8:47 ` [PATCH bpf-next v2 3/3] selftests/bpf: add test for legacy/perf kprobe/uprobe attach mode menglong8.dong

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).