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

[email protected]
Newsgroups org.kernel.vger.bpf,org.kernel.vger.stable
Message-ID <64d0032d093c0b2ef48dfc68ab6525ff6a10b95852e3b21a34c87d8185679e9f@mail.kernel.org>
> 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 layout does not match its verified
> bounds.
>
> Reject the freplace attach with -EINVAL when the extension and the
> target program reference mismatched cgroup storage maps.

The changelog describes the check as enforcing "identical storage maps"
(matching the prog-array path's owner cookie comparison), but the code
compares only value_size:

    if (prog_map && (!tgt_map || prog_map->value_size != tgt_map->value_size))
            return -EINVAL;

Two different cgroup storage maps with equal value_size are accepted.
The precedent cited, __bpf_prog_map_compatible() in kernel/bpf/core.c,
matches map identity via map->owner->storage_cookie[i], not size.

The value_size comparison is correct and sufficient for preventing the
out-of-bounds access (bpf_get_local_storage() returns storage sized from
the owning map's value_size, while the verifier bounds the extension by
its own map's value_size), so this isn't a memory-safety gap.

With equal value_size the extension still operates on the target's
storage, e.g. an extension whose map lacks BPF_F_RDONLY_PROG can write
into a target storage map created with BPF_F_RDONLY_PROG
(LOCAL_STORAGE_CREATE_FLAG_MASK includes BPF_F_ACCESS_MASK in
kernel/bpf/local_storage.c), and value layouts may differ (BPF_SPIN_LOCK
is permitted for BPF_MAP_TYPE_CGROUP_STORAGE per kernel/bpf/syscall.c).

Should the check be tightened to map identity (matching the cited
commit), or should the changelog be reworded to say the check only
rejects value_size mismatches?

> diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> index 1a721fc4bef5..3743f6c25e2c 100644
> --- a/kernel/bpf/trampoline.c
> +++ b/kernel/bpf/trampoline.c

[ ... ]

> @@ -821,6 +823,20 @@ 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), while the
> +	 * verifier bounds its accesses by its own map's value_size. A
> +	 * value_size mismatch leads to slab out-of-bounds access.
> +	 */

This isn't a bug, but the comment formatting differs from the BPF
subsystem style. Under kernel/bpf/, multi-line comments place the
opening /* on its own line:

    /*
     * At runtime the extension program inherits the target program's
     * ...
     */

The pre-existing comment just above (around the function start) uses the
same style as the new comment, so this may be intentional consistency
with the file.

> +	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 && (!tgt_map || prog_map->value_size != tgt_map->value_size))
> +			return -EINVAL;
> +	}
> +
>  	return 0;
>  }
>

---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31804018762
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.