Skip to content

bpf: Enforce cgroup storage map consistency for freplace attach - #13296

Closed
kernel-patches-daemon-bpf[bot] wants to merge 1 commit into
bpf_basefrom
series/1146069=>bpf
Closed

bpf: Enforce cgroup storage map consistency for freplace attach#13296
kernel-patches-daemon-bpf[bot] wants to merge 1 commit into
bpf_basefrom
series/1146069=>bpf

Conversation

@kernel-patches-daemon-bpf

Copy link
Copy Markdown

Pull request for series with
subject: bpf: Enforce cgroup storage map consistency for freplace attach
version: 1
url: https://patchwork.kernel.org/project/netdevbpf/list/?series=1146069

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: a13307e
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1146069
version: 1

@kernel-patches-review-bot

Copy link
Copy Markdown
commit 8c14c6499aa0c82798922b617388024636cca5f7
Author: Aohan Mei <henrymei@tencent.com>

bpf: Enforce cgroup storage map consistency for freplace attach

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. 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 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

In-Reply-To-Subject: bpf: Enforce cgroup storage map consistency for freplace attach
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/31804018762

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: a13307e
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1146069
version: 1

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: a13307e
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1146069
version: 1

@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: a13307e
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1146069
version: 1

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. 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 abad3d0 ("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.

Fixes: 7d9c342 ("bpf: Make cgroup storages shared between programs on the same cgroup")
Reported-by: TencentOS Corvus AI <corvus@tencent.com>
Cc: stable@vger.kernel.org
Assisted-by: CodeBuddy:Kimi-K3
Signed-off-by: Aohan Mei <henrymei@tencent.com>
@kernel-patches-daemon-bpf

Copy link
Copy Markdown
Author

Upstream branch: a13307e
series: https://patchwork.kernel.org/project/netdevbpf/list/?series=1146069
version: 1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants