BPF List
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Martin KaFai Lau" <martin.lau@linux.dev>
Cc: bpf@vger.kernel.org
Subject: Re: [RFC PATCH bpf-next 09/12] bpf: Add infrastructure to support attaching struct_ops to cgroups
Date: Tue, 19 May 2026 22:50:02 +0000	[thread overview]
Message-ID: <20260519225002.986EB1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260519215841.2984970-10-martin.lau@linux.dev>

Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [High] bpf_cgroup_struct_ops_foreach does not skip dummy items, leading to unintended execution of cfi_stubs.
- [High] Using a loadable module's cfi_stubs as a dummy sentinel causes a Use-After-Free when the module is unloaded and reloaded.
- [Medium] The macro bpf_cgroup_struct_ops_foreach uses rcu_dereference(), which is incompatible with sleepable struct_ops programs.
- [Medium] cgroup_bpf_struct_ops_register() lacks concurrency protection and global uniqueness enforcement.
--

commit bad29e4e0d1357905491993ee45063766d0f7705
Author: Martin KaFai Lau <martin.lau@kernel.org>

bpf: Add infrastructure to support attaching struct_ops to cgroups

This patch adds necessary infrastructure to attach a struct_ops
map to a cgroup. The initial need was to support migrating
the legacy BPF_PROG_TYPE_SOCK_OPS to a struct_ops.

> diff --git a/include/linux/bpf-cgroup.h b/include/linux/bpf-cgroup.h
> index b2e79c2b41d51..8080f4a5c14b6 100644
> --- a/include/linux/bpf-cgroup.h
> +++ b/include/linux/bpf-cgroup.h

[ ... ]

> @@ -110,6 +112,18 @@ struct bpf_prog_list {
>  	u32 flags;
>  };
>  
> +#define bpf_cgroup_struct_ops_foreach(var, item, cgrp, atype)		\
> +	for (item = rcu_dereference((cgrp)->bpf.effective[atype])->items;\
> +	     ((var) = READ_ONCE(item->kdata));				\
> +	     item++)

[Severity: High]
Does this macro need to skip dummy sentinel items?

In cgroups with BPF_F_ALLOW_MULTI, compute_effective_progs() inserts dummy
sentinel items at the boundaries between cgroup levels. For struct_ops, this
dummy is the cfi_stubs pointer.

This macro appears to iterate over all non-NULL items and fails to skip the
dummy sentinel, which could cause the subsystem to repeatedly yield the
cfi_stubs pointer as a valid attached struct_ops instance.

[Severity: Medium]
Will this rcu_dereference() trigger Lockdep warnings for sleepable struct_ops
programs?

The commit message mentions adding free_after_mult_rcu_gp to support a mix of
sleepable and non-sleepable struct_ops, but plain rcu_dereference() enforces
rcu_read_lock_held().

If a subsystem iterates the array while holding rcu_read_lock_trace()
(required for sleepable execution), this might trigger a 'suspicious
rcu_dereference_check() usage' warning. Conversely, if it holds
rcu_read_lock(), the struct_ops program cannot sleep without causing a panic.

> +
> +static inline bool cgroup_bpf_is_struct_ops_atype(enum cgroup_bpf_attach_type atype)
> +{

[ ... ]

> diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
> index a033aa479ab6e..d496db48d2b86 100644
> --- a/kernel/bpf/cgroup.c
> +++ b/kernel/bpf/cgroup.c
> @@ -24,6 +24,29 @@
>  DEFINE_STATIC_KEY_ARRAY_FALSE(cgroup_bpf_enabled_key, MAX_CGROUP_BPF_ATTACH_TYPE);
>  EXPORT_SYMBOL(cgroup_bpf_enabled_key);
>  
> +static u32 struct_ops_type_id[MAX_CGROUP_BPF_ATTACH_TYPE];
> +static void *struct_ops_cfi_stubs[MAX_CGROUP_BPF_ATTACH_TYPE];
> +static bool struct_ops_mult_rcu[MAX_CGROUP_BPF_ATTACH_TYPE];
> +
> +void cgroup_bpf_struct_ops_register(int atype, u32 type_id, void *cfi_stubs, bool mult_rcu)
> +{
> +	struct_ops_type_id[atype] = type_id;
> +	struct_ops_cfi_stubs[atype] = cfi_stubs;
> +	struct_ops_mult_rcu[atype] = mult_rcu;
> +}

[Severity: Medium]
Does this registration function need concurrency protection to prevent global
array corruption?

If two modules are loaded concurrently and declare the same cgroup_atype, it
seems this could cause a data race or silently overwrite the registered type_id
and cfi_stubs of a legitimate module.

> +
> +static enum cgroup_bpf_attach_type find_atype_by_struct_ops_id(u32 type_id)

[ ... ]

>  static void *bpf_cgroup_array_dummy(enum cgroup_bpf_attach_type atype)
>  {
> +	if (cgroup_bpf_is_struct_ops_atype(atype))
> +		return struct_ops_cfi_stubs[atype];
>  	return bpf_prog_dummy();
>  }

[Severity: High]
Can using a loadable module's cfi_stubs as a dummy sentinel cause a
use-after-free when the module is unloaded and reloaded?

If all maps are detached, the module providing the struct_ops can be unloaded,
and its cfi_stubs memory freed. However, the cgroup's effective array might
still retain the dangling pointer to the freed cfi_stubs if BPF_F_ALLOW_MULTI
was set.

If the module is reloaded, cgroup_bpf_struct_ops_register() updates
struct_ops_cfi_stubs[atype] with a new pointer. If a user then queries the
cgroup via BPF_PROG_QUERY, the loop checks
item->prog == bpf_cgroup_array_dummy(atype) to skip the dummy. Since the
array contains the old freed pointer, it won't match the new cfi_stubs
pointer, and the query loop might mistakenly treat the old dummy as a valid
map, causing a use-after-free when calling bpf_struct_ops_kdata_map_id().

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260519215841.2984970-1-martin.lau@linux.dev?part=9

  reply	other threads:[~2026-05-19 22:50 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-19 21:58 [RFC PATCH bpf-next 00/12] bpf: A common way to attach struct_ops to a cgroup Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 01/12] bpf: Remove __rcu tagging in st_link->map Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 02/12] bpf: Make struct_ops tasks_rcu grace period optional Martin KaFai Lau
2026-05-19 22:54   ` sashiko-bot
2026-05-20  0:25     ` Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 03/12] bpf: Add bpf_struct_ops accessor helpers Martin KaFai Lau
2026-05-19 22:25   ` sashiko-bot
2026-05-19 21:58 ` [RFC PATCH bpf-next 04/12] bpf: Remove unnecessary prog_list_prog() check Martin KaFai Lau
2026-05-19 22:49   ` sashiko-bot
2026-05-19 21:58 ` [RFC PATCH bpf-next 05/12] bpf: Replace prog_list_prog() check with direct pl->prog and pl->link check Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 06/12] bpf: Add prog_list_init_item(), prog_list_replace_item(), and prog_list_id() Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 07/12] bpf: Move LSM trampoline unlink into bpf_cgroup_link_auto_detach() Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 08/12] bpf: Add a few bpf_cgroup_array_* helper functions Martin KaFai Lau
2026-05-19 22:45   ` sashiko-bot
2026-05-19 22:50     ` Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 09/12] bpf: Add infrastructure to support attaching struct_ops to cgroups Martin KaFai Lau
2026-05-19 22:50   ` sashiko-bot [this message]
2026-05-19 23:56     ` Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 10/12] bpf: tcp: Support selected sock_ops callbacks as struct_ops Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 11/12] libbpf: Support attaching struct_ops to a cgroup Martin KaFai Lau
2026-05-19 21:58 ` [RFC PATCH bpf-next 12/12] selftests/bpf: Test " Martin KaFai Lau
2026-05-19 23:03   ` sashiko-bot

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=20260519225002.986EB1F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=martin.lau@linux.dev \
    --cc=sashiko-reviews@lists.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