* [PATCH bpf 0/3] bpf: expose cgroup preorder attachment state to userspace
@ 2026-09-18 17:24 Hui Su
2026-09-18 17:24 ` [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries Hui Su
` (2 more replies)
0 siblings, 3 replies; 8+ messages in thread
From: Hui Su @ 2026-09-18 17:24 UTC (permalink / raw)
To: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi
Cc: Yonghong Song, Quentin Monnet, Martin KaFai Lau, Song Liu,
Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan,
linux-kselftest, linux-kernel, Hui Su
Commit 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs")
introduced BPF_F_PREORDER to request pre-order execution across the
cgroup hierarchy. While the kernel records BPF_F_PREORDER in pl->flags,
__cgroup_bpf_query() currently fails to report it to user space in
prog_attach_flags[] during direct cgroup program queries.
This series fixes the kernel query path, extends BPF selftests to
verify the fix, and updates bpftool to recognize and format the
BPF_F_PREORDER flag.
Patch 1 fixes __cgroup_bpf_query() to merge (pl->flags & BPF_F_PREORDER)
with cgroup flags when copying per-program attach flags to user space.
Patch 2 extends selftests/bpf (cgroup_mprog_opts) to verify that direct
and link queries report BPF_F_PREORDER (0x42), matching programs by
prog_id with guarded failure paths.
Patch 3 adds bpftool support: a bitmask flags formatter for cgroup show,
support for "preorder" in cgroup attach, documentation updates, and bash
completion.
Testing:
- Verified on unpatched kernel: selftest reproduces failure
(actual 2 != expected 66).
- Verified on patched kernel (bpf/master): both cgroup_mprog_opts and
cgroup_preorder pass 100% in QEMU guest environment.
- Verified bpftool build, format unit tests, and checkpatch
(0 errors, 0 warnings).
Hui Su (3):
bpf: Report BPF_F_PREORDER in cgroup program queries
selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments
bpftool: Add support for BPF_F_PREORDER cgroup attach flag
kernel/bpf/cgroup.c | 16 ++--
.../bpftool/Documentation/bpftool-cgroup.rst | 9 +-
tools/bpf/bpftool/bash-completion/bpftool | 2 +-
tools/bpf/bpftool/cgroup.c | 55 +++++++----
.../bpf/prog_tests/cgroup_mprog_opts.c | 94 ++++++++++++++++++-
5 files changed, 144 insertions(+), 32 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 8+ messages in thread* [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries 2026-09-18 17:24 [PATCH bpf 0/3] bpf: expose cgroup preorder attachment state to userspace Hui Su @ 2026-09-18 17:24 ` Hui Su 2026-09-18 17:51 ` Alexei Starovoitov 2026-09-18 18:23 ` bot+bpf-ci 2026-09-18 17:24 ` [PATCH bpf 2/3] selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments Hui Su 2026-09-18 17:24 ` [PATCH bpf 3/3] bpftool: Add support for BPF_F_PREORDER cgroup attach flag Hui Su 2 siblings, 2 replies; 8+ messages in thread From: Hui Su @ 2026-09-18 17:24 UTC (permalink / raw) To: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Yonghong Song, Quentin Monnet, Martin KaFai Lau, Song Liu, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan, linux-kselftest, linux-kernel, Hui Su Commit 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs") introduced BPF_F_PREORDER to request pre-order execution across the cgroup hierarchy, altering the effective prog array ordering. While pl->flags stores BPF_F_PREORDER for each attached program, __cgroup_bpf_query() currently fails to report it. When querying attached programs (!effective_query), __cgroup_bpf_query() fills prog_attach_flags[] with cgrp->bpf.flags[atype] for all entries, omitting the per-program BPF_F_PREORDER attribute. As a result, user space tools and query callers cannot distinguish pre-ordered programs from standard multi-prog attachments via BPF_PROG_QUERY. Fix this by merging (pl->flags & BPF_F_PREORDER) with the cgroup-wide flags when copying prog_attach_flags to user space. Only BPF_F_PREORDER is extracted from pl->flags to ensure transient positioning flags (such as BPF_F_BEFORE, BPF_F_AFTER, BPF_F_ID, or BPF_F_REPLACE) are not leaked to user space. Also perform both ID and attach flags copies within the same hlist iteration. Fixes: 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs") Signed-off-by: Hui Su <sh_def@163.com> --- kernel/bpf/cgroup.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 149672c76c49..e7c7efa1baa7 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -1353,19 +1353,19 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, id = prog->aux->id; if (copy_to_user(prog_ids + i, &id, sizeof(id))) return -EFAULT; + if (prog_attach_flags) { + flags = cgrp->bpf.flags[atype] | + (pl->flags & BPF_F_PREORDER); + if (copy_to_user(prog_attach_flags + i, + &flags, sizeof(flags))) + return -EFAULT; + } if (++i == cnt) break; } - if (prog_attach_flags) { - flags = cgrp->bpf.flags[atype]; - - for (i = 0; i < cnt; i++) - if (copy_to_user(prog_attach_flags + i, - &flags, sizeof(flags))) - return -EFAULT; + if (prog_attach_flags) prog_attach_flags += cnt; - } } prog_ids += cnt; -- 2.55.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries 2026-09-18 17:24 ` [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries Hui Su @ 2026-09-18 17:51 ` Alexei Starovoitov 2026-09-18 18:23 ` bot+bpf-ci 1 sibling, 0 replies; 8+ messages in thread From: Alexei Starovoitov @ 2026-09-18 17:51 UTC (permalink / raw) To: Hui Su, bpf, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Yonghong Song, Quentin Monnet, Martin KaFai Lau, Song Liu, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan, linux-kselftest, linux-kernel On Sat, Sep 19, 2026 at 02:24 AM Hui Su <sh_def@163.com> wrote: > As a result, user space tools and query callers cannot distinguish > pre-ordered programs from standard multi-prog attachments via > BPF_PROG_QUERY. [...] > Fixes: 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs") That's not a fix. Nothing is broken. The patch changes what BPF_PROG_QUERY returns to user space and existing bpftool will start printing "unknown(42)" for such progs. That shouldn't go to stable. Drop the Fixes tag and resend the series for bpf-next. pw-bot: cr ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries 2026-09-18 17:24 ` [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries Hui Su 2026-09-18 17:51 ` Alexei Starovoitov @ 2026-09-18 18:23 ` bot+bpf-ci 1 sibling, 0 replies; 8+ messages in thread From: bot+bpf-ci @ 2026-09-18 18:23 UTC (permalink / raw) To: sh_def, bpf, ast, daniel, andrii, eddyz87, memxor Cc: yonghong.song, qmo, martin.lau, song, jolsa, emil, ihor.solodrai, shuah, linux-kselftest, linux-kernel, sh_def, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai [-- Attachment #1: Type: text/plain, Size: 3777 bytes --] > diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c > index 149672c76c49c..e7c7efa1baa75 100644 > --- a/kernel/bpf/cgroup.c > +++ b/kernel/bpf/cgroup.c > @@ -1353,19 +1353,19 @@ static int __cgroup_bpf_query(struct cgroup *cgrp, const union bpf_attr *attr, > id = prog->aux->id; > if (copy_to_user(prog_ids + i, &id, sizeof(id))) > return -EFAULT; > + if (prog_attach_flags) { > + flags = cgrp->bpf.flags[atype] | > + (pl->flags & BPF_F_PREORDER); > + if (copy_to_user(prog_attach_flags + i, > + &flags, sizeof(flags))) > + return -EFAULT; > + } > if (++i == cnt) > break; > } > > - if (prog_attach_flags) { > - flags = cgrp->bpf.flags[atype]; > - > - for (i = 0; i < cnt; i++) > - if (copy_to_user(prog_attach_flags + i, > - &flags, sizeof(flags))) > - return -EFAULT; > + if (prog_attach_flags) > prog_attach_flags += cnt; > - } > } > > prog_ids += cnt; This changes BPF_PROG_QUERY to report a new flag value (BPF_F_PREORDER) that was never reported before. Could this cause compatibility issues with the stable backport? Before this patch, prog_attach_flags[i] could only contain BPF_F_ALLOW_OVERRIDE (0x1) and BPF_F_ALLOW_MULTI (0x2). After this patch, it can additionally carry BPF_F_PREORDER (0x40), producing new values 0x40 and 0x42 where 0x00/0x02 appeared before. Existing in-tree userspace does exact-match formatting on these values. tools/bpf/bpftool/cgroup.c, show_attached_bpf_progs(), before commit 2af5b738880b2 (the third commit in this series): attach_flags = prog_attach_flags[iter] ?: p.attach_flags; switch (attach_flags) { case BPF_F_ALLOW_MULTI: attach_flags_str = "multi"; break; case BPF_F_ALLOW_OVERRIDE: attach_flags_str = "override"; break; case 0: attach_flags_str = ""; break; default: snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags); attach_flags_str = buf; } The series' third commit documents the fallout: bpftool displays "unknown(40)" when BPF_F_PREORDER is present alone, or "unknown(42)" when combined with BPF_F_ALLOW_MULTI. Within this series that is resolved (bpftool is fixed in commit 3), but the tagging creates an asymmetry: this commit carries Fixes: 4b82b181a26c (v6.15) which drives stable selection, while neither the selftest nor the bpftool commit carries a Fixes: tag or stable Cc. A stable backport of this commit alone would land the new query output on a stable tree whose bpftool still has the exact-match switch, turning bpftool cgroup show output from "multi" into "unknown(42)" for pre-ordered attachments. The same skew applies to any distro bpftool older than commit 3. Should the Fixes: tag be dropped, or should the bpftool commit also carry the same Fixes: tag so the two are backported together? Also, the commit message does not state that BPF_PROG_QUERY starts returning a previously-unreported bit in prog_attach_flags[]. Could that compatibility fact be stated explicitly for reviewers? --- Alexei Starovoitov raised a concern about the Fixes tag and target tree. Alexei noted that this is not a bug fix but a user-space API change, and existing bpftool will display "unknown(42)" for programs with BPF_F_PREORDER. The suggestion was to target bpf-next (not bpf) and drop the Fixes tag to prevent backporting to stable kernels. Should this series target bpf-next instead of bpf, and should the Fixes tag be removed? --- 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/35376083935 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf 2/3] selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments 2026-09-18 17:24 [PATCH bpf 0/3] bpf: expose cgroup preorder attachment state to userspace Hui Su 2026-09-18 17:24 ` [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries Hui Su @ 2026-09-18 17:24 ` Hui Su 2026-09-18 18:23 ` bot+bpf-ci 2026-09-18 17:24 ` [PATCH bpf 3/3] bpftool: Add support for BPF_F_PREORDER cgroup attach flag Hui Su 2 siblings, 1 reply; 8+ messages in thread From: Hui Su @ 2026-09-18 17:24 UTC (permalink / raw) To: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Yonghong Song, Quentin Monnet, Martin KaFai Lau, Song Liu, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan, linux-kselftest, linux-kernel, Hui Su Extend cgroup_mprog_opts selftests to verify that BPF_PROG_QUERY reports BPF_F_PREORDER in prog_attach_flags for both direct program and link attachments. Specifically, in test_preorder_prog_attach_detach() and test_preorder_link_attach_detach(), verify that: - Programs attached with BPF_F_PREORDER report BPF_F_ALLOW_MULTI | BPF_F_PREORDER (0x42) in prog_attach_flags. - Programs attached without BPF_F_PREORDER report BPF_F_ALLOW_MULTI (0x2). - Transient flags such as BPF_F_AFTER or BPF_F_LINK are not present in prog_attach_flags. - Per-program attach flags are validated by matching each attached prog_id via a query helper, avoiding fragile assumptions on the internal slot order of the direct query list. Signed-off-by: Hui Su <sh_def@163.com> --- .../bpf/prog_tests/cgroup_mprog_opts.c | 94 ++++++++++++++++++- 1 file changed, 91 insertions(+), 3 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c b/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c index bb60704a3ef9..343357d9c460 100644 --- a/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c +++ b/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c @@ -273,13 +273,31 @@ static void test_link_attach_detach(int atype) close(cg); } +static int find_prog_attach_flags(const struct bpf_prog_query_opts *opts, + __u32 prog_id, __u32 *flags) +{ + __u32 i; + + for (i = 0; i < opts->count; i++) { + if (opts->prog_ids[i] == prog_id) { + *flags = opts->prog_attach_flags[i]; + return 0; + } + } + return -ENOENT; +} + static void test_preorder_prog_attach_detach(int atype) { LIBBPF_OPTS(bpf_prog_attach_opts, opta); LIBBPF_OPTS(bpf_prog_detach_opts, optd); - __u32 fd1, fd2, fd3, fd4; + LIBBPF_OPTS(bpf_prog_query_opts, optq); + __u32 fd1, fd2, fd3, fd4, id1, id2, id3, id4; + __u32 prog_attach_flags[10] = {0}; + __u32 prog_ids[10] = {0}; struct cgroup_mprog *skel; int cg, err; + __u32 flags; cg = test__join_cgroup("/preorder_prog_attach_detach"); if (!ASSERT_GE(cg, 0, "join_cgroup /preorder_prog_attach_detach")) @@ -294,6 +312,11 @@ static void test_preorder_prog_attach_detach(int atype) fd3 = bpf_program__fd(skel->progs.getsockopt_3); fd4 = bpf_program__fd(skel->progs.getsockopt_4); + id1 = id_from_prog_fd(fd1); + id2 = id_from_prog_fd(fd2); + id3 = id_from_prog_fd(fd3); + id4 = id_from_prog_fd(fd4); + assert_mprog_count(cg, atype, 0); LIBBPF_OPTS_RESET(opta, @@ -357,6 +380,34 @@ static void test_preorder_prog_attach_detach(int atype) assert_mprog_count(cg, atype, 4); + optq.prog_ids = prog_ids; + optq.prog_attach_flags = prog_attach_flags; + optq.count = 10; + err = bpf_prog_query_opts(cg, atype, &optq); + if (!ASSERT_OK(err, "prog_query")) + goto cleanup4; + + ASSERT_EQ(optq.count, 4, "count"); + /* Direct query reports attached programs in cgroup list order. + * Lookup by prog_id to verify per-program flags independently of slot index. + */ + err = find_prog_attach_flags(&optq, id1, &flags); + if (ASSERT_OK(err, "find id1")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id1"); + + err = find_prog_attach_flags(&optq, id2, &flags); + if (ASSERT_OK(err, "find id2")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id2"); + + err = find_prog_attach_flags(&optq, id3, &flags); + if (ASSERT_OK(err, "find id3")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id3"); + + err = find_prog_attach_flags(&optq, id4, &flags); + if (ASSERT_OK(err, "find id4")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id4"); + +cleanup4: err = bpf_prog_detach_opts(fd4, cg, atype, &optd); ASSERT_OK(err, "prog_detach"); assert_mprog_count(cg, atype, 3); @@ -384,10 +435,14 @@ static void test_preorder_prog_attach_detach(int atype) static void test_preorder_link_attach_detach(int atype) { LIBBPF_OPTS(bpf_cgroup_opts, opta); + LIBBPF_OPTS(bpf_prog_query_opts, optq); struct bpf_link *link1, *link2, *link3, *link4; struct cgroup_mprog *skel; - __u32 fd2; - int cg; + __u32 fd2, id1, id2, id3, id4; + __u32 prog_attach_flags[10] = {0}; + __u32 prog_ids[10] = {0}; + int cg, err; + __u32 flags; cg = test__join_cgroup("/preorder_link_attach_detach"); if (!ASSERT_GE(cg, 0, "join_cgroup /preorder_link_attach_detach")) @@ -399,6 +454,11 @@ static void test_preorder_link_attach_detach(int atype) fd2 = bpf_program__fd(skel->progs.getsockopt_2); + id1 = id_from_prog_fd(bpf_program__fd(skel->progs.getsockopt_1)); + id2 = id_from_prog_fd(fd2); + id3 = id_from_prog_fd(bpf_program__fd(skel->progs.getsockopt_3)); + id4 = id_from_prog_fd(bpf_program__fd(skel->progs.getsockopt_4)); + assert_mprog_count(cg, atype, 0); LIBBPF_OPTS_RESET(opta, @@ -460,6 +520,34 @@ static void test_preorder_link_attach_detach(int atype) assert_mprog_count(cg, atype, 4); + optq.prog_ids = prog_ids; + optq.prog_attach_flags = prog_attach_flags; + optq.count = 10; + err = bpf_prog_query_opts(cg, atype, &optq); + if (!ASSERT_OK(err, "prog_query")) + goto cleanup4; + + ASSERT_EQ(optq.count, 4, "count"); + /* Direct query reports attached programs in cgroup list order. + * Lookup by prog_id to verify per-program flags independently of slot index. + */ + err = find_prog_attach_flags(&optq, id1, &flags); + if (ASSERT_OK(err, "find id1")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id1"); + + err = find_prog_attach_flags(&optq, id2, &flags); + if (ASSERT_OK(err, "find id2")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id2"); + + err = find_prog_attach_flags(&optq, id3, &flags); + if (ASSERT_OK(err, "find id3")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id3"); + + err = find_prog_attach_flags(&optq, id4, &flags); + if (ASSERT_OK(err, "find id4")) + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id4"); + +cleanup4: bpf_link__destroy(link4); assert_mprog_count(cg, atype, 3); -- 2.55.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf 2/3] selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments 2026-09-18 17:24 ` [PATCH bpf 2/3] selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments Hui Su @ 2026-09-18 18:23 ` bot+bpf-ci 0 siblings, 0 replies; 8+ messages in thread From: bot+bpf-ci @ 2026-09-18 18:23 UTC (permalink / raw) To: sh_def, bpf, ast, daniel, andrii, eddyz87, memxor Cc: yonghong.song, qmo, martin.lau, song, jolsa, emil, ihor.solodrai, shuah, linux-kselftest, linux-kernel, sh_def, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai [-- Attachment #1: Type: text/plain, Size: 3518 bytes --] > diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c b/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c > index bb60704a3ef92..343357d9c460e 100644 > --- a/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c > +++ b/tools/testing/selftests/bpf/prog_tests/cgroup_mprog_opts.c [ ... ] > @@ -357,6 +380,34 @@ static void test_preorder_prog_attach_detach(int atype) > > assert_mprog_count(cg, atype, 4); > > + optq.prog_ids = prog_ids; > + optq.prog_attach_flags = prog_attach_flags; > + optq.count = 10; > + err = bpf_prog_query_opts(cg, atype, &optq); > + if (!ASSERT_OK(err, "prog_query")) > + goto cleanup4; > + > + ASSERT_EQ(optq.count, 4, "count"); > + /* Direct query reports attached programs in cgroup list order. > + * Lookup by prog_id to verify per-program flags independently of slot index. > + */ > + err = find_prog_attach_flags(&optq, id1, &flags); > + if (ASSERT_OK(err, "find id1")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id1"); > + > + err = find_prog_attach_flags(&optq, id2, &flags); > + if (ASSERT_OK(err, "find id2")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id2"); > + > + err = find_prog_attach_flags(&optq, id3, &flags); > + if (ASSERT_OK(err, "find id3")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id3"); > + > + err = find_prog_attach_flags(&optq, id4, &flags); > + if (ASSERT_OK(err, "find id4")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id4"); > + > +cleanup4: > err = bpf_prog_detach_opts(fd4, cg, atype, &optd); [ ... ] > @@ -460,6 +520,34 @@ static void test_preorder_link_attach_detach(int atype) > > assert_mprog_count(cg, atype, 4); > > + optq.prog_ids = prog_ids; > + optq.prog_attach_flags = prog_attach_flags; > + optq.count = 10; > + err = bpf_prog_query_opts(cg, atype, &optq); > + if (!ASSERT_OK(err, "prog_query")) > + goto cleanup4; > + > + ASSERT_EQ(optq.count, 4, "count"); > + /* Direct query reports attached programs in cgroup list order. > + * Lookup by prog_id to verify per-program flags independently of slot index. > + */ > + err = find_prog_attach_flags(&optq, id1, &flags); > + if (ASSERT_OK(err, "find id1")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id1"); > + > + err = find_prog_attach_flags(&optq, id2, &flags); > + if (ASSERT_OK(err, "find id2")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id2"); > + > + err = find_prog_attach_flags(&optq, id3, &flags); > + if (ASSERT_OK(err, "find id3")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI | BPF_F_PREORDER, "flags id3"); > + > + err = find_prog_attach_flags(&optq, id4, &flags); > + if (ASSERT_OK(err, "find id4")) > + ASSERT_EQ(flags, BPF_F_ALLOW_MULTI, "flags id4"); > + > +cleanup4: > bpf_link__destroy(link4); This isn't a bug, but since the patch already introduces a helper (find_prog_attach_flags), would it be worth folding this query-and-check block into one too, so the two preorder subtests share it instead of carrying identical copies? The pattern appears twice: first in test_preorder_prog_attach_detach() and again verbatim in test_preorder_link_attach_detach() - same query setup, same comment, same four id/flag expectations, together with duplicated locals (prog_ids[10], prog_attach_flags[10], flags, optq). --- 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/35376083935 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH bpf 3/3] bpftool: Add support for BPF_F_PREORDER cgroup attach flag 2026-09-18 17:24 [PATCH bpf 0/3] bpf: expose cgroup preorder attachment state to userspace Hui Su 2026-09-18 17:24 ` [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries Hui Su 2026-09-18 17:24 ` [PATCH bpf 2/3] selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments Hui Su @ 2026-09-18 17:24 ` Hui Su 2026-09-18 18:23 ` bot+bpf-ci 2 siblings, 1 reply; 8+ messages in thread From: Hui Su @ 2026-09-18 17:24 UTC (permalink / raw) To: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi Cc: Yonghong Song, Quentin Monnet, Martin KaFai Lau, Song Liu, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai, Shuah Khan, linux-kselftest, linux-kernel, Hui Su Commit 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs") introduced BPF_F_PREORDER to request pre-order execution across the cgroup hierarchy. Furthermore, attachments legitimately use combinations such as BPF_F_ALLOW_MULTI | BPF_F_PREORDER. With BPF_PROG_QUERY reporting the per-program BPF_F_PREORDER attribute, bpftool's exact-match formatter falls back to "unknown(40)" when BPF_F_PREORDER is present alone, or "unknown(42)" when combined with BPF_F_ALLOW_MULTI. Additionally, do_attach() only accepts "multi" and "override", rejecting "preorder" with "unknown option". Before: $ bpftool cgroup show <cg> 1234 cgroup_inet_ingress unknown(42) test_prog $ bpftool cgroup attach <cg> cgroup_inet_ingress id 5678 multi preorder Error: unknown option: preorder After: $ bpftool cgroup show <cg> 1234 cgroup_inet_ingress multi,preorder test_prog $ bpftool cgroup attach <cg> cgroup_inet_ingress id 5678 multi preorder (attaches successfully) Refactor the attach flags formatter to use a bitmask formatter that outputs comma-separated flag names while preserving unrecognized bits as "unknown(...)". Also accept "preorder" in do_attach(), and update bpftool-cgroup.rst, usage help, and bash completion. Signed-off-by: Hui Su <sh_def@163.com> --- .../bpftool/Documentation/bpftool-cgroup.rst | 9 ++- tools/bpf/bpftool/bash-completion/bpftool | 2 +- tools/bpf/bpftool/cgroup.c | 55 +++++++++++++------ 3 files changed, 45 insertions(+), 21 deletions(-) diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst index e8185596a759..8ec2546c0b8e 100644 --- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst @@ -45,7 +45,7 @@ CGROUP COMMANDS | **cgroup_unix_recvmsg** | **cgroup_sysctl** | | **cgroup_getsockopt** | **cgroup_setsockopt** | | **cgroup_inet_sock_release** } -| *ATTACH_FLAGS* := { **multi** | **override** } +| *ATTACH_FLAGS* := { **multi** | **override** | **preorder** } DESCRIPTION =========== @@ -75,10 +75,13 @@ bpftool cgroup attach *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*] Attach program *PROG* to the cgroup *CGROUP* with attach type *ATTACH_TYPE* and optional *ATTACH_FLAGS*. - *ATTACH_FLAGS* can be one of: **override** if a sub-cgroup installs some + *ATTACH_FLAGS* can include: **override** if a sub-cgroup installs some bpf program, the program in this cgroup yields to sub-cgroup program; **multi** if a sub-cgroup installs some bpf program, that cgroup program - gets run in addition to the program in this cgroup. + gets run in addition to the program in this cgroup; + **preorder** requests that this program executes before programs attached + further down the cgroup hierarchy during evaluation. **preorder** can be + combined with **multi**. Only one program is allowed to be attached to a cgroup with no attach flags or the **override** flag. Attaching another program will release old diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool index 75cbcb512eba..819757d7a360 100644 --- a/tools/bpf/bpftool/bash-completion/bpftool +++ b/tools/bpf/bpftool/bash-completion/bpftool @@ -1057,7 +1057,7 @@ _bpftool() attach|detach) local BPFTOOL_CGROUP_ATTACH_TYPES="$(bpftool feature list_builtins attach_types 2>/dev/null | \ grep '^cgroup_')" - local ATTACH_FLAGS='multi override' + local ATTACH_FLAGS='multi override preorder' # Check for $prev = $command first if [ $prev = $command ]; then _filedir diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c index ce69d1e5468e..aec1281c95d8 100644 --- a/tools/bpf/bpftool/cgroup.c +++ b/tools/bpf/bpftool/cgroup.c @@ -56,7 +56,7 @@ static const int cgroup_attach_types[] = { }; #define HELP_SPEC_ATTACH_FLAGS \ - "ATTACH_FLAGS := { multi | override }" + "ATTACH_FLAGS := { multi | override | preorder }" #define HELP_SPEC_ATTACH_TYPES \ " ATTACH_TYPE := { cgroup_inet_ingress | cgroup_inet_egress |\n" \ @@ -269,6 +269,39 @@ static int show_effective_bpf_progs(int cgroup_fd, enum bpf_attach_type type, return 0; } +static const char *format_attach_flags(__u32 attach_flags, char *buf, size_t sz) +{ + static const struct { + __u32 flag; + const char *name; + } flags[] = { + { BPF_F_ALLOW_MULTI, "multi" }, + { BPF_F_ALLOW_OVERRIDE, "override" }, + { BPF_F_PREORDER, "preorder" }, + }; + size_t len = 0; + size_t i; + int n; + + buf[0] = '\0'; + for (i = 0; i < ARRAY_SIZE(flags); i++) { + if (attach_flags & flags[i].flag) { + n = snprintf(buf + len, sz - len, "%s%s", + len ? "," : "", flags[i].name); + if (n < 0 || (size_t)n >= sz - len) + return buf; + len += n; + attach_flags &= ~flags[i].flag; + } + } + + if (attach_flags) + snprintf(buf + len, sz - len, "%sunknown(%x)", + len ? "," : "", attach_flags); + + return buf; +} + static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type, int level) { @@ -276,7 +309,7 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type, __u32 prog_attach_flags[1024] = {0}; const char *attach_flags_str; __u32 prog_ids[1024] = {0}; - char buf[32]; + char buf[64]; __u32 iter; int ret; @@ -296,21 +329,7 @@ static int show_attached_bpf_progs(int cgroup_fd, enum bpf_attach_type type, __u32 attach_flags; attach_flags = prog_attach_flags[iter] ?: p.attach_flags; - - switch (attach_flags) { - case BPF_F_ALLOW_MULTI: - attach_flags_str = "multi"; - break; - case BPF_F_ALLOW_OVERRIDE: - attach_flags_str = "override"; - break; - case 0: - attach_flags_str = ""; - break; - default: - snprintf(buf, sizeof(buf), "unknown(%x)", attach_flags); - attach_flags_str = buf; - } + attach_flags_str = format_attach_flags(attach_flags, buf, sizeof(buf)); show_bpf_prog(prog_ids[iter], type, attach_flags_str, level); @@ -593,6 +612,8 @@ static int do_attach(int argc, char **argv) attach_flags |= BPF_F_ALLOW_MULTI; } else if (is_prefix(argv[i], "override")) { attach_flags |= BPF_F_ALLOW_OVERRIDE; + } else if (is_prefix(argv[i], "preorder")) { + attach_flags |= BPF_F_PREORDER; } else { p_err("unknown option: %s", argv[i]); goto exit_cgroup; -- 2.55.0 ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH bpf 3/3] bpftool: Add support for BPF_F_PREORDER cgroup attach flag 2026-09-18 17:24 ` [PATCH bpf 3/3] bpftool: Add support for BPF_F_PREORDER cgroup attach flag Hui Su @ 2026-09-18 18:23 ` bot+bpf-ci 0 siblings, 0 replies; 8+ messages in thread From: bot+bpf-ci @ 2026-09-18 18:23 UTC (permalink / raw) To: sh_def, bpf, ast, daniel, andrii, eddyz87, memxor Cc: yonghong.song, qmo, martin.lau, song, jolsa, emil, ihor.solodrai, shuah, linux-kselftest, linux-kernel, sh_def, ast, andrii, daniel, martin.lau, eddyz87, yonghong.song, mason, ihor.solodrai [-- Attachment #1: Type: text/plain, Size: 6612 bytes --] > diff --git a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst > index e8185596a759b..8ec2546c0b8ee 100644 > --- a/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst > +++ b/tools/bpf/bpftool/Documentation/bpftool-cgroup.rst > @@ -45,7 +45,7 @@ CGROUP COMMANDS > | **cgroup_unix_recvmsg** | **cgroup_sysctl** | > | **cgroup_getsockopt** | **cgroup_setsockopt** | > | **cgroup_inet_sock_release** } > -| *ATTACH_FLAGS* := { **multi** | **override** } > +| *ATTACH_FLAGS* := { **multi** | **override** | **preorder** } > > DESCRIPTION > =========== > @@ -75,10 +75,13 @@ bpftool cgroup attach *CGROUP* *ATTACH_TYPE* *PROG* [*ATTACH_FLAGS*] > Attach program *PROG* to the cgroup *CGROUP* with attach type *ATTACH_TYPE* > and optional *ATTACH_FLAGS*. > > - *ATTACH_FLAGS* can be one of: **override** if a sub-cgroup installs some > + *ATTACH_FLAGS* can include: **override** if a sub-cgroup installs some > bpf program, the program in this cgroup yields to sub-cgroup program; > **multi** if a sub-cgroup installs some bpf program, that cgroup program > - gets run in addition to the program in this cgroup. > + gets run in addition to the program in this cgroup; > + **preorder** requests that this program executes before programs attached > + further down the cgroup hierarchy during evaluation. **preorder** can be > + combined with **multi**. Does the new description accurately capture BPF_F_PREORDER's ordering behavior? The paragraph says preorder programs execute "before programs attached further down the cgroup hierarchy", which focuses on descendant cgroups. But compute_effective_progs() in kernel/bpf/cgroup.c places all preorder programs before all non-preorder programs regardless of where they are attached: fstart = preorder_cnt; bstart = preorder_cnt - 1; ... if (pl->flags & BPF_F_PREORDER) { item = &progs->items[bstart]; bstart--; } else { item = &progs->items[fstart]; fstart++; } This means a preorder program runs before every non-preorder program, including those attached in the same cgroup and in ancestor cgroups. Commit 4b82b181a26c's example shows root with p1,p2 and a child with p3,p4 where p2 and p4 are preorder - the effective order is "p2 p4 p3 p1". So the child's preorder p4 runs before the root's non-preorder p1, and p2 runs before its same-cgroup sibling p1. Also, the paragraph says preorder "can be combined with multi", but do_attach() now accepts "preorder" as a standalone flag. When used alone (without multi), does __cgroup_bpf_attach() stay in the NONE regime where "Only one program is allowed to be attached to a cgroup"? The phrase "can be combined" leaves it ambiguous whether preorder alone enables multi-prog attachment. > > Only one program is allowed to be attached to a cgroup with no attach flags > or the **override** flag. Attaching another program will release old [ ... ] > diff --git a/tools/bpf/bpftool/bash-completion/bpftool b/tools/bpf/bpftool/bash-completion/bpftool > index 75cbcb512ebae..819757d7a3609 100644 > --- a/tools/bpf/bpftool/bash-completion/bpftool > +++ b/tools/bpf/bpftool/bash-completion/bpftool > @@ -1057,7 +1057,7 @@ _bpftool() > attach|detach) > local BPFTOOL_CGROUP_ATTACH_TYPES="$(bpftool feature list_builtins attach_types 2>/dev/null | \ > grep '^cgroup_')" > - local ATTACH_FLAGS='multi override' > + local ATTACH_FLAGS='multi override preorder' > # Check for $prev = $command first > if [ $prev = $command ]; then > _filedir Can bash completion handle combined flags after this change? The commit message's After: example shows: $ bpftool cgroup attach <cg> cgroup_inet_ingress id 5678 multi preorder and the rst documentation states "preorder can be combined with multi". But ATTACH_FLAGS is passed to _bpftool_one_of_list(), which is defined as: _bpftool_one_of_list() { _bpftool_search_list $* && return 1 COMPREPLY+=( $( compgen -W "$*" -- "$cur" ) ) } This helper returns early once any word from the list is already on the command line, leaving COMPREPLY empty. That was correct when the list was the mutually-exclusive pair {multi, override}, but now that preorder can combine with multi, typing "... multi <TAB>" finds "multi" in the words array and suppresses all completions. Won't this prevent completing the second flag? > diff --git a/tools/bpf/bpftool/cgroup.c b/tools/bpf/bpftool/cgroup.c > index ce69d1e5468e3..aec1281c95d8e 100644 > --- a/tools/bpf/bpftool/cgroup.c > +++ b/tools/bpf/bpftool/cgroup.c > @@ -56,7 +56,7 @@ static const int cgroup_attach_types[] = { > }; > > #define HELP_SPEC_ATTACH_FLAGS \ > - "ATTACH_FLAGS := { multi | override }" > + "ATTACH_FLAGS := { multi | override | preorder }" [ ... ] > +static const char *format_attach_flags(__u32 attach_flags, char *buf, size_t sz) > +{ > + static const struct { > + __u32 flag; > + const char *name; > + } flags[] = { > + { BPF_F_ALLOW_MULTI, "multi" }, > + { BPF_F_ALLOW_OVERRIDE, "override" }, > + { BPF_F_PREORDER, "preorder" }, > + }; > + size_t len = 0; > + size_t i; > + int n; > + > + buf[0] = '\0'; > + for (i = 0; i < ARRAY_SIZE(flags); i++) { > + if (attach_flags & flags[i].flag) { > + n = snprintf(buf + len, sz - len, "%s%s", > + len ? "," : "", flags[i].name); > + if (n < 0 || (size_t)n >= sz - len) > + return buf; > + len += n; > + attach_flags &= ~flags[i].flag; > + } > + } > + > + if (attach_flags) > + snprintf(buf + len, sz - len, "%sunknown(%x)", > + len ? "," : "", attach_flags); > + > + return buf; > +} [ ... ] > @@ -593,6 +612,8 @@ static int do_attach(int argc, char **argv) > attach_flags |= BPF_F_ALLOW_MULTI; > } else if (is_prefix(argv[i], "override")) { > attach_flags |= BPF_F_ALLOW_OVERRIDE; > + } else if (is_prefix(argv[i], "preorder")) { > + attach_flags |= BPF_F_PREORDER; > } else { > p_err("unknown option: %s", argv[i]); > goto exit_cgroup; [ ... ] This looks like a bug fix for commit 4b82b181a26c. Should this include: Fixes: 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs") --- 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/35376083935 ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-09-18 18:23 UTC | newest] Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-09-18 17:24 [PATCH bpf 0/3] bpf: expose cgroup preorder attachment state to userspace Hui Su 2026-09-18 17:24 ` [PATCH bpf 1/3] bpf: Report BPF_F_PREORDER in cgroup program queries Hui Su 2026-09-18 17:51 ` Alexei Starovoitov 2026-09-18 18:23 ` bot+bpf-ci 2026-09-18 17:24 ` [PATCH bpf 2/3] selftests/bpf: Test querying BPF_F_PREORDER cgroup attachments Hui Su 2026-09-18 18:23 ` bot+bpf-ci 2026-09-18 17:24 ` [PATCH bpf 3/3] bpftool: Add support for BPF_F_PREORDER cgroup attach flag Hui Su 2026-09-18 18:23 ` bot+bpf-ci
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®