* [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading
@ 2026-05-29 3:16 chenyuan_fl
2026-05-29 3:39 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-05-29 3:16 UTC (permalink / raw)
To: bpf; +Cc: andrii, eddyz87, ast, daniel, shuah, linux-kselftest, Yuan Chen
From: Yuan Chen <chenyuan@kylinos.cn>
The bpf_object__prepare() function internally calls bpf_object__probe_loading(),
which attempts to load SOCKET_FILTER and TRACEPOINT programs to verify the BPF
environment. Without these permissions in the token, the probe fails and causes
the tests to fail.
Fix the following test cases by adding SOCKET_FILTER and TRACEPOINT permissions:
- obj_priv_map
- obj_priv_prog
- obj_priv_freplace_prog
- obj_priv_freplace_prog_fail
- obj_priv_btf_fail
- obj_priv_btf_success
- obj_priv_implicit_token
- obj_priv_implicit_token_envvar
- obj_priv_prog_kallsyms
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
.../testing/selftests/bpf/prog_tests/token.c | 68 ++++++++++++++-----
1 file changed, 51 insertions(+), 17 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
index f2f5d36ae00a..25a76e09a3c9 100644
--- a/tools/testing/selftests/bpf/prog_tests/token.c
+++ b/tools/testing/selftests/bpf/prog_tests/token.c
@@ -1168,8 +1168,13 @@ void serial_test_token(void)
}
if (test__start_subtest("obj_priv_map")) {
struct bpffs_opts opts = {
- .cmds = bit(BPF_MAP_CREATE),
+ /* BPF_PROG_LOAD is needed for bpf_object__probe_loading */
+ .cmds = bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
.maps = bit(BPF_MAP_TYPE_QUEUE),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
+ .attachs = ~0ULL,
};
subtest_userns(&opts, userns_obj_priv_map);
@@ -1177,7 +1182,10 @@ void serial_test_token(void)
if (test__start_subtest("obj_priv_prog")) {
struct bpffs_opts opts = {
.cmds = bit(BPF_PROG_LOAD),
- .progs = bit(BPF_PROG_TYPE_XDP),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_XDP) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
@@ -1185,16 +1193,24 @@ void serial_test_token(void)
}
if (test__start_subtest("obj_priv_freplace_prog")) {
struct bpffs_opts opts = {
- .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID),
- .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP),
+ .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) |
+ bit(BPF_BTF_GET_FD_BY_ID),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
subtest_userns(&opts, userns_obj_priv_freplace_prog);
}
if (test__start_subtest("obj_priv_freplace_prog_fail")) {
struct bpffs_opts opts = {
- .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) | bit(BPF_BTF_GET_FD_BY_ID),
- .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP),
+ .cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD) |
+ bit(BPF_BTF_GET_FD_BY_ID),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_EXT) | bit(BPF_PROG_TYPE_XDP) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
subtest_userns(&opts, userns_obj_priv_freplace_prog_fail);
@@ -1204,7 +1220,10 @@ void serial_test_token(void)
/* disallow BTF loading */
.cmds = bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
.maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
- .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_STRUCT_OPS) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
@@ -1213,9 +1232,13 @@ void serial_test_token(void)
if (test__start_subtest("obj_priv_btf_success")) {
struct bpffs_opts opts = {
/* allow BTF loading */
- .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
- .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
- .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
+ .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) |
+ bit(BPF_PROG_LOAD),
+ .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_STRUCT_OPS) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
@@ -1224,9 +1247,13 @@ void serial_test_token(void)
if (test__start_subtest("obj_priv_implicit_token")) {
struct bpffs_opts opts = {
/* allow BTF loading */
- .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
- .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
- .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
+ .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) |
+ bit(BPF_PROG_LOAD),
+ .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_STRUCT_OPS) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
@@ -1235,9 +1262,13 @@ void serial_test_token(void)
if (test__start_subtest("obj_priv_implicit_token_envvar")) {
struct bpffs_opts opts = {
/* allow BTF loading */
- .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
- .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
- .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
+ .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) |
+ bit(BPF_PROG_LOAD),
+ .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_STRUCT_OPS) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
@@ -1257,7 +1288,10 @@ void serial_test_token(void)
char kptr_restrict_orig[32] = {};
struct bpffs_opts opts = {
.cmds = bit(BPF_BTF_LOAD) | bit(BPF_PROG_LOAD),
- .progs = bit(BPF_PROG_TYPE_XDP),
+ /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
+ .progs = bit(BPF_PROG_TYPE_XDP) |
+ bit(BPF_PROG_TYPE_SOCKET_FILTER) |
+ bit(BPF_PROG_TYPE_TRACEPOINT),
.attachs = ~0ULL,
};
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading
2026-05-29 3:16 [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading chenyuan_fl
@ 2026-05-29 3:39 ` sashiko-bot
2026-05-29 3:57 ` bot+bpf-ci
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
2 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-05-29 3:39 UTC (permalink / raw)
To: chenyuan_fl; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] The patch masks a libbpf bug by inappropriately expanding token privileges in tests, defeating the purpose of testing fine-grained token delegation.
- [Medium] The patch silently adds BPF_MAP_TYPE_ARRAY and BPF_PROG_LOAD permissions to test options without documenting them in the commit message.
--
commit f600b2d49f35c6ad7110d3da0ab207e0df841447
Author: Yuan Chen <chenyuan@kylinos.cn>
selftests/bpf: fix token tests for bpf_object__prepare() probe_loading
This patch modifies BPF token selftests to add SOCKET_FILTER, TRACEPOINT,
and ARRAY map permissions to various subtests. This is intended to fix test
failures caused by libbpf's internal environment probe loading.
> The bpf_object__prepare() function internally calls bpf_object__probe_loading(),
> which attempts to load SOCKET_FILTER and TRACEPOINT programs to verify the BPF
> environment. Without these permissions in the token, the probe fails and causes
> the tests to fail.
>
> Fix the following test cases by adding SOCKET_FILTER and TRACEPOINT permissions:
[Severity: Medium]
The commit message explicitly mentions adding SOCKET_FILTER and TRACEPOINT
permissions. However, the patch also adds BPF_PROG_LOAD to the obj_priv_map
test, and BPF_MAP_TYPE_ARRAY to several other tests.
Could the commit message be updated to reflect all the changes being made,
or should these undocumented changes be removed?
> diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
> index f2f5d36ae00a4..25a76e09a3c96 100644
> --- a/tools/testing/selftests/bpf/prog_tests/token.c
> +++ b/tools/testing/selftests/bpf/prog_tests/token.c
> @@ -1168,8 +1168,13 @@ void serial_test_token(void)
> }
> if (test__start_subtest("obj_priv_map")) {
> struct bpffs_opts opts = {
> - .cmds = bit(BPF_MAP_CREATE),
> + /* BPF_PROG_LOAD is needed for bpf_object__probe_loading */
> + .cmds = bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> .maps = bit(BPF_MAP_TYPE_QUEUE),
> + /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
> + .progs = bit(BPF_PROG_TYPE_SOCKET_FILTER) |
> + bit(BPF_PROG_TYPE_TRACEPOINT),
> + .attachs = ~0ULL,
> };
[Severity: Medium]
By adding BPF_PROG_LOAD, SOCKET_FILTER, and TRACEPOINT here, does this
defeat the purpose of the obj_priv_map test?
This test appears specifically designed to verify that a token restricted to
only BPF_MAP_CREATE can successfully authorize map-only operations.
If bpf_object__probe_loading() causes the entire object load to abort with
-EPERM when a confined token is used, isn't this a functional bug in libbpf
rather than a test issue?
Should libbpf be fixed to handle probe -EPERM gracefully (or skip probes for
objects without programs) instead of expanding the token privileges in the
tests?
[ ... ]
> @@ -1213,9 +1232,13 @@ void serial_test_token(void)
> if (test__start_subtest("obj_priv_btf_success")) {
> struct bpffs_opts opts = {
> /* allow BTF loading */
> - .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> - .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
> - .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
> + .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) |
> + bit(BPF_PROG_LOAD),
> + .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
> + /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
> + .progs = bit(BPF_PROG_TYPE_STRUCT_OPS) |
> + bit(BPF_PROG_TYPE_SOCKET_FILTER) |
> + bit(BPF_PROG_TYPE_TRACEPOINT),
> .attachs = ~0ULL,
> };
[Severity: Medium]
Is there a specific reason BPF_MAP_TYPE_ARRAY is being added to the
maps allowance here? It seems unrelated to the probe loading fix described
in the commit message.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260529031604.888137-1-chenyuan_fl@163.com?part=1
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading
2026-05-29 3:16 [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading chenyuan_fl
2026-05-29 3:39 ` sashiko-bot
@ 2026-05-29 3:57 ` bot+bpf-ci
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
2 siblings, 0 replies; 25+ messages in thread
From: bot+bpf-ci @ 2026-05-29 3:57 UTC (permalink / raw)
To: chenyuan_fl, bpf
Cc: andrii, eddyz87, ast, daniel, shuah, linux-kselftest, chenyuan,
ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, clm,
ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3193 bytes --]
> The bpf_object__prepare() function internally calls bpf_object__probe_loading(),
> which attempts to load SOCKET_FILTER and TRACEPOINT programs to verify the BPF
> environment. Without these permissions in the token, the probe fails and causes
> the tests to fail.
> Fix the following test cases by adding SOCKET_FILTER and TRACEPOINT permissions:
> - obj_priv_map
> - obj_priv_prog
> - obj_priv_freplace_prog
> - obj_priv_freplace_prog_fail
> - obj_priv_btf_fail
> - obj_priv_btf_success
> - obj_priv_implicit_token
> - obj_priv_implicit_token_envvar
> - obj_priv_prog_kallsyms
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
The commit message describes adding SOCKET_FILTER and TRACEPOINT
permissions, but the patch also adds bit(BPF_PROG_LOAD) to the
obj_priv_map test and bit(BPF_MAP_TYPE_ARRAY) to obj_priv_btf_success,
obj_priv_implicit_token, and obj_priv_implicit_token_envvar.
Could the commit message be updated to describe these additional changes,
or should they be dropped if they are not needed?
This fixes failing token selftests but does not carry a Fixes: tag. The
tests began depending on the probe permissions once they started routing
through bpf_object__prepare(). Commit a024843d92cc introduced the
bpf_object__prepare() call into prog_tests/token.c. Should this include:
Fixes: a024843d92cc ("selftests/bpf: Test freplace from user namespace")
> diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
> index f2f5d36ae00a..25a76e09a3c9 100644
> --- a/tools/testing/selftests/bpf/prog_tests/token.c
> +++ b/tools/testing/selftests/bpf/prog_tests/token.c
> @@ -1168,8 +1168,13 @@ void serial_test_token(void)
> }
> if (test__start_subtest("obj_priv_map")) {
> struct bpffs_opts opts = {
> - .cmds = bit(BPF_MAP_CREATE),
> + /* BPF_PROG_LOAD is needed for bpf_object__probe_loading */
> + .cmds = bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> .maps = bit(BPF_MAP_TYPE_QUEUE),
> + /* Allow SOCKET_FILTER and TRACEPOINT for bpf_object__probe_loading */
> + .progs = bit(BPF_PROG_TYPE_SOCKET_FILTER) |
> + bit(BPF_PROG_TYPE_TRACEPOINT),
> + .attachs = ~0ULL,
> };
>
> subtest_userns(&opts, userns_obj_priv_map);
The obj_priv_map test is meant to verify a token restricted to
BPF_MAP_CREATE. Widening it with BPF_PROG_LOAD, SOCKET_FILTER, TRACEPOINT
and .attachs = ~0ULL relaxes the very restriction the test was checking.
If bpf_object__probe_loading() aborts the entire object load with -EPERM
under a confined token, is that better handled in libbpf, for example by
treating the probe -EPERM gracefully or skipping the probe for objects
that have no programs, rather than expanding the token privileges in the
test?
This was raised on the v1 posting and does not appear to have been
addressed:
https://lore.kernel.org/bpf/20260529031604.888137-1-chenyuan_fl@163.com/
> @@ -1177,7 +1182,10 @@ void serial_test_token(void)
[ ... ]
---
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/26616379941
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes
2026-05-29 3:16 [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading chenyuan_fl
2026-05-29 3:39 ` sashiko-bot
2026-05-29 3:57 ` bot+bpf-ci
@ 2026-06-04 3:10 ` chenyuan_fl
2026-06-04 3:10 ` [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
` (3 more replies)
2 siblings, 4 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-04 3:10 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
From: Yuan Chen <chenyuan@kylinos.cn>
When BPF programs reference global variables (e.g., struct_ops
programs with global data), libbpf creates internal ARRAY maps to
back them. This depends on FEAT_GLOBAL_DATA, which is gated by
feature probes that load test programs (SOCKET_FILTER, KPROBE, etc.)
into the kernel.
In a user namespace with an implicit BPF token, two problems arise:
1. bpf_object__probe_loading() passes the token fd to test program
loads. When the token's allowed program type mask excludes the
probe types, the kernel drops the token reference, causing
subsequent struct_ops loads to fail because the token object
has been released.
2. The feature probe framework uses probe_fd() which returns 0 on
BPF syscall failure, and feat_supported() interprets ret==0 as
"feature absent". The token rescue path only handles ret<0,
so the probe failure is incorrectly cached as a missing feature,
and internal maps for global data are never created.
Together, these cause struct_ops programs referencing global data
to fail verification with "fd X is not pointing to valid bpf_map".
This series fixes both issues:
Patch 1: Skip bpf_object__probe_loading() entirely when a BPF
token is present. Token creation itself proves the
kernel BPF subsystem works.
Patch 2: Add BPF_MAP_TYPE_ARRAY to the token delegation mask for
struct_ops selftests so global data maps can be created.
Patch 3: Fix probe_fd() to return the actual error code instead
of 0 on failure, and add a token-aware rescue path in
feat_supported() for ret<0 cases.
Reproducible by running the implicit token tests with struct_ops in a
user namespace (tools/testing/selftests/bpf, test_progs -t token).
v2:
- Replace the workaround of granting SOCKET_FILTER/KPROBE permissions
in the token with a proper fix at the feature probe level in libbpf.
- probe_fd() now returns the actual error code on failure instead of
0, allowing feat_supported() to distinguish probe errors from
genuine feature absence.
- Add token_fd rescue path in feat_supported() for ret<0 cases.
Yuan Chen (3):
libbpf: Skip bpf_object__probe_loading() when BPF token is in use
selftests/bpf: Add ARRAY map type to token tests that use struct_ops
global data
libbpf: fix feature probe failures for implicit BPF tokens
tools/lib/bpf/features.c | 23 +++++++++++++++++--
tools/lib/bpf/libbpf.c | 10 +++-----
.../testing/selftests/bpf/prog_tests/token.c | 6 ++---
3 files changed, 27 insertions(+), 12 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
@ 2026-06-04 3:10 ` chenyuan_fl
2026-06-04 4:05 ` bot+bpf-ci
2026-06-04 11:16 ` Mykyta Yatsenko
2026-06-04 3:10 ` [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data chenyuan_fl
` (2 subsequent siblings)
3 siblings, 2 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-04 3:10 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
From: Yuan Chen <chenyuan@kylinos.cn>
bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
TRACEPOINT programs to verify the BPF environment works. When a
BPF token is in use with restricted program type permissions, these
probe loads may fail because the token does not allow the specific
program types, even though BPF loading is perfectly functional.
Fix by skipping the probe when a token FD is present: BPF token
creation itself proves the kernel has a working BPF subsystem.
Real BPF issues will be caught during actual program and map loading.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/lib/bpf/libbpf.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ab2071fdd3e8..7e21c5eb9533 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
BPF_EXIT_INSN(),
};
int ret, insn_cnt = ARRAY_SIZE(insns);
- LIBBPF_OPTS(bpf_prog_load_opts, opts,
- .token_fd = obj->token_fd,
- .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
- );
- if (obj->gen_loader)
+ if (obj->gen_loader || obj->token_fd)
return 0;
ret = bump_rlimit_memlock();
@@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
errstr(ret));
/* make sure basic loading works */
- ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0)
- ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0) {
ret = errno;
pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
2026-06-04 3:10 ` [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
@ 2026-06-04 3:10 ` chenyuan_fl
2026-06-04 3:25 ` sashiko-bot
2026-06-08 18:14 ` Andrii Nakryiko
2026-06-04 3:10 ` [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens chenyuan_fl
2026-06-10 14:50 ` [PATCH bpf-next v3 0/2] libbpf: fix implicit BPF token feature probe failures chenyuan_fl
3 siblings, 2 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-04 3:10 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
From: Yuan Chen <chenyuan@kylinos.cn>
obj_priv_btf_success, obj_priv_implicit_token and
obj_priv_implicit_token_envvar use the dummy_st_ops_success skeleton,
whose struct_ops programs reference global variables backed by ARRAY
maps. Without BPF_MAP_TYPE_ARRAY in the token allowed map types,
bpf_object__load() fails because the kernel rejects ARRAY map creation
for global data.
Add BPF_MAP_TYPE_ARRAY to the token permission mask for these three
subtests so their skeletons can load successfully.
This is distinct from the libbpf probe issue: the skeletons genuinely
require ARRAY maps for their global data, not merely for probing.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/testing/selftests/bpf/prog_tests/token.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
index f2f5d36ae00a..1812de87bedb 100644
--- a/tools/testing/selftests/bpf/prog_tests/token.c
+++ b/tools/testing/selftests/bpf/prog_tests/token.c
@@ -1214,7 +1214,7 @@ void serial_test_token(void)
struct bpffs_opts opts = {
/* allow BTF loading */
.cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
- .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
+ .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
.progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
.attachs = ~0ULL,
};
@@ -1225,7 +1225,7 @@ void serial_test_token(void)
struct bpffs_opts opts = {
/* allow BTF loading */
.cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
- .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
+ .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
.progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
.attachs = ~0ULL,
};
@@ -1236,7 +1236,7 @@ void serial_test_token(void)
struct bpffs_opts opts = {
/* allow BTF loading */
.cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
- .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
+ .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
.progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
.attachs = ~0ULL,
};
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
2026-06-04 3:10 ` [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
2026-06-04 3:10 ` [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data chenyuan_fl
@ 2026-06-04 3:10 ` chenyuan_fl
2026-06-04 3:27 ` sashiko-bot
` (2 more replies)
2026-06-10 14:50 ` [PATCH bpf-next v3 0/2] libbpf: fix implicit BPF token feature probe failures chenyuan_fl
3 siblings, 3 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-04 3:10 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
From: Yuan Chen <chenyuan@kylinos.cn>
probe_fd() converts BPF syscall failures to return value 0,
which feat_supported() interprets as 'feature absent' (ret==0),
even when the probe failed due to a BPF token's restricted
program/map type mask.
In a user namespace with an implicit BPF token, the sequence is:
1. bpf_object_open() -> no feat_cache yet -> global cache used
2. bpf_object_prepare_token() -> creates token, sets feat_cache->token_fd
3. bpf_object__create_maps() -> feat_supported() runs probe
-> bpf_prog_load(SOCKET_FILTER) with token -> -EPERM
-> probe_fd(-EPERM) -> returns 0
-> feat_supported sees ret==0 -> FEAT_MISSING
-> internal maps (global data) skipped -> verifier EINVAL
Fix by making probe_fd() return the negative error on failure
instead of 0, so feat_supported() enters the ret<0 path.
Additionally add a token_fd rescue in feat_supported() for the
ret<0 case: when a BPF token is present, a failed feature probe
is treated as 'feature supported' because token creation itself
proves the kernel BPF subsystem works. Real BPF issues will
be caught during actual program/map loading.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/lib/bpf/features.c | 23 +++++++++++++++++++++--
1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
index b7e388f99d0b..f934452e52f0 100644
--- a/tools/lib/bpf/features.c
+++ b/tools/lib/bpf/features.c
@@ -16,7 +16,14 @@ int probe_fd(int fd)
{
if (fd >= 0)
close(fd);
- return fd >= 0;
+ /* Return 1 on success, negative error on failure, so
+ * feat_supported() can distinguish probe errors from
+ * genuine feature absence. When a BPF token is present,
+ * a negative return triggers the rescue path that marks
+ * the feature as SUPPORTED (token creation itself proves
+ * the kernel BPF subsystem works).
+ */
+ return fd >= 0 ? 1 : fd;
}
static int probe_kern_prog_name(int token_fd)
@@ -725,9 +732,21 @@ bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_
} else if (ret == 0) {
WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
} else {
+ /*
+ * A BPF token may restrict which program/map types
+ * are permitted, causing the probe to fail even
+ * though the kernel supports the feature. When a
+ * token is present the probe is best-effort: BPF
+ * token creation itself proves the kernel has a
+ * working BPF subsystem. Real BPF issues will be
+ * caught during actual program/map loading.
+ */
+ if (cache->token_fd)
+ WRITE_ONCE(cache->res[feat_id], FEAT_SUPPORTED);
+ else
+ WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
pr_warn("Detection of kernel %s support failed: %s\n",
feat->desc, errstr(ret));
- WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
}
}
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data
2026-06-04 3:10 ` [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data chenyuan_fl
@ 2026-06-04 3:25 ` sashiko-bot
2026-06-08 18:14 ` Andrii Nakryiko
1 sibling, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-04 3:25 UTC (permalink / raw)
To: chenyuan_fl; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] The patch introduces a test logic asymmetry by adding `BPF_MAP_TYPE_ARRAY` to the positive test `obj_priv_btf_success` but omitting it from the paired negative test `obj_priv_btf_fail`.
--
commit 86da58cc137440e9870bfb020bfbb8bab233e69a
Author: Yuan Chen <chenyuan@kylinos.cn>
selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data
This commit adds BPF_MAP_TYPE_ARRAY to the allowed map types for the token
permissions of three positive subtests: obj_priv_btf_success,
obj_priv_implicit_token, and obj_priv_implicit_token_envvar. This allows
their skeletons to successfully load since they require ARRAY maps for global
data.
> diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
> index f2f5d36ae00a4..1812de87bedb8 100644
> --- a/tools/testing/selftests/bpf/prog_tests/token.c
> +++ b/tools/testing/selftests/bpf/prog_tests/token.c
> @@ -1214,7 +1214,7 @@ void serial_test_token(void)
> struct bpffs_opts opts = {
> /* allow BTF loading */
> .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> - .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
> + .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
[Severity: Medium]
Should the negative test obj_priv_btf_fail also receive this update to its
map permissions?
Looking at obj_priv_btf_fail() earlier in the file, it is designed to verify
that lacking BPF_BTF_LOAD properly prevents BTF loading. It currently uses
only bit(BPF_MAP_TYPE_STRUCT_OPS) for its map permissions.
If a kernel regression incorrectly allowed BTF loading to bypass the token
restrictions, wouldn't obj_priv_btf_fail still fail during map creation
because it lacks BPF_MAP_TYPE_ARRAY, thereby silently masking the BTF load
enforcement regression?
> .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
> .attachs = ~0ULL,
> };
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260604031033.806727-1-chenyuan_fl@163.com?part=2
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens
2026-06-04 3:10 ` [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens chenyuan_fl
@ 2026-06-04 3:27 ` sashiko-bot
2026-06-04 4:05 ` bot+bpf-ci
2026-06-04 14:40 ` Mykyta Yatsenko
2 siblings, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-04 3:27 UTC (permalink / raw)
To: chenyuan_fl; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] Modifying `probe_fd()` to return negative error codes breaks feature sanitization by forcibly overriding missing features to `FEAT_SUPPORTED` if a BPF token is present.
- [Medium] `probe_fd()` returns a literal `-1` from direct syscall wrappers, causing `feat_supported()` to always report `-EPERM` and mask the true error code.
- [Medium] Missing curly braces in the BPF token rescue logic causes unconditional warning spam for all probe failures.
- [Medium] Several feature probes return `0` instead of propagating negative error codes on failure, silently bypassing the new BPF token rescue mechanism.
--
commit 0eceda08312936da19e1be0b6d87937f64f2f067
Author: Yuan Chen <chenyuan@kylinos.cn>
Subject: libbpf: fix feature probe failures for implicit BPF tokens
This commit modifies probe_fd() to return negative values instead of 0 on
failure. It also updates feat_supported() to mark features as supported if a
BPF token is present and the probe returns a negative error.
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index b7e388f99d0bb..f934452e52f01 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -16,7 +16,14 @@ int probe_fd(int fd)
> {
> if (fd >= 0)
> close(fd);
> - return fd >= 0;
> + /* Return 1 on success, negative error on failure, so
> + * feat_supported() can distinguish probe errors from
> + * genuine feature absence. When a BPF token is present,
> + * a negative return triggers the rescue path that marks
> + * the feature as SUPPORTED (token creation itself proves
> + * the kernel BPF subsystem works).
> + */
> + return fd >= 0 ? 1 : fd;
[Severity: Medium]
Does this return a literal -1 instead of the actual error code?
Several feature probes use internal direct syscall wrappers like
sys_bpf_prog_load() which return -1 on failure and leave the real error in
errno:
tools/lib/bpf/features.c:probe_kern_prog_name() {
...
ret = sys_bpf_prog_load(&attr, attr_sz, PROG_LOAD_ATTEMPTS);
return probe_fd(ret);
}
Since probe_fd() returns this -1 unmodified instead of -errno,
feat_supported() will pass -1 to errstr(). Because -1 equals -EPERM, does
this cause the error string to unconditionally resolve to "Operation not
permitted" and mask the true reason for the probe failure (like -EINVAL)?
[ ... ]
> @@ -725,9 +732,21 @@ bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_
> } else if (ret == 0) {
> WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> } else {
> + /*
> + * A BPF token may restrict which program/map types
> + * are permitted, causing the probe to fail even
> + * though the kernel supports the feature. When a
> + * token is present the probe is best-effort: BPF
> + * token creation itself proves the kernel has a
> + * working BPF subsystem. Real BPF issues will be
> + * caught during actual program/map loading.
> + */
> + if (cache->token_fd)
> + WRITE_ONCE(cache->res[feat_id], FEAT_SUPPORTED);
[Severity: High]
Will this forcefully override genuine missing features to FEAT_SUPPORTED if
a token is present?
By returning < 0 from probe_fd(), genuine feature absences now fall into this
error-handling path. If a newer BPF feature is missing on an older kernel
that supports tokens, libbpf might incorrectly mark it as supported and skip
essential sanitizations (like stripping unsupported BTF tags). Does this
bypass the fallback logic and cause the final program load to fatally fail?
[Severity: Medium]
Are there existing probes that still return 0 on failure and bypass this
rescue mechanism?
For instance, probe_prog_bind_map() returns 0 if bpf_prog_load() fails:
tools/lib/bpf/features.c:probe_prog_bind_map() {
...
prog = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns,
insn_cnt, &prog_opts);
if (prog < 0) {
close(map);
return 0;
}
...
}
Since these functions were not updated to propagate negative error codes, they
evaluate via the else if (ret == 0) branch and are immediately marked as
FEAT_MISSING. Does this leave unprivileged BPF token support broken for these
specific features?
> + else
> + WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> pr_warn("Detection of kernel %s support failed: %s\n",
> feat->desc, errstr(ret));
[Severity: Medium]
Is the else block missing curly braces?
Without curly braces around the else block, the pr_warn() call executes
unconditionally for any negative return value. Combined with probe_fd() now
returning < 0 for all missing features, will this loudly spam warnings to the
console for normal feature absence checks?
> - WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> }
> }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260604031033.806727-1-chenyuan_fl@163.com?part=3
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens
2026-06-04 3:10 ` [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens chenyuan_fl
2026-06-04 3:27 ` sashiko-bot
@ 2026-06-04 4:05 ` bot+bpf-ci
2026-06-04 14:40 ` Mykyta Yatsenko
2 siblings, 0 replies; 25+ messages in thread
From: bot+bpf-ci @ 2026-06-04 4:05 UTC (permalink / raw)
To: chenyuan_fl, chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song,
clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 4125 bytes --]
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index b7e388f99d0b..f934452e52f0 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -16,7 +16,14 @@ int probe_fd(int fd)
> {
> if (fd >= 0)
> close(fd);
> - return fd >= 0;
> + /* Return 1 on success, negative error on failure, so
> + * feat_supported() can distinguish probe errors from
> + * genuine feature absence. When a BPF token is present,
> + * a negative return triggers the rescue path that marks
> + * the feature as SUPPORTED (token creation itself proves
> + * the kernel BPF subsystem works).
> + */
> + return fd >= 0 ? 1 : fd;
> }
Does this return a literal -1 instead of the actual error code? Several
feature probes use internal direct syscall wrappers like sys_bpf_prog_load()
which return -1 on failure and leave the real error in errno. Since probe_fd()
returns this -1 unmodified instead of -errno, feat_supported() will pass -1 to
errstr():
tools/lib/bpf/features.c:feat_supported() {
...
pr_warn("Detection of kernel %s support failed: %s\n",
feat->desc, errstr(ret));
...
}
Because -1 equals -EPERM, does this cause the error string to unconditionally
resolve to "Operation not permitted" and mask the true reason for the probe
failure (like -EINVAL)?
https://lore.kernel.org/bpf/20260604032734.CE0D01F00893@smtp.kernel.org/
>
> static int probe_kern_prog_name(int token_fd)
[ ... ]
> @@ -725,9 +732,21 @@ bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_
> } else if (ret == 0) {
> WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> } else {
> + /*
> + * A BPF token may restrict which program/map types
> + * are permitted, causing the probe to fail even
> + * though the kernel supports the feature. When a
> + * token is present the probe is best-effort: BPF
> + * token creation itself proves the kernel has a
> + * working BPF subsystem. Real BPF issues will be
> + * caught during actual program/map loading.
> + */
> + if (cache->token_fd)
> + WRITE_ONCE(cache->res[feat_id], FEAT_SUPPORTED);
> + else
> + WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
Will this forcefully override genuine missing features to FEAT_SUPPORTED if a
token is present?
By returning < 0 from probe_fd(), genuine feature absences now fall into this
error-handling path. If a newer BPF feature is missing on an older kernel that
supports tokens, libbpf might incorrectly mark it as supported and skip
essential sanitizations (like stripping unsupported BTF tags).
Does this bypass the fallback logic and cause the final program load to fatally
fail?
https://lore.kernel.org/bpf/20260604032734.CE0D01F00893@smtp.kernel.org/
> pr_warn("Detection of kernel %s support failed: %s\n",
> feat->desc, errstr(ret));
> - WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> }
> }
Are there existing probes that still return 0 on failure and bypass this rescue
mechanism?
For instance, probe_prog_bind_map() returns 0 if bpf_prog_load() fails:
tools/lib/bpf/features.c:probe_prog_bind_map() {
...
if (prog < 0) {
close(map);
return 0;
}
...
}
Since these functions were not updated to propagate negative error codes, they
evaluate via the else if (ret == 0) branch and are immediately marked as
FEAT_MISSING.
Does this leave unprivileged BPF token support broken for these specific
features?
https://lore.kernel.org/bpf/20260604032734.CE0D01F00893@smtp.kernel.org/
Without curly braces around the else block, the pr_warn() call executes
unconditionally for any negative return value. Combined with probe_fd() now
returning < 0 for all missing features, will this loudly spam warnings to the
console for normal feature absence checks?
https://lore.kernel.org/bpf/20260604032734.CE0D01F00893@smtp.kernel.org/
---
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/26928747574
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-04 3:10 ` [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
@ 2026-06-04 4:05 ` bot+bpf-ci
2026-06-04 11:16 ` Mykyta Yatsenko
1 sibling, 0 replies; 25+ messages in thread
From: bot+bpf-ci @ 2026-06-04 4:05 UTC (permalink / raw)
To: chenyuan_fl, chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song,
clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1390 bytes --]
> libbpf: Skip bpf_object__probe_loading() when BPF token is in use
>
> bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
> TRACEPOINT programs to verify the BPF environment works. When a
> BPF token is in use with restricted program type permissions, these
> probe loads may fail because the token does not allow the specific
> program types, even though BPF loading is perfectly functional.
>
> Fix by skipping the probe when a token FD is present: BPF token
> creation itself proves the kernel has a working BPF subsystem.
> Real BPF issues will be caught during actual program and map loading.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
This looks like a fix for a regression that was introduced when the BPF
token was first wired into the probe loads, which switched the trivial
SOCKET_FILTER/TRACEPOINT bpf_prog_load() probe calls from passing NULL to
passing &opts with .token_fd = obj->token_fd, making the probes subject to
the token's restricted program-type permissions.
Should this include:
Fixes: 1d0dd6ea2e38 ("libbpf: wire up BPF token support at BPF object level")
---
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/26928747574
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-04 3:10 ` [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
2026-06-04 4:05 ` bot+bpf-ci
@ 2026-06-04 11:16 ` Mykyta Yatsenko
2026-06-08 18:17 ` Andrii Nakryiko
1 sibling, 1 reply; 25+ messages in thread
From: Mykyta Yatsenko @ 2026-06-04 11:16 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
On 6/4/26 4:10 AM, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
> TRACEPOINT programs to verify the BPF environment works. When a
> BPF token is in use with restricted program type permissions, these
> probe loads may fail because the token does not allow the specific
> program types, even though BPF loading is perfectly functional.
>
> Fix by skipping the probe when a token FD is present: BPF token
> creation itself proves the kernel has a working BPF subsystem.
> Real BPF issues will be caught during actual program and map loading.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
> tools/lib/bpf/libbpf.c | 10 +++-------
> 1 file changed, 3 insertions(+), 7 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index ab2071fdd3e8..7e21c5eb9533 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
> BPF_EXIT_INSN(),
> };
> int ret, insn_cnt = ARRAY_SIZE(insns);
> - LIBBPF_OPTS(bpf_prog_load_opts, opts,
> - .token_fd = obj->token_fd,
> - .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
> - );
>
> - if (obj->gen_loader)
> + if (obj->gen_loader || obj->token_fd)
This change makes sense, bpf_object__probe_loading() does very basic
check that BPF works on a given kernel. In this case, when token is
passed, this is ok to skip. An alternative, trying to make
bpf_object__probe_loading() correctly token aware is worse.
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
> return 0;
>
> ret = bump_rlimit_memlock();
> @@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
> errstr(ret));
>
> /* make sure basic loading works */
> - ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
> + ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
> if (ret < 0)
> - ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
> if (ret < 0) {
> ret = errno;
> pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens
2026-06-04 3:10 ` [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens chenyuan_fl
2026-06-04 3:27 ` sashiko-bot
2026-06-04 4:05 ` bot+bpf-ci
@ 2026-06-04 14:40 ` Mykyta Yatsenko
2026-06-08 18:18 ` Andrii Nakryiko
2 siblings, 1 reply; 25+ messages in thread
From: Mykyta Yatsenko @ 2026-06-04 14:40 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
On 6/4/26 4:10 AM, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> probe_fd() converts BPF syscall failures to return value 0,
> which feat_supported() interprets as 'feature absent' (ret==0),
> even when the probe failed due to a BPF token's restricted
> program/map type mask.
>
> In a user namespace with an implicit BPF token, the sequence is:
> 1. bpf_object_open() -> no feat_cache yet -> global cache used
> 2. bpf_object_prepare_token() -> creates token, sets feat_cache->token_fd
> 3. bpf_object__create_maps() -> feat_supported() runs probe
> -> bpf_prog_load(SOCKET_FILTER) with token -> -EPERM
> -> probe_fd(-EPERM) -> returns 0
> -> feat_supported sees ret==0 -> FEAT_MISSING
> -> internal maps (global data) skipped -> verifier EINVAL
>
> Fix by making probe_fd() return the negative error on failure
> instead of 0, so feat_supported() enters the ret<0 path.
>
> Additionally add a token_fd rescue in feat_supported() for the
> ret<0 case: when a BPF token is present, a failed feature probe
> is treated as 'feature supported' because token creation itself
> proves the kernel BPF subsystem works. Real BPF issues will
> be caught during actual program/map loading.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
It looks wrong to say that any feature is supported just because there is
token_fd present. In patch 1 we only checked that BPF is available, so
it was ok skipping probing. This one looks a bit more risky.
Is the reason this code fails because of BPF_PROG_TYPE_SOCKET_FILTER not enabled
in the token? I suggest fetch the first supported program type from the token and
pass it down to bpf_prog_load().
> tools/lib/bpf/features.c | 23 +++++++++++++++++++++--
> 1 file changed, 21 insertions(+), 2 deletions(-)
>
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index b7e388f99d0b..f934452e52f0 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -16,7 +16,14 @@ int probe_fd(int fd)
> {
> if (fd >= 0)
> close(fd);
> - return fd >= 0;
> + /* Return 1 on success, negative error on failure, so
> + * feat_supported() can distinguish probe errors from
> + * genuine feature absence. When a BPF token is present,
> + * a negative return triggers the rescue path that marks
> + * the feature as SUPPORTED (token creation itself proves
> + * the kernel BPF subsystem works).
> + */
> + return fd >= 0 ? 1 : fd;
> }
>
> static int probe_kern_prog_name(int token_fd)
> @@ -725,9 +732,21 @@ bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_
> } else if (ret == 0) {
> WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> } else {
> + /*
> + * A BPF token may restrict which program/map types
> + * are permitted, causing the probe to fail even
> + * though the kernel supports the feature. When a
> + * token is present the probe is best-effort: BPF
> + * token creation itself proves the kernel has a
> + * working BPF subsystem. Real BPF issues will be
> + * caught during actual program/map loading.
> + */
> + if (cache->token_fd)
> + WRITE_ONCE(cache->res[feat_id], FEAT_SUPPORTED);
> + else
> + WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> pr_warn("Detection of kernel %s support failed: %s\n",
> feat->desc, errstr(ret));
> - WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> }
> }
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data
2026-06-04 3:10 ` [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data chenyuan_fl
2026-06-04 3:25 ` sashiko-bot
@ 2026-06-08 18:14 ` Andrii Nakryiko
1 sibling, 0 replies; 25+ messages in thread
From: Andrii Nakryiko @ 2026-06-08 18:14 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
On Wed, Jun 3, 2026 at 8:11 PM <chenyuan_fl@163.com> wrote:
>
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> obj_priv_btf_success, obj_priv_implicit_token and
> obj_priv_implicit_token_envvar use the dummy_st_ops_success skeleton,
> whose struct_ops programs reference global variables backed by ARRAY
> maps. Without BPF_MAP_TYPE_ARRAY in the token allowed map types,
> bpf_object__load() fails because the kernel rejects ARRAY map creation
> for global data.
>
> Add BPF_MAP_TYPE_ARRAY to the token permission mask for these three
> subtests so their skeletons can load successfully.
>
> This is distinct from the libbpf probe issue: the skeletons genuinely
> require ARRAY maps for their global data, not merely for probing.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
> tools/testing/selftests/bpf/prog_tests/token.c | 6 +++---
> 1 file changed, 3 insertions(+), 3 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/token.c b/tools/testing/selftests/bpf/prog_tests/token.c
> index f2f5d36ae00a..1812de87bedb 100644
> --- a/tools/testing/selftests/bpf/prog_tests/token.c
> +++ b/tools/testing/selftests/bpf/prog_tests/token.c
> @@ -1214,7 +1214,7 @@ void serial_test_token(void)
> struct bpffs_opts opts = {
> /* allow BTF loading */
> .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> - .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
> + .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
> .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
> .attachs = ~0ULL,
> };
> @@ -1225,7 +1225,7 @@ void serial_test_token(void)
> struct bpffs_opts opts = {
> /* allow BTF loading */
> .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> - .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
> + .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
> .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
> .attachs = ~0ULL,
> };
> @@ -1236,7 +1236,7 @@ void serial_test_token(void)
> struct bpffs_opts opts = {
> /* allow BTF loading */
> .cmds = bit(BPF_BTF_LOAD) | bit(BPF_MAP_CREATE) | bit(BPF_PROG_LOAD),
> - .maps = bit(BPF_MAP_TYPE_STRUCT_OPS),
> + .maps = bit(BPF_MAP_TYPE_STRUCT_OPS) | bit(BPF_MAP_TYPE_ARRAY),
Hm.. ARRAY map is unprivileged, you shouldn't need this. Are you sure
this test failing for you is not a consequence of the issue you fixed
in the first patch?
> .progs = bit(BPF_PROG_TYPE_STRUCT_OPS),
> .attachs = ~0ULL,
> };
> --
> 2.54.0
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-04 11:16 ` Mykyta Yatsenko
@ 2026-06-08 18:17 ` Andrii Nakryiko
2026-06-09 13:11 ` [PATCH bpf] " chenyuan_fl
0 siblings, 1 reply; 25+ messages in thread
From: Andrii Nakryiko @ 2026-06-08 18:17 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: chenyuan_fl, andrii, ast, bpf, chenyuan, daniel, eddyz87,
linux-kselftest, shuah
On Thu, Jun 4, 2026 at 4:16 AM Mykyta Yatsenko
<mykyta.yatsenko5@gmail.com> wrote:
>
> On 6/4/26 4:10 AM, chenyuan_fl@163.com wrote:
> > From: Yuan Chen <chenyuan@kylinos.cn>
> >
> > bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
> > TRACEPOINT programs to verify the BPF environment works. When a
> > BPF token is in use with restricted program type permissions, these
> > probe loads may fail because the token does not allow the specific
> > program types, even though BPF loading is perfectly functional.
> >
> > Fix by skipping the probe when a token FD is present: BPF token
> > creation itself proves the kernel has a working BPF subsystem.
> > Real BPF issues will be caught during actual program and map loading.
> >
> > Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> > ---
> > tools/lib/bpf/libbpf.c | 10 +++-------
> > 1 file changed, 3 insertions(+), 7 deletions(-)
> >
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index ab2071fdd3e8..7e21c5eb9533 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
> > BPF_EXIT_INSN(),
> > };
> > int ret, insn_cnt = ARRAY_SIZE(insns);
> > - LIBBPF_OPTS(bpf_prog_load_opts, opts,
> > - .token_fd = obj->token_fd,
> > - .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
> > - );
> >
> > - if (obj->gen_loader)
> > + if (obj->gen_loader || obj->token_fd)
>
> This change makes sense, bpf_object__probe_loading() does very basic
> check that BPF works on a given kernel. In this case, when token is
> passed, this is ok to skip. An alternative, trying to make
> bpf_object__probe_loading() correctly token aware is worse.
>
> Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
This is the only patch in the series that makes sense to apply, but I
don't see this series in patchworks. Can you please resend just this
one to BPF mailing list? Thanks
>
> > return 0;
> >
> > ret = bump_rlimit_memlock();
> > @@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
> > errstr(ret));
> >
> > /* make sure basic loading works */
> > - ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
> > + ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
> > if (ret < 0)
> > - ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> > + ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
> > if (ret < 0) {
> > ret = errno;
> > pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens
2026-06-04 14:40 ` Mykyta Yatsenko
@ 2026-06-08 18:18 ` Andrii Nakryiko
0 siblings, 0 replies; 25+ messages in thread
From: Andrii Nakryiko @ 2026-06-08 18:18 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: chenyuan_fl, andrii, ast, bpf, chenyuan, daniel, eddyz87,
linux-kselftest, shuah
On Thu, Jun 4, 2026 at 7:40 AM Mykyta Yatsenko
<mykyta.yatsenko5@gmail.com> wrote:
>
> On 6/4/26 4:10 AM, chenyuan_fl@163.com wrote:
> > From: Yuan Chen <chenyuan@kylinos.cn>
> >
> > probe_fd() converts BPF syscall failures to return value 0,
> > which feat_supported() interprets as 'feature absent' (ret==0),
> > even when the probe failed due to a BPF token's restricted
> > program/map type mask.
> >
> > In a user namespace with an implicit BPF token, the sequence is:
> > 1. bpf_object_open() -> no feat_cache yet -> global cache used
> > 2. bpf_object_prepare_token() -> creates token, sets feat_cache->token_fd
> > 3. bpf_object__create_maps() -> feat_supported() runs probe
> > -> bpf_prog_load(SOCKET_FILTER) with token -> -EPERM
> > -> probe_fd(-EPERM) -> returns 0
> > -> feat_supported sees ret==0 -> FEAT_MISSING
> > -> internal maps (global data) skipped -> verifier EINVAL
> >
> > Fix by making probe_fd() return the negative error on failure
> > instead of 0, so feat_supported() enters the ret<0 path.
> >
> > Additionally add a token_fd rescue in feat_supported() for the
> > ret<0 case: when a BPF token is present, a failed feature probe
> > is treated as 'feature supported' because token creation itself
> > proves the kernel BPF subsystem works. Real BPF issues will
> > be caught during actual program/map loading.
> >
> > Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> > ---
>
> It looks wrong to say that any feature is supported just because there is
> token_fd present. In patch 1 we only checked that BPF is available, so
> it was ok skipping probing. This one looks a bit more risky.
Yep, agreed, this is not the right approach. Please double check what
kind of issues you still have with only patch 1 applied, and let's
discuss possible solutions (if there are still problems).
> Is the reason this code fails because of BPF_PROG_TYPE_SOCKET_FILTER not enabled
> in the token? I suggest fetch the first supported program type from the token and
> pass it down to bpf_prog_load().
>
> > tools/lib/bpf/features.c | 23 +++++++++++++++++++++--
> > 1 file changed, 21 insertions(+), 2 deletions(-)
> >
> > diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> > index b7e388f99d0b..f934452e52f0 100644
> > --- a/tools/lib/bpf/features.c
> > +++ b/tools/lib/bpf/features.c
> > @@ -16,7 +16,14 @@ int probe_fd(int fd)
> > {
> > if (fd >= 0)
> > close(fd);
> > - return fd >= 0;
> > + /* Return 1 on success, negative error on failure, so
> > + * feat_supported() can distinguish probe errors from
> > + * genuine feature absence. When a BPF token is present,
> > + * a negative return triggers the rescue path that marks
> > + * the feature as SUPPORTED (token creation itself proves
> > + * the kernel BPF subsystem works).
> > + */
> > + return fd >= 0 ? 1 : fd;
> > }
> >
> > static int probe_kern_prog_name(int token_fd)
> > @@ -725,9 +732,21 @@ bool feat_supported(struct kern_feature_cache *cache, enum kern_feature_id feat_
> > } else if (ret == 0) {
> > WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> > } else {
> > + /*
> > + * A BPF token may restrict which program/map types
> > + * are permitted, causing the probe to fail even
> > + * though the kernel supports the feature. When a
> > + * token is present the probe is best-effort: BPF
> > + * token creation itself proves the kernel has a
> > + * working BPF subsystem. Real BPF issues will be
> > + * caught during actual program/map loading.
> > + */
> > + if (cache->token_fd)
> > + WRITE_ONCE(cache->res[feat_id], FEAT_SUPPORTED);
> > + else
> > + WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> > pr_warn("Detection of kernel %s support failed: %s\n",
> > feat->desc, errstr(ret));
> > - WRITE_ONCE(cache->res[feat_id], FEAT_MISSING);
> > }
> > }
> >
>
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH bpf] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-08 18:17 ` Andrii Nakryiko
@ 2026-06-09 13:11 ` chenyuan_fl
2026-06-09 13:35 ` Mykyta Yatsenko
2026-06-09 13:42 ` bot+bpf-ci
0 siblings, 2 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-09 13:11 UTC (permalink / raw)
To: andrii.nakryiko
Cc: andrii, ast, bpf, chenyuan, chenyuan_fl, daniel, eddyz87,
linux-kselftest, mykyta.yatsenko5, shuah
From: Yuan Chen <chenyuan@kylinos.cn>
bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
TRACEPOINT programs to verify the BPF environment works. When a
BPF token is in use with restricted program type permissions, these
probe loads may fail because the token does not allow the specific
program types, even though BPF loading is perfectly functional.
Fix by skipping the probe when a token FD is present: BPF token
creation itself proves the kernel has a working BPF subsystem.
Real BPF issues will be caught during actual program and map loading.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/lib/bpf/libbpf.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ab2071fdd3e8..7e21c5eb9533 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
BPF_EXIT_INSN(),
};
int ret, insn_cnt = ARRAY_SIZE(insns);
- LIBBPF_OPTS(bpf_prog_load_opts, opts,
- .token_fd = obj->token_fd,
- .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
- );
- if (obj->gen_loader)
+ if (obj->gen_loader || obj->token_fd)
return 0;
ret = bump_rlimit_memlock();
@@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
errstr(ret));
/* make sure basic loading works */
- ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0)
- ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0) {
ret = errno;
pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH bpf] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-09 13:11 ` [PATCH bpf] " chenyuan_fl
@ 2026-06-09 13:35 ` Mykyta Yatsenko
2026-06-09 13:42 ` bot+bpf-ci
1 sibling, 0 replies; 25+ messages in thread
From: Mykyta Yatsenko @ 2026-06-09 13:35 UTC (permalink / raw)
To: chenyuan_fl, andrii.nakryiko
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah
On 6/9/26 2:11 PM, chenyuan_fl@163.com wrote:
> From: Yuan Chen <chenyuan@kylinos.cn>
>
> bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
> TRACEPOINT programs to verify the BPF environment works. When a
> BPF token is in use with restricted program type permissions, these
> probe loads may fail because the token does not allow the specific
> program types, even though BPF loading is perfectly functional.
>
> Fix by skipping the probe when a token FD is present: BPF token
> creation itself proves the kernel has a working BPF subsystem.
> Real BPF issues will be caught during actual program and map loading.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
> ---
Please resend your patch applying these:
- don't send as a response to old thread
- this is v3
- target bpf-next
- add fixes tag
- include any Acked-bys
> tools/lib/bpf/libbpf.c | 10 +++-------
> 1 file changed, 3 insertions(+), 7 deletions(-)
>
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index ab2071fdd3e8..7e21c5eb9533 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
> BPF_EXIT_INSN(),
> };
> int ret, insn_cnt = ARRAY_SIZE(insns);
> - LIBBPF_OPTS(bpf_prog_load_opts, opts,
> - .token_fd = obj->token_fd,
> - .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
> - );
>
> - if (obj->gen_loader)
> + if (obj->gen_loader || obj->token_fd)
> return 0;
>
> ret = bump_rlimit_memlock();
> @@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
> errstr(ret));
>
> /* make sure basic loading works */
> - ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
> + ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
> if (ret < 0)
> - ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
> if (ret < 0) {
> ret = errno;
> pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-09 13:11 ` [PATCH bpf] " chenyuan_fl
2026-06-09 13:35 ` Mykyta Yatsenko
@ 2026-06-09 13:42 ` bot+bpf-ci
1 sibling, 0 replies; 25+ messages in thread
From: bot+bpf-ci @ 2026-06-09 13:42 UTC (permalink / raw)
To: chenyuan_fl, andrii.nakryiko
Cc: andrii, ast, bpf, chenyuan, chenyuan_fl, daniel, eddyz87,
linux-kselftest, mykyta.yatsenko5, shuah, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3020 bytes --]
> commit 234ebb868e2e11460c8be69f6726ec05ff912183
> Author: Yuan Chen <chenyuan@kylinos.cn>
> Date: Tue Jun 9 21:11:00 2026 +0800
>
> libbpf: Skip bpf_object__probe_loading() when BPF token is in use
>
> bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
> TRACEPOINT programs to verify the BPF environment works. When a
> BPF token is in use with restricted program type permissions, these
> probe loads may fail because the token does not allow the specific
> program types, even though BPF loading is perfectly functional.
>
> Fix by skipping the probe when a token FD is present: BPF token
> creation itself proves the kernel has a working BPF subsystem.
> Real BPF issues will be caught during actual program and map loading.
>
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
This looks like a fix for a regression introduced when token_fd was wired
into feature probing logic. The CI bot suggested in the v2 review that this
should include:
Fixes: f3dcee938f48 ("libbpf: Wire up token_fd into feature probing logic")
The commit f3dcee938f48 added token_fd support to bpf_object__probe_loading(),
which made the trivial SOCKET_FILTER and TRACEPOINT probe loads subject to the
token's restricted program-type permissions. This can cause the probes to fail
even when BPF loading is perfectly functional.
Should this patch include the Fixes tag to help backporting and tracking the
regression it addresses?
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index 3a80a018fc7d..a3ce25928120 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
> BPF_EXIT_INSN(),
> };
> int ret, insn_cnt = ARRAY_SIZE(insns);
> - LIBBPF_OPTS(bpf_prog_load_opts, opts,
> - .token_fd = obj->token_fd,
> - .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
> - );
>
> - if (obj->gen_loader)
> + if (obj->gen_loader || obj->token_fd)
> return 0;
>
> ret = bump_rlimit_memlock();
> @@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
> errstr(ret));
>
> /* make sure basic loading works */
> - ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
> + ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
> if (ret < 0)
> - ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
> if (ret < 0) {
> ret = errno;
> pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
---
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/27208871676
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH bpf-next v3 0/2] libbpf: fix implicit BPF token feature probe failures
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
` (2 preceding siblings ...)
2026-06-04 3:10 ` [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens chenyuan_fl
@ 2026-06-10 14:50 ` chenyuan_fl
2026-06-10 14:50 ` [PATCH bpf-next v3 1/2] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
2026-06-10 14:50 ` [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes chenyuan_fl
3 siblings, 2 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-10 14:50 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, mykyta.yatsenko5, andrii.nakryiko
From: Yuan Chen <chenyuan@kylinos.cn>
v2: https://lore.kernel.org/bpf/CAEf4BzbbmTFaNjT4bRTEm3BxAROkRrTdfxwPNy9HmMt_LFaSHw@mail.gmail.com/
When BPF programs reference global variables (e.g., struct_ops
programs with global data), libbpf creates internal ARRAY maps to
back them. This depends on FEAT_GLOBAL_DATA, which is gated by
feature probes that load test programs (SOCKET_FILTER, KPROBE, etc.)
into the kernel.
In a user namespace with an implicit BPF token, two problems arise:
1. bpf_object__probe_loading() passes the token fd to test program
loads. When the token's allowed program type mask excludes the
probe types, the kernel drops the token reference, causing
subsequent struct_ops loads to fail because the token object
has been released.
2. Feature probes hardcode SOCKET_FILTER/TRACEPOINT as the program
type for their test loads. When the token restricts program
types, these loads fail and features (FEAT_GLOBAL_DATA, etc.)
are incorrectly reported as missing, so internal maps for global
data are never created.
Together, these cause struct_ops programs referencing global data
to fail verification with "fd X is not pointing to valid bpf_map".
This series fixes both issues:
Patch 1: Skip bpf_object__probe_loading() entirely when a BPF
token is present. Token creation itself proves the
kernel BPF subsystem works.
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
Patch 2: Fetch the first probeable program type from the token's
allowed_progs mask instead of hardcoding SOCKET_FILTER
or TRACEPOINT. When no probeable type exists, return
success (token creation proves the BPF subsystem works).
v3 changes:
- Drop the selftest patch (ARRAY map type addition) — no longer needed.
- Patch 2: implement reviewer's suggestion to fetch the first supported
program type from the token instead of blanket skipping. Use an
18-type probeable list of types known to accept trivial "return 0"
programs without specific expected_attach_type. When no probeable
type exists (e.g. only STRUCT_OPS), assume the feature is supported.
v2 changes:
- Replace the workaround of granting SOCKET_FILTER/KPROBE permissions
in the token with a proper fix at the feature probe level in libbpf.
Yuan Chen (2):
libbpf: Skip bpf_object__probe_loading() when BPF token is in use
libbpf: fetch probeable prog type from token for feature probes
tools/lib/bpf/features.c | 97 ++++++++++++++++++++++++++++++++++++++++++++----
tools/lib/bpf/libbpf.c | 10 ++---
2 files changed, 93 insertions(+), 14 deletions(-)
--
2.54.0
^ permalink raw reply [flat|nested] 25+ messages in thread
* [PATCH bpf-next v3 1/2] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-10 14:50 ` [PATCH bpf-next v3 0/2] libbpf: fix implicit BPF token feature probe failures chenyuan_fl
@ 2026-06-10 14:50 ` chenyuan_fl
2026-06-10 16:30 ` bot+bpf-ci
2026-06-10 14:50 ` [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes chenyuan_fl
1 sibling, 1 reply; 25+ messages in thread
From: chenyuan_fl @ 2026-06-10 14:50 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, mykyta.yatsenko5, andrii.nakryiko
From: Yuan Chen <chenyuan@kylinos.cn>
bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
TRACEPOINT programs to verify the BPF environment works. When a
BPF token is in use with restricted program type permissions, these
probe loads may fail because the token does not allow the specific
program types, even though BPF loading is perfectly functional.
Fix by skipping the probe when a token FD is present: BPF token
creation itself proves the kernel has a working BPF subsystem.
Real BPF issues will be caught during actual program and map loading.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/lib/bpf/libbpf.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index ab2071fdd3e8..7e21c5eb9533 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -5167,12 +5167,8 @@ bpf_object__probe_loading(struct bpf_object *obj)
BPF_EXIT_INSN(),
};
int ret, insn_cnt = ARRAY_SIZE(insns);
- LIBBPF_OPTS(bpf_prog_load_opts, opts,
- .token_fd = obj->token_fd,
- .prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
- );
- if (obj->gen_loader)
+ if (obj->gen_loader || obj->token_fd)
return 0;
ret = bump_rlimit_memlock();
@@ -5181,9 +5177,9 @@ bpf_object__probe_loading(struct bpf_object *obj)
errstr(ret));
/* make sure basic loading works */
- ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0)
- ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
+ ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, NULL);
if (ret < 0) {
ret = errno;
pr_warn("Error in %s(): %s. Couldn't load trivial BPF program. Make sure your kernel supports BPF (CONFIG_BPF_SYSCALL=y) and/or that RLIMIT_MEMLOCK is set to big enough value.\n",
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes
2026-06-10 14:50 ` [PATCH bpf-next v3 0/2] libbpf: fix implicit BPF token feature probe failures chenyuan_fl
2026-06-10 14:50 ` [PATCH bpf-next v3 1/2] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
@ 2026-06-10 14:50 ` chenyuan_fl
2026-06-10 15:04 ` sashiko-bot
2026-06-10 16:30 ` bot+bpf-ci
1 sibling, 2 replies; 25+ messages in thread
From: chenyuan_fl @ 2026-06-10 14:50 UTC (permalink / raw)
To: chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, mykyta.yatsenko5, andrii.nakryiko
From: Yuan Chen <chenyuan@kylinos.cn>
Feature probes (FEAT_GLOBAL_DATA, FEAT_PROG_NAME, etc.) hardcode
SOCKET_FILTER or TRACEPOINT as the program type for their test
loads. When a BPF token restricts program types, these loads
fail and the features are incorrectly reported as missing.
Fetch the first probeable program type from the token's allowed_progs
mask. A new helper, token_probeable_prog_type(), queries the token
and returns the first match from an 18-type list of program types
known to accept trivial "return 0" programs without specific
expected_attach_type. Types requiring expected_attach_type
(CGROUP_SOCK, CGROUP_SOCK_ADDR, LWT_*, NETFILTER, etc.) are
intentionally excluded. Without a token, defaults to SOCKET_FILTER.
When the token has no probeable type (e.g. only STRUCT_OPS),
conservatively assume the feature is supported: token creation
proves the BPF subsystem works, and real issues will be caught
during actual program/map loading.
Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
---
tools/lib/bpf/features.c | 97 ++++++++++++++++++++++++++++++++++++----
1 file changed, 89 insertions(+), 8 deletions(-)
diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
index b7e388f99d0b..f008ee50e246 100644
--- a/tools/lib/bpf/features.c
+++ b/tools/lib/bpf/features.c
@@ -19,6 +19,57 @@ int probe_fd(int fd)
return fd >= 0;
}
+/* Fetch the first program type from the token that can be used for
+ * feature probes. Only a few common types are checked that are known
+ * to accept a trivial "return 0" program. Returns the type on success,
+ * -EINVAL if the token has no probeable type.
+ */
+static int token_probeable_prog_type(int token_fd)
+{
+ /* Types that accept a simple "return 0" probe program */
+ /* Types that accept a trivial "return 0" program without
+ * specific expected_attach_type. Types requiring expected_attach_type
+ * (CGROUP_SOCK, CGROUP_SOCK_ADDR, LWT_*, NETFILTER) are excluded.
+ */
+ static const int probeable[] = {
+ BPF_PROG_TYPE_SOCKET_FILTER,
+ BPF_PROG_TYPE_KPROBE,
+ BPF_PROG_TYPE_SCHED_CLS,
+ BPF_PROG_TYPE_SCHED_ACT,
+ BPF_PROG_TYPE_TRACEPOINT,
+ BPF_PROG_TYPE_XDP,
+ BPF_PROG_TYPE_PERF_EVENT,
+ BPF_PROG_TYPE_CGROUP_SKB,
+ BPF_PROG_TYPE_SOCK_OPS,
+ BPF_PROG_TYPE_SK_SKB,
+ BPF_PROG_TYPE_CGROUP_DEVICE,
+ BPF_PROG_TYPE_SK_MSG,
+ BPF_PROG_TYPE_RAW_TRACEPOINT,
+ BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
+ BPF_PROG_TYPE_CGROUP_SOCKOPT,
+ BPF_PROG_TYPE_CGROUP_SYSCTL,
+ BPF_PROG_TYPE_FLOW_DISSECTOR,
+ BPF_PROG_TYPE_SK_LOOKUP,
+ };
+ struct bpf_token_info info = {};
+ __u32 info_len = sizeof(info);
+ int i, err;
+
+ if (!token_fd)
+ return BPF_PROG_TYPE_SOCKET_FILTER;
+
+ err = bpf_obj_get_info_by_fd(token_fd, &info, &info_len);
+ if (err)
+ return -errno;
+
+ for (i = 0; i < ARRAY_SIZE(probeable); i++) {
+ if (info.allowed_progs & (1ULL << probeable[i]))
+ return probeable[i];
+ }
+
+ return -EINVAL;
+}
+
static int probe_kern_prog_name(int token_fd)
{
const size_t attr_sz = offsetofend(union bpf_attr, prog_token_fd);
@@ -27,10 +78,14 @@ static int probe_kern_prog_name(int token_fd)
BPF_EXIT_INSN(),
};
union bpf_attr attr;
- int ret;
+ int ret, prog_type;
+
+ prog_type = token_probeable_prog_type(token_fd);
+ if (prog_type < 0)
+ return 1;
memset(&attr, 0, attr_sz);
- attr.prog_type = BPF_PROG_TYPE_SOCKET_FILTER;
+ attr.prog_type = prog_type;
attr.license = ptr_to_u64("GPL");
attr.insns = ptr_to_u64(insns);
attr.insn_cnt = (__u32)ARRAY_SIZE(insns);
@@ -61,6 +116,7 @@ static int probe_kern_global_data(int token_fd)
.prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
);
int ret, map, insn_cnt = ARRAY_SIZE(insns);
+ int prog_type;
map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_global", sizeof(int), 32, 1, &map_opts);
if (map < 0) {
@@ -72,7 +128,12 @@ static int probe_kern_global_data(int token_fd)
insns[0].imm = map;
- ret = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &prog_opts);
+ prog_type = token_probeable_prog_type(token_fd);
+ if (prog_type < 0) {
+ close(map);
+ return 1;
+ }
+ ret = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &prog_opts);
close(map);
return probe_fd(ret);
}
@@ -257,8 +318,13 @@ static int probe_kern_probe_read_kernel(int token_fd)
BPF_EXIT_INSN(),
};
int fd, insn_cnt = ARRAY_SIZE(insns);
+ int prog_type;
- fd = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
+ prog_type = token_probeable_prog_type(token_fd);
+ if (prog_type < 0)
+ return 1;
+
+ fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &opts);
return probe_fd(fd);
}
@@ -277,6 +343,7 @@ static int probe_prog_bind_map(int token_fd)
.prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
);
int ret, map, prog, insn_cnt = ARRAY_SIZE(insns);
+ int prog_type;
map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_det_bind", sizeof(int), 32, 1, &map_opts);
if (map < 0) {
@@ -286,7 +353,12 @@ static int probe_prog_bind_map(int token_fd)
return ret;
}
- prog = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &prog_opts);
+ prog = prog_type = token_probeable_prog_type(token_fd);
+ if (prog_type < 0) {
+ close(map);
+ return 1;
+ }
+ prog = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &prog_opts);
if (prog < 0) {
close(map);
return 0;
@@ -435,8 +507,13 @@ static int probe_kern_bpf_cookie(int token_fd)
.prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
);
int ret, insn_cnt = ARRAY_SIZE(insns);
+ int prog_type;
- ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
+ prog_type = token_probeable_prog_type(token_fd);
+ if (prog_type < 0)
+ return 1;
+
+ ret = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &opts);
return probe_fd(ret);
}
@@ -509,7 +586,7 @@ static int probe_kern_arg_ctx_tag(int token_fd)
static int probe_ldimm64_full_range_off(int token_fd)
{
char log_buf[1024];
- int prog_fd, map_fd;
+ int prog_fd, map_fd, prog_type;
int ret;
LIBBPF_OPTS(bpf_map_create_opts, map_opts,
.token_fd = token_fd,
@@ -527,6 +604,10 @@ static int probe_ldimm64_full_range_off(int token_fd)
};
int insn_cnt = ARRAY_SIZE(insns);
+ prog_type = token_probeable_prog_type(token_fd);
+ if (prog_type < 0)
+ return 1;
+
map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "arr", sizeof(int), 1, 1, &map_opts);
if (map_fd < 0) {
ret = -errno;
@@ -537,7 +618,7 @@ static int probe_ldimm64_full_range_off(int token_fd)
insns[0].imm = map_fd;
log_buf[0] = '\0';
- prog_fd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, "global_reloc", "GPL", insns, insn_cnt, &prog_opts);
+ prog_fd = bpf_prog_load(prog_type, "global_reloc", "GPL", insns, insn_cnt, &prog_opts);
ret = -errno;
close(map_fd);
--
2.54.0
^ permalink raw reply related [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes
2026-06-10 14:50 ` [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes chenyuan_fl
@ 2026-06-10 15:04 ` sashiko-bot
2026-06-10 16:30 ` bot+bpf-ci
1 sibling, 0 replies; 25+ messages in thread
From: sashiko-bot @ 2026-06-10 15:04 UTC (permalink / raw)
To: chenyuan_fl; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Feature probes for FEAT_BPF_COOKIE and FEAT_PROBE_READ_KERN will unconditionally fail because they test helpers unsupported by the dynamically selected BPF_PROG_TYPE_SOCKET_FILTER.
--
commit 0109a2d3173a7dbf585e1f1ba9c12c5a9120c9eb
Author: Yuan Chen <chenyuan@kylinos.cn>
libbpf: fetch probeable prog type from token for feature probes
This commit updates feature probes to dynamically select a program type
based on the provided BPF token instead of hardcoding SOCKET_FILTER or
TRACEPOINT. If no token is provided, it defaults to SOCKET_FILTER.
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index b7e388f99d0bb..f008ee50e2466 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
[ ... ]
> @@ -257,8 +318,13 @@ static int probe_kern_probe_read_kernel(int token_fd)
> BPF_EXIT_INSN(),
> };
> int fd, insn_cnt = ARRAY_SIZE(insns);
> + int prog_type;
>
> - fd = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + prog_type = token_probeable_prog_type(token_fd);
> + if (prog_type < 0)
> + return 1;
> +
> + fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &opts);
[Severity: High]
Will this unconditionally fail the probe for FEAT_PROBE_READ_KERN?
If no token is provided, or the token allows SOCKET_FILTER,
token_probeable_prog_type() returns BPF_PROG_TYPE_SOCKET_FILTER.
Because SOCKET_FILTER does not support the bpf_probe_read_kernel helper,
the verifier will reject the load with an unknown func error.
Does this result in libbpf falsely reporting the feature as missing for
all applications?
[ ... ]
> @@ -435,8 +507,13 @@ static int probe_kern_bpf_cookie(int token_fd)
> .prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
> );
> int ret, insn_cnt = ARRAY_SIZE(insns);
> + int prog_type;
>
> - ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + prog_type = token_probeable_prog_type(token_fd);
> + if (prog_type < 0)
> + return 1;
> +
> + ret = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &opts);
[Severity: High]
Similarly, will this break the FEAT_BPF_COOKIE probe?
If prog_type resolves to BPF_PROG_TYPE_SOCKET_FILTER, it will not support
the bpf_get_attach_cookie helper being tested here, causing the verifier
to reject the probe program.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260610145059.113412-1-chenyuan_fl@163.com?part=2
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v3 1/2] libbpf: Skip bpf_object__probe_loading() when BPF token is in use
2026-06-10 14:50 ` [PATCH bpf-next v3 1/2] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
@ 2026-06-10 16:30 ` bot+bpf-ci
0 siblings, 0 replies; 25+ messages in thread
From: bot+bpf-ci @ 2026-06-10 16:30 UTC (permalink / raw)
To: chenyuan_fl, chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, mykyta.yatsenko5, andrii.nakryiko, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2056 bytes --]
> bpf_object__probe_loading() tries to load trivial SOCKET_FILTER and
> TRACEPOINT programs to verify the BPF environment works. When a
> BPF token is in use with restricted program type permissions, these
> probe loads may fail because the token does not allow the specific
> program types, even though BPF loading is perfectly functional.
> Fix by skipping the probe when a token FD is present: BPF token
> creation itself proves the kernel has a working BPF subsystem.
> Real BPF issues will be caught during actual program and map loading.
> Signed-off-by: Yuan Chen <chenyuan@kylinos.cn>
This describes a bug fix but there is no Fixes: tag.
The probe-loading failure with a restricted BPF token came in when the
token-aware opts were added to bpf_object__probe_loading(), passing the
token FD into the trivial SOCKET_FILTER and TRACEPOINT probe loads:
LIBBPF_OPTS(bpf_prog_load_opts, opts,
.token_fd = obj->token_fd,
.prog_flags = obj->token_fd ? BPF_F_TOKEN_FD : 0,
);
which is the code this patch removes. Should this include:
Fixes: 6b434b61b4d9 ("libbpf: Wire up BPF token support at BPF object level")
In the earlier resend thread, Mykyta Yatsenko asked for a Fixes: tag to
be added:
https://lore.kernel.org/bpf/2ec75142-04b6-4d03-9aad-7441b6350f2b@gmail.com/
> Please resend your patch applying these: ... add fixes tag ...
That request does not appear to be reflected in this version, which still
carries no Fixes: tag.
The same thread also asked to include any Acked-bys. Mykyta Yatsenko gave
an Acked-by on v2:
https://lore.kernel.org/bpf/e23baad8-1709-4210-81c8-22741b9dfb3e@gmail.com/
> This change makes sense ...
> Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
Should this be carried forward as:
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
---
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/27285576775
^ permalink raw reply [flat|nested] 25+ messages in thread
* Re: [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes
2026-06-10 14:50 ` [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes chenyuan_fl
2026-06-10 15:04 ` sashiko-bot
@ 2026-06-10 16:30 ` bot+bpf-ci
1 sibling, 0 replies; 25+ messages in thread
From: bot+bpf-ci @ 2026-06-10 16:30 UTC (permalink / raw)
To: chenyuan_fl, chenyuan_fl
Cc: andrii, ast, bpf, chenyuan, daniel, eddyz87, linux-kselftest,
shuah, mykyta.yatsenko5, andrii.nakryiko, ast, andrii, daniel,
martin.lau, eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 6062 bytes --]
> diff --git a/tools/lib/bpf/features.c b/tools/lib/bpf/features.c
> index b7e388f99d0b..f008ee50e246 100644
> --- a/tools/lib/bpf/features.c
> +++ b/tools/lib/bpf/features.c
> @@ -19,6 +19,57 @@ int probe_fd(int fd)
> return fd >= 0;
> }
>
> +/* Fetch the first program type from the token that can be used for
> + * feature probes. Only a few common types are checked that are known
> + * to accept a trivial "return 0" program. Returns the type on success,
> + * -EINVAL if the token has no probeable type.
> + */
> +static int token_probeable_prog_type(int token_fd)
> +{
> + /* Types that accept a simple "return 0" probe program */
> + /* Types that accept a trivial "return 0" program without
> + * specific expected_attach_type. Types requiring expected_attach_type
> + * (CGROUP_SOCK, CGROUP_SOCK_ADDR, LWT_*, NETFILTER) are excluded.
> + */
There seem to be two comment blocks describing the probeable[] array
back-to-back here. The first single-line comment looks like a leftover
from an earlier revision; should it be removed?
> + static const int probeable[] = {
> + BPF_PROG_TYPE_SOCKET_FILTER,
> + BPF_PROG_TYPE_KPROBE,
> + BPF_PROG_TYPE_SCHED_CLS,
> + BPF_PROG_TYPE_SCHED_ACT,
> + BPF_PROG_TYPE_TRACEPOINT,
> + BPF_PROG_TYPE_XDP,
> + BPF_PROG_TYPE_PERF_EVENT,
> + BPF_PROG_TYPE_CGROUP_SKB,
> + BPF_PROG_TYPE_SOCK_OPS,
> + BPF_PROG_TYPE_SK_SKB,
> + BPF_PROG_TYPE_CGROUP_DEVICE,
> + BPF_PROG_TYPE_SK_MSG,
> + BPF_PROG_TYPE_RAW_TRACEPOINT,
> + BPF_PROG_TYPE_RAW_TRACEPOINT_WRITABLE,
> + BPF_PROG_TYPE_CGROUP_SOCKOPT,
> + BPF_PROG_TYPE_CGROUP_SYSCTL,
> + BPF_PROG_TYPE_FLOW_DISSECTOR,
> + BPF_PROG_TYPE_SK_LOOKUP,
> + };
The list places BPF_PROG_TYPE_SOCKET_FILTER first, and the no-token case
also returns SOCKET_FILTER. This matters for the two probes below that
previously used TRACEPOINT.
> + struct bpf_token_info info = {};
> + __u32 info_len = sizeof(info);
> + int i, err;
> +
> + if (!token_fd)
> + return BPF_PROG_TYPE_SOCKET_FILTER;
> +
> + err = bpf_obj_get_info_by_fd(token_fd, &info, &info_len);
> + if (err)
> + return -errno;
> +
> + for (i = 0; i < ARRAY_SIZE(probeable); i++) {
> + if (info.allowed_progs & (1ULL << probeable[i]))
> + return probeable[i];
> + }
> +
> + return -EINVAL;
> +}
> +
[ ... ]
> @@ -257,8 +318,13 @@ static int probe_kern_probe_read_kernel(int token_fd)
> BPF_EXIT_INSN(),
> };
> int fd, insn_cnt = ARRAY_SIZE(insns);
> + int prog_type;
>
> - fd = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + prog_type = token_probeable_prog_type(token_fd);
> + if (prog_type < 0)
> + return 1;
> +
> + fd = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &opts);
This probe tests for BPF_FUNC_probe_read_kernel and previously hardcoded
BPF_PROG_TYPE_TRACEPOINT. In the no-token case token_probeable_prog_type()
now returns BPF_PROG_TYPE_SOCKET_FILTER instead.
For a TRACEPOINT program, probe_read_kernel is reachable through:
tp_prog_func_proto() -> bpf_tracing_func_proto()
For a SOCKET_FILTER program the helper is only reachable through
bpf_base_func_proto(), where it is gated behind
bpf_token_capable(CAP_PERFMON) and
security_locked_down(LOCKDOWN_BPF_READ_KERNEL), and is not exposed via
sk_filter_func_proto().
Does this narrow the conditions under which the probe succeeds, so that
FEAT_PROBE_READ_KERNEL can be misreported in the no-token case that
previously used TRACEPOINT?
> + return probe_fd(fd);
> }
>
[ ... ]
> @@ -277,6 +343,7 @@ static int probe_prog_bind_map(int token_fd)
> .prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
> );
> int ret, map, prog, insn_cnt = ARRAY_SIZE(insns);
> + int prog_type;
>
> map = bpf_map_create(BPF_MAP_TYPE_ARRAY, "libbpf_det_bind", sizeof(int), 32, 1, &map_opts);
> if (map < 0) {
> @@ -286,7 +353,12 @@ static int probe_prog_bind_map(int token_fd)
> return ret;
> }
>
> - prog = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER, NULL, "GPL", insns, insn_cnt, &prog_opts);
> + prog = prog_type = token_probeable_prog_type(token_fd);
This assigns the result to both prog and prog_type, but prog is
unconditionally overwritten by the bpf_prog_load() call just below before
it is ever read. The assignment to prog looks like dead code; should this
just be:
prog_type = token_probeable_prog_type(token_fd);
> + if (prog_type < 0) {
> + close(map);
> + return 1;
> + }
> + prog = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &prog_opts);
> if (prog < 0) {
> close(map);
> return 0;
[ ... ]
> @@ -435,8 +507,13 @@ static int probe_kern_bpf_cookie(int token_fd)
> .prog_flags = token_fd ? BPF_F_TOKEN_FD : 0,
> );
> int ret, insn_cnt = ARRAY_SIZE(insns);
> + int prog_type;
>
> - ret = bpf_prog_load(BPF_PROG_TYPE_TRACEPOINT, NULL, "GPL", insns, insn_cnt, &opts);
> + prog_type = token_probeable_prog_type(token_fd);
> + if (prog_type < 0)
> + return 1;
> +
> + ret = bpf_prog_load(prog_type, NULL, "GPL", insns, insn_cnt, &opts);
This probe tests for BPF_FUNC_get_attach_cookie and previously hardcoded
BPF_PROG_TYPE_TRACEPOINT. In the no-token case token_probeable_prog_type()
now returns BPF_PROG_TYPE_SOCKET_FILTER.
The get_attach_cookie func_proto is only returned for tracing program
types (kprobe via kprobe_prog_func_proto, tracepoint via tp_prog_func_proto,
perf_event via pe_prog_func_proto, raw_tp/tracing).
For a SOCKET_FILTER program, helper resolution goes:
sk_filter_func_proto() -> bpf_sk_base_func_proto() -> bpf_base_func_proto()
none of which expose BPF_FUNC_get_attach_cookie.
Does this mean the verifier rejects the trivial program, bpf_prog_load()
fails, probe_fd() returns 0, and feat_supported() caches FEAT_MISSING, so
FEAT_BPF_COOKIE is reported as unsupported on kernels that do support it,
even with no token in use?
> + return probe_fd(ret);
> }
>
---
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/27285576775
^ permalink raw reply [flat|nested] 25+ messages in thread
end of thread, other threads:[~2026-06-10 16:30 UTC | newest]
Thread overview: 25+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-29 3:16 [PATCH] selftests/bpf: fix token tests for bpf_object__prepare() probe_loading chenyuan_fl
2026-05-29 3:39 ` sashiko-bot
2026-05-29 3:57 ` bot+bpf-ci
2026-06-04 3:10 ` [PATCH bpf-next v2 0/3] libbpf: fix implicit BPF token handling in loading and feature probes chenyuan_fl
2026-06-04 3:10 ` [PATCH bpf-next v2 1/3] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
2026-06-04 4:05 ` bot+bpf-ci
2026-06-04 11:16 ` Mykyta Yatsenko
2026-06-08 18:17 ` Andrii Nakryiko
2026-06-09 13:11 ` [PATCH bpf] " chenyuan_fl
2026-06-09 13:35 ` Mykyta Yatsenko
2026-06-09 13:42 ` bot+bpf-ci
2026-06-04 3:10 ` [PATCH bpf-next v2 2/3] selftests/bpf: Add ARRAY map type to token tests that use struct_ops global data chenyuan_fl
2026-06-04 3:25 ` sashiko-bot
2026-06-08 18:14 ` Andrii Nakryiko
2026-06-04 3:10 ` [PATCH bpf-next v2 3/3] libbpf: fix feature probe failures for implicit BPF tokens chenyuan_fl
2026-06-04 3:27 ` sashiko-bot
2026-06-04 4:05 ` bot+bpf-ci
2026-06-04 14:40 ` Mykyta Yatsenko
2026-06-08 18:18 ` Andrii Nakryiko
2026-06-10 14:50 ` [PATCH bpf-next v3 0/2] libbpf: fix implicit BPF token feature probe failures chenyuan_fl
2026-06-10 14:50 ` [PATCH bpf-next v3 1/2] libbpf: Skip bpf_object__probe_loading() when BPF token is in use chenyuan_fl
2026-06-10 16:30 ` bot+bpf-ci
2026-06-10 14:50 ` [PATCH bpf-next v3 2/2] libbpf: fetch probeable prog type from token for feature probes chenyuan_fl
2026-06-10 15:04 ` sashiko-bot
2026-06-10 16:30 ` bot+bpf-ci
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.