From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: Guannan Wang <wgnbuaa@gmail.com>, bpf@vger.kernel.org
Cc: daniel@iogearbox.net, gregkh@linuxfoundation.org, ast@kernel.org,
andrii@kernel.org, xlabai@tencent.com
Subject: Re: [PATCH bpf] bpf: Use array_map_meta_equal for percpu array inner map replacement
Date: Thu, 14 May 2026 13:39:22 +0100 [thread overview]
Message-ID: <c5130e06-d81e-4511-a5de-1fcbde6674ce@gmail.com> (raw)
In-Reply-To: <20260514074454.77491-1-wgnbuaa@gmail.com>
On 5/14/26 8:44 AM, Guannan Wang wrote:
> percpu_array_map_ops.map_meta_equal points to the generic
> bpf_map_meta_equal(), which does not compare max_entries. When a
> percpu array serves as an inner map, replacing it with one that has
> fewer max_entries bypasses the check. Since percpu_array_map_gen_lookup()
> inlines the original template's index_mask as a JIT immediate, a lookup
> on the replacement map can access pptrs[] out of bounds.
>
> Point percpu_array_map_ops.map_meta_equal to array_map_meta_equal(),
> which already enforces the max_entries equality check.
>
> Add a selftest to verify that replacing a percpu array inner map with
> a differently-sized one is rejected.
>
> Fixes: db69718b8efa ("bpf: inline bpf_map_lookup_elem() for PERCPU_ARRAY maps")
> Signed-off-by: Guannan Wang <wgnbuaa@gmail.com>
> ---
> kernel/bpf/arraymap.c | 2 +-
> .../bpf/prog_tests/percpu_array_inner_map.c | 57 +++++++++++++++++++
> 2 files changed, 58 insertions(+), 1 deletion(-)
> create mode 100644 tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c
>
> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
> index 5e25e0353..dfb2110ab 100644
> --- a/kernel/bpf/arraymap.c
> +++ b/kernel/bpf/arraymap.c
> @@ -827,7 +827,7 @@ const struct bpf_map_ops array_map_ops = {
> };
>
> const struct bpf_map_ops percpu_array_map_ops = {
> - .map_meta_equal = bpf_map_meta_equal,
> + .map_meta_equal = array_map_meta_equal,
It looks like the patch f4d05259213ff ("bpf: Add map_meta_equal map ops")
introduced map_meta_equal op and set bpf_map_meta_equal for percpu_array_map_ops,
correct at that time.
But as db69718b8efa ("bpf: inline bpf_map_lookup_elem() for PERCPU_ARRAY maps")
introduced inlined lookup that uses max_elements, the map_meta_equal should have
been aligned to check for that.
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
> .map_alloc_check = array_map_alloc_check,
> .map_alloc = array_map_alloc,
> .map_free = array_map_free,
> diff --git a/tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c b/tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c
> new file mode 100644
> index 000000000..2a8b23813
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/percpu_array_inner_map.c
> @@ -0,0 +1,57 @@
> +// SPDX-License-Identifier: GPL-2.0
> +#include <test_progs.h>
> +
> +/*
> + * Test that replacing an inner percpu array map with one that has different
> + * max_entries is rejected. percpu_array_map_gen_lookup() inlines the
> + * template's index_mask, so allowing a smaller replacement would cause OOB.
> + */
> +void test_percpu_array_inner_map(void)
> +{
> + LIBBPF_OPTS(bpf_map_create_opts, opts);
> + int outer_fd, tmpl_fd, good_fd, bad_fd, err;
> + int zero = 0;
> +
> + /* Create template: percpu array with 8 entries */
> + tmpl_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "tmpl",
> + sizeof(int), sizeof(long), 8, NULL);
> + if (!ASSERT_OK_FD(tmpl_fd, "create_tmpl"))
> + return;
> +
> + /* Create outer array-of-maps using template */
> + opts.inner_map_fd = tmpl_fd;
> + outer_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY_OF_MAPS, "outer",
> + sizeof(int), sizeof(int), 1, &opts);
> + if (!ASSERT_OK_FD(outer_fd, "create_outer"))
> + goto close_tmpl;
> +
> + /* Insert template as initial inner map */
> + err = bpf_map_update_elem(outer_fd, &zero, &tmpl_fd, 0);
> + if (!ASSERT_OK(err, "insert_tmpl"))
> + goto close_outer;
> +
> + /* Replacement with same max_entries should succeed */
> + good_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "good",
> + sizeof(int), sizeof(long), 8, NULL);
> + if (!ASSERT_OK_FD(good_fd, "create_good"))
> + goto close_outer;
> +
> + err = bpf_map_update_elem(outer_fd, &zero, &good_fd, 0);
> + ASSERT_OK(err, "replace_same_max_entries");
> + close(good_fd);
> +
> + /* Replacement with fewer max_entries must fail */
> + bad_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_ARRAY, "bad",
> + sizeof(int), sizeof(long), 2, NULL);
> + if (!ASSERT_OK_FD(bad_fd, "create_bad"))
> + goto close_outer;
> +
> + err = bpf_map_update_elem(outer_fd, &zero, &bad_fd, 0);
> + ASSERT_ERR(err, "replace_smaller_max_entries");
> + close(bad_fd);
> +
> +close_outer:
> + close(outer_fd);
> +close_tmpl:
> + close(tmpl_fd);
> +}
next prev parent reply other threads:[~2026-05-14 12:39 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-14 7:44 [PATCH bpf] bpf: Use array_map_meta_equal for percpu array inner map replacement Guannan Wang
2026-05-14 12:39 ` Mykyta Yatsenko [this message]
2026-05-14 15:30 ` patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=c5130e06-d81e-4511-a5de-1fcbde6674ce@gmail.com \
--to=mykyta.yatsenko5@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=gregkh@linuxfoundation.org \
--cc=wgnbuaa@gmail.com \
--cc=xlabai@tencent.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.