bpf: Allow uprobe_multi binary specified by file descriptor
Subsystems (8)
Jiri Olsa
reviewerv2 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.
v1: https://lore.kernel.org/bpf/[email protected]/T/#m0275d5f39805c57dc8fd3308c640237dc7aec4db
v2 changes:
- move path retrieval in separate function so CLASS(..) is not used in function with goto-based cleanup [sashiko]
- force zero path_fd in case BPF_F_UPROBE_MULTI_PATH_FD is not set [sashiko]
- add space around | in bpf_uprobe_multi_link_attach [Alexei]
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 | 51 +++++++++++++++++++++++++++----------- 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, 148 insertions(+), 21 deletions(-)
Jiri Olsa
reviewerPATCH v2 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
[email protected]
AI reviewRe: [PATCHv2 bpf-next 1/6] bpf: Use user_path_at for path resolution in uprobe_multi
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Missing access_ok() checks before calling __get_user() on user-controlled arrays, leading to arbitrary kernel memory read. --
commit e18574361f20d4f27005e4d927610e3ce16986dd
Author: Jiri Olsa <[email protected]>
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.
Quoted 4 lines
kernel/trace/bpf_trace.c +0
-0
[ ... ]
Quoted 6 lines
kernel/trace/bpf_trace.c +0
-2@@ -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)) {
kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3266
Quoted 10 lines
kernel/trace/bpf_trace.c +1
-6- 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;
[Severity: Critical]
This isn't a bug introduced by this patch, but while looking at bpf_uprobe_multi_link_attach(), I noticed the user-provided arrays uoffsets, uref_ctr_offsets, and ucookies are accessed shortly after this path resolution:
kernel/trace/bpf_trace.c:bpf_uprobe_multi_link_attach() {
...
if (__get_user(uprobes[i].offset, uoffsets + i)) {
...
if (uref_ctr_offsets && __get_user(uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) {
...
if (ucookies && __get_user(uprobes[i].cookie, ucookies + i)) {
...
}Are these arrays validated with access_ok() before __get_user() is called?
Because __get_user() bypasses the access_ok() address-space bounds check on most architectures, could an attacker supply kernel addresses for these arrays, causing the kernel to read arbitrary memory and store it into the uprobes structures?
If an attacker retrieves these contents by querying the link info via bpf_obj_get_info_by_fd() (which calls bpf_uprobe_multi_link_fill_link_info() and copies the memory back to user space), could this act as an arbitrary kernel memory read primitive to bypass kernel lockdown and KASLR?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCHv2 bpf-next 1/6] bpf: Use user_path_at for path resolution in uprobe_multi
Quoted 62 lines · On Wed, Jun 10, 2026 at 02:52:35PM +0000, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Missingaccess_ok()checks before calling__get_user()on user-controlled arrays, leading to arbitrary kernel memory read. --commit
e18574361f20d4f27005e4d927610e3ce16986dd
Author: Jiri Olsa <[email protected]>bpf: Use
user_path_atfor path resolution inuprobe_multiResolve the
uprobe_multiuser path withuser_path_at()instead of copying the string withstrndup_user()and passing it tokern_path(). This removes the temporary allocation and keeps the lookup logic in one helper.Quoted 4 lines
kernel/trace/bpf_trace.c +0
-0[ ... ]
Quoted 6 lines
kernel/trace/bpf_trace.c +0
-2@@ -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)) {kernel/trace/bpf_trace.c int bpf_uprobe_multi_link_attach(const union bpf_attr *attr, struct bpf_prog *pr · line 3266
Quoted 10 lines
kernel/trace/bpf_trace.c +1
-6- 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;[Severity: Critical]
This isn't a bug introduced by this patch, but while looking atbpf_uprobe_multi_link_attach(), I noticed the user-provided arrays uoffsets,uref_ctr_offsets, and ucookies are accessed shortly after this path resolution:kernel/trace/bpf_trace.c:bpf_uprobe_multi_link_attach() { ... if (__get_user(uprobes[i].offset, uoffsets + i)) { ... if (uref_ctr_offsets && __get_user(uprobes[i].ref_ctr_offset, uref_ctr_offsets + i)) { ... if (ucookies && __get_user(uprobes[i].cookie, ucookies + i)) { ... }Are these arrays validated with
access_ok()before__get_user()is called?Because
__get_user()bypasses theaccess_ok()address-space bounds check on most architectures, could an attacker supply kernel addresses for these arrays, causing the kernel to read arbitrary memory and store it into the uprobes structures?
Quoted 4 lines
If an attacker retrieves these contents by querying the link info via
bpf_obj_get_info_by_fd()(which callsbpf_uprobe_multi_link_fill_link_info()and copies the memory back to user space), could this act as an arbitrary kernel memory read primitive to bypass kernel lockdown and KASLR?
ugh right.. will include fix for this in next version
jirka
Jiri Olsa
reviewerPATCH v2 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 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 | 43 +++++++++++++++++++++++++++++----- tools/include/uapi/linux/bpf.h | 7 +++++- 4 files changed, 51 insertions(+), 10 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 +37 -6
82 lines not on this page · raw message
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: [PATCHv2 bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor
This change in bpf_link_show_fdinfo() switches the uprobe_multi check from an equality test to a bitwise test. Once a second flag bit exists (the BPF_F_UPROBE_MULTI_PATH_FD flag added by this same…
kernel/bpf/syscall.c static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp) · line 3479
Quoted 11 lines
kernel/bpf/syscall.c +1
-1@@ -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");
This change in bpf_link_show_fdinfo() switches the uprobe_multi check from an equality test to a bitwise test. Once a second flag bit exists (the BPF_F_UPROBE_MULTI_PATH_FD flag added by this same patch), a uretprobe_multi link created with both flags set would be misreported as "uprobe_multi" because the equality test no longer matches.
The equality comparison was introduced in:
803f0700a3bb ("bpf: Show precise link_type for {uprobe,kprobe}_multi fdinfo")
Should this change include:
Quoted 15 lines
kernel/trace/bpf_trace.c +7
-0@@ -3214,6 +3215,38 @@ static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx)return run_ctx->uprobe->cookie; } +static int bpf_uprobe_multi_get_path (const union bpf_attr *attr,struct path *path) +{ +void __user *upath =u64_to_user_ptr (attr->link_create.uprobe_multi.path); +u32 path_fd = attr->link_create.uprobe_multi.path_fd; +u32 flags = attr->link_create.uprobe_multi.flags; + +if (flags &BPF_F_UPROBE_MULTI_PATH_FD ) {
[ ... ]
kernel/trace/bpf_trace.c static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) · line 3245
Quoted 8 lines
kernel/trace/bpf_trace.c +8
-0+ } + +/* +* 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 || path_fd) +return -EINVAL ;
This isn't a bug, but the non-FD branch (taken when BPF_F_UPROBE_MULTI_PATH_FD is not set) reads path_fd in the check 'if (!upath || path_fd)'.
path_fd is only meaningful when BPF_F_UPROBE_MULTI_PATH_FD is set. A caller that supplies a valid string path but leaves path_fd as non-zero garbage (in a struct large enough to include path_fd) would get a spurious -EINVAL here.
The garbage value is never dereferenced or used for arithmetic, so this looks more like defensive input validation than a dangerous use, and old-style callers passing the pre-path_fd struct size get path_fd zeroed and pass cleanly.
Is rejecting a non-zero path_fd in the string-path mode intended, or should path_fd be ignored when the flag is absent?
kernel/trace/bpf_trace.c static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) · line 3248
Quoted 3 lines
kernel/trace/bpf_trace.c +3
-0+ +return user_path_at (AT_FDCWD , upath,LOOKUP_FOLLOW , path); +}
---
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/27284577665
Re: [PATCHv2 bpf-next 2/6] bpf: Add support to specify uprobe_multi target via file descriptor
Quoted 18 lines · On Wed, Jun 10, 2026 at 03:51:39PM +0000, [email protected] wrote:
kernel/bpf/syscall.c static void bpf_link_show_fdinfo(struct seq_file *m, struct file *filp) · line 3479
Quoted 11 lines
kernel/bpf/syscall.c +1
-1@@ -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");This change in
bpf_link_show_fdinfo()switches theuprobe_multicheck from an equality test to a bitwise test. Once a second flag bit exists (theBPF_F_UPROBE_MULTI_PATH_FDflag added by this same patch), auretprobe_multilink created with both flags set would be misreported as "uprobe_multi" because the equality test no longer matches.
Quoted 7 lines
The equality comparison was introduced in:
803f0700a3bb("bpf: Show preciselink_typefor {uprobe,kprobe}_multi fdinfo")Should this change include:
Fixes 803f0700a3bb ("bpf: Show precise link_type for {uprobe,kprobe}_multi fdinfo")
answered this one in previous version
jirka
Quoted 54 lines
Quoted 16 lines
kernel/trace/bpf_trace.c +7
-0@@ -3214,6 +3215,38 @@ static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx)return run_ctx->uprobe->cookie; } +static int bpf_uprobe_multi_get_path (const union bpf_attr *attr,struct path *path) +{ +void __user *upath =u64_to_user_ptr (attr->link_create.uprobe_multi.path); +u32 path_fd = attr->link_create.uprobe_multi.path_fd; +u32 flags = attr->link_create.uprobe_multi.flags; + +if (flags &BPF_F_UPROBE_MULTI_PATH_FD ) {[ ... ]
kernel/trace/bpf_trace.c static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) · line 3245
Quoted 8 lines
kernel/trace/bpf_trace.c +8
-0+ } + +/* +* 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 || path_fd) +return -EINVAL ;This isn't a bug, but the non-FD branch (taken when
BPF_F_UPROBE_MULTI_PATH_FDis not set) readspath_fdin the check 'if (!upath ||path_fd)'.
path_fdis only meaningful whenBPF_F_UPROBE_MULTI_PATH_FDis set. A caller that supplies a valid string path but leavespath_fdas non-zero garbage (in a struct large enough to includepath_fd) would get a spurious-EINVALhere.The garbage value is never dereferenced or used for arithmetic, so this looks more like defensive input validation than a dangerous use, and old-style callers passing the pre-path_fd struct size get
path_fdzeroed and pass cleanly.Is rejecting a non-zero
path_fdin the string-path mode intended, or shouldpath_fdbe ignored when the flag is absent?kernel/trace/bpf_trace.c static u64 bpf_uprobe_multi_cookie(struct bpf_run_ctx *ctx) · line 3248
Quoted 3 lines
kernel/trace/bpf_trace.c +3
-0+ +return user_path_at (AT_FDCWD , upath,LOOKUP_FOLLOW , path); +}---
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/27284577665
Jiri Olsa
reviewerPATCH v2 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
[email protected]
AI reviewRe: [PATCHv2 bpf-next 3/6] libbpf: Add path_fd to struct bpf_link_create_opts
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] Compilation fails due to missing `path_fd` in the `uprobe_multi` UAPI struct. --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Compilation fails due to missing path_fd in the uprobe_multi UAPI struct. --
commit c73ec6f8d6c5a6bb4c8a75f70c333cac0d6d30d4
Author: Jiri Olsa <[email protected]>
libbpf: Add path_fd to struct bpf_link_create_opts
This commit adds the path_fd field to struct bpf_link_create_opts for uprobe_multi. It passes this new field through the kernel attribute interface.
tools/lib/bpf/bpf.c int bpf_link_create(int prog_fd, int target_fd, · line 845
Quoted 9 lines
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 );
[Severity: Low]
Will this assignment cause a build failure?
Looking at the UAPI header in tools/include/uapi/linux/bpf.h, the uprobe_multi struct inside union bpf_attr doesn't appear to have a path_fd member:
struct {
__aligned_u64 path;
__aligned_u64 offsets;
__aligned_u64 ref_ctr_offsets;
__aligned_u64 cookies;
__u32 cnt;
__u32 flags;
__u32 pid;
} uprobe_multi;Should the path_fd member be added to the UAPI bpf_attr union as well?
Quoted 3 lines
tools/lib/bpf/bpf.c +0
-0if (!OPTS_ZEROED (opts, uprobe_multi))return libbpf_err (-EINVAL );break ;
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCHv2 bpf-next 3/6] libbpf: Add path_fd to struct bpf_link_create_opts
Quoted 25 lines · On Wed, Jun 10, 2026 at 02:50:18PM +0000, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] Compilation fails due to missingpath_fdin theuprobe_multiUAPI struct. --commit
c73ec6f8d6c5a6bb4c8a75f70c333cac0d6d30d4
Author: Jiri Olsa <[email protected]>libbpf: Add
path_fdto structbpf_link_create_optsThis commit adds the
path_fdfield to structbpf_link_create_optsforuprobe_multi. It passes this new field through the kernel attribute interface.tools/lib/bpf/bpf.c int bpf_link_create(int prog_fd, int target_fd, · line 845
Quoted 9 lines
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 );[Severity: Low]
Will this assignment cause a build failure?
Quoted 3 lines
Looking at the UAPI header in
tools/include/uapi/linux/bpf.h, theuprobe_multistruct inside unionbpf_attrdoesn't appear to have apath_fdmember:
compiles fine, path_fd was added in previous patch
jirka
Quoted 19 lines
struct { __aligned_u64 path; __aligned_u64 offsets; __aligned_u64 ref_ctr_offsets; __aligned_u64 cookies; __u32 cnt; __u32 flags; __u32 pid; } uprobe_multi;Should the
path_fdmember be added to the UAPIbpf_attrunion as well?Quoted 3 lines
tools/lib/bpf/bpf.c +0
-0if (!OPTS_ZEROED (opts, uprobe_multi))return libbpf_err (-EINVAL );break ;Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Jiri Olsa
reviewerPATCH v2 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 ) +{ +LIBBPF_OPTS (bpf_link_create_opts, opts); +const char *resolve_path ="/proc/self/exe" ; +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
[email protected]
AI reviewRe: [PATCHv2 bpf-next 4/6] selftests/bpf: Add uprobe_multi path_fd test
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] The selftest references a nonexistent struct member `path_fd` and an undeclared flag…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The selftest references a nonexistent struct member path_fd and an undeclared flag BPF_F_UPROBE_MULTI_PATH_FD, which will cause a compilation error. --
commit e5937d581d08ece9671b371d37fb6cd0d497b692
Author: Jiri Olsa <[email protected]>
selftests/bpf: Add uprobe_multi path_fd test
This commit adds 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.
Quoted 4 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +0
-0
[ ... ]
Quoted 9 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +5
-0@@ -757,6 +758,65 @@ static void test_link_api(void)__test_link_api (&child); } +static void test_link_api_path_fd (void ) +{ +LIBBPF_OPTS (bpf_link_create_opts, opts); +const char *resolve_path ="/proc/self/exe" ; +int prog_fd, link_fd =-1 , path_fd =-1 ;
[ ... ]
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c static void test_link_api(void) · line 787
Quoted 8 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +8
-0+ 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 ;
[Severity: Low]
Does this code reference an API that hasn't been introduced yet?
The struct field path_fd is not a valid member of uprobe_multi within struct bpf_link_create_opts in the libbpf headers, and the BPF_F_UPROBE_MULTI_PATH_FD macro is undeclared.
Because the patch doesn't include the corresponding kernel or libbpf changes, it looks like this will cause a compilation error.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCHv2 bpf-next 4/6] selftests/bpf: Add uprobe_multi path_fd test
Quoted 44 lines · On Wed, Jun 10, 2026 at 02:50:45PM +0000, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The selftest references a nonexistent struct memberpath_fdand an undeclared flagBPF_F_UPROBE_MULTI_PATH_FD, which will cause a compilation error. --commit
e5937d581d08ece9671b371d37fb6cd0d497b692
Author: Jiri Olsa <[email protected]>selftests/bpf: Add
uprobe_multipath_fdtestThis commit adds a
uprobe_multilink API selftest that opens/proc/self/exeand passes the resulting descriptor through opts.uprobe_multi.path_fd withBPF_F_UPROBE_MULTI_PATH_FDset.Quoted 4 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +0
-0[ ... ]
Quoted 9 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +5
-0@@ -757,6 +758,65 @@ static void test_link_api(void)__test_link_api (&child); } +static void test_link_api_path_fd (void ) +{ +LIBBPF_OPTS (bpf_link_create_opts, opts); +const char *resolve_path ="/proc/self/exe" ; +int prog_fd, link_fd =-1 , path_fd =-1 ;[ ... ]
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c static void test_link_api(void) · line 787
Quoted 8 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +8
-0+ 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 ;[Severity: Low]
Does this code reference an API that hasn't been introduced yet?
Quoted 6 lines
The struct field
path_fdis not a valid member ofuprobe_multiwithin structbpf_link_create_optsin the libbpf headers, and theBPF_F_UPROBE_MULTI_PATH_FDmacro is undeclared.Because the patch doesn't include the corresponding kernel or libbpf changes, it looks like this will cause a compilation error.
compiles fine, it was introduced in:
bpf: Add support to specify uprobe_multi target via file descriptor
jirka
Jiri Olsa
reviewerPATCH v2 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
[email protected]
AI reviewRe: [PATCHv2 bpf-next 5/6] selftests/bpf: Add uprobe_multi path_fd fail tests
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] The patch references an undefined struct member `path_fd` and an undeclared macro…
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The patch references an undefined struct member path_fd and an undeclared macro BPF_F_UPROBE_MULTI_PATH_FD, which will cause compilation to fail. --
commit 0e3f7d4f9ed46a64d02a1c29acb4f8e2215cb7c0
Author: Jiri Olsa <[email protected]>
selftests/bpf: Add uprobe_multi path_fd fail tests
This commit adds tests to the attach_api_fails suite to verify that invalid setups using the new path_fd feature in uprobe_multi fail as expected.
Quoted 4 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +0
-0@@ -536,7 +536,37 @@ static void test_attach_api_fails(void)
[ ... ]
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c static void test_attach_api_fails(void) · line 547
Quoted 9 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +8
-1-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,
[Severity: Low]
Does this commit depend on a missing prerequisite patch?
The path_fd member and BPF_F_UPROBE_MULTI_PATH_FD macro do not appear to be defined in the current tree's bpf_link_create_opts struct or UAPI headers, which will cause a compilation failure here.
Quoted 18 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +18
-0+ .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, + );
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Re: [PATCHv2 bpf-next 5/6] selftests/bpf: Add uprobe_multi path_fd fail tests
Quoted 33 lines · On Wed, Jun 10, 2026 at 02:48:21PM +0000, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] The patch references an undefined struct memberpath_fdand an undeclared macroBPF_F_UPROBE_MULTI_PATH_FD, which will cause compilation to fail. --commit
0e3f7d4f9ed46a64d02a1c29acb4f8e2215cb7c0
Author: Jiri Olsa <[email protected]>selftests/bpf: Add
uprobe_multipath_fdfail testsThis commit adds tests to the
attach_api_failssuite to verify that invalid setups using the newpath_fdfeature inuprobe_multifail as expected.Quoted 4 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +0
-0@@ -536,7 +536,37 @@ static void test_attach_api_fails(void)[ ... ]
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c static void test_attach_api_fails(void) · line 547
Quoted 9 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +8
-1-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,[Severity: Low]
Does this commit depend on a missing prerequisite patch?
Quoted 3 lines
The
path_fdmember andBPF_F_UPROBE_MULTI_PATH_FDmacro do not appear to be defined in the current tree'sbpf_link_create_optsstruct or UAPI headers, which will cause a compilation failure here.
it compiles fine, it was added in this commit:
bpf: Add support to specify uprobe_multi target via file descriptor
jirka
Quoted 22 lines
Quoted 19 lines
tools/testing/selftests/bpf/prog_tests/uprobe_multi_test.c +18
-0+ .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, + );Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Jiri Olsa
reviewerPATCH v2 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