From nobody Mon Sep 28 13:17:46 2026 Received: from mail-pl1-f169.google.com (mail-pl1-f169.google.com [209.85.214.169]) (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 7C4923ACEE2 for ; Fri, 21 Aug 2026 08:48:58 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.214.169 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787302140; cv=none; b=UXumG8ADSO/d6XYkpbB1vBQiBz63RRBiLK1JENCzk8NH/02b2I/VTVMVjeMvZtfHfOZHLsW2JXGZAjbwPWC+21zsbXedtFZuYo0lKJl4VUaP8F+kuD6xURBBt5uaGNAxDe6C9P0lC9XLOvtDDoIjoR5abzoQD5ToeSCrKooMG/o= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787302140; c=relaxed/simple; bh=auit6dJltMpMVdfk93UUlHOF7Xuq5X5jz1un/m4E4Q4=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=FfvOloqxwmr8/iyUoR6caiQs5HnYuMioQw6e4s+6MBMQDtF8LOkOKhLStdgbAV1L5drxVc1HgL1mJJmm3FVqIbJyHEfVlnZ+EGddrZwhSQTXGY92Ela5a3snDneZdBZaWYquJkJ0ySgNIb3rEz0pnLqEUqino8eFqZmEoC2kJ0s= 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=RAOSiUhR; arc=none smtp.client-ip=209.85.214.169 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="RAOSiUhR" Received: by mail-pl1-f169.google.com with SMTP id d9443c01a7336-2ce7d2adef4so10895685ad.3 for ; Fri, 21 Aug 2026 01:48:58 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1787302138; x=1787906938; 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:content-type; bh=lIWaHIfvDsxfbMU61aIVlsPkb+smxtYg8ROPDZM3qQQ=; b=RAOSiUhRmM6CvF7IqtlgNFRm6JXJJWxbPB4kDx0S/Ll0rAB2xUN0/PM119N133WuZR dC1Dy9+Jf4Cs9l11Cj2j6E1V/Wy+S1oeWaUdDT1d1eZT+3k/z0eT/6kyJrFwavGuou+0 A8owo86tez/2eD+8YWJO0THzDTRzM2tGe7qeGMffFtZsYy8f3GwGxogWVb8diCwNu1yi 6RPV8RcaDAO3gnde/PBkiuNUZtnPbHCudpOQoCmj4X56LdAjSuxTtyHBI5wSlhOU6VCb 8hKVTakv0xop9x/m0e3ylmL7P77ke5AA2WcMr56bmdYW+KaadbBOyxYInqsrfVmtJ/oS EcDQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1787302138; x=1787906938; 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:content-type; bh=lIWaHIfvDsxfbMU61aIVlsPkb+smxtYg8ROPDZM3qQQ=; b=lUaIap0j3Sx7IibOLC/qyBy9OuHLJJ73BTGWkLAs5Nmw6jfyQ2kIbtpkKPClue3v2Z lgwxipk/UF2Zs/GcE5AP0hYSK7IthoByx+yrDCWL7A0Vl6VweoX81vF2dk2esK8PnP2t mMEJt7Uk2mZ/mcb+FL/RCbNwH1tozIXh2LD/ZGn6UYML/wnAeT5pv0Q3saSFw0Gto+Ym kkBvVcDiT2PFVkRASdp/8plQBetA1K/A1PAstUBRUhlo2NgDIw31i+7Ob50xNQjJ3KAr OcT70ynINOuk6SVWB6s+3TSGTz5PUwLfJXvSXrClEa2F33tu1o0QzQm7tBT5Z8wAsRCQ kuRg== X-Forwarded-Encrypted: i=1; AHgh+Rr73u4bFZgPRoSwIfrtBi7ArFyPScmNCepyAJdok7iVoIzEoYa1fjKqLfxUqK/xgXO6S40VEsUZbWdUB98=@vger.kernel.org X-Gm-Message-State: AFuF++ljqMwRC0O/LUC2+URHedp9kXBi55wwCjqDhhWUHqVQc8XeBMF6 nWqJ5SVwRWVpUpYCc+ACx7aKA1Mhd/qi767UMNgZUX/bYyixd21HkPNQ X-Gm-Gg: AR+sD10CvsZuvACiDcrRVMmTC7TIymNFDBcYKQc7PLSCgDNHWJmZwe8GyCk8zf4PuEQ S9pdF1oas2Sv/0OfQ3lPB7MccEDGOLTvSXdLXMtBK6pFO6qa9wkQVw3UdlN4J9GIdQSRyqBmWfd ODgoiYhR+s9M2Yp3k4Vu4kkditVDcgZSDYKJ6zjDLTw72yUtodkMUG6bDXi+LysNaW+7VpmBe+S +ZrlTRVKX2bLuiID936DLns8PCH4Oa9ofF5luLnvm+loHvWkdVqOsKIIeatBpREvZzrWy8n7SPO lSVNhT0Oja9RVcHPLzVa0eDGkq4QxRCB05PDpsPTEtswE+DyS8KMdG7gr8/JbjbGoRhTYORxMAz axsA0MjxizjkA8mrYFPU3G4Un1ftZVh05W1B+VOFCM+MMHmCLo96xg9usV3RZIr+hHlak7WPlM8 ajKbsQazP9z+4J7De0ffRfPN7dZRIKUaJZ9HzolmpYrj0Vyi5AYRzqqrXCBVsx6Uc370gRsB+pp yARuGn3EchSgFRD6WqpyRM4x8NbKmKDXxrbhSkI40MlzvfA+s6L X-Received: by 2002:a17:902:fc4f:b0:2ce:93a3:c168 with SMTP id d9443c01a7336-2d64afe9f5dmr95925235ad.7.1787302137796; Fri, 21 Aug 2026 01:48:57 -0700 (PDT) Received: from secrnd-cstp.tailb7f510.ts.net ([125.131.91.97]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d62d555b2esm16432225ad.11.2026.08.21.01.48.53 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 21 Aug 2026 01:48:56 -0700 (PDT) From: Sanghyun Park To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Eduard Zingerman , Kumar Kartikeya Dwivedi , bpf@vger.kernel.org Cc: Sanghyun Park , Leon Hwang , John Fastabend , Martin KaFai Lau , Song Liu , Yonghong Song , Jiri Olsa , Emil Tsalapatis , Ihor Solodrai , Stanislav Fomichev , Pu Lehui , linux-kernel@vger.kernel.org Subject: [PATCH bpf-next v3] bpf: Fix stack out-of-bounds write in cgroup link update Date: Fri, 21 Aug 2026 17:47:27 +0900 Message-ID: <20260821084726.3769957-2-sanghyun.park.cnu@gmail.com> X-Mailer: git-send-email 2.48.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" The cgroup link update path checks only the program type. Several cgroup hooks share a type while using different runtime contexts or verifier contracts. A UDP6 sock_addr program can therefore replace a UDP4 program and write beyond the four-byte ipc.addr context into adjacent fields of the stack-local struct ipcm_cookie. The same omission lets an LSM_MAC program replace an LSM_CGROUP program despite the incompatible return semantics. Validate replacement programs against the link attach type. Use the existing per-type rules where applicable, and compare LSM expected_attach_type explicitly because both flavors share BPF_PROG_TYPE_LSM. Preserve legacy non-enforcing CGROUP_SKB ingress/egress updates. CGROUP_SKB programs do not require CAP_NET_ADMIN when loaded. That permission is checked when the program is attached. Once the link exists, updates are controlled through its FD, so BPF_LINK_UPDATE does not check CAP_NET_ADMIN again. Keep this behavior and only validate the attach type during link update. Fixes: 0c991ebc8c69 ("bpf: Implement bpf_prog replacement for an active bpf= _cgroup_link") Signed-off-by: Sanghyun Park --- v3: - Factor the CGROUP_SKB CAP_NET_ADMIN check into an attach-only helper. v2: https://lore.kernel.org/r/20260818061021.2551771-2-sanghyun.park.cnu@gm= ail.com - Extend validation from cgroup sock_addr programs to all cgroup program types, including exact LSM attach flavors. - Preserve legacy CGROUP_SKB ingress/egress replacement compatibility. - Keep the CGROUP_SKB CAP_NET_ADMIN check on attach, not link update. v1: https://lore.kernel.org/r/20260805052858.2390918-3-sanghyun.park.cnu@gm= ail.com --- kernel/bpf/syscall.c | 41 ++++++++++++++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 9 deletions(-) diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 6874ba1424af05..dfea337ff25ea5 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -4483,12 +4483,6 @@ static int bpf_prog_attach_check_attach_type(const s= truct bpf_prog *prog, case BPF_PROG_TYPE_SK_LOOKUP: return attach_type =3D=3D prog->expected_attach_type ? 0 : -EINVAL; case BPF_PROG_TYPE_CGROUP_SKB: - if (!bpf_token_capable(prog->aux->token, CAP_NET_ADMIN)) - /* cg-skb progs can be loaded by unpriv user. - * check permissions at attach time. - */ - return -EPERM; - ptype =3D attach_type_to_prog_type(attach_type); if (prog->type !=3D ptype) return -EINVAL; @@ -4542,6 +4536,19 @@ static int bpf_prog_attach_check_attach_type(const s= truct bpf_prog *prog, } } =20 +static int bpf_prog_attach_check(const struct bpf_prog *prog, + enum bpf_attach_type attach_type) +{ + if (prog->type =3D=3D BPF_PROG_TYPE_CGROUP_SKB && + !bpf_token_capable(prog->aux->token, CAP_NET_ADMIN)) + /* cg-skb progs can be loaded by unpriv user. + * check permissions at attach time. + */ + return -EPERM; + + return bpf_prog_attach_check_attach_type(prog, attach_type); +} + static bool is_cgroup_prog_type(enum bpf_prog_type ptype, enum bpf_attach_= type atype, bool check_atype) { @@ -4606,7 +4613,7 @@ static int bpf_prog_attach(const union bpf_attr *attr) if (IS_ERR(prog)) return PTR_ERR(prog); =20 - if (bpf_prog_attach_check_attach_type(prog, attr->attach_type)) { + if (bpf_prog_attach_check(prog, attr->attach_type)) { bpf_prog_put(prog); return -EINVAL; } @@ -5805,8 +5812,7 @@ static int link_create(union bpf_attr *attr, bpfptr_t= uattr) if (IS_ERR(prog)) return PTR_ERR(prog); =20 - ret =3D bpf_prog_attach_check_attach_type(prog, - attr->link_create.attach_type); + ret =3D bpf_prog_attach_check(prog, attr->link_create.attach_type); if (ret) goto out; =20 @@ -5931,6 +5937,7 @@ static int link_update(union bpf_attr *attr) { struct bpf_prog *old_prog =3D NULL, *new_prog; struct bpf_link *link; + enum bpf_attach_type atype; u32 flags; int ret; =20 @@ -5968,6 +5975,22 @@ static int link_update(union bpf_attr *attr) goto out_put_progs; } =20 + if (link->type =3D=3D BPF_LINK_TYPE_CGROUP) { + atype =3D link->attach_type; + /* + * BPF_LSM_MAC and BPF_LSM_CGROUP share BPF_PROG_TYPE_LSM, so + * the helper's default prog-type check cannot distinguish them. + */ + if (new_prog->type =3D=3D BPF_PROG_TYPE_LSM && + new_prog->expected_attach_type !=3D atype) + ret =3D -EINVAL; + else + ret =3D bpf_prog_attach_check_attach_type(new_prog, + atype); + if (ret) + goto out_put_progs; + } + if (link->ops->update_prog) ret =3D link->ops->update_prog(link, new_prog, old_prog); else