* [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
* 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 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
* [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 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
* 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 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
* [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 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 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 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-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
* 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
* [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 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.