* [PATCH bpf-next v3 1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively
2026-09-01 8:46 [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
@ 2026-09-01 8:46 ` Toke Høiland-Jørgensen
2026-09-03 0:22 ` Andrii Nakryiko
2026-09-01 8:46 ` [PATCH bpf-next v3 2/4] selftests/bpf: Set BPF program flags non-destructively Toke Høiland-Jørgensen
` (3 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-09-01 8:46 UTC (permalink / raw)
To: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Larysa Zaremba, David S. Miller,
Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi
Cc: bpf, netdev, Toke Høiland-Jørgensen
When setting the XDP hints ifname, bpftool would set the
BPF_F_XDP_DEV_BOUND_ONLY without looking at the existing program flags,
overriding any other flag values. This was always a destructive action,
but after we change libbpf to carry the frags section flag in
prog_flags, this can impact bpftool loading of XDP frags programs.
Change the flag setting to be non-destructive by OR'ing it with the
existing flags.
Fixes: f46392ee3dec ("bpftool: Specify XDP Hints ifname when loading program")
Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
tools/bpf/bpftool/prog.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index a9f730d407a9..8c2f9255b36d 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -1769,7 +1769,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
}
if (prog_type == BPF_PROG_TYPE_XDP && xdpmeta_ifindex) {
- bpf_program__set_flags(pos, BPF_F_XDP_DEV_BOUND_ONLY);
+ bpf_program__set_flags(pos, bpf_program__flags(pos) | BPF_F_XDP_DEV_BOUND_ONLY);
bpf_program__set_ifindex(pos, xdpmeta_ifindex);
} else {
bpf_program__set_ifindex(pos, offload_ifindex);
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH bpf-next v3 1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively
2026-09-01 8:46 ` [PATCH bpf-next v3 1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively Toke Høiland-Jørgensen
@ 2026-09-03 0:22 ` Andrii Nakryiko
2026-09-03 7:53 ` Toke Høiland-Jørgensen
0 siblings, 1 reply; 11+ messages in thread
From: Andrii Nakryiko @ 2026-09-03 0:22 UTC (permalink / raw)
To: Toke Høiland-Jørgensen
Cc: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Larysa Zaremba, David S. Miller,
Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi, bpf, netdev
On Tue, Sep 1, 2026 at 1:47 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>
> When setting the XDP hints ifname, bpftool would set the
> BPF_F_XDP_DEV_BOUND_ONLY without looking at the existing program flags,
> overriding any other flag values. This was always a destructive action,
> but after we change libbpf to carry the frags section flag in
> prog_flags, this can impact bpftool loading of XDP frags programs.
>
> Change the flag setting to be non-destructive by OR'ing it with the
> existing flags.
>
> Fixes: f46392ee3dec ("bpftool: Specify XDP Hints ifname when loading program")
> Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
> ---
> tools/bpf/bpftool/prog.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
> index a9f730d407a9..8c2f9255b36d 100644
> --- a/tools/bpf/bpftool/prog.c
> +++ b/tools/bpf/bpftool/prog.c
> @@ -1769,7 +1769,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
> }
>
> if (prog_type == BPF_PROG_TYPE_XDP && xdpmeta_ifindex) {
> - bpf_program__set_flags(pos, BPF_F_XDP_DEV_BOUND_ONLY);
> + bpf_program__set_flags(pos, bpf_program__flags(pos) | BPF_F_XDP_DEV_BOUND_ONLY);
maybe we should just add bpf_program__add_flags() and
bpf_program__clear_flags() to make life a touch easier and code in
selftests and bpftool a touch less verbose?
> bpf_program__set_ifindex(pos, xdpmeta_ifindex);
> } else {
> bpf_program__set_ifindex(pos, offload_ifindex);
>
> --
> 2.55.0
>
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH bpf-next v3 1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively
2026-09-03 0:22 ` Andrii Nakryiko
@ 2026-09-03 7:53 ` Toke Høiland-Jørgensen
0 siblings, 0 replies; 11+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-09-03 7:53 UTC (permalink / raw)
To: Andrii Nakryiko
Cc: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Larysa Zaremba, David S. Miller,
Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi, bpf, netdev
Andrii Nakryiko <andrii.nakryiko@gmail.com> writes:
> On Tue, Sep 1, 2026 at 1:47 AM Toke Høiland-Jørgensen <toke@redhat.com> wrote:
>>
>> When setting the XDP hints ifname, bpftool would set the
>> BPF_F_XDP_DEV_BOUND_ONLY without looking at the existing program flags,
>> overriding any other flag values. This was always a destructive action,
>> but after we change libbpf to carry the frags section flag in
>> prog_flags, this can impact bpftool loading of XDP frags programs.
>>
>> Change the flag setting to be non-destructive by OR'ing it with the
>> existing flags.
>>
>> Fixes: f46392ee3dec ("bpftool: Specify XDP Hints ifname when loading program")
>> Reviewed-by: Larysa Zaremba <larysa.zaremba@intel.com>
>> Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
>> ---
>> tools/bpf/bpftool/prog.c | 2 +-
>> 1 file changed, 1 insertion(+), 1 deletion(-)
>>
>> diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
>> index a9f730d407a9..8c2f9255b36d 100644
>> --- a/tools/bpf/bpftool/prog.c
>> +++ b/tools/bpf/bpftool/prog.c
>> @@ -1769,7 +1769,7 @@ static int load_with_options(int argc, char **argv, bool first_prog_only)
>> }
>>
>> if (prog_type == BPF_PROG_TYPE_XDP && xdpmeta_ifindex) {
>> - bpf_program__set_flags(pos, BPF_F_XDP_DEV_BOUND_ONLY);
>> + bpf_program__set_flags(pos, bpf_program__flags(pos) | BPF_F_XDP_DEV_BOUND_ONLY);
>
> maybe we should just add bpf_program__add_flags() and
> bpf_program__clear_flags() to make life a touch easier and code in
> selftests and bpftool a touch less verbose?
Sure, I can follow up with those. Also makes for a convenient feature
detection target for this change :)
-Toke
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 2/4] selftests/bpf: Set BPF program flags non-destructively
2026-09-01 8:46 [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
2026-09-01 8:46 ` [PATCH bpf-next v3 1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively Toke Høiland-Jørgensen
@ 2026-09-01 8:46 ` Toke Høiland-Jørgensen
2026-09-01 9:54 ` bot+bpf-ci
2026-09-01 8:46 ` [PATCH bpf-next v3 3/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
` (2 subsequent siblings)
4 siblings, 1 reply; 11+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-09-01 8:46 UTC (permalink / raw)
To: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Larysa Zaremba, David S. Miller,
Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi
Cc: bpf, netdev, Toke Høiland-Jørgensen
A couple of the BPF selftests would set the program flags without
looking at the existing program flags, overriding any other flag values.
To avoid issues when we change libbpf to carry section flags in
prog_flags, change this to always set the flag value non-destructively
by OR'ing it with the existing flags.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
tools/testing/selftests/bpf/prog_tests/attach_probe.c | 6 ++++--
tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c | 2 +-
tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c | 2 +-
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c | 4 ++--
tools/testing/selftests/bpf/xdp_hw_metadata.c | 2 +-
5 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
index e8c1a619e330..7dadb90e7b68 100644
--- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
+++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
@@ -543,8 +543,10 @@ static void test_kprobe_sleepable(void)
return;
/* sleepable kprobe test case needs flags set before loading */
- if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
- BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
+ if (!ASSERT_OK(bpf_program__set_flags(
+ skel->progs.handle_kprobe_sleepable,
+ bpf_program__flags(skel->progs.handle_kprobe_sleepable) | BPF_F_SLEEPABLE),
+ "kprobe_sleepable_flags"))
goto cleanup;
if (!ASSERT_OK(test_attach_kprobe_sleepable__load(skel),
diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
index 73f669014b69..652307a1b22e 100644
--- a/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
+++ b/tools/testing/selftests/bpf/prog_tests/bpf_verif_scale.c
@@ -35,7 +35,7 @@ static int check_load(const char *file, enum bpf_prog_type type)
}
bpf_program__set_type(prog, type);
- bpf_program__set_flags(prog, testing_prog_flags());
+ bpf_program__set_flags(prog, bpf_program__flags(prog) | testing_prog_flags());
bpf_program__set_log_level(prog, 4 | extra_prog_load_log_flags);
err = bpf_object__load(obj);
diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
index 2e0ddef77ba5..ed3fd0a88dab 100644
--- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
+++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
@@ -362,7 +362,7 @@ static void test_attach_api_fails(void)
sl_skel->bss->user_ptr = sl_skel;
err = bpf_program__set_flags(sl_skel->progs.handle_kprobe_multi_sleepable,
- BPF_F_SLEEPABLE);
+ bpf_program__flags(sl_skel->progs.handle_kprobe_multi_sleepable) | BPF_F_SLEEPABLE);
if (!ASSERT_OK(err, "sleep_skel_set_flags"))
goto cleanup;
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
index 5c31054ad4a4..047dfdc322a2 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
@@ -408,14 +408,14 @@ void test_xdp_metadata(void)
prog = bpf_object__find_program_by_name(bpf_obj->obj, "rx");
bpf_program__set_ifindex(prog, rx_ifindex);
- bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY);
+ bpf_program__set_flags(prog, bpf_program__flags(prog) | BPF_F_XDP_DEV_BOUND_ONLY);
/* Make sure we can load a dev-bound program that performs
* XDP_REDIRECT into a devmap.
*/
new_prog = bpf_object__find_program_by_name(bpf_obj->obj, "redirect");
bpf_program__set_ifindex(new_prog, rx_ifindex);
- bpf_program__set_flags(new_prog, BPF_F_XDP_DEV_BOUND_ONLY);
+ bpf_program__set_flags(new_prog, bpf_program__flags(new_prog) | BPF_F_XDP_DEV_BOUND_ONLY);
if (!ASSERT_OK(xdp_metadata__load(bpf_obj), "load skeleton"))
goto out;
diff --git a/tools/testing/selftests/bpf/xdp_hw_metadata.c b/tools/testing/selftests/bpf/xdp_hw_metadata.c
index 6db3b5555a22..c5501b3fdf48 100644
--- a/tools/testing/selftests/bpf/xdp_hw_metadata.c
+++ b/tools/testing/selftests/bpf/xdp_hw_metadata.c
@@ -845,7 +845,7 @@ int main(int argc, char *argv[])
prog = bpf_object__find_program_by_name(bpf_obj->obj, "rx");
bpf_program__set_ifindex(prog, ifindex);
- bpf_program__set_flags(prog, BPF_F_XDP_DEV_BOUND_ONLY);
+ bpf_program__set_flags(prog, bpf_program__flags(prog) | BPF_F_XDP_DEV_BOUND_ONLY);
printf("load bpf program...\n");
ret = xdp_hw_metadata__load(bpf_obj);
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH bpf-next v3 2/4] selftests/bpf: Set BPF program flags non-destructively
2026-09-01 8:46 ` [PATCH bpf-next v3 2/4] selftests/bpf: Set BPF program flags non-destructively Toke Høiland-Jørgensen
@ 2026-09-01 9:54 ` bot+bpf-ci
0 siblings, 0 replies; 11+ messages in thread
From: bot+bpf-ci @ 2026-09-01 9:54 UTC (permalink / raw)
To: toke, qmo, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, larysa.zaremba, davem,
kuba, hawk, john.fastabend, sdf, lorenzo
Cc: bpf, netdev, toke, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2406 bytes --]
> diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> index e8c1a619e330e..7dadb90e7b689 100644
> --- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> +++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c
> @@ -543,8 +543,10 @@ static void test_kprobe_sleepable(void)
> return;
>
> /* sleepable kprobe test case needs flags set before loading */
> - if (!ASSERT_OK(bpf_program__set_flags(skel->progs.handle_kprobe_sleepable,
> - BPF_F_SLEEPABLE), "kprobe_sleepable_flags"))
> + if (!ASSERT_OK(bpf_program__set_flags(
> + skel->progs.handle_kprobe_sleepable,
> + bpf_program__flags(skel->progs.handle_kprobe_sleepable) | BPF_F_SLEEPABLE),
> + "kprobe_sleepable_flags"))
> goto cleanup;
This isn't a bug, but would a local like
`struct bpf_program *prog = skel->progs.handle_kprobe_sleepable;` let
this keep the original one-line ASSERT_OK() shape? The read-modify-write
now names the skeleton field twice in one expression, pushing the line
to 106 columns. The other sites in this patch (bpf_verif_scale.c,
xdp_metadata.c, xdp_hw_metadata.c) already have a short prog local and
read as one clean line.
[ ... ]
> diff --git a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> index 2e0ddef77ba51..ed3fd0a88dab6 100644
> --- a/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> +++ b/tools/testing/selftests/bpf/prog_tests/kprobe_multi_test.c
> @@ -362,7 +362,7 @@ static void test_attach_api_fails(void)
> sl_skel->bss->user_ptr = sl_skel;
>
> err = bpf_program__set_flags(sl_skel->progs.handle_kprobe_multi_sleepable,
> - BPF_F_SLEEPABLE);
> + bpf_program__flags(sl_skel->progs.handle_kprobe_multi_sleepable) | BPF_F_SLEEPABLE);
> if (!ASSERT_OK(err, "sleep_skel_set_flags"))
> goto cleanup;
This isn't a bug, but could the program pointer be pulled into a local
here so the flags update stays inside the 100-column limit? Repeating
the 44-character skeleton field name inside its own argument list pushes
this line to 121 columns.
---
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/33489985893
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 3/4] libbpf: Move section-defined program flags to prog_flags
2026-09-01 8:46 [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
2026-09-01 8:46 ` [PATCH bpf-next v3 1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively Toke Høiland-Jørgensen
2026-09-01 8:46 ` [PATCH bpf-next v3 2/4] selftests/bpf: Set BPF program flags non-destructively Toke Høiland-Jørgensen
@ 2026-09-01 8:46 ` Toke Høiland-Jørgensen
2026-09-01 9:54 ` bot+bpf-ci
2026-09-01 8:46 ` [PATCH bpf-next v3 4/4] selftests/bpf: Check for flag presence in bpf_program__flags() Toke Høiland-Jørgensen
2026-09-03 0:30 ` [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags patchwork-bot+netdevbpf
4 siblings, 1 reply; 11+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-09-01 8:46 UTC (permalink / raw)
To: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Larysa Zaremba, David S. Miller,
Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi
Cc: bpf, netdev, Toke Høiland-Jørgensen
The libbpf section definition modifiers for XDP frags support and
sleepable programs stores the flags bits only in the private section
definition cookie from object open to load time. This has the
unfortunate consequence that API consumers cannot see (or manipulate)
the flag between object open and program load.
In particular, libxdp has special handling of frags-enabled programs to
make them compatible with the dispatcher. This doesn't work on XDP
programs that enable frags through the 'xdp.frags' section definition
because the flag is not visible through bpf_program__flags()[0].
Fix this by changing how libbpf loads the program flags from section
definitions: instead of using the private section definition cookie, add
a setup function to the default section definitions that stores the
flags for sleepable and XDP frags programs in the prog_flags field of
struct bpf_program.
Exposing the flags this way means that any use of
bpf_program__set_flags() will override the flags unless the caller takes
care of updating flags in a non-destructive way. This is unavoidable
with the set-only API, and any user setting flags unconditionally is
already broken in the sense that they will also override any other
current and future flags.
In addition, prog_flags survives program type changes through
bpf_program__set_type(). It is the responsibility of the caller to
ensure the flags are cleared if they are incompatible with the new
program type.
[0] https://github.com/xdp-project/xdp-tools/issues/587
Fixes: 082c4bfba4f7 ("libbpf: Add SEC name for xdp frags programs")
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
tools/lib/bpf/libbpf.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
index b749c01742ee..27779b4cddd0 100644
--- a/tools/lib/bpf/libbpf.c
+++ b/tools/lib/bpf/libbpf.c
@@ -7879,6 +7879,19 @@ static int tracing_multi_mod_fd(struct bpf_program *prog, int *btf_obj_fd)
return 0;
}
+static int libbpf_setup_prog_flags(struct bpf_program *prog, long cookie)
+{
+ enum sec_def_flags def = cookie;
+
+ if (def & SEC_SLEEPABLE)
+ prog->prog_flags |= BPF_F_SLEEPABLE;
+
+ if (def & SEC_XDP_FRAGS)
+ prog->prog_flags |= BPF_F_XDP_HAS_FRAGS;
+
+ return 0;
+}
+
/* this is called as prog->sec_def->prog_prepare_load_fn for libbpf-supported sec_defs */
static int libbpf_prepare_prog_load(struct bpf_program *prog,
struct bpf_prog_load_opts *opts, long cookie)
@@ -7889,12 +7902,6 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog,
if ((def & SEC_EXP_ATTACH_OPT) && !kernel_supports(prog->obj, FEAT_EXP_ATTACH_TYPE))
opts->expected_attach_type = 0;
- if (def & SEC_SLEEPABLE)
- opts->prog_flags |= BPF_F_SLEEPABLE;
-
- if (prog->type == BPF_PROG_TYPE_XDP && (def & SEC_XDP_FRAGS))
- opts->prog_flags |= BPF_F_XDP_HAS_FRAGS;
-
/* special check for usdt to use uprobe_multi link */
if ((def & SEC_USDT) && kernel_supports(prog->obj, FEAT_UPROBE_MULTI_LINK)) {
/* for BPF_TRACE_UPROBE_MULTI, user might want to query expected_attach_type
@@ -10099,6 +10106,7 @@ int bpf_program__clone(struct bpf_program *prog, const struct bpf_prog_load_opts
.prog_type = BPF_PROG_TYPE_##ptype, \
.expected_attach_type = atype, \
.cookie = (long)(flags), \
+ .prog_setup_fn = libbpf_setup_prog_flags, \
.prog_prepare_load_fn = libbpf_prepare_prog_load, \
__VA_ARGS__ \
}
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH bpf-next v3 3/4] libbpf: Move section-defined program flags to prog_flags
2026-09-01 8:46 ` [PATCH bpf-next v3 3/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
@ 2026-09-01 9:54 ` bot+bpf-ci
2026-09-03 0:22 ` Andrii Nakryiko
0 siblings, 1 reply; 11+ messages in thread
From: bot+bpf-ci @ 2026-09-01 9:54 UTC (permalink / raw)
To: toke, qmo, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, larysa.zaremba, davem,
kuba, hawk, john.fastabend, sdf, lorenzo
Cc: bpf, netdev, toke, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 3218 bytes --]
> diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> index f09cbfd8e729d..c036e8a91ed88 100644
> --- a/tools/lib/bpf/libbpf.c
> +++ b/tools/lib/bpf/libbpf.c
> @@ -7879,6 +7879,19 @@ static int tracing_multi_mod_fd(struct bpf_program *prog, int *btf_obj_fd)
> return 0;
> }
>
> +static int libbpf_setup_prog_flags(struct bpf_program *prog, long cookie)
> +{
> + enum sec_def_flags def = cookie;
> +
> + if (def & SEC_SLEEPABLE)
> + prog->prog_flags |= BPF_F_SLEEPABLE;
> +
> + if (def & SEC_XDP_FRAGS)
> + prog->prog_flags |= BPF_F_XDP_HAS_FRAGS;
> +
> + return 0;
> +}
> +
> /* this is called as prog->sec_def->prog_prepare_load_fn for libbpf-supported sec_defs */
> static int libbpf_prepare_prog_load(struct bpf_program *prog,
> struct bpf_prog_load_opts *opts, long cookie)
> @@ -7889,12 +7902,6 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog,
> if ((def & SEC_EXP_ATTACH_OPT) && !kernel_supports(prog->obj, FEAT_EXP_ATTACH_TYPE))
> opts->expected_attach_type = 0;
>
> - if (def & SEC_SLEEPABLE)
> - opts->prog_flags |= BPF_F_SLEEPABLE;
> -
> - if (prog->type == BPF_PROG_TYPE_XDP && (def & SEC_XDP_FRAGS))
> - opts->prog_flags |= BPF_F_XDP_HAS_FRAGS;
> -
Does this change break bpf_program__clone() when the caller passes
non-zero opts.prog_flags?
Before this patch, libbpf_prepare_prog_load() OR'd in the section flags
after the caller's override:
/* in bpf_program__clone() */
attr.prog_flags = OPTS_GET(opts, prog_flags, 0) ?: prog->prog_flags;
...
prog->sec_def->prog_prepare_load_fn(prog, &attr, ...);
/* in libbpf_prepare_prog_load() */
if (def & SEC_SLEEPABLE)
opts->prog_flags |= BPF_F_SLEEPABLE;
So a caller doing:
LIBBPF_OPTS(bpf_prog_load_opts, opts, .prog_flags = BPF_F_TEST_STATE_FREQ);
fd = bpf_program__clone(prog, &opts);
would get TEST_STATE_FREQ | SLEEPABLE for a program in SEC("fentry.s/...").
After this patch, the flags live only in prog->prog_flags, and the `?:`
in bpf_program__clone() discards prog->prog_flags entirely when the
caller passes non-zero opts.prog_flags:
attr.prog_flags = OPTS_GET(opts, prog_flags, 0) ?: prog->prog_flags;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
returns TEST_STATE_FREQ, prog->prog_flags is ignored
So the same caller now gets only TEST_STATE_FREQ without SLEEPABLE. For
sleepable-only helpers like bpf_copy_from_user, this produces a verifier
rejection. For BPF_PROG_TYPE_SYSCALL, which requires prog->sleepable,
it fails at load. For xdp.frags programs, BPF_F_XDP_HAS_FRAGS is lost.
Looking at the pattern immediately below in the same function:
if (attr.token_fd)
attr.prog_flags |= BPF_F_TOKEN_FD;
should the section flags be OR'd in unconditionally, or should the
caller-override `?:` be removed for prog_flags? The commit message
mentions bpf_program__set_flags() and bpf_program__set_type() as
affected APIs but doesn't mention bpf_program__clone().
---
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/33489985893
^ permalink raw reply [flat|nested] 11+ messages in thread* Re: [PATCH bpf-next v3 3/4] libbpf: Move section-defined program flags to prog_flags
2026-09-01 9:54 ` bot+bpf-ci
@ 2026-09-03 0:22 ` Andrii Nakryiko
0 siblings, 0 replies; 11+ messages in thread
From: Andrii Nakryiko @ 2026-09-03 0:22 UTC (permalink / raw)
To: bot+bpf-ci, Mykyta Yatsenko
Cc: toke, qmo, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, larysa.zaremba, davem,
kuba, hawk, john.fastabend, sdf, lorenzo, bpf, netdev, martin.lau,
mason
On Tue, Sep 1, 2026 at 2:54 AM <bot+bpf-ci@kernel.org> wrote:
>
> > diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c
> > index f09cbfd8e729d..c036e8a91ed88 100644
> > --- a/tools/lib/bpf/libbpf.c
> > +++ b/tools/lib/bpf/libbpf.c
> > @@ -7879,6 +7879,19 @@ static int tracing_multi_mod_fd(struct bpf_program *prog, int *btf_obj_fd)
> > return 0;
> > }
> >
> > +static int libbpf_setup_prog_flags(struct bpf_program *prog, long cookie)
> > +{
> > + enum sec_def_flags def = cookie;
> > +
> > + if (def & SEC_SLEEPABLE)
> > + prog->prog_flags |= BPF_F_SLEEPABLE;
> > +
> > + if (def & SEC_XDP_FRAGS)
> > + prog->prog_flags |= BPF_F_XDP_HAS_FRAGS;
> > +
> > + return 0;
> > +}
> > +
> > /* this is called as prog->sec_def->prog_prepare_load_fn for libbpf-supported sec_defs */
> > static int libbpf_prepare_prog_load(struct bpf_program *prog,
> > struct bpf_prog_load_opts *opts, long cookie)
> > @@ -7889,12 +7902,6 @@ static int libbpf_prepare_prog_load(struct bpf_program *prog,
> > if ((def & SEC_EXP_ATTACH_OPT) && !kernel_supports(prog->obj, FEAT_EXP_ATTACH_TYPE))
> > opts->expected_attach_type = 0;
> >
> > - if (def & SEC_SLEEPABLE)
> > - opts->prog_flags |= BPF_F_SLEEPABLE;
> > -
> > - if (prog->type == BPF_PROG_TYPE_XDP && (def & SEC_XDP_FRAGS))
> > - opts->prog_flags |= BPF_F_XDP_HAS_FRAGS;
> > -
>
> Does this change break bpf_program__clone() when the caller passes
> non-zero opts.prog_flags?
>
> Before this patch, libbpf_prepare_prog_load() OR'd in the section flags
> after the caller's override:
>
> /* in bpf_program__clone() */
> attr.prog_flags = OPTS_GET(opts, prog_flags, 0) ?: prog->prog_flags;
> ...
> prog->sec_def->prog_prepare_load_fn(prog, &attr, ...);
>
> /* in libbpf_prepare_prog_load() */
> if (def & SEC_SLEEPABLE)
> opts->prog_flags |= BPF_F_SLEEPABLE;
>
> So a caller doing:
>
> LIBBPF_OPTS(bpf_prog_load_opts, opts, .prog_flags = BPF_F_TEST_STATE_FREQ);
> fd = bpf_program__clone(prog, &opts);
>
> would get TEST_STATE_FREQ | SLEEPABLE for a program in SEC("fentry.s/...").
>
> After this patch, the flags live only in prog->prog_flags, and the `?:`
> in bpf_program__clone() discards prog->prog_flags entirely when the
> caller passes non-zero opts.prog_flags:
>
> attr.prog_flags = OPTS_GET(opts, prog_flags, 0) ?: prog->prog_flags;
> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> returns TEST_STATE_FREQ, prog->prog_flags is ignored
>
> So the same caller now gets only TEST_STATE_FREQ without SLEEPABLE. For
> sleepable-only helpers like bpf_copy_from_user, this produces a verifier
> rejection. For BPF_PROG_TYPE_SYSCALL, which requires prog->sleepable,
> it fails at load. For xdp.frags programs, BPF_F_XDP_HAS_FRAGS is lost.
>
> Looking at the pattern immediately below in the same function:
>
> if (attr.token_fd)
> attr.prog_flags |= BPF_F_TOKEN_FD;
>
> should the section flags be OR'd in unconditionally, or should the
no, I don't think so. In the given example, I think BPF_F_SLEEPABLE
flag should be provided by the caller explicitly.
Mykyta, can you please check if veristat would need some adjustments
due to these changes? Thanks!
> caller-override `?:` be removed for prog_flags? The commit message
> mentions bpf_program__set_flags() and bpf_program__set_type() as
> affected APIs but doesn't mention bpf_program__clone().
>
>
> ---
> 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/33489985893
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH bpf-next v3 4/4] selftests/bpf: Check for flag presence in bpf_program__flags()
2026-09-01 8:46 [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
` (2 preceding siblings ...)
2026-09-01 8:46 ` [PATCH bpf-next v3 3/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
@ 2026-09-01 8:46 ` Toke Høiland-Jørgensen
2026-09-03 0:30 ` [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags patchwork-bot+netdevbpf
4 siblings, 0 replies; 11+ messages in thread
From: Toke Høiland-Jørgensen @ 2026-09-01 8:46 UTC (permalink / raw)
To: Quentin Monnet, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Larysa Zaremba, David S. Miller,
Jakub Kicinski, Jesper Dangaard Brouer, John Fastabend,
Stanislav Fomichev, Lorenzo Bianconi
Cc: bpf, netdev, Toke Høiland-Jørgensen
Add a check that the BPF_F_XDP_HAS_FRAGS and BPF_F_SLEEPABLE flags show
up in bpf_program__flags() when opening a BPF program with the flag
definitions in their section definitions.
Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
---
tools/testing/selftests/bpf/prog_tests/kernel_flag.c | 3 +++
tools/testing/selftests/bpf/prog_tests/xdp_adjust_frags.c | 3 +++
tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c | 5 +++++
3 files changed, 11 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/kernel_flag.c b/tools/testing/selftests/bpf/prog_tests/kernel_flag.c
index 97b00c7efe94..25eb59f460ab 100644
--- a/tools/testing/selftests/bpf/prog_tests/kernel_flag.c
+++ b/tools/testing/selftests/bpf/prog_tests/kernel_flag.c
@@ -16,6 +16,9 @@ void test_kernel_flag(void)
if (!ASSERT_OK_PTR(lsm_skel, "lsm_skel"))
return;
+ ASSERT_EQ(bpf_program__flags(lsm_skel->progs.bpf) & BPF_F_SLEEPABLE,
+ BPF_F_SLEEPABLE, "sleepable in program flags");
+
lsm_skel->bss->monitored_tid = sys_gettid();
ret = test_kernel_flag__attach(lsm_skel);
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_frags.c b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_frags.c
index fce203640f8c..a894b1ab46f4 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_adjust_frags.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_adjust_frags.c
@@ -18,6 +18,9 @@ static void test_xdp_update_frags(void)
return;
prog = bpf_object__next_program(obj, NULL);
+ ASSERT_EQ(bpf_program__flags(prog) & BPF_F_XDP_HAS_FRAGS,
+ BPF_F_XDP_HAS_FRAGS, "frags in program flags");
+
if (bpf_object__load(obj))
return;
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c b/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
index a8ab05216c38..dff6b3e7266e 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_devmap_attach.c
@@ -146,6 +146,11 @@ static void test_xdp_with_devmap_frags_helpers(void)
if (!ASSERT_OK_PTR(skel, "test_xdp_with_devmap_helpers__open_and_load"))
return;
+ ASSERT_EQ(bpf_program__flags(skel->progs.xdp_dummy_dm_frags) & BPF_F_XDP_HAS_FRAGS,
+ BPF_F_XDP_HAS_FRAGS, "frags in program flags");
+ ASSERT_EQ(bpf_program__flags(skel->progs.xdp_dummy_dm) & BPF_F_XDP_HAS_FRAGS,
+ 0, "frags not in program flags");
+
dm_fd_frags = bpf_program__fd(skel->progs.xdp_dummy_dm_frags);
map_fd = bpf_map__fd(skel->maps.dm_ports);
err = bpf_prog_get_info_by_fd(dm_fd_frags, &info, &len);
--
2.55.0
^ permalink raw reply related [flat|nested] 11+ messages in thread* Re: [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags
2026-09-01 8:46 [PATCH bpf-next v3 0/4] libbpf: Move section-defined program flags to prog_flags Toke Høiland-Jørgensen
` (3 preceding siblings ...)
2026-09-01 8:46 ` [PATCH bpf-next v3 4/4] selftests/bpf: Check for flag presence in bpf_program__flags() Toke Høiland-Jørgensen
@ 2026-09-03 0:30 ` patchwork-bot+netdevbpf
4 siblings, 0 replies; 11+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-09-03 0:30 UTC (permalink / raw)
To: =?utf-8?b?VG9rZSBIw7hpbGFuZC1Kw7hyZ2Vuc2VuIDx0b2tlQHJlZGhhdC5jb20+?=
Cc: qmo, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, larysa.zaremba, davem,
kuba, hawk, john.fastabend, sdf, lorenzo, bpf, netdev
Hello:
This series was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:
On Tue, 01 Sep 2026 10:46:53 +0200 you wrote:
> This series moves the libbpf section-defined program flags into
> bpf_program->prog_flags, thereby making them available for applications
> to inspect and modify before loading the program into the kernel. See
> patch 3 in the series for details.
>
> Setting program flags with bpf_program__set_flags() was always
> potentially a destructive action, as it clobbers any existing flags.
> Since this changes the flags value to be pre-populated at
> initialisation, this clobbering can be visible in cases it wasn't
> before. To prevent any fallout, the first two commits fixes up existing
> in-tree users of bpf_program__set_flags() to be non-destructive.
>
> [...]
Here is the summary with links:
- [bpf-next,v3,1/4] bpftool: Set BPF_F_XDP_DEV_BOUND_ONLY flag non-destructively
https://git.kernel.org/bpf/bpf-next/c/06d6f845c4bd
- [bpf-next,v3,2/4] selftests/bpf: Set BPF program flags non-destructively
https://git.kernel.org/bpf/bpf-next/c/d6746a246b36
- [bpf-next,v3,3/4] libbpf: Move section-defined program flags to prog_flags
https://git.kernel.org/bpf/bpf-next/c/d6b633b585f3
- [bpf-next,v3,4/4] selftests/bpf: Check for flag presence in bpf_program__flags()
https://git.kernel.org/bpf/bpf-next/c/99c71666dcb1
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 11+ messages in thread