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