From: Masoud Aghasi <maghasi@disroot.org>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: bpf <bpf@vger.kernel.org>, Andrii Nakryiko <andrii@kernel.org>,
Eduard <eddyz87@gmail.com>, Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Kumar Kartikeya Dwivedi <memxor@gmail.com>,
Martin KaFai Lau <martin.lau@linux.dev>,
Song Liu <song@kernel.org>,
Yonghong Song <yonghong.song@linux.dev>,
Jiri Olsa <jolsa@kernel.org>,
Emil Tsalapatis <emil@etsalapatis.com>,
Ihor Solodrai <ihor.solodrai@linux.dev>,
John Fastabend <john.fastabend@gmail.com>,
Brian Vazquez <brianvv@google.com>
Subject: Re: [PATCH v3] bpf: Fix u32 overflow issue in map batch operations
Date: Sun, 6 Sep 2026 23:42:46 +0100 [thread overview]
Message-ID: <5574f80b-104c-48d7-8d1e-74b1cc720a41@disroot.org> (raw)
In-Reply-To: <CAADnVQLX5bjLTPm8Ch0wNuojHrKw6R5iJDBRsMJwrWMSupVwew@mail.gmail.com>
On 04/09/2026 05:45, Alexei Starovoitov wrote:
> On Thu, Sep 3, 2026 at 1:28 AM Masoud Aghasi <maghasi@disroot.org> wrote:
>>
>> Several map batch operation implementations such as
>> generic_map_lookup_batch() use calculations in the form of
>> "values + cp * map->value_size" to compute the desired userspace memory
>> address for reading or writing. This can overflow the u32 type
>> (the result of "cp * map->value_size") when the map size exceeds 4GB.
>>
>> generic_map_lookup_batch() may corrupt values for some keys in
>> userspace memory, and in some cases it mismatches values for some keys
>> while still reporting success.
>
> without selftest I have to assume that this is AI hallucination.
>
> pw-bot: cr
I post the selftest here to make it easier to reproduce the bug
and also not having issues with the CI. I also added the output that
I received locally, which shows tests fail for map sizes bigger
than 4GB. I hope it helps, please let me know if you need any
more clarifications.
```c
// SPDX-License-Identifier: GPL-2.0
#include <test_progs.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <bpf/bpf.h>
#include <bpf/libbpf.h>
#define TEST_BATCH_LOOKUP 1
#define TEST_BATCH_UPDATE 2
static void validate_batch_lookup(const int map_fd, const __u32 max_entries,
void *keys, void *values)
{
int err;
__u32 out_batch, count;
/* Do batch lookup on the map and validate the result */
count = max_entries;
err = bpf_map_lookup_batch(map_fd, NULL, &out_batch, keys, values,
&count, NULL);
if (!ASSERT_EQ(err, 0, "map_lookup_batch"))
return;
if (!ASSERT_EQ(count, max_entries, "map_lookup_batch_count"))
return;
if (!ASSERT_EQ(*(__u64 *)values, 0llu, "map_lookup_batch_value"))
return;
}
static void validate_batch_update(const int map_fd, const __u32 max_entries,
const __u32 value_size, void *keys,
void *values)
{
int err;
__u32 count, key;
/* Do batch update on the map */
count = max_entries;
err = bpf_map_update_batch(map_fd, keys, values, &count, NULL);
if (!ASSERT_EQ(err, 0, "map_update_batch"))
return;
if (!ASSERT_EQ(count, max_entries, "map_update_batch_count"))
return;
/* Validate the last value */
key = max_entries - 1;
err = bpf_map_lookup_elem(map_fd, &key, values);
if (!ASSERT_EQ(err, 0, "map_update_batch_lookup"))
return;
if (!ASSERT_EQ(*(__u64 *)values, key, "map_update_batch_value"))
return;
}
static void test_array_batch_overflow(const __u32 max_entries,
const __u32 value_size, int test_type)
{
int map_fd, err;
void *keys, *values;
__u32 i;
const __u32 key_size = sizeof(int);
keys = calloc(max_entries, key_size);
if (!keys) {
test__skip();
return;
}
values = calloc(max_entries, value_size);
if (!values) {
free(keys);
test__skip();
return;
}
map_fd = bpf_map_create(BPF_MAP_TYPE_ARRAY, "array_map", key_size,
value_size, max_entries, NULL);
if (map_fd < 0) {
if (errno == ENOMEM)
test__skip();
else
ASSERT_GE(map_fd, 0, "map_create");
free(keys);
free(values);
return;
}
/* Update all elements with unique values */
for (i = 0; i < max_entries; i++) {
*(__u32 *)(keys + (__u64)i * key_size) = i;
*(__u64 *)(values + (__u64)i * value_size) = (__u64)i;
err = bpf_map_update_elem(map_fd, &i,
values + (__u64)i * value_size, 0);
if (err) {
ASSERT_EQ(err, 0, "map_update_elem");
goto cleanup;
}
}
if (test_type == TEST_BATCH_LOOKUP)
validate_batch_lookup(map_fd, max_entries, keys, values);
else if (test_type == TEST_BATCH_UPDATE)
validate_batch_update(map_fd, max_entries, value_size, keys,
values);
cleanup:
free(keys);
free(values);
close(map_fd);
}
void test_map_batch_overflow(void)
{
if (test__start_subtest("array_lookup"))
test_array_batch_overflow(17, 1024U, TEST_BATCH_LOOKUP);
if (test__start_subtest("array_lookup_4gb_plus"))
test_array_batch_overflow(17, 0x10000000U, TEST_BATCH_LOOKUP);
if (test__start_subtest("array_update"))
test_array_batch_overflow(17, 1024U, TEST_BATCH_UPDATE);
if (test__start_subtest("array_update_4gb_plus"))
test_array_batch_overflow(17, 0x10000000U, TEST_BATCH_UPDATE);
}
```
The output of "sudo ./test_progs -t map_batch_overflow":
#212/1 map_batch_overflow/array_lookup:OK
validate_batch_lookup:PASS:map_lookup_batch 0 nsec
validate_batch_lookup:PASS:map_lookup_batch_count 0 nsec
validate_batch_lookup:FAIL:map_lookup_batch_value unexpected map_lookup_batch_value: actual 16 != expected 0
#212/2 map_batch_overflow/array_lookup_4gb_plus:FAIL
#212/3 map_batch_overflow/array_update:OK
validate_batch_update:PASS:map_update_batch 0 nsec
validate_batch_update:PASS:map_update_batch_count 0 nsec
validate_batch_update:PASS:map_update_batch_lookup 0 nsec
validate_batch_update:FAIL:map_update_batch_value unexpected map_update_batch_value: actual 0 != expected 16
#212/4 map_batch_overflow/array_update_4gb_plus:FAIL
#212 map_batch_overflow:FAIL
All error logs:
validate_batch_lookup:PASS:map_lookup_batch 0 nsec
validate_batch_lookup:PASS:map_lookup_batch_count 0 nsec
validate_batch_lookup:FAIL:map_lookup_batch_value unexpected map_lookup_batch_value: actual 16 != expected 0
#212/2 map_batch_overflow/array_lookup_4gb_plus:FAIL
validate_batch_update:PASS:map_update_batch 0 nsec
validate_batch_update:PASS:map_update_batch_count 0 nsec
validate_batch_update:PASS:map_update_batch_lookup 0 nsec
validate_batch_update:FAIL:map_update_batch_value unexpected map_update_batch_value: actual 0 != expected 16
#212/4 map_batch_overflow/array_update_4gb_plus:FAIL
#212 map_batch_overflow:FAIL
Summary: 0/2 PASSED, 0 SKIPPED, 1 FAILED
next prev parent reply other threads:[~2026-09-06 22:43 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-24 11:31 [PATCH] bpf: Fix u32 overflow issue in map batch operations Masoud Aghasi
2026-08-24 11:42 ` sashiko-bot
2026-08-25 10:21 ` Masoud Aghasi
2026-09-02 20:44 ` [PATCH v2] " Masoud Aghasi
2026-09-02 21:50 ` bot+bpf-ci
2026-09-03 8:27 ` [PATCH v3] " Masoud Aghasi
2026-09-03 8:45 ` sashiko-bot
2026-09-03 12:31 ` Masoud Aghasi
2026-09-04 4:45 ` Alexei Starovoitov
2026-09-04 13:19 ` Masoud Aghasi
2026-09-06 22:42 ` Masoud Aghasi [this message]
2026-09-06 23:34 ` Masoud Aghasi
2026-08-24 12:17 ` [PATCH] " bot+bpf-ci
2026-08-24 19:15 ` Masoud Aghasi
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=5574f80b-104c-48d7-8d1e-74b1cc720a41@disroot.org \
--to=maghasi@disroot.org \
--cc=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=brianvv@google.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=song@kernel.org \
--cc=yonghong.song@linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox