Re: [PATCH bpf] bpf: Enforce cgroup storage map consistency for freplace attach
| 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