BPF List
 help / color / mirror / Atom feed
* [PATCH] bpf: Fix cgroup link update after a failed effective array rebuild
@ 2026-11-12 13:49 Shihuang Liu
  2026-11-12 14:07 ` sashiko-bot
  2026-11-12 19:57 ` Alexei Starovoitov
  0 siblings, 2 replies; 3+ messages in thread
From: Shihuang Liu @ 2026-11-12 13:49 UTC (permalink / raw)
  To: bpf
  Cc: linux-kernel, Shihuang Liu, stable, Alexei Starovoitov,
	Daniel Borkmann, Andrii Nakryiko, Eduard Zingerman,
	Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
	Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai,
	Tadeusz Struk

replace_effective_prog() uses the position of a cgroup program list
entry as a physical index into the effective program array.  When an
OOM detach falls back to purge_effective_progs(), the detached entry is
replaced by a dummy but the other entries keep their position, so the
list position no longer matches the array index.  A later link update
then writes the new program into the wrong slot, leaving the old
program pointer in the array.  The array does not hold a reference, so
the old program can be freed while it is still published.

Translate the position to the corresponding non-dummy entry before
writing, and use the same helper for deletion and replacement.  This
covers both regular programs and cgroup struct_ops entries.

Fixes: 4c46091ee985 ("bpf: Fix KASAN use-after-free Read in compute_effective_progs")
Cc: stable@vger.kernel.org
Signed-off-by: Shihuang Liu <shlomojune6@gmail.com>
---
 kernel/bpf/cgroup.c | 42 +++++++++++++++++++++++++++++++-----------
 1 file changed, 31 insertions(+), 11 deletions(-)

diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
index 57a785241d42fb..db3f173e83c693 100644
--- a/kernel/bpf/cgroup.c
+++ b/kernel/bpf/cgroup.c
@@ -403,6 +403,28 @@ static int bpf_cgroup_array_length(struct bpf_prog_array *array,
 	return cnt;
 }
 
+/* Return the entry at logical position @index in an effective program
+ * array.  Dummy entries left behind by a failed rebuild are skipped because
+ * they do not correspond to an entry in the program list.
+ */
+static struct bpf_prog_array_item *
+bpf_cgroup_array_item_at(struct bpf_prog_array *array, int index,
+			 enum cgroup_bpf_attach_type atype)
+{
+	void *dummy = bpf_cgroup_array_dummy(atype);
+	struct bpf_prog_array_item *item;
+
+	for (item = array->items; item->prog; item++) {
+		if (item->prog == dummy)
+			continue;
+		if (!index)
+			return item;
+		index--;
+	}
+
+	return NULL;
+}
+
 static int bpf_cgroup_array_copy_to_user(struct bpf_prog_array *array,
 					 __u32 __user *prog_ids, int cnt,
 					 enum cgroup_bpf_attach_type atype)
@@ -432,16 +454,12 @@ static int bpf_cgroup_array_delete_safe_at(struct bpf_prog_array *array,
 {
 	struct bpf_prog_array_item *item;
 
-	for (item = array->items; item->prog; item++) {
-		if (item->prog == bpf_cgroup_array_dummy(atype))
-			continue;
-		if (!index) {
-			WRITE_ONCE(item->prog, bpf_cgroup_array_dummy(atype));
-			return 0;
-		}
-		index--;
-	}
-	return -ENOENT;
+	item = bpf_cgroup_array_item_at(array, index, atype);
+	if (!item)
+		return -ENOENT;
+
+	WRITE_ONCE(item->prog, bpf_cgroup_array_dummy(atype));
+	return 0;
 }
 
 /**
@@ -1175,7 +1193,9 @@ static void replace_effective_prog(struct cgroup *cgrp,
 		progs = rcu_dereference_protected(
 				desc->bpf.effective[atype],
 				lockdep_is_held(&cgroup_mutex));
-		item = &progs->items[pos];
+		item = bpf_cgroup_array_item_at(progs, pos, atype);
+		if (WARN_ON_ONCE(!item))
+			continue;
 		prog_list_replace_item(pl, item);
 	}
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [PATCH] bpf: Fix cgroup link update after a failed effective array rebuild
  2026-11-12 13:49 [PATCH] bpf: Fix cgroup link update after a failed effective array rebuild Shihuang Liu
@ 2026-11-12 14:07 ` sashiko-bot
  2026-11-12 19:57 ` Alexei Starovoitov
  1 sibling, 0 replies; 3+ messages in thread
From: sashiko-bot @ 2026-11-12 14:07 UTC (permalink / raw)
  To: Shihuang Liu, bpf

Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [Medium] bpf: wrong slot in replace_effective_prog() after override
  OOM detach
- [Low] bpf: multi-line comment above bpf_cgroup_array_item_at()
  violates style
--

commit 417086c03fb15b10d49180c23398c0440bbc2a1b
Author: Shihuang Liu <shlomojune6@gmail.com>

bpf: Fix cgroup link update after a failed effective array rebuild

This commit introduces bpf_cgroup_array_item_at() to skip dummy entries
left by a failed effective array rebuild when looking up a program slot in
bpf_cgroup_array_delete_safe_at() and replace_effective_prog().

> diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c
> index 57a785241d42f..db3f173e83c69 100644
> --- a/kernel/bpf/cgroup.c
> +++ b/kernel/bpf/cgroup.c
> @@ -403,6 +403,28 @@ static int bpf_cgroup_array_length(struct bpf_prog_array *array,
>  	return cnt;
>  }
>  
> +/* Return the entry at logical position @index in an effective program
> + * array.  Dummy entries left behind by a failed rebuild are skipped because
> + * they do not correspond to an entry in the program list.
> + */

[Severity: Low]
This isn't a bug, but BPF coding style places the opening /* of a
multi-line comment on its own line.

[ ... ]

> @@ -1175,7 +1193,9 @@ static void replace_effective_prog(struct cgroup *cgrp,
>  		progs = rcu_dereference_protected(
>  				desc->bpf.effective[atype],
>  				lockdep_is_held(&cgroup_mutex));
> -		item = &progs->items[pos];
> +		item = bpf_cgroup_array_item_at(progs, pos, atype);
> +		if (WARN_ON_ONCE(!item))
> +			continue;
>  		prog_list_replace_item(pl, item);
>  	}
>  }

[Severity: Medium]
Can bpf_cgroup_array_item_at() still resolve the wrong slot in
desc->bpf.effective[atype] when a descendant cgroup overrides an ancestor
BPF_F_ALLOW_OVERRIDE program and then detaches its last program via the
purge_effective_progs() fallback?

In a 3-level hierarchy P -> C -> GC where P has BPF_F_ALLOW_MULTI links,
C has a BPF_F_ALLOW_OVERRIDE program prog_C, and GC has an overriding
program prog_GC, GC's effective array contains [prog_GC, link_P1, ...] and
omits prog_C.  If detaching prog_GC fails to allocate in
update_effective_progs(), __cgroup_bpf_detach() replaces items[0] with a
dummy via purge_effective_progs() and removes prog_GC from
GC->bpf.progs[atype], leaving GC->bpf.effective[atype] as
[dummy, link_P1, ...].

When link_P1 is later updated, effective_prog_pos() sees an empty
GC->bpf.progs[atype] (cnt == 0), so it no longer skips C:

kernel/bpf/cgroup.c:effective_prog_pos() {
	...
	do {
		if (cnt > 0 && !(p->bpf.flags[atype] & BPF_F_ALLOW_MULTI))
			continue;
	...
}

effective_prog_pos() counts prog_C at index 0 and returns pos = 1 for
link_P1.  bpf_cgroup_array_item_at(progs, 1, atype) then skips items[0]
(dummy) and treats items[1] (link_P1) as index 0, either overwriting the
next link at items[2] or hitting WARN_ON_ONCE(!item).  In either case,
items[1] retains old_prog after __cgroup_bpf_replace() drops its
reference, causing a use-after-free when GC's effective array runs.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261112134942.288831-1-shlomojune6@gmail.com?part=1

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] bpf: Fix cgroup link update after a failed effective array rebuild
  2026-11-12 13:49 [PATCH] bpf: Fix cgroup link update after a failed effective array rebuild Shihuang Liu
  2026-11-12 14:07 ` sashiko-bot
@ 2026-11-12 19:57 ` Alexei Starovoitov
  1 sibling, 0 replies; 3+ messages in thread
From: Alexei Starovoitov @ 2026-11-12 19:57 UTC (permalink / raw)
  To: Shihuang Liu, bpf
  Cc: linux-kernel, stable, Alexei Starovoitov, Daniel Borkmann,
	Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
	Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
	Emil Tsalapatis, Ihor Solodrai, Tadeusz Struk

On Thu Nov 12, 2026 at 1:49 PM UTC, Shihuang Liu wrote:
> replace_effective_prog() uses the position of a cgroup program list
> entry as a physical index into the effective program array.  When an
> OOM detach falls back to purge_effective_progs(), the detached entry is
> replaced by a dummy but the other entries keep their position, so the
> list position no longer matches the array index.  A later link update
> then writes the new program into the wrong slot, leaving the old
> program pointer in the array.  The array does not hold a reference, so
> the old program can be freed while it is still published.

I doubt you managed to reproduce such scenario.
So wont-fix until there is one.

pw-bot: cr

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2026-11-12 19:57 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-12 13:49 [PATCH] bpf: Fix cgroup link update after a failed effective array rebuild Shihuang Liu
2026-11-12 14:07 ` sashiko-bot
2026-11-12 19:57 ` Alexei Starovoitov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox