[PATCH bpf v2] bpf: Enforce cgroup storage map consistency for freplace attach

Aohan Mei <[email protected]>
Newsgroups org.kernel.vger.stable,org.kernel.vger.bpf
Message-ID <[email protected]>
From: Aohan Mei <[email protected]>

When a BPF_PROG_TYPE_EXT program replaces a cgroup program, it
executes with the target's runtime context, including the per-program
cgroup storage descriptor attached to the cgroup prog item:
bpf_get_local_storage() resolves the buffer via
prog_item->cgroup_storage, so the extension's own storage map never
provides storage at runtime. The verifier, however, bounds the
extension's bpf_get_local_storage() accesses by the extension's own
storage map.

The prog-array path already enforces that programs sharing a
runtime storage context reference identical storage maps (via the
owner cookie matching added in commit abad3d0bad72 ("bpf: Fix oob
access in cgroup local storage")), but the freplace path performs
no such consistency check in bpf_freplace_check_tgt_prog(). An
extension whose storage map differs from the target's therefore
operates on a buffer whose size, flags and layout do not match its
verified assumptions: a smaller target buffer leads to slab
out-of-bounds access, and even equal-sized maps can bypass
BPF_F_RDONLY_PROG or mismatch BPF_SPIN_LOCK fields.

Reject the freplace attach with -EINVAL unless the extension
references the exact same cgroup storage map as the target program,
matching the cookie semantics of __bpf_prog_map_compatible().

Fixes: 7d9c3427894f ("bpf: Make cgroup storages shared between programs on the same cgroup")
Reported-by: TencentOS Corvus AI <[email protected]>
Cc: [email protected]
Assisted-by: CodeBuddy:Kimi-K3
Signed-off-by: Aohan Mei <[email protected]>
---
 kernel/bpf/trampoline.c | 23 +++++++++++++++++++++--
 1 file changed, 21 insertions(+), 2 deletions(-)

Changes in v2:
- Tighten the check from a value_size comparison to map identity:
  the extension's own map never provides storage at runtime, so a
  different map can only create verifier/runtime inconsistencies
  (BPF_F_RDONLY_PROG bypass, BPF_SPIN_LOCK layout mismatch), pointed
  out by the bpf CI review.
- Reformat the added comment to the kernel multi-line style.

diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
index 1a721fc4bef5..043bee6aaab2 100644
--- a/kernel/bpf/trampoline.c
+++ b/kernel/bpf/trampoline.c
@@ -806,9 +806,11 @@ static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
 	}
 }
 
-static int bpf_freplace_check_tgt_prog(struct bpf_prog *tgt_prog)
+static int bpf_freplace_check_tgt_prog(struct bpf_prog *tgt_prog,
+				       struct bpf_prog *prog)
 {
 	struct bpf_prog_aux *aux = tgt_prog->aux;
+	enum bpf_cgroup_storage_type i;
 
 	guard(mutex)(&aux->ext_mutex);
 	if (aux->prog_array_member_cnt)
@@ -821,6 +823,23 @@ static int bpf_freplace_check_tgt_prog(struct bpf_prog *tgt_prog)
 		return -EBUSY;
 
 	aux->is_extended = true;
+
+	/*
+	 * At runtime the extension program inherits the target program's
+	 * cgroup storage context (via prog_item->cgroup_storage), so its
+	 * own map never provides storage; the verifier, however, bounds
+	 * its accesses (size, flags, layout) by that map. Require both
+	 * programs to reference the same map, matching the cookie
+	 * semantics of the prog-array path.
+	 */
+	for_each_cgroup_storage_type(i) {
+		struct bpf_map *tgt_map = tgt_prog->aux->cgroup_storage[i];
+		struct bpf_map *prog_map = prog->aux->cgroup_storage[i];
+
+		if (prog_map && prog_map != tgt_map)
+			return -EINVAL;
+	}
+
 	return 0;
 }
 
@@ -926,7 +945,7 @@ static int __bpf_trampoline_link_prog(struct bpf_tramp_node *node,
 		/* Cannot attach extension if fentry/fexit are in use. */
 		if (cnt)
 			return -EBUSY;
-		err = bpf_freplace_check_tgt_prog(tgt_prog);
+		err = bpf_freplace_check_tgt_prog(tgt_prog, node->link->prog);
 		if (err)
 			return err;
 		tr->extension_prog = node->link->prog;
-- 
2.43.7
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.