From nobody Sun May 24 19:33:57 2026 Received: from mail-wm1-f46.google.com (mail-wm1-f46.google.com [209.85.128.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 238B8356767 for ; Fri, 22 May 2026 16:22:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.128.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779466974; cv=none; b=GKmo3L6dDR0g5LMcSohVIwKzEYnUfy5dtx0LwhXARlrcxhktyFbis/hXBfToZN3TH5HQTmdhMlyMLZ1tHeRq5+DwF4SCT4gw15wZOH7b93E0BYi3UhSzWWCaj8mroFoldcX5HBsX2yIP94GBvkJtytSj58ApVocfLHGirse9I7w= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779466974; c=relaxed/simple; bh=qF2i7auJVSjO6/9vGlkMpnDgSR4rDFGTBdNP4hyUbiI=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=UU0nhqPkCgxKEw+ZAcqm4mqRH9MHgdHkTkalnz6ojFaqrVoL0e5tP10+EsyDui0gWa50GF5i7SeXtoEDBHzMCc0tMJyHcL9KfBztxLb42MKZxtb8F1BrjgAcvrRt57S1ZiTxQ1IK9HXwSvpoldSNS8boBMd/ftl5ua3KYGjWSdI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=Q6yqWkcE; arc=none smtp.client-ip=209.85.128.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="Q6yqWkcE" Received: by mail-wm1-f46.google.com with SMTP id 5b1f17b1804b1-49040362e4aso15843255e9.0 for ; Fri, 22 May 2026 09:22:52 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1779466971; x=1780071771; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to; bh=Ue9oZkFNnJgvX/B5djQomJS6gXyPBQAHkbvxsnpMpQM=; b=Q6yqWkcEslGU5DubJTpbJJ8mFEebnWmXvLHjzG+yfJRSB/tk6CIHhsGKC3MCdFztSZ DlSEjELf7QdZmpINGpp1EDsMpjGuchXMWlDqBkdxMOI4Fg72Gmb5vLz63hoqs+/3IzJW OUxHtdNAC4uHMX0YYkkoGcFdDbw/2VC11fiJPk9Oq4kU1rDSKf4YC0RDeYeaC6zf5IvW txKlnejqECT9rWAD0Av9ixDSRPXbTAOlHf58xwGIqySt9MyawwzXnZ23d3jeO2/Nxdlz iw+HanORypjALWWPOZRCL3REsllgbKV0F6yrKQ/mvPCE05f6w89OKZ18zW56QGtFcJ64 /qiA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1779466971; x=1780071771; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=Ue9oZkFNnJgvX/B5djQomJS6gXyPBQAHkbvxsnpMpQM=; b=H1j629dnXEaSwGMMyv2qo9i/vMo/dixhmyRYFX/9EEumpQeiW2uKPZ4UX6yn9a3wsu wgy78f4Tmta0ZnRpwbXXHWBS889q5aPthkKC4CpLVpcyQ+aomShgBfujCx2I6gAWEKNM Jh6qKalUz356V2orZySXclXy06z7MYCJ1zLAz9xSXn9qG7dJB1swWnClAlkLaOrSOhW/ l2T5DfrM78HLegwwxtTA8pIgVGITg74Vf5fjxMsWpmzuscbW90Tz3dS9Uil3gyGaDWic oNy+OoWE0CCiXcXqd5zf87BrryKlnwfDfG5GO4ZcOabUYIEvdogaGRKfAktpn/1OxWru NIVw== X-Forwarded-Encrypted: i=1; AFNElJ8RZq0U1DF7SY6VpY+7kMeNAVcfEuceEPVnCxq/BXaDFh/QmFVSjMZe/Qsng7BXSdF2iwKG/hRaZ45c4wU=@vger.kernel.org X-Gm-Message-State: AOJu0YxFbb8CHJFJxbFJWweAFLgroPp7eeEfIIhUDVogl8KSg3Aay5B8 vozu0emMnrOH8IlfvVensyenTnEPIp6gTS/tmd3jpePsBl0vs+69YYFT X-Gm-Gg: Acq92OG7G7/I81UzLQxqfnyto2LRmgNVPCWKukH6nXSNqRjwMEGkECj802496uQwcek nmwLGzLDY54xXm/EF/xlJ3UNMAFymlw51QGUrRxhiu138owy/v9vsT6JHLJCmMysan0Nt+EPC3i Kld4ggfhYpnmB/3wAVUp026Gmz04E0iekt3X6GBnM9tOYtixTYHqNuf97bV0ZhUg3EPL9OhSBYh gehYOjxA5LMcz3/R3ZH1Yz/WSA4nsWjT730fYKmA0j40AzhIT8SxpHgkm10T7xMlrFWLlsezsQH qBFgmj2dofw9i9f4XA1jw5f5Z2oiBhuVkUSvD4ugUVRUKV/qwr485zmq/x6lvMPIvirPY2tc/EY vaKNcbljDQ2pU1ncXoTQTj99atWHt6QTcQjxtQnQ1uFZGsZ6EBBL+lMyr4sYYR3DxPvzPZdLa6h nygTZvYZskzAJxfnbzhIeWFu8e4rbEWmpjVHOvQ1+grl2ajTtJ2ztpYaoPDUtzjCjwZh9vI6kyR pe94O/9ZJWjpDUcdKduav4Tm+uKH09eCT7eG4ifuvrbR2Nc4eDi/aXOz+JmB1zVY78fmSmUyF7a pITear2Qlfn46Q== X-Received: by 2002:a05:600c:8684:b0:489:5022:39a4 with SMTP id 5b1f17b1804b1-4904248f5aemr41640915e9.9.1779466971410; Fri, 22 May 2026 09:22:51 -0700 (PDT) Received: from localhost.localdomain ([149.22.234.166]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-4904561f682sm53330385e9.13.2026.05.22.09.22.50 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 22 May 2026 09:22:50 -0700 (PDT) From: Himanshu Anand To: ast@kernel.org, daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev Cc: yonghong.song@linux.dev, bpf@vger.kernel.org, linux-kernel@vger.kernel.org, Himanshu Anand Subject: [PATCH] bpf: Fix preorder-unaware index in replace_effective_prog and purge_effective_progs replace_effective_prog() and purge_effective_progs() compute the target index in the effective program array by sequentially walking the hlist (pos++). However, since commit 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs"), compute_effective_progs() partitions the effective array: preorder programs occupy indices 0..preorder_cnt-1 and normal programs occupy indices preorder_cnt..end. The sequential hlist walk does not account for this partitioning, so when BPF_F_PREORDER programs coexist with normal programs the computed index diverges from the actual position in the effective array. In replace_effective_prog() this causes BPF_LINK_UPDATE to overwrite the wrong slot: the freed program pointer remains in the correct slot while an unrelated neighbor is clobbered. Fix both functions by searching the effective array directly for the target program pointer instead of computing an index from the hlist. This is correct regardless of array layout since it matches by pointer identity. For purge_effective_progs(), resolve the effective prog from the link when the direct prog pointer is NULL (link-based detach path). Fixes: 4b82b181a26c ("bpf: Allow pre-ordering for bpf cgroup progs") Signed-off-by: Himanshu Anand Date: Fri, 22 May 2026 17:22:48 +0100 Message-Id: <20260522162248.55586-1-anand.himanshu17@gmail.com> X-Mailer: git-send-email 2.34.1 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Signed-off-by: Himanshu Anand --- kernel/bpf/cgroup.c | 74 ++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 45 deletions(-) diff --git a/kernel/bpf/cgroup.c b/kernel/bpf/cgroup.c index 876f6a81a9b6..437e1e873bf8 100644 --- a/kernel/bpf/cgroup.c +++ b/kernel/bpf/cgroup.c @@ -923,15 +923,12 @@ static int cgroup_bpf_attach(struct cgroup *cgrp, */ static void replace_effective_prog(struct cgroup *cgrp, enum cgroup_bpf_attach_type atype, - struct bpf_cgroup_link *link) + struct bpf_cgroup_link *link, + struct bpf_prog *old_prog) { struct bpf_prog_array_item *item; struct cgroup_subsys_state *css; struct bpf_prog_array *progs; - struct bpf_prog_list *pl; - struct hlist_head *head; - struct cgroup *cg; - int pos; =20 css_for_each_descendant_pre(css, &cgrp->self) { struct cgroup *desc =3D container_of(css, struct cgroup, self); @@ -939,27 +936,20 @@ static void replace_effective_prog(struct cgroup *cgr= p, if (percpu_ref_is_zero(&desc->bpf.refcnt)) continue; =20 - /* find position of link in effective progs array */ - for (pos =3D 0, cg =3D desc; cg; cg =3D cgroup_parent(cg)) { - if (pos && !(cg->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) - continue; - - head =3D &cg->bpf.progs[atype]; - hlist_for_each_entry(pl, head, node) { - if (!prog_list_prog(pl)) - continue; - if (pl->link =3D=3D link) - goto found; - pos++; - } - } -found: - BUG_ON(!cg); + /* find the old prog in effective array by direct pointer + * comparison, since compute_effective_progs() partitions + * the array (preorder progs first) and the hlist walk + * order does not match the effective array order. + */ progs =3D rcu_dereference_protected( desc->bpf.effective[atype], lockdep_is_held(&cgroup_mutex)); - item =3D &progs->items[pos]; - WRITE_ONCE(item->prog, link->link.prog); + for (item =3D &progs->items[0]; item->prog; item++) { + if (item->prog =3D=3D old_prog) { + WRITE_ONCE(item->prog, link->link.prog); + break; + } + } } } =20 @@ -1003,7 +993,7 @@ static int __cgroup_bpf_replace(struct cgroup *cgrp, =20 cgrp->bpf.revisions[atype] +=3D 1; old_prog =3D xchg(&link->link.prog, new_prog); - replace_effective_prog(cgrp, atype, link); + replace_effective_prog(cgrp, atype, link, old_prog); bpf_prog_put(old_prog); return 0; } @@ -1078,11 +1068,9 @@ static void purge_effective_progs(struct cgroup *cgr= p, struct bpf_prog *prog, struct bpf_cgroup_link *link, enum cgroup_bpf_attach_type atype) { + struct bpf_prog *target_prog =3D prog ? : link->link.prog; struct cgroup_subsys_state *css; struct bpf_prog_array *progs; - struct bpf_prog_list *pl; - struct hlist_head *head; - struct cgroup *cg; int pos; =20 /* recompute effective prog array in place */ @@ -1092,28 +1080,24 @@ static void purge_effective_progs(struct cgroup *cg= rp, struct bpf_prog *prog, if (percpu_ref_is_zero(&desc->bpf.refcnt)) continue; =20 - /* find position of link or prog in effective progs array */ - for (pos =3D 0, cg =3D desc; cg; cg =3D cgroup_parent(cg)) { - if (pos && !(cg->bpf.flags[atype] & BPF_F_ALLOW_MULTI)) - continue; - - head =3D &cg->bpf.progs[atype]; - hlist_for_each_entry(pl, head, node) { - if (!prog_list_prog(pl)) - continue; - if (pl->prog =3D=3D prog && pl->link =3D=3D link) - goto found; - pos++; - } - } - - /* no link or prog match, skip the cgroup of this layer */ - continue; -found: + /* find the prog in the effective array by direct pointer + * comparison instead of computing index from hlist walk, + * since compute_effective_progs() partitions the array. + * Use target_prog which resolves link->link.prog for + * link-based entries where prog is NULL. + */ progs =3D rcu_dereference_protected( desc->bpf.effective[atype], lockdep_is_held(&cgroup_mutex)); =20 + for (pos =3D 0; progs->items[pos].prog; pos++) { + if (progs->items[pos].prog =3D=3D target_prog) + break; + } + + if (!progs->items[pos].prog) + continue; + /* Remove the program from the array */ WARN_ONCE(bpf_prog_array_delete_safe_at(progs, pos), "Failed to purge a prog from array at index %d", pos); --=20 2.34.1