bpf: Allow uprobe_multi binary specified by file descriptor
Subsystems (8)
Jiri Olsa
reviewercover 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(-)
Jiri Olsa
reviewerPATCH 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
@@ -3226,7 +3226,6 @@ int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *prvoid __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
Jiri Olsa
reviewerPATCH 2/6 bpf: Add support to specify uprobe_multi target via file descriptor
In reply to Jiri OlsaAllow 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.
--- 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
@@ -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
@@ -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_fdstatic int link_create (union bpf_attr *attr,bpfptr_t uattr) {struct bpf_prog *prog;
kernel/trace/bpf_trace.c +30 -7
@@ -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 *prreturn -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
@@ -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
[email protected]
AI reviewRe: [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
[ ... ]
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
-2uref_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
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 unusedpath_fdfield when theBPF_F_UPROBE_MULTI_PATH_FDflag is not set.
- [Low] Mixing scope-based cleanup (CLASS()) withgoto-based error handling inbpf_uprobe_multi_link_attach. --commit
f7958ff1ce57c1ab456d3f134881a0081a58b8ed
Author: Jiri Olsa <[email protected]>bpf: Add support to specify
uprobe_multitarget via file descriptorThis commit adds the
BPF_F_UPROBE_MULTI_PATH_FDflag to allowuprobe_multilinks 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[ ... ]
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
-2uref_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 unusedpath_fdfield here?
Quoted 7 lines
When the
BPF_F_UPROBE_MULTI_PATH_FDflag is not set, this branch is taken andattr->link_create.uprobe_multi.path_fdis 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_fdneeds 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
[email protected]
AI reviewRe: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor
In reply to Jiri OlsaThis 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_multilink to identify the target binary by an already opened file descriptor.Adding new
BPF_F_UPROBE_MULTI_PATH_FDflag and thepath_fdfield 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_PATHfile descriptors, because we need need to read the binary first to get probes offsets, so I'm using theCLASS(fd, f), which fails forO_PATHfds.Assisted-by Codex:GPT-5.4Signed-off-by Jiri Olsa <[email protected]>
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?
---
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
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_multilink to identify the target binary by an already opened file descriptor.Adding new
BPF_F_UPROBE_MULTI_PATH_FDflag and thepath_fdfield 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_PATHfile descriptors, because we need need to read the binary first to get probes offsets, so I'm using theCLASS(fd, f), which fails forO_PATHfds.Assisted-by Codex:GPT-5.4Signed-off-by Jiri Olsa <[email protected]>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 whileBPF_F_UPROBE_MULTI_RETURNwas the only defineduprobe_multiflag. This commit adds a second flag (BPF_F_UPROBE_MULTI_PATH_FD), so the exact "==" comparison would misreport auretprobe_multilink 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.mdCI run summary: https://github.com/kernel-patches/bpf/actions/runs/27201419867
Re: [PATCH bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor
In reply to Jiri Olsakernel/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
-1flags = 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 ' '.
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
-1flags = 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.
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
-1flags = 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
Jiri Olsa
reviewerPATCH 3/6 libbpf: Add path_fd to struct bpf_link_create_opts
In reply to Jiri OlsaAdding the path_fd field to struct bpf_link_create_opts and passing it through kernel attr interface.
--- 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
@@ -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
@@ -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
Jiri Olsa
reviewerPATCH 4/6 selftests/bpf: Add uprobe_multi path_fd test
In reply to Jiri OlsaAdd 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.
--- .../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
@@ -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
Jiri Olsa
reviewerPATCH 5/6 selftests/bpf: Add uprobe_multi path_fd fail tests
In reply to Jiri OlsaAdding 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
@@ -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
Jiri Olsa
reviewerPATCH 6/6 selftests/bpf: Fix typo in verify_umulti_link_info
In reply to Jiri OlsaWe 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
@@ -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