* [PATCH] bpf: Fix u32 overflow issue in map batch operations
@ 2026-08-24 11:31 Masoud Aghasi
2026-08-24 11:42 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 12+ messages in thread
From: Masoud Aghasi @ 2026-08-24 11:31 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, Masoud Aghasi
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.
Other batch operations may fail to delete or update some keys,
or the syscall may return unexpected errors.
This patch resolves the mentioned issues by converting the cp's type
to size_t in the effected places.
I created a BPF and a userspace C program to demonstrate the issue.
Example BPF program:
```c
struct my_value {
char buf[0x10000000];
};
struct {
__uint(type, BPF_MAP_TYPE_ARRAY);
__uint(max_entries, 17);
__type(key, int);
__type(value, struct my_value);
} map SEC(".maps");
char LICENSE[] SEC("license") = "GPL";
```
Example userspace program:
```c
int main(int argc, char *argv[]) {
struct bpf_object *obj;
char filename[256];
int err, ret = 0;
struct bpf_map *map;
int map_fd;
const __u64 max_entries = 17;
const __u64 value_size = 0x10000000; // 256MB
char *values, *keys;
__u32 count, out_batch;
if (argc != 2) {
printf("Usage: %s [bpf_prog.o]", argv[0]);
return EXIT_FAILURE;
}
snprintf(filename, sizeof(filename), "%s", argv[1]);
obj = bpf_object__open(filename);
if (libbpf_get_error(obj)) {
printf("BPF open failed!\n");
return EXIT_FAILURE;
}
values = calloc(max_entries, value_size);
if (!values) {
printf("calloc values failed!\n");
goto err_out;
}
keys = calloc(max_entries, sizeof(__u32));
if (!keys) {
printf("calloc keys failed!\n");
goto err_out;
}
err = bpf_object__load(obj);
if (err) {
printf("BPF load failed! err:%d\n", err);
goto err_out;
}
map = bpf_object__find_map_by_name(obj, "map");
if (!map) {
printf("map not found!\n");
goto err_out;
}
map_fd = bpf_map__fd(map);
if (map_fd < 0) {
printf("invalid map FD!\n");
goto err_out;
}
__u32 key;
for (__u64 i = 0; i < max_entries; i++) {
memset(values + (i * value_size), i & 0xFF, value_size);
key = i;
err = bpf_map_update_elem(map_fd, &key, values + (i * value_size), BPF_ANY);
if (err) {
printf("bpf_map_update_elem failed: %d\n", err);
goto err_out;
}
}
count = max_entries;
err = bpf_map_lookup_batch(map_fd, NULL, &out_batch, keys, values, &count,
NULL);
if (err) {
printf("bpf_map_lookup_batch failed: %d\n", err);
goto err_out;
}
printf("count: %u, out_batch: %u\n", count, out_batch);
for (__u64 i = 0; i < max_entries; i++) {
for (__u64 j = 0; j < value_size; j++) {
if (values[(i * value_size) + j] != (unsigned char)(i & 0xFF)) {
printf("Invalid map entry, key: %u, value: %hhu, i: %llu, j: %llu\n",
*(((__u32 *)keys) + i), values[(i * value_size) + j], i, j);
goto err_out;
}
}
}
printf("Finished with no errors!\n");
ret = EXIT_SUCCESS;
goto out;
err_out:
ret = EXIT_FAILURE;
out:
bpf_object__close(obj);
if (values)
free(values);
if (keys)
free(keys);
return ret;
}
```
The test needs enough free memory (around 14GB for the total system).
The key/value mismatch occurs when max_entries is 17 and value_size
is 0x10000000 (256MB). Reducing max_entries to 16 eliminates the issue.
Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op")
Signed-off-by: Masoud Aghasi <maghasi@disroot.org>
---
kernel/bpf/hashtab.c | 4 ++--
kernel/bpf/syscall.c | 10 +++++-----
2 files changed, 7 insertions(+), 7 deletions(-)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index d40cb5dd446c..384319aa9177 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -1977,9 +1977,9 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
rcu_read_unlock();
bpf_enable_instrumentation();
- if (bucket_cnt && (copy_to_user(ukeys + total * key_size, keys,
+ if (bucket_cnt && (copy_to_user(ukeys + (size_t)total * key_size, keys,
key_size * bucket_cnt) ||
- copy_to_user(uvalues + total * value_size, values,
+ copy_to_user(uvalues + (size_t)total * value_size, values,
value_size * bucket_cnt))) {
ret = -EFAULT;
goto after_loop;
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6874ba1424af..731388ae00ad 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2036,7 +2036,7 @@ int generic_map_delete_batch(struct bpf_map *map,
for (cp = 0; cp < max_count; cp++) {
err = -EFAULT;
- if (copy_from_user(key, keys + cp * map->key_size,
+ if (copy_from_user(key, keys + (size_t)cp * map->key_size,
map->key_size))
break;
@@ -2098,9 +2098,9 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file,
for (cp = 0; cp < max_count; cp++) {
err = -EFAULT;
- if (copy_from_user(key, keys + cp * map->key_size,
+ if (copy_from_user(key, keys + (size_t)cp * map->key_size,
map->key_size) ||
- copy_from_user(value, values + cp * value_size, value_size))
+ copy_from_user(value, values + (size_t)cp * value_size, value_size))
break;
err = bpf_map_update_value(map, map_file, key, value,
@@ -2179,12 +2179,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
if (err)
goto free_buf;
- if (copy_to_user(keys + cp * map->key_size, key,
+ if (copy_to_user(keys + (size_t)cp * map->key_size, key,
map->key_size)) {
err = -EFAULT;
goto free_buf;
}
- if (copy_to_user(values + cp * value_size, value, value_size)) {
+ if (copy_to_user(values + (size_t)cp * value_size, value, value_size)) {
err = -EFAULT;
goto free_buf;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH] bpf: Fix u32 overflow issue in map batch operations
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-08-24 12:17 ` [PATCH] " bot+bpf-ci
2026-08-24 19:15 ` Masoud Aghasi
2 siblings, 1 reply; 12+ messages in thread
From: sashiko-bot @ 2026-08-24 11:42 UTC (permalink / raw)
To: Masoud Aghasi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [High] Missing `size_t` cast in `key_size * bucket_cnt` and `value_size * bucket_cnt` length calculations leads to 32-bit integer overflow and silent data truncation in `__htab_map_lookup_and_delete_batch`.
--
--- Patch [1]: [PATCH] bpf: Fix u32 overflow issue in map batch operations ---
commit c9edb3a32ad168bfaf9df954c22a4563c73796f6
Author: Masoud Aghasi <maghasi@disroot.org>
bpf: Fix u32 overflow issue in map batch operations
This patch addresses a u32 overflow issue in map batch operations where
address calculations exceeding 4GB could lead to data corruption. It
resolves this by casting the counter variables to size_t before
multiplying them by the map's key or value size.
> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
> index d8db1cebc1936..334eeb297892e 100644
> --- a/kernel/bpf/hashtab.c
> +++ b/kernel/bpf/hashtab.c
> @@ -1978,9 +1978,9 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
>
> rcu_read_unlock();
> bpf_enable_instrumentation();
> - if (bucket_cnt && (copy_to_user(ukeys + total * key_size, keys,
> + if (bucket_cnt && (copy_to_user(ukeys + (size_t)total * key_size, keys,
> key_size * bucket_cnt) ||
> - copy_to_user(uvalues + total * value_size, values,
> + copy_to_user(uvalues + (size_t)total * value_size, values,
[Severity: High]
This is a pre-existing issue, but does key_size * bucket_cnt or
value_size * bucket_cnt also need a size_t cast here?
If value_size * bucket_cnt exceeds 4GB, the 32-bit integer overflow would
truncate the length argument to copy_to_user() in
__htab_map_lookup_and_delete_batch(), causing it to copy less data than
expected. This could result in silent data loss since the elements are
permanently deleted from the kernel map, while the syscall falsely returns
success.
> value_size * bucket_cnt))) {
> ret = -EFAULT;
> goto after_loop;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260824113123.270057-1-maghasi@disroot.org?part=1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH] bpf: Fix u32 overflow issue in map batch operations
2026-08-24 11:42 ` sashiko-bot
@ 2026-08-25 10:21 ` Masoud Aghasi
2026-09-02 20:44 ` [PATCH v2] " Masoud Aghasi
0 siblings, 1 reply; 12+ messages in thread
From: Masoud Aghasi @ 2026-08-25 10:21 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, maghasi
On 24/08/2026 12:42, sashiko-bot@kernel.org wrote:
>
> [Severity: High]
> This is a pre-existing issue, but does key_size * bucket_cnt or
> value_size * bucket_cnt also need a size_t cast here?
>
> If value_size * bucket_cnt exceeds 4GB, the 32-bit integer overflow would
> truncate the length argument to copy_to_user() in
> __htab_map_lookup_and_delete_batch(), causing it to copy less data than
> expected. This could result in silent data loss since the elements are
> permanently deleted from the kernel map, while the syscall falsely returns
> success.
>
>> value_size * bucket_cnt))) {
>> ret = -EFAULT;
>> goto after_loop;
>
Yes, I was able to produce "bucket_cnt > 1024" using a map with
BPF_F_ZERO_SEED flag set, 64bit key_size and generating an special
sequence of keys using the below code:
```c
int counter = 0;
__u64 keys[1025];
for (unsigned long i = 0x10000; i <= 0xffffffffffffffff; i++) {
if ((jhash2((__u32 *)&i, 2, 0) & (0x10000 - 1)) == 0) {
keys[counter] = i;
counter++;
if(counter > 1024)
break;
}
}
```
So the overflow is possible and I will include the fix in the patch v2.
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v2] bpf: Fix u32 overflow issue in map batch operations
2026-08-25 10:21 ` Masoud Aghasi
@ 2026-09-02 20:44 ` Masoud Aghasi
2026-09-02 21:50 ` bot+bpf-ci
2026-09-03 8:27 ` [PATCH v3] " Masoud Aghasi
0 siblings, 2 replies; 12+ messages in thread
From: Masoud Aghasi @ 2026-09-02 20:44 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, Masoud Aghasi
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.
Other batch operations may fail to delete or update some keys,
or the syscall may return unexpected errors.
This patch resolves the mentioned issues by adding size_t casts in the
affected places.
Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op")
Fixes: aa2e93b8e58e ("bpf: Add generic support for update and delete batch ops")
Fixes: 057996380a42 ("bpf: Add batch ops to all htab bpf map")
Signed-off-by: Masoud Aghasi <maghasi@disroot.org>
---
v2:
- Fix the additional u32 overflow pointed out by Sashiko bot.
- Simplify the commit message by removing the reproducer program.
- Add all relevant fixes tags to the commit message.
v1: https://lore.kernel.org/bpf/20260824113123.270057-1-maghasi@disroot.org/
kernel/bpf/hashtab.c | 8 ++++----
kernel/bpf/syscall.c | 10 +++++-----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index d40cb5dd446c..bd3704ed9333 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -1977,10 +1977,10 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
rcu_read_unlock();
bpf_enable_instrumentation();
- if (bucket_cnt && (copy_to_user(ukeys + total * key_size, keys,
- key_size * bucket_cnt) ||
- copy_to_user(uvalues + total * value_size, values,
- value_size * bucket_cnt))) {
+ if (bucket_cnt && (copy_to_user(ukeys + (size_t)total * key_size, keys,
+ (size_t)key_size * bucket_cnt) ||
+ copy_to_user(uvalues + (size_t)total * value_size, values,
+ (size_t)value_size * bucket_cnt))) {
ret = -EFAULT;
goto after_loop;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6874ba1424af..731388ae00ad 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2036,7 +2036,7 @@ int generic_map_delete_batch(struct bpf_map *map,
for (cp = 0; cp < max_count; cp++) {
err = -EFAULT;
- if (copy_from_user(key, keys + cp * map->key_size,
+ if (copy_from_user(key, keys + (size_t)cp * map->key_size,
map->key_size))
break;
@@ -2098,9 +2098,9 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file,
for (cp = 0; cp < max_count; cp++) {
err = -EFAULT;
- if (copy_from_user(key, keys + cp * map->key_size,
+ if (copy_from_user(key, keys + (size_t)cp * map->key_size,
map->key_size) ||
- copy_from_user(value, values + cp * value_size, value_size))
+ copy_from_user(value, values + (size_t)cp * value_size, value_size))
break;
err = bpf_map_update_value(map, map_file, key, value,
@@ -2179,12 +2179,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
if (err)
goto free_buf;
- if (copy_to_user(keys + cp * map->key_size, key,
+ if (copy_to_user(keys + (size_t)cp * map->key_size, key,
map->key_size)) {
err = -EFAULT;
goto free_buf;
}
- if (copy_to_user(values + cp * value_size, value, value_size)) {
+ if (copy_to_user(values + (size_t)cp * value_size, value, value_size)) {
err = -EFAULT;
goto free_buf;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v2] bpf: Fix u32 overflow issue in map batch operations
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
1 sibling, 0 replies; 12+ messages in thread
From: bot+bpf-ci @ 2026-09-02 21:50 UTC (permalink / raw)
To: maghasi, bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, maghasi, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 909 bytes --]
> This patch resolves the mentioned issues by adding size_t casts in the
> affected places.
>
> Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op")
> Fixes: aa2e93b8e58e ("bpf: Add generic support for update and delete batch ops")
> Fixes: 057996380a42 ("bpf: Add batch ops to all htab bpf map")
>
> Signed-off-by: Masoud Aghasi <maghasi@disroot.org>
This isn't a bug, but would it read more like the usual bpf changelogs
to phrase the last paragraph in the imperative mood ("Cast the offset
calculations to size_t ...") rather than "This patch resolves", and to
drop the blank line so the Fixes: and Signed-off-by: tags sit in one
contiguous block?
---
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/33683717098
^ permalink raw reply [flat|nested] 12+ messages in thread* [PATCH v3] bpf: Fix u32 overflow issue in map batch operations
2026-09-02 20:44 ` [PATCH v2] " Masoud Aghasi
2026-09-02 21:50 ` bot+bpf-ci
@ 2026-09-03 8:27 ` Masoud Aghasi
2026-09-03 8:45 ` sashiko-bot
2026-09-04 4:45 ` Alexei Starovoitov
1 sibling, 2 replies; 12+ messages in thread
From: Masoud Aghasi @ 2026-09-03 8:27 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, Masoud Aghasi
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.
Other batch operations may fail to delete or update some keys,
or the syscall may return unexpected errors.
Add size_t casts to prevent the affected offset and size calculations
from overflowing.
Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op")
Fixes: aa2e93b8e58e ("bpf: Add generic support for update and delete batch ops")
Fixes: 057996380a42 ("bpf: Add batch ops to all htab bpf map")
Signed-off-by: Masoud Aghasi <maghasi@disroot.org>
---
v3:
- Reword the commit message to use imperative style.
v2: https://lore.kernel.org/bpf/20260902204439.287888-1-maghasi@disroot.org/
- Fix the additional u32 overflow pointed out by Sashiko bot.
- Simplify the commit message by removing the reproducer program.
- Add all relevant fixes tags to the commit message.
v1: https://lore.kernel.org/bpf/20260824113123.270057-1-maghasi@disroot.org/
kernel/bpf/hashtab.c | 8 ++++----
kernel/bpf/syscall.c | 10 +++++-----
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index d40cb5dd446c..bd3704ed9333 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -1977,10 +1977,10 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
rcu_read_unlock();
bpf_enable_instrumentation();
- if (bucket_cnt && (copy_to_user(ukeys + total * key_size, keys,
- key_size * bucket_cnt) ||
- copy_to_user(uvalues + total * value_size, values,
- value_size * bucket_cnt))) {
+ if (bucket_cnt && (copy_to_user(ukeys + (size_t)total * key_size, keys,
+ (size_t)key_size * bucket_cnt) ||
+ copy_to_user(uvalues + (size_t)total * value_size, values,
+ (size_t)value_size * bucket_cnt))) {
ret = -EFAULT;
goto after_loop;
}
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 6874ba1424af..731388ae00ad 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -2036,7 +2036,7 @@ int generic_map_delete_batch(struct bpf_map *map,
for (cp = 0; cp < max_count; cp++) {
err = -EFAULT;
- if (copy_from_user(key, keys + cp * map->key_size,
+ if (copy_from_user(key, keys + (size_t)cp * map->key_size,
map->key_size))
break;
@@ -2098,9 +2098,9 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file,
for (cp = 0; cp < max_count; cp++) {
err = -EFAULT;
- if (copy_from_user(key, keys + cp * map->key_size,
+ if (copy_from_user(key, keys + (size_t)cp * map->key_size,
map->key_size) ||
- copy_from_user(value, values + cp * value_size, value_size))
+ copy_from_user(value, values + (size_t)cp * value_size, value_size))
break;
err = bpf_map_update_value(map, map_file, key, value,
@@ -2179,12 +2179,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
if (err)
goto free_buf;
- if (copy_to_user(keys + cp * map->key_size, key,
+ if (copy_to_user(keys + (size_t)cp * map->key_size, key,
map->key_size)) {
err = -EFAULT;
goto free_buf;
}
- if (copy_to_user(values + cp * value_size, value, value_size)) {
+ if (copy_to_user(values + (size_t)cp * value_size, value, value_size)) {
err = -EFAULT;
goto free_buf;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 12+ messages in thread* Re: [PATCH v3] bpf: Fix u32 overflow issue in map batch operations
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
1 sibling, 1 reply; 12+ messages in thread
From: sashiko-bot @ 2026-09-03 8:45 UTC (permalink / raw)
To: Masoud Aghasi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [Critical] Missing size_t casts in queue_stack_maps.c cause pointer arithmetic to overflow u32, corrupting map data.
- [High] qs->size is typed as u32, which can silently overflow to 0 when max_entries is U32_MAX.
--
commit aa1d0d53f1c01402c01cb62c0b2ef581ca4869bd
Author: Masoud Aghasi <maghasi@disroot.org>
bpf: Fix u32 overflow issue in map batch operations
This patch fixes a u32 overflow in several map batch operations that can occur
when the map size exceeds 4GB. It adds size_t casts to prevent the offset and
size calculations from overflowing during memory operations.
> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> index 6874ba1424af0..731388ae00ad1 100644
> --- a/kernel/bpf/syscall.c
> +++ b/kernel/bpf/syscall.c
[ ... ]
> @@ -2179,12 +2179,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
> if (err)
> goto free_buf;
>
> - if (copy_to_user(keys + cp * map->key_size, key,
> + if (copy_to_user(keys + (size_t)cp * map->key_size, key,
> map->key_size)) {
> err = -EFAULT;
> goto free_buf;
> }
> - if (copy_to_user(values + cp * value_size, value, value_size)) {
> + if (copy_to_user(values + (size_t)cp * value_size, value, value_size)) {
> err = -EFAULT;
> goto free_buf;
> }
[Severity: Critical]
This is a pre-existing issue, but since this patch fixes u32 overflows for
map element offsets, could we also address similar overflows in
queue_stack_maps.c?
If a queue or stack map is created where the capacity (max_entries *
value_size) exceeds 4GB, do these calculations wrap the element offset when
head, tail, or index counters multiply with map.value_size?
kernel/bpf/queue_stack_maps.c:__queue_map_get() {
...
ptr = &qs->elements[qs->tail * qs->map.value_size];
...
}
kernel/bpf/queue_stack_maps.c:__stack_map_get() {
...
ptr = &qs->elements[index * qs->map.value_size];
...
}
kernel/bpf/queue_stack_maps.c:queue_stack_map_push_elem() {
...
dst = &qs->elements[qs->head * qs->map.value_size];
...
}
[Severity: High]
This is also a pre-existing issue, but I noticed a potential truncation
when allocating these maps:
kernel/bpf/queue_stack_maps.c:queue_stack_map_alloc() {
...
qs->size = size;
...
}
If a user allocates a queue or stack map with max_entries set exactly to
U32_MAX, the required size calculation (u64)attr->max_entries + 1 evaluates
to 0x100000000. Because qs->size is typed as u32, does this assignment
silently truncate the size to 0, resulting in a map that behaves like it has
0 capacity?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260903082734.623904-1-maghasi@disroot.org?part=1
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH v3] bpf: Fix u32 overflow issue in map batch operations
2026-09-03 8:45 ` sashiko-bot
@ 2026-09-03 12:31 ` Masoud Aghasi
0 siblings, 0 replies; 12+ messages in thread
From: Masoud Aghasi @ 2026-09-03 12:31 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, sashiko-reviews, maghasi
On 03/09/2026 09:45, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] Missing size_t casts in queue_stack_maps.c cause pointer arithmetic to overflow u32, corrupting map data.
> - [High] qs->size is typed as u32, which can silently overflow to 0 when max_entries is U32_MAX.
> --
>
> commit aa1d0d53f1c01402c01cb62c0b2ef581ca4869bd
> Author: Masoud Aghasi <maghasi@disroot.org>
>
> bpf: Fix u32 overflow issue in map batch operations
>
> This patch fixes a u32 overflow in several map batch operations that can occur
> when the map size exceeds 4GB. It adds size_t casts to prevent the offset and
> size calculations from overflowing during memory operations.
>
>> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> index 6874ba1424af0..731388ae00ad1 100644
>> --- a/kernel/bpf/syscall.c
>> +++ b/kernel/bpf/syscall.c
> [ ... ]
>> @@ -2179,12 +2179,12 @@ int generic_map_lookup_batch(struct bpf_map *map,
>> if (err)
>> goto free_buf;
>>
>> - if (copy_to_user(keys + cp * map->key_size, key,
>> + if (copy_to_user(keys + (size_t)cp * map->key_size, key,
>> map->key_size)) {
>> err = -EFAULT;
>> goto free_buf;
>> }
>> - if (copy_to_user(values + cp * value_size, value, value_size)) {
>> + if (copy_to_user(values + (size_t)cp * value_size, value, value_size)) {
>> err = -EFAULT;
>> goto free_buf;
>> }
>
> [Severity: Critical]
> This is a pre-existing issue, but since this patch fixes u32 overflows for
> map element offsets, could we also address similar overflows in
> queue_stack_maps.c?
>
> If a queue or stack map is created where the capacity (max_entries *
> value_size) exceeds 4GB, do these calculations wrap the element offset when
> head, tail, or index counters multiply with map.value_size?
>
> kernel/bpf/queue_stack_maps.c:__queue_map_get() {
> ...
> ptr = &qs->elements[qs->tail * qs->map.value_size];
> ...
> }
>
> kernel/bpf/queue_stack_maps.c:__stack_map_get() {
> ...
> ptr = &qs->elements[index * qs->map.value_size];
> ...
> }
>
> kernel/bpf/queue_stack_maps.c:queue_stack_map_push_elem() {
> ...
> dst = &qs->elements[qs->head * qs->map.value_size];
> ...
> }
>
> [Severity: High]
> This is also a pre-existing issue, but I noticed a potential truncation
> when allocating these maps:
>
> kernel/bpf/queue_stack_maps.c:queue_stack_map_alloc() {
> ...
> qs->size = size;
> ...
> }
>
> If a user allocates a queue or stack map with max_entries set exactly to
> U32_MAX, the required size calculation (u64)attr->max_entries + 1 evaluates
> to 0x100000000. Because qs->size is typed as u32, does this assignment
> silently truncate the size to 0, resulting in a map that behaves like it has
> 0 capacity?
>
These issues are already fixed by commit:
802a30c5db72 ("bpf: Fix queue/stack map u32 index overflow")
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] bpf: Fix u32 overflow issue in map batch operations
2026-09-03 8:27 ` [PATCH v3] " Masoud Aghasi
2026-09-03 8:45 ` sashiko-bot
@ 2026-09-04 4:45 ` Alexei Starovoitov
2026-09-04 13:19 ` Masoud Aghasi
1 sibling, 1 reply; 12+ messages in thread
From: Alexei Starovoitov @ 2026-09-04 4:45 UTC (permalink / raw)
To: Masoud Aghasi
Cc: bpf, Andrii Nakryiko, Eduard, Alexei Starovoitov, Daniel Borkmann,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai,
John Fastabend, Brian Vazquez
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
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH v3] bpf: Fix u32 overflow issue in map batch operations
2026-09-04 4:45 ` Alexei Starovoitov
@ 2026-09-04 13:19 ` Masoud Aghasi
0 siblings, 0 replies; 12+ messages in thread
From: Masoud Aghasi @ 2026-09-04 13:19 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: bpf, Andrii Nakryiko, Eduard, Alexei Starovoitov, Daniel Borkmann,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai,
John Fastabend, Brian Vazquez
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
Thanks for the review.
I didn't found this bug using AI. I posted the sample program that
reproduces the issue in v1. The reason I didn't include a selftest is
that reproducing the issue requires 8GB+ memory allocation, which I
don't think is appropriate for the regular BPF selftest suite.
Personally, I'm not sure an opt-in test would provide much value as a
regression test, since it would not be exercised during the regular
selftest runs. However, I'm happy to add an opt-in EXTENDED selftest in
v4 (using TEST_GEN_PROGS_EXTENDED in Makefile), if you think retaining
an explicit reproducer in the kernel selftests is worthwhile.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH] bpf: Fix u32 overflow issue in map batch operations
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-24 12:17 ` bot+bpf-ci
2026-08-24 19:15 ` Masoud Aghasi
2 siblings, 0 replies; 12+ messages in thread
From: bot+bpf-ci @ 2026-08-24 12:17 UTC (permalink / raw)
To: maghasi, bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv, maghasi, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2854 bytes --]
> Fixes: cb4d03ab499d ("bpf: Add generic support for lookup batch op")
The single Fixes: tag covers only one of the three commits whose code this
patch corrects.
cb4d03ab499d introduced generic_map_lookup_batch() - that tag is correct
for the changes in kernel/bpf/syscall.c at generic_map_lookup_batch().
The other hunks fix different commits:
generic_map_delete_batch() and generic_map_update_batch() were added by
aa2e93b8e58e ("bpf: Add generic support for update and delete batch ops"),
which introduced the buggy expressions:
+ key = __bpf_copy_key(keys + cp * map->key_size, map->key_size);
+ if (copy_from_user(value, values + cp * value_size, value_size))
__htab_map_lookup_and_delete_batch() was added by 057996380a42 ("bpf: Add
batch ops to all htab bpf map"), which introduced:
+ if (bucket_cnt && (copy_to_user(ukeys + total * key_size, keys,
+ key_size * bucket_cnt) ||
+ copy_to_user(uvalues + total * value_size, values,
Without these tags the stable backport scope is wrong: a tree that has
aa2e93b8e58e or 057996380a42 but predates cb4d03ab499d (or vice versa)
will not be matched.
Would it make sense to add:
Fixes: aa2e93b8e58e ("bpf: Add generic support for update and delete batch ops")
Fixes: 057996380a42 ("bpf: Add batch ops to all htab bpf map")
> This patch resolves the mentioned issues by converting the cp's type
> to size_t in the effected places.
The changelog misdescribes what the patch does, in two ways.
First, no type is converted. The diff only adds (size_t) casts at the use
sites; every declaration is untouched. generic_map_lookup_batch() still
declares "u32 value_size, cp, max_count;" at kernel/bpf/syscall.c,
generic_map_update_batch() still declares "u32 value_size, cp, max_count;",
and generic_map_delete_batch() still declares "u32 cp, max_count;".
This matters beyond wording, because actually converting cp to size_t would
have been a bug: all three functions report progress with
copy_to_user(&uattr->batch.count, &cp, sizeof(cp))
and uattr->batch.count is __u32 in the uapi, so a size_t cp would write
8 bytes into a 4-byte field on 64-bit. Casting at the use site, as the
patch actually does, is the correct approach - the changelog should
describe it that way so a reviewer does not "simplify" it later.
Second, there is no cp in the hashtab.c hunk. __htab_map_lookup_and_delete_batch()
uses total (declared "u32 bucket_cnt, total, key_size, value_size;" at
kernel/bpf/hashtab.c), so "the cp's type" does not describe that change.
(Also "effected places" should read "affected places".)
---
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/32723998558
^ permalink raw reply [flat|nested] 12+ messages in thread* Re: [PATCH] bpf: Fix u32 overflow issue in map batch operations
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-24 12:17 ` [PATCH] " bot+bpf-ci
@ 2026-08-24 19:15 ` Masoud Aghasi
2 siblings, 0 replies; 12+ messages in thread
From: Masoud Aghasi @ 2026-08-24 19:15 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, john.fastabend,
brianvv
On 24/08/2026 12:42, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
>
> Pre-existing issues:
> - [High] Missing `size_t` cast in `key_size * bucket_cnt` and
`value_size * bucket_cnt` length calculations leads to 32-bit integer
overflow and silent data truncation in `__htab_map_lookup_and_delete_batch`.
> --
>
> --- Patch [1]: [PATCH] bpf: Fix u32 overflow issue in map batch
operations ---
> commit c9edb3a32ad168bfaf9df954c22a4563c73796f6
> Author: Masoud Aghasi <maghasi@disroot.org>
>
> bpf: Fix u32 overflow issue in map batch operations
>
> This patch addresses a u32 overflow issue in map batch operations where
> address calculations exceeding 4GB could lead to data corruption. It
> resolves this by casting the counter variables to size_t before
> multiplying them by the map's key or value size.
>
>> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
>> index d8db1cebc1936..334eeb297892e 100644
>> --- a/kernel/bpf/hashtab.c
>> +++ b/kernel/bpf/hashtab.c
>> @@ -1978,9 +1978,9 @@ __htab_map_lookup_and_delete_batch(struct
bpf_map *map,
>>
>> rcu_read_unlock();
>> bpf_enable_instrumentation();
>> - if (bucket_cnt && (copy_to_user(ukeys + total * key_size, keys,
>> + if (bucket_cnt && (copy_to_user(ukeys + (size_t)total * key_size, keys,
>> key_size * bucket_cnt) ||
>> - copy_to_user(uvalues + total * value_size, values,
>> + copy_to_user(uvalues + (size_t)total * value_size, values,
>
> [Severity: High]
> This is a pre-existing issue, but does key_size * bucket_cnt or
> value_size * bucket_cnt also need a size_t cast here?
>
> If value_size * bucket_cnt exceeds 4GB, the 32-bit integer overflow would
> truncate the length argument to copy_to_user() in
> __htab_map_lookup_and_delete_batch(), causing it to copy less data than
> expected. This could result in silent data loss since the elements are
> permanently deleted from the kernel map, while the syscall falsely returns
> success.
>
>> value_size * bucket_cnt))) {
>> ret = -EFAULT;
>> goto after_loop;
>
As far as I understand it, the key_size + value_size must be less than
4MB at-least on x86_64 systems. so if the bucket_cnt be higher than
1024, an overflow would be possible. Also the possibility of the
bucket_cnt be higher than 1024 depends on the hashing algorithm used.
As the hash is a u32 value and the key of the hash map could be a bigger
type, I would say there is a possibility of overflow here as well, and
we must add the fix for this case too, in the v2.
I will try to look deeper into the hashing algorithm and see whether I
can reproduce a bucket_cnt large enough to trigger the overflow. If
anyone has a more concrete understanding of the bounds here, please let
me know.
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-09-04 13:20 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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-08-24 12:17 ` [PATCH] " bot+bpf-ci
2026-08-24 19:15 ` Masoud Aghasi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox