Skip to contentSkip to conversation

bpf: Allow uprobe_multi binary specified by file descriptor

PATCH Superseded Jiri Olsa 5 participants 14 messages Jun 9 – Jun 10

Subsystems (8)
Kselftest BPF Tracing BPF selftests +4 more subsystems

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore

Jiri Olsa

author reviewer
#0 lore raw

cover bpf: Allow uprobe_multi binary specified by file descriptor

hi,
we'd like to be able to open uprobe_multi link on top of binary identified by file descriptor. This allows us to avoid the race where the binary is replaced between path resolution and attachment, ensuring we monitor the intended binary.

thanks,
jirka

---
Jiri Olsa (6):
bpf: Use user_path_at for path resolution in uprobe_multi
bpf: Add support to specify uprobe_multi target via file descriptor
libbpf: Add path_fd to struct bpf_link_create_opts selftests/bpf: Add uprobe_multi path_fd test selftests/bpf: Add uprobe_multi path_fd fail tests selftests/bpf: Fix typo in verify_umulti_link_info

 include/uapi/linux/bpf.h                                   |  7 +++++-
 kernel/bpf/syscall.c                                       |  4 +--
 kernel/trace/bpf_trace.c                                   | 43 +++++++++++++++++++++-----------
 tools/include/uapi/linux/bpf.h                             |  7 +++++-
 tools/lib/bpf/bpf.c                                        |  1 +
 tools/lib/bpf/bpf.h                                        |  3 ++-
 tools/testing/selftests/bpf/prog_tests/fill_link_info.c    |  2 +-
 tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 8 files changed, 140 insertions(+), 21 deletions(-)
author reviewer
#1 lore raw

PATCH 1/6 bpf: Use user_path_at for path resolution in uprobe_multi

Resolve the uprobe_multi user path with user_path_at() instead of copying the string with strndup_user() and passing it to kern_path(). This removes the temporary allocation and keeps the lookup logic in one helper.

---
 kernel/trace/bpf_trace.c | 10 +---------
 1 file changed, 1 insertion(+), 9 deletions(-)
kernel/trace/bpf_trace.c +1 -9
index 90432f0fc2a8..970ce7bbf99e 100644
@@ -3226,7 +3226,6 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 	void __user *upath;
 	u32 flags, cnt, i;
 	struct path path;
-	char *name;
 	pid_t pid;
 	int err;
 
@@ -3261,14 +3260,7 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 	uref_ctr_offsets = u64_to_user_ptr(attr->link_create.uprobe_multi.ref_ctr_offsets);
 	ucookies = u64_to_user_ptr(attr->link_create.uprobe_multi.cookies);
 
-	name = strndup_user(upath, PATH_MAX);
-	if (IS_ERR(name)) {
-		err = PTR_ERR(name);
-		return err;
-	}
-
-	err = kern_path(name, LOOKUP_FOLLOW, &path);
-	kfree(name);
+	err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
 	if (err)
 		return err;
 
Signature · 1 line
2.54.0
author reviewer
#2 lore raw

PATCH 2/6 bpf: Add support to specify uprobe_multi target via file descriptor

In reply to Jiri Olsa

Allow uprobe_multi link to identify the target binary by an already opened file descriptor.

Adding new BPF_F_UPROBE_MULTI_PATH_FD flag and the path_fd field for the attr.link_create.uprobe_multi struct.

When the flag is set, we resolve the target from path_fd, without the flag, we keep the existing string path behavior.

I don't see a use case for supporting O_PATH file descriptors, because we need need to read the binary first to get probes offsets, so I'm using the CLASS(fd, f), which fails for O_PATH fds.

Assisted-by Codex:GPT-5.4
---
 include/uapi/linux/bpf.h       |  7 ++++++-
 kernel/bpf/syscall.c           |  4 ++--
 kernel/trace/bpf_trace.c       | 37 +++++++++++++++++++++++++++-------
 tools/include/uapi/linux/bpf.h |  7 ++++++-
 4 files changed, 44 insertions(+), 11 deletions(-)
include/uapi/linux/bpf.h +6 -1
index 11dd610fa5fa..89b36de5fdbb 100644
@@ -1327,7 +1327,11 @@ enum {
  * BPF_TRACE_UPROBE_MULTI attach type to create return probe.
  */
 enum {
-	BPF_F_UPROBE_MULTI_RETURN = (1U << 0)
+	/* Get return uprobe. */
+	BPF_F_UPROBE_MULTI_RETURN     = (1U << 0),
+
+	/* Get path from provided path_fd. */
+	BPF_F_UPROBE_MULTI_PATH_FD    = (1U << 1),
 };
 
 /* link_create.netfilter.flags used in LINK_CREATE command for
@@ -1864,6 +1868,7 @@ union bpf_attr {
 				__u32		cnt;
 				__u32		flags;
 				__u32		pid;
+				__u32		path_fd;
 			} uprobe_multi;
 			struct {
 				union {
kernel/bpf/syscall.c +2 -2
index d4188a992bd8..cef9bd6316a5 100644
@@ -3475,7 +3475,7 @@ static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp)
 			seq_printf(m, "link_type:\t%s\n", link->flags == BPF_F_KPROBE_MULTI_RETURN ?
 				   "kretprobe_multi" : "kprobe_multi");
 		else if (link->type == BPF_LINK_TYPE_UPROBE_MULTI)
-			seq_printf(m, "link_type:\t%s\n", link->flags == BPF_F_UPROBE_MULTI_RETURN ?
+			seq_printf(m, "link_type:\t%s\n", link->flags & BPF_F_UPROBE_MULTI_RETURN ?
 				   "uretprobe_multi" : "uprobe_multi");
 		else
 			seq_printf(m, "link_type:\t%s\n", bpf_link_type_strs[type]);
@@ -5835,7 +5835,7 @@ static int bpf_map_do_batch(const union bpf_attr *attr,
 	return err;
 }
 
-#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.pid
+#define BPF_LINK_CREATE_LAST_FIELD link_create.uprobe_multi.path_fd
 static int link_create(union bpf_attr *attr, bpfptr_t uattr)
 {
 	struct bpf_prog *prog;
kernel/trace/bpf_trace.c +30 -7
index 970ce7bbf99e..4965006d58ee 100644
@@ -23,6 +23,7 @@
 #include <linux/sort.h>
 #include <linux/key.h>
 #include <linux/namei.h>
+#include <linux/file.h>
 
 #include <net/bpf_sk_storage.h>
 
@@ -3240,29 +3241,51 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr
 		return -EINVAL;
 
 	flags = attr->link_create.uprobe_multi.flags;
-	if (flags & ~BPF_F_UPROBE_MULTI_RETURN)
+	if (flags & ~(BPF_F_UPROBE_MULTI_RETURN|BPF_F_UPROBE_MULTI_PATH_FD))
 		return -EINVAL;
 
 	/*
-	 * path, offsets and cnt are mandatory,
+	 * offsets and cnt are mandatory,
 	 * ref_ctr_offsets and cookies are optional
 	 */
-	upath = u64_to_user_ptr(attr->link_create.uprobe_multi.path);
 	uoffsets = u64_to_user_ptr(attr->link_create.uprobe_multi.offsets);
 	cnt = attr->link_create.uprobe_multi.cnt;
 	pid = attr->link_create.uprobe_multi.pid;
 
-	if (!upath || !uoffsets || !cnt || pid < 0)
+	if (!uoffsets || !cnt || pid < 0)
 		return -EINVAL;
 	if (cnt > MAX_UPROBE_MULTI_CNT)
 		return -E2BIG;
 
 	uref_ctr_offsets = u64_to_user_ptr(attr->link_create.uprobe_multi.ref_ctr_offsets);
 	ucookies = u64_to_user_ptr(attr->link_create.uprobe_multi.cookies);
+	upath = u64_to_user_ptr(attr->link_create.uprobe_multi.path);
 
-	err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
-	if (err)
-		return err;
+	if (flags & BPF_F_UPROBE_MULTI_PATH_FD) {
+		/*
+		 * When BPF_F_UPROBE_MULTI_PATH_FD is set, the executable is identified
+		 * by path_fd, and upath must be NULL.
+		 */
+		if (upath)
+			return -EINVAL;
+
+		CLASS(fd, f)(attr->link_create.uprobe_multi.path_fd);
+		if (fd_empty(f))
+			return -EBADF;
+		path = fd_file(f)->f_path;
+		path_get(&path);
+	} else {
+		/*
+		 * When BPF_F_UPROBE_MULTI_PATH_FD is not set, the path is resolved
+		 * relative to the cwd (AT_FDCWD) or absolute  using the upath string.
+		 */
+		if (!upath)
+			return -EINVAL;
+
+		err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
+		if (err)
+			return err;
+	}
 
 	if (!d_is_reg(path.dentry)) {
 		err = -EBADF;
tools/include/uapi/linux/bpf.h +6 -1
index 11dd610fa5fa..89b36de5fdbb 100644
@@ -1327,7 +1327,11 @@ enum {
  * BPF_TRACE_UPROBE_MULTI attach type to create return probe.
  */
 enum {
-	BPF_F_UPROBE_MULTI_RETURN = (1U << 0)
+	/* Get return uprobe. */
+	BPF_F_UPROBE_MULTI_RETURN     = (1U << 0),
+
+	/* Get path from provided path_fd. */
+	BPF_F_UPROBE_MULTI_PATH_FD    = (1U << 1),
 };
 
 /* link_create.netfilter.flags used in LINK_CREATE command for
@@ -1864,6 +1868,7 @@ union bpf_attr {
 				__u32		cnt;
 				__u32		flags;
 				__u32		pid;
+				__u32		path_fd;
 			} uprobe_multi;
 			struct {
 				union {
Signature · 1 line
2.54.0
#3 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [Medium] Missing strict zero-validation for the unused `path_fd` field when the…

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Missing strict zero-validation for the unused path_fd field when the BPF_F_UPROBE_MULTI_PATH_FD flag is not set.
- [Low] Mixing scope-based cleanup (CLASS()) with goto-based error handling in bpf_uprobe_multi_link_attach. --

commit f7958ff1ce57c1ab456d3f134881a0081a58b8ed
Author: Jiri Olsa <[email protected]>

bpf: Add support to specify uprobe_multi target via file descriptor

This commit adds the BPF_F_UPROBE_MULTI_PATH_FD flag to allow uprobe_multi links to specify the target binary using an already opened file descriptor instead of a path string.

Quoted 4 lines
kernel/trace/bpf_trace.c +0 -0
index 970ce7bbf99e1..4965006d58ee6 100644

[ ... ]

Quoted 1 line
kernel/trace/bpf_trace.c +0 -0
@@ -3240,29 +3241,51 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr

[ ... ]

Quoted 6 lines
kernel/trace/bpf_trace.c +1 -2
 	uref_ctr_offsets = u64_to_user_ptr(attr->link_create.uprobe_multi.ref_ctr_offsets);
 	ucookies = u64_to_user_ptr(attr->link_create.uprobe_multi.cookies);
+	upath = u64_to_user_ptr(attr->link_create.uprobe_multi.path);
 
-	err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
-	if (err)

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3272

Quoted 10 lines
kernel/trace/bpf_trace.c +9 -1
-		return err;
+	if (flags & BPF_F_UPROBE_MULTI_PATH_FD) {
+		/*
+		 * When BPF_F_UPROBE_MULTI_PATH_FD is set, the executable is identified
+		 * by path_fd, and upath must be NULL.
+		 */
+		if (upath)
+			return -EINVAL;
+
+		CLASS(fd, f)(attr->link_create.uprobe_multi.path_fd);

[Severity: Low]
Does this code violate the cleanup subsystem guidelines by mixing scope-based cleanup with goto-based error handling?

The bpf_uprobe_multi_link_attach() function relies heavily on goto labels for error paths (e.g., error_path_put, error_free, error_unregister). The kernel guidelines state that goto-based cleanup and scope-based cleanup helpers (like CLASS) should never be mixed in the same function.

Should this function be fully converted to scope-based cleanup, or should it use explicit fdget()/fdput() without CLASS() instead?

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3283

Quoted 11 lines
kernel/trace/bpf_trace.c +11 -0
+		if (fd_empty(f))
+			return -EBADF;
+		path = fd_file(f)->f_path;
+		path_get(&path);
+	} else {
+		/*
+		 * When BPF_F_UPROBE_MULTI_PATH_FD is not set, the path is resolved
+		 * relative to the cwd (AT_FDCWD) or absolute  using the upath string.
+		 */
+		if (!upath)
+			return -EINVAL;

[Severity: Medium]
Should there be strict zero-validation for the unused path_fd field here?

When the BPF_F_UPROBE_MULTI_PATH_FD flag is not set, this branch is taken and attr->link_create.uprobe_multi.path_fd is ignored without being validated as zero.

If userspace passes uninitialized garbage in this field, it won't be rejected. Could this break forward compatibility if path_fd needs to be assigned a new meaning in the future?

Quoted 5 lines
kernel/trace/bpf_trace.c +5 -0
+
+		err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
+		if (err)
+			return err;
+	}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#4 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

Quoted 42 lines · On Tue, Jun 09, 2026 at 10:57:22AM +0000, [email protected] wrote:

Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] Missing strict zero-validation for the unused path_fd field when the BPF_F_UPROBE_MULTI_PATH_FD flag is not set.
- [Low] Mixing scope-based cleanup (CLASS()) with goto-based error handling in bpf_uprobe_multi_link_attach. --

commit f7958ff1ce57c1ab456d3f134881a0081a58b8ed
Author: Jiri Olsa <[email protected]>

bpf: Add support to specify uprobe_multi target via file descriptor

This commit adds the BPF_F_UPROBE_MULTI_PATH_FD flag to allow uprobe_multi links to specify the target binary using an already opened file descriptor instead of a path string.

Quoted 4 lines
kernel/trace/bpf_trace.c +0 -0
index 970ce7bbf99e1..4965006d58ee6 100644

[ ... ]

Quoted 1 line
kernel/trace/bpf_trace.c +0 -0
@@ -3240,29 +3241,51 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr

[ ... ]

Quoted 6 lines
kernel/trace/bpf_trace.c +1 -2
 	uref_ctr_offsets = u64_to_user_ptr(attr->link_create.uprobe_multi.ref_ctr_offsets);
 	ucookies = u64_to_user_ptr(attr->link_create.uprobe_multi.cookies);
+	upath = u64_to_user_ptr(attr->link_create.uprobe_multi.path);
 
-	err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
-	if (err)

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3272

Quoted 10 lines
kernel/trace/bpf_trace.c +9 -1
-		return err;
+	if (flags & BPF_F_UPROBE_MULTI_PATH_FD) {
+		/*
+		 * When BPF_F_UPROBE_MULTI_PATH_FD is set, the executable is identified
+		 * by path_fd, and upath must be NULL.
+		 */
+		if (upath)
+			return -EINVAL;
+
+		CLASS(fd, f)(attr->link_create.uprobe_multi.path_fd);

[Severity: Low]
Does this code violate the cleanup subsystem guidelines by mixing scope-based cleanup with goto-based error handling?

Quoted 7 lines

The bpf_uprobe_multi_link_attach() function relies heavily on goto labels for error paths (e.g., error_path_put, error_free, error_unregister). The kernel guidelines state that goto-based cleanup and scope-based cleanup helpers (like CLASS) should never be mixed in the same function.

Should this function be fully converted to scope-based cleanup, or should it use explicit fdget()/fdput() without CLASS() instead?

ah true, I'll unwind the fd retrieval or perhaps move the path retrival into separate function, will check

Quoted 15 lines

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3283

Quoted 11 lines
kernel/trace/bpf_trace.c +11 -0
+		if (fd_empty(f))
+			return -EBADF;
+		path = fd_file(f)->f_path;
+		path_get(&path);
+	} else {
+		/*
+		 * When BPF_F_UPROBE_MULTI_PATH_FD is not set, the path is resolved
+		 * relative to the cwd (AT_FDCWD) or absolute  using the upath string.
+		 */
+		if (!upath)
+			return -EINVAL;

[Severity: Medium]
Should there be strict zero-validation for the unused path_fd field here?

Quoted 7 lines

When the BPF_F_UPROBE_MULTI_PATH_FD flag is not set, this branch is taken and attr->link_create.uprobe_multi.path_fd is ignored without being validated as zero.

If userspace passes uninitialized garbage in this field, it won't be rejected. Could this break forward compatibility if path_fd needs to be assigned a new meaning in the future?

right, I'll add the path_fd check in here

jirka

Quoted 9 lines
Quoted 6 lines
kernel/trace/bpf_trace.c +5 -0
+
+		err = user_path_at(AT_FDCWD, upath, LOOKUP_FOLLOW, &path);
+		if (err)
+			return err;
+	}
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
#5 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

In reply to Jiri Olsa
This change also fixes a latent bug in bpf_link_show_fdinfo(), changing the exact-equality test to a bitwise test:
Quoted 9 lines

Allow uprobe_multi link to identify the target binary by an already opened file descriptor.

Adding new BPF_F_UPROBE_MULTI_PATH_FD flag and the path_fd field for the attr.link_create.uprobe_multi struct.

When the flag is set, we resolve the target from path_fd, without the flag, we keep the existing string path behavior.

Quoted 6 lines

I don't see a use case for supporting O_PATH file descriptors, because we need need to read the binary first to get probes offsets, so I'm using the CLASS(fd, f), which fails for O_PATH fds.

Assisted-by Codex:GPT-5.4

This change also fixes a latent bug in bpf_link_show_fdinfo(), changing the exact-equality test to a bitwise test:

	else if (link->type == BPF_LINK_TYPE_UPROBE_MULTI)
		seq_printf(m, "link_type:\t%s\n", link->flags & BPF_F_UPROBE_MULTI_RETURN ?
			   "uretprobe_multi" : "uprobe_multi");

The original "link->flags == BPF_F_UPROBE_MULTI_RETURN" was harmless while BPF_F_UPROBE_MULTI_RETURN was the only defined uprobe_multi flag. This commit adds a second flag (BPF_F_UPROBE_MULTI_PATH_FD), so the exact "==" comparison would misreport a uretprobe_multi link as "uprobe_multi" whenever both flags are set.

Should this carry a Fixes: tag pointing at the commit that introduced the fragile comparison?

Fixes 803f0700a3bb ("bpf: Show precise link_type for {uprobe,kprobe}_multi fdinfo")

---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27201419867

#6 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

Quoted 29 lines · On Tue, Jun 09, 2026 at 11:17:11AM +0000, [email protected] wrote:
Quoted 9 lines

Allow uprobe_multi link to identify the target binary by an already opened file descriptor.

Adding new BPF_F_UPROBE_MULTI_PATH_FD flag and the path_fd field for the attr.link_create.uprobe_multi struct.

When the flag is set, we resolve the target from path_fd, without the flag, we keep the existing string path behavior.

Quoted 6 lines

I don't see a use case for supporting O_PATH file descriptors, because we need need to read the binary first to get probes offsets, so I'm using the CLASS(fd, f), which fails for O_PATH fds.

Assisted-by Codex:GPT-5.4

This change also fixes a latent bug in bpf_link_show_fdinfo(), changing the exact-equality test to a bitwise test:

	else if (link->type == BPF_LINK_TYPE_UPROBE_MULTI)
		seq_printf(m, "link_type:\t%s\n", link->flags & BPF_F_UPROBE_MULTI_RETURN ?
			   "uretprobe_multi" : "uprobe_multi");

The original "link->flags == BPF_F_UPROBE_MULTI_RETURN" was harmless while BPF_F_UPROBE_MULTI_RETURN was the only defined uprobe_multi flag. This commit adds a second flag (BPF_F_UPROBE_MULTI_PATH_FD), so the exact "==" comparison would misreport a uretprobe_multi link as "uprobe_multi" whenever both flags are set.

Quoted 4 lines

Should this carry a Fixes: tag pointing at the commit that introduced the fragile comparison?

Fixes 803f0700a3bb ("bpf: Show precise link_type for {uprobe,kprobe}_multi fdinfo")

hum, I don't think so, it wasn't really a bug until this change

jirka

Quoted 7 lines

---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27201419867

#7 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

In reply to Jiri Olsa

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3244

Quoted 3 lines · Jiri Olsa
kernel/trace/bpf_trace.c +1 -1
 	flags = attr->link_create.uprobe_multi.flags;
-	if (flags & ~BPF_F_UPROBE_MULTI_RETURN)
+	if (flags & ~(BPF_F_UPROBE_MULTI_RETURN|BPF_F_UPROBE_MULTI_PATH_FD))

In addition to what bots said, pls run checkpatch on above. It should complain of lack of ' '.

#8 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

Quoted 7 lines · Alexei Starovoitov

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3244

Quoted 3 lines · Jiri Olsa
kernel/trace/bpf_trace.c +1 -1
 	flags = attr->link_create.uprobe_multi.flags;
-	if (flags & ~BPF_F_UPROBE_MULTI_RETURN)
+	if (flags & ~(BPF_F_UPROBE_MULTI_RETURN|BPF_F_UPROBE_MULTI_PATH_FD))

In addition to what bots said, pls run checkpatch on above. It should complain of lack of ' '.

it complains only about a typo..

jirka

---

jolsa@krava:~/kernel$ ./scripts/checkpatch.pl 0002-bpf-Add-support-to-specify-uprobe_multi-target-via-f.patch 
WARNING: Possible repeated word: 'need'
#17: 
we need need to read the binary first to get probes offsets, so I'm

total: 0 errors, 1 warnings, 119 lines checked

NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.

0002-bpf-Add-support-to-specify-uprobe_multi-target-via-f.patch has style problems, please review.

NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.

#9 lore raw

Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor

Quoted 10 lines · Jiri Olsa
Quoted 7 lines · Alexei Starovoitov

kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3244

Quoted 3 lines · Jiri Olsa
kernel/trace/bpf_trace.c +1 -1
 	flags = attr->link_create.uprobe_multi.flags;
-	if (flags & ~BPF_F_UPROBE_MULTI_RETURN)
+	if (flags & ~(BPF_F_UPROBE_MULTI_RETURN|BPF_F_UPROBE_MULTI_PATH_FD))

In addition to what bots said, pls run checkpatch on above. It should complain of lack of ' '.

it complains only about a typo..

ah the --strict option that triggers that.. will fix

jirka

author reviewer
#10 lore raw

PATCH 3/6 libbpf: Add path_fd to struct bpf_link_create_opts

In reply to Jiri Olsa

Adding the path_fd field to struct bpf_link_create_opts and passing it through kernel attr interface.

Assisted-by Codex:GPT-5.4
---
 tools/lib/bpf/bpf.c | 1 +
 tools/lib/bpf/bpf.h | 3 ++-
 2 files changed, 3 insertions(+), 1 deletion(-)
tools/lib/bpf/bpf.c +1 -0
index f37e3416f61a..96819c082c77 100644
@@ -842,6 +842,7 @@ int bpf_link_create(int prog_fd, int target_fd,
 		attr.link_create.uprobe_multi.ref_ctr_offsets = ptr_to_u64(OPTS_GET(opts, uprobe_multi.ref_ctr_offsets, 0));
 		attr.link_create.uprobe_multi.cookies = ptr_to_u64(OPTS_GET(opts, uprobe_multi.cookies, 0));
 		attr.link_create.uprobe_multi.pid = OPTS_GET(opts, uprobe_multi.pid, 0);
+		attr.link_create.uprobe_multi.path_fd = OPTS_GET(opts, uprobe_multi.path_fd, 0);
 		if (!OPTS_ZEROED(opts, uprobe_multi))
 			return libbpf_err(-EINVAL);
 		break;
tools/lib/bpf/bpf.h +2 -1
index 012354131cf6..7534a593edae 100644
@@ -444,6 +444,7 @@ struct bpf_link_create_opts {
 			const unsigned long *ref_ctr_offsets;
 			const __u64 *cookies;
 			__u32 pid;
+			__u32 path_fd;
 		} uprobe_multi;
 		struct {
 			__u64 cookie;
@@ -477,7 +478,7 @@ struct bpf_link_create_opts {
 	};
 	size_t :0;
 };
-#define bpf_link_create_opts__last_field uprobe_multi.pid
+#define bpf_link_create_opts__last_field uprobe_multi.path_fd
 
 LIBBPF_API int bpf_link_create(int prog_fd, int target_fd,
 			       enum bpf_attach_type attach_type,
Signature · 1 line
2.54.0
author reviewer
#11 lore raw

PATCH 4/6 selftests/bpf: Add uprobe_multi path_fd test

In reply to Jiri Olsa

Add a uprobe_multi link API selftest that opens /proc/self/exe and passes the resulting descriptor through opts.uprobe_multi.path_fd with BPF_F_UPROBE_MULTI_PATH_FD set.

Assisted-by Codex:GPT-5.4
---
 .../bpf/prog_tests/uprobe_multi_test.c        | 62 +++++++++++++++++++
 1 file changed, 62 insertions(+)
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +62 -0
index 56cbea280fbd..8c9eba1d4084 100644
@@ -2,6 +2,7 @@
 
 #include <unistd.h>
 #include <pthread.h>
+#include <fcntl.h>
 #include <test_progs.h>
 #include "uprobe_multi.skel.h"
 #include "uprobe_multi_bench.skel.h"
@@ -757,6 +758,65 @@ static void test_link_api(void)
 	__test_link_api(&child);
 }
 
+static void test_link_api_path_fd(void)
+{
+	const char *resolve_path = "/proc/self/exe";
+	LIBBPF_OPTS(bpf_link_create_opts, opts);
+	int prog_fd, link_fd = -1, path_fd = -1;
+	struct uprobe_multi *skel = NULL;
+	unsigned long *offsets = NULL;
+	const char *syms[3] = {
+		"uprobe_multi_func_1",
+		"uprobe_multi_func_2",
+		"uprobe_multi_func_3",
+	};
+	int err;
+
+	err = elf_resolve_syms_offsets(resolve_path, ARRAY_SIZE(syms), syms,
+				       &offsets, STT_FUNC);
+	if (!ASSERT_OK(err, "elf_resolve_syms_offsets"))
+		return;
+
+	path_fd = open(resolve_path, O_RDONLY);
+	if (!ASSERT_GE(path_fd, 0, "path_fd"))
+		goto cleanup;
+
+	opts.uprobe_multi.path_fd = path_fd;
+	opts.uprobe_multi.offsets = offsets;
+	opts.uprobe_multi.cnt = ARRAY_SIZE(syms);
+	opts.uprobe_multi.flags = BPF_F_UPROBE_MULTI_PATH_FD;
+
+	skel = uprobe_multi__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "uprobe_multi__open_and_load"))
+		goto cleanup;
+
+	prog_fd = bpf_program__fd(skel->progs.uprobe);
+	link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts);
+	if (!ASSERT_GE(link_fd, 0, "bpf_link_create"))
+		goto cleanup;
+
+	skel->bss->uprobe_multi_func_1_addr = (__u64)uprobe_multi_func_1;
+	skel->bss->uprobe_multi_func_2_addr = (__u64)uprobe_multi_func_2;
+	skel->bss->uprobe_multi_func_3_addr = (__u64)uprobe_multi_func_3;
+	skel->bss->pid = getpid();
+
+	uprobe_multi_func_1();
+	uprobe_multi_func_2();
+	uprobe_multi_func_3();
+
+	ASSERT_EQ(skel->bss->uprobe_multi_func_1_result, 1, "uprobe_multi_func_1_result");
+	ASSERT_EQ(skel->bss->uprobe_multi_func_2_result, 1, "uprobe_multi_func_2_result");
+	ASSERT_EQ(skel->bss->uprobe_multi_func_3_result, 1, "uprobe_multi_func_3_result");
+
+cleanup:
+	if (link_fd >= 0)
+		close(link_fd);
+	if (path_fd >= 0)
+		close(path_fd);
+	uprobe_multi__destroy(skel);
+	free(offsets);
+}
+
 static struct bpf_program *
 get_program(struct uprobe_multi_consumers *skel, int prog)
 {
@@ -1354,6 +1414,8 @@ void test_uprobe_multi_test(void)
 		test_attach_api_syms();
 	if (test__start_subtest("link_api"))
 		test_link_api();
+	if (test__start_subtest("link_api_path_fd"))
+		test_link_api_path_fd();
 	if (test__start_subtest("bench_uprobe"))
 		test_bench_attach_uprobe();
 	if (test__start_subtest("bench_usdt"))
Signature · 1 line
2.54.0
author reviewer
#12 lore raw

PATCH 5/6 selftests/bpf: Add uprobe_multi path_fd fail tests

In reply to Jiri Olsa

Adding tests to attach_api_fails suite to make sure we fail wrong setup for path_fd usage.

---
 .../bpf/prog_tests/uprobe_multi_test.c        | 32 ++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +31 -1
index 8c9eba1d4084..71eea809dce3 100644
@@ -537,7 +537,37 @@ static void test_attach_api_fails(void)
 	link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts);
 	if (!ASSERT_ERR(link_fd, "link_fd"))
 		goto cleanup;
-	ASSERT_EQ(link_fd, -EINVAL, "pid_is_wrong");
+	if (!ASSERT_EQ(link_fd, -EINVAL, "pid_is_wrong"))
+		goto cleanup;
+
+	/* wrong path_fd */
+	LIBBPF_OPTS_RESET(opts,
+		.uprobe_multi.path = NULL,
+		.uprobe_multi.path_fd = -1,
+		.uprobe_multi.flags = BPF_F_UPROBE_MULTI_PATH_FD,
+		.uprobe_multi.offsets = (unsigned long *) &offset,
+		.uprobe_multi.cnt = 1,
+	);
+
+	link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts);
+	if (!ASSERT_ERR(link_fd, "link_fd"))
+		goto cleanup;
+	if (!ASSERT_EQ(link_fd, -EBADF, "path_fd_is_wrong"))
+		goto cleanup;
+
+	/* path and path_fd both set with BPF_F_UPROBE_MULTI_PATH_FD flag */
+	LIBBPF_OPTS_RESET(opts,
+		.uprobe_multi.path = path,
+		.uprobe_multi.path_fd = 1,
+		.uprobe_multi.flags = BPF_F_UPROBE_MULTI_PATH_FD,
+		.uprobe_multi.offsets = (unsigned long *) &offset,
+		.uprobe_multi.cnt = 1,
+	);
+
+	link_fd = bpf_link_create(prog_fd, 0, BPF_TRACE_UPROBE_MULTI, &opts);
+	if (!ASSERT_ERR(link_fd, "link_fd"))
+		goto cleanup;
+	ASSERT_EQ(link_fd, -EINVAL, "path_and_path_fd_together");
 
 cleanup:
 	if (link_fd >= 0)
Signature · 1 line
2.54.0
author reviewer
#13 lore raw

PATCH 6/6 selftests/bpf: Fix typo in verify_umulti_link_info

In reply to Jiri Olsa

We verify info.uprobe_multi.flags against wrong kprobe-multi flag (BPF_F_KPROBE_MULTI_RETURN). It's the same value as the correct flag (BPF_F_UPROBE_MULTI_RETURN), so there's not functional change.

---
 tools/testing/selftests/bpf/prog_tests/fill_link_info.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
tools/testing/selftests/bpf/prog_tests/fill_link_info.c +1 -1
index e40114620751..f589eefbf9fb 100644
@@ -469,7 +469,7 @@ verify_umulti_link_info(int fd, bool retprobe, __u64 *offsets,
 
 		ASSERT_EQ(info.uprobe_multi.pid, getpid(), "info.uprobe_multi.pid");
 		ASSERT_EQ(info.uprobe_multi.count, 3, "info.uprobe_multi.count");
-		ASSERT_EQ(info.uprobe_multi.flags & BPF_F_KPROBE_MULTI_RETURN,
+		ASSERT_EQ(info.uprobe_multi.flags & BPF_F_UPROBE_MULTI_RETURN,
 			  retprobe, "info.uprobe_multi.flags.retprobe");
 		ASSERT_EQ(info.uprobe_multi.path_size, strlen(path) + 1, "info.uprobe_multi.path_size");
 		ASSERT_STREQ(path_buf, path, "info.uprobe_multi.path");
Signature · 1 line
2.54.0