From: Leon Hwang <leon.hwang@linux.dev>
To: bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
John Fastabend <john.fastabend@gmail.com>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
Steven Rostedt <rostedt@goodmis.org>,
Masami Hiramatsu <mhiramat@kernel.org>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
KP Singh <kpsingh@kernel.org>,
Matt Bobrowski <matt@bobrowski.net>,
Shuah Khan <shuah@kernel.org>, Leon Hwang <leon.hwang@linux.dev>,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-kselftest@vger.kernel.org, netdev@vger.kernel.org
Subject: [PATCH bpf-next 4/9] bpf: Add log support for cgroup prog link_create
Date: Mon, 9 Nov 2026 22:08:11 +0800 [thread overview]
Message-ID: <20261109140816.5196-5-leon.hwang@linux.dev> (raw)
In-Reply-To: <20261109140816.5196-1-leon.hwang@linux.dev>
Cgroup prog BPF_LINK_CREATE returns errors without explaining invalid
flags, target FDs, or relative attachment parameters. Revision mismatches,
cgroup hierarchy restrictions, conflicting attachment flags, and the
per-cgroup program limit can also cause unexplained failures.
Pass the BPF_LINK_CREATE log through the cgroup attachment helpers and
report these failures at the checks that reject the attachment. Diagnose
relative link attachments that omit BPF_F_LINK.
Signed-off-by: Leon Hwang <leon.hwang@linux.dev>
---
include/linux/bpf-cgroup.h | 7 +++-
kernel/bpf/cgroup.c | 76 +++++++++++++++++++++++++++-----------
kernel/bpf/syscall.c | 4 +-
3 files changed, 61 insertions(+), 26 deletions(-)
diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
index 02ef7f899b3d..ddcdd136fd49 100644
--- a/include/linux/bpf-cgroup.h
+++ b/include/linux/bpf-cgroup.h
@@ -4,6 +4,7 @@
#include <linux/bpf.h>
#include <linux/bpf-cgroup-defs.h>
+#include <linux/bpf_verifier.h>
#include <linux/errno.h>
#include <linux/jump_label.h>
#include <linux/percpu.h>
@@ -425,7 +426,8 @@ int cgroup_bpf_prog_attach(const union bpf_attr *attr,
enum bpf_prog_type ptype, struct bpf_prog *prog);
int cgroup_bpf_prog_detach(const union bpf_attr *attr,
enum bpf_prog_type ptype);
-int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog);
+int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog,
+ struct bpf_verifier_log *log);
int cgroup_bpf_prog_query(const union bpf_attr *attr,
union bpf_attr __user *uattr, u32 uattr_size);
@@ -452,7 +454,8 @@ static inline int cgroup_bpf_prog_detach(const union bpf_attr *attr,
}
static inline int cgroup_bpf_link_attach(const union bpf_attr *attr,
- struct bpf_prog *prog)
+ struct bpf_prog *prog,
+ struct bpf_verifier_log *log)
{
return -EINVAL;
}
diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 57a785241d42..a4d49c4df712 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -854,7 +854,8 @@ static struct bpf_prog *bpf_get_anchor_prog(u32 flags, u32 id_or_fd)
}
static struct bpf_prog_list *get_prog_list(struct hlist_head *progs, struct bpf_prog *prog,
- struct bpf_cgroup_link *link, u32 flags, u32 id_or_fd)
+ struct bpf_cgroup_link *link, u32 flags, u32 id_or_fd,
+ struct bpf_verifier_log *log)
{
bool is_link = flags & BPF_F_LINK, is_id = flags & BPF_F_ID;
struct bpf_prog_list *pltmp, *pl = ERR_PTR(-EINVAL);
@@ -867,20 +868,30 @@ static struct bpf_prog_list *get_prog_list(struct hlist_head *progs, struct bpf_
is_after = flags & BPF_F_AFTER;
if (is_link || is_id || id_or_fd) {
/* flags must have either BPF_F_BEFORE or BPF_F_AFTER */
- if (is_before == is_after)
+ if (is_before == is_after) {
+ bpf_log(log, "Specify exactly one of BPF_F_BEFORE or BPF_F_AFTER.\n");
return ERR_PTR(-EINVAL);
- if ((is_link && !link) || (!is_link && !prog))
+ }
+ if (is_link && !link)
+ return ERR_PTR(-EINVAL);
+ if (!is_link && !prog) {
+ bpf_log(log, "BPF_F_LINK is required for relative link attachment.\n");
return ERR_PTR(-EINVAL);
+ }
} else if (!hlist_empty(progs)) {
/* flags cannot have both BPF_F_BEFORE and BPF_F_AFTER */
- if (is_before && is_after)
+ if (is_before && is_after) {
+ bpf_log(log, "BPF_F_BEFORE and BPF_F_AFTER are mutually exclusive.\n");
return ERR_PTR(-EINVAL);
+ }
}
if (is_link) {
anchor_link = bpf_get_anchor_link(flags, id_or_fd);
- if (IS_ERR(anchor_link))
+ if (IS_ERR(anchor_link)) {
+ bpf_log(log, "Invalid relative link %s.\n", is_id ? "ID" : "FD");
return ERR_CAST(anchor_link);
+ }
} else if (is_id || id_or_fd) {
anchor_prog = bpf_get_anchor_prog(flags, id_or_fd);
if (IS_ERR(anchor_prog))
@@ -905,13 +916,16 @@ static struct bpf_prog_list *get_prog_list(struct hlist_head *progs, struct bpf_
hlist_for_each_entry(pltmp, progs, node) {
if ((anchor_prog && anchor_prog == pltmp->prog) ||
(anchor_link && anchor_link == &pltmp->link->link)) {
- if (!!(pltmp->flags & BPF_F_PREORDER) != preorder)
+ if (!!(pltmp->flags & BPF_F_PREORDER) != preorder) {
+ bpf_log(log, "Relative attachment BPF_F_PREORDER mismatch.\n");
goto out;
+ }
pl = pltmp;
goto out;
}
}
+ bpf_log(log, "Relative attachment not found in target cgroup.\n");
pl = ERR_PTR(-ENOENT);
out:
if (anchor_link)
@@ -923,11 +937,11 @@ static struct bpf_prog_list *get_prog_list(struct hlist_head *progs, struct bpf_
static int insert_pl_to_hlist(struct bpf_prog_list *pl, struct hlist_head *progs,
struct bpf_prog *prog, struct bpf_cgroup_link *link,
- u32 flags, u32 id_or_fd)
+ u32 flags, u32 id_or_fd, struct bpf_verifier_log *log)
{
struct bpf_prog_list *pltmp;
- pltmp = get_prog_list(progs, prog, link, flags, id_or_fd);
+ pltmp = get_prog_list(progs, prog, link, flags, id_or_fd, log);
if (IS_ERR(pltmp))
return PTR_ERR(pltmp);
@@ -952,6 +966,7 @@ static int insert_pl_to_hlist(struct bpf_prog_list *pl, struct hlist_head *progs
* @flags: Option flags
* @id_or_fd: Relative prog id or fd
* @revision: bpf_prog_list revision
+ * @log: Optional log for attachment errors
*
* Exactly one of @prog or @link can be non-null.
* Must be called with cgroup_mutex held.
@@ -960,7 +975,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link,
enum bpf_attach_type type, u32 flags, u32 id_or_fd,
- u64 revision)
+ u64 revision, struct bpf_verifier_log *log)
{
u32 saved_flags = (flags & (BPF_F_ALLOW_OVERRIDE | BPF_F_ALLOW_MULTI));
struct bpf_prog *old_prog = NULL;
@@ -991,23 +1006,33 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp,
atype = bpf_cgroup_atype_find(type, new_prog->aux->attach_btf_id);
if (atype < 0)
return -EINVAL;
- if (revision && revision != cgrp->bpf.revisions[atype])
+ if (revision && revision != cgrp->bpf.revisions[atype]) {
+ bpf_log(log, "Cgroup revision mismatch: expected %llu, actual %llu.\n",
+ revision, cgrp->bpf.revisions[atype]);
return -ESTALE;
+ }
progs = &cgrp->bpf.progs[atype];
- if (!hierarchy_allows_attach(cgrp, atype))
+ if (!hierarchy_allows_attach(cgrp, atype)) {
+ bpf_log(log, "Cgroup hierarchy does not allow attachment.\n");
return -EPERM;
+ }
- if (!hlist_empty(progs) && cgrp->bpf.flags[atype] != saved_flags)
+ if (!hlist_empty(progs) && cgrp->bpf.flags[atype] != saved_flags) {
/* Disallow attaching non-overridable on top
* of existing overridable in this cgroup.
* Disallow attaching multi-prog if overridable or none
*/
+ bpf_log(log, "Attachment flags conflict with existing flags.\n");
return -EPERM;
+ }
- if (prog_list_length(progs, NULL) >= BPF_CGROUP_MAX_PROGS)
+ if (prog_list_length(progs, NULL) >= BPF_CGROUP_MAX_PROGS) {
+ bpf_log(log, "Too many programs attached to cgroup (limit %u).\n",
+ BPF_CGROUP_MAX_PROGS);
return -E2BIG;
+ }
pl = find_attach_entry(progs, prog, link, replace_prog,
flags & BPF_F_ALLOW_MULTI);
@@ -1029,7 +1054,7 @@ static int __cgroup_bpf_attach(struct cgroup *cgrp,
return -ENOMEM;
}
- err = insert_pl_to_hlist(pl, progs, prog, link, flags, id_or_fd);
+ err = insert_pl_to_hlist(pl, progs, prog, link, flags, id_or_fd, log);
if (err) {
kfree(pl);
bpf_cgroup_storages_free(new_storage);
@@ -1089,13 +1114,14 @@ static int cgroup_bpf_attach(struct cgroup *cgrp,
struct bpf_prog *prog, struct bpf_prog *replace_prog,
struct bpf_cgroup_link *link,
enum bpf_attach_type type,
- u32 flags, u32 id_or_fd, u64 revision)
+ u32 flags, u32 id_or_fd, u64 revision,
+ struct bpf_verifier_log *log)
{
int ret;
cgroup_lock();
ret = __cgroup_bpf_attach(cgrp, prog, replace_prog, link, type, flags,
- id_or_fd, revision);
+ id_or_fd, revision, log);
cgroup_unlock();
return ret;
}
@@ -1572,7 +1598,7 @@ int cgroup_bpf_prog_attach(const union bpf_attr *attr,
ret = cgroup_bpf_attach(cgrp, prog, replace_prog, NULL,
attr->attach_type, attr->attach_flags,
- attr->relative_fd, attr->expected_revision);
+ attr->relative_fd, attr->expected_revision, NULL);
if (replace_prog)
bpf_prog_put(replace_prog);
@@ -1702,19 +1728,24 @@ static const struct bpf_link_ops bpf_cgroup_link_lops = {
BPF_F_PREORDER | \
BPF_F_LINK)
-int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
+int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog,
+ struct bpf_verifier_log *log)
{
struct bpf_link_primer link_primer;
struct bpf_cgroup_link *link;
struct cgroup *cgrp;
int err;
- if (attr->link_create.flags & (~BPF_F_LINK_ATTACH_MASK))
+ if (attr->link_create.flags & (~BPF_F_LINK_ATTACH_MASK)) {
+ bpf_log(log, "Invalid flags.\n");
return -EINVAL;
+ }
cgrp = cgroup_get_from_fd(attr->link_create.target_fd);
- if (IS_ERR(cgrp))
+ if (IS_ERR(cgrp)) {
+ bpf_log(log, "Invalid target_fd.\n");
return PTR_ERR(cgrp);
+ }
link = kzalloc_obj(*link, GFP_USER);
if (!link) {
@@ -1734,7 +1765,7 @@ int cgroup_bpf_link_attach(const union bpf_attr *attr, struct bpf_prog *prog)
err = cgroup_bpf_attach(cgrp, NULL, NULL, link,
link->link.attach_type, BPF_F_ALLOW_MULTI | attr->link_create.flags,
attr->link_create.cgroup.relative_fd,
- attr->link_create.cgroup.expected_revision);
+ attr->link_create.cgroup.expected_revision, log);
if (err) {
bpf_link_cleanup(&link_primer);
goto out_put_cgroup;
@@ -3184,7 +3215,8 @@ int cgroup_bpf_struct_ops_attach(struct bpf_map *map, const union bpf_attr *attr
cgrp->bpf.flags[atype] = BPF_F_ALLOW_MULTI;
err = insert_pl_to_hlist(pl, progs, NULL, link,
- flags | BPF_F_ALLOW_MULTI, attr->link_create.cgroup.relative_fd);
+ flags | BPF_F_ALLOW_MULTI,
+ attr->link_create.cgroup.relative_fd, NULL);
if (err)
goto unlock;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index db135859a2d1..43417824d851 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -5907,7 +5907,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_a
case BPF_PROG_TYPE_CGROUP_DEVICE:
case BPF_PROG_TYPE_CGROUP_SYSCTL:
case BPF_PROG_TYPE_CGROUP_SOCKOPT:
- ret = cgroup_bpf_link_attach(attr, prog);
+ ret = cgroup_bpf_link_attach(attr, prog, log);
break;
case BPF_PROG_TYPE_EXT:
ret = bpf_tracing_prog_attach(prog,
@@ -5930,7 +5930,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t uattr, struct bpf_common_a
else if (prog->expected_attach_type == BPF_TRACE_ITER)
ret = bpf_iter_link_attach(attr, uattr, prog, log);
else if (prog->expected_attach_type == BPF_LSM_CGROUP)
- ret = cgroup_bpf_link_attach(attr, prog);
+ ret = cgroup_bpf_link_attach(attr, prog, log);
else if (is_tracing_multi(prog->expected_attach_type))
ret = bpf_tracing_multi_attach(prog, attr, log);
else
--
2.55.0
next prev parent reply other threads:[~2026-11-09 14:08 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-09 14:08 [PATCH bpf-next 0/9] bpf: Add log support for tracing link_create Leon Hwang
2026-11-09 14:08 ` [PATCH bpf-next 1/9] " Leon Hwang
2026-11-09 14:47 ` bot+bpf-ci
2026-11-09 14:08 ` [PATCH bpf-next 2/9] bpf: Add log support for tracing_multi link_create Leon Hwang
2026-11-09 14:08 ` [PATCH bpf-next 3/9] bpf: Add log support for iter link_create Leon Hwang
2026-11-09 14:08 ` Leon Hwang [this message]
2026-11-09 14:47 ` [PATCH bpf-next 4/9] bpf: Add log support for cgroup prog link_create bot+bpf-ci
2026-11-09 14:08 ` [PATCH bpf-next 5/9] libbpf: Add log_opts support for BPF_TRACE_ITER Leon Hwang
2026-11-09 14:47 ` bot+bpf-ci
2026-11-09 14:08 ` [PATCH bpf-next 6/9] selftests/bpf: Verify tracing link_create logs Leon Hwang
2026-11-09 14:47 ` bot+bpf-ci
2026-11-09 14:08 ` [PATCH bpf-next 7/9] selftests/bpf: Verify tracing_multi " Leon Hwang
2026-11-09 14:08 ` [PATCH bpf-next 8/9] selftests/bpf: Verify iter " Leon Hwang
2026-11-09 14:08 ` [PATCH bpf-next 9/9] selftests/bpf: Verify cgroup prog " Leon Hwang
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261109140816.5196-5-leon.hwang@linux.dev \
--to=leon.hwang@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=mathieu.desnoyers@efficios.com \
--cc=matt@bobrowski.net \
--cc=memxor@gmail.com \
--cc=mhiramat@kernel.org \
--cc=netdev@vger.kernel.org \
--cc=rostedt@goodmis.org \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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®