* [PATCH 0/2] bpf: Fix incorrect handling of user flags by percpu map updates
@ 2026-09-28 10:28 Masoud Aghasi
2026-09-28 10:28 ` [PATCH 1/2] " Masoud Aghasi
2026-09-28 10:28 ` [PATCH 2/2] selftests/bpf: add test for percpu map flags combination Masoud Aghasi
0 siblings, 2 replies; 5+ messages in thread
From: Masoud Aghasi @ 2026-09-28 10:28 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, leon.hwang,
Masoud Aghasi
For BPF_MAP_TYPE_PERCPU_HASH map, htab_map_check_update_flags() and
check_flags() are not considering the possibility of a combination of
(BPF_NOEXIST, BPF_EXIST) flags with (BPF_F_CPU, BPF_F_ALL_CPUS) flags.
This causes the (BPF_NOEXIST, BPF_EXIST) flags to lose their effect.
For example, when using (BPF_F_CPU | BPF_EXIST) flag combination
with bpf_map_update_elem() on a BPF_MAP_TYPE_PERCPU_HASH map, the
BPF_EXIST flag does not prevent new insertions as expected.
Also for BPF_MAP_TYPE_PERCPU_ARRAY map, using the (BPF_F_ALL_CPUS |
BPF_EXIST) flag combination with bpf_map_update_elem() results in an
incorrect EINVAL error response, even though the flag combination is
valid.
This series fixes the bug by adding proper flag validations and checks
and adds a regression test.
Masoud Aghasi (2):
bpf: Fix incorrect handling of user flags by percpu map updates
selftests/bpf: add test for percpu map flags combination
kernel/bpf/arraymap.c | 4 ++--
kernel/bpf/hashtab.c | 9 ++++++---
.../selftests/bpf/prog_tests/percpu_alloc.c | 20 +++++++++++++++++++
3 files changed, 28 insertions(+), 5 deletions(-)
--
2.47.3
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] bpf: Fix incorrect handling of user flags by percpu map updates
2026-09-28 10:28 [PATCH 0/2] bpf: Fix incorrect handling of user flags by percpu map updates Masoud Aghasi
@ 2026-09-28 10:28 ` Masoud Aghasi
2026-09-28 10:41 ` sashiko-bot
2026-09-28 10:28 ` [PATCH 2/2] selftests/bpf: add test for percpu map flags combination Masoud Aghasi
1 sibling, 1 reply; 5+ messages in thread
From: Masoud Aghasi @ 2026-09-28 10:28 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, leon.hwang,
Masoud Aghasi
For BPF_MAP_TYPE_PERCPU_HASH map, htab_map_check_update_flags() and
check_flags() are not considering the possibility of a combination of
(BPF_NOEXIST, BPF_EXIST) flags with (BPF_F_CPU, BPF_F_ALL_CPUS) flags.
This causes the (BPF_NOEXIST, BPF_EXIST) flags to lose their effect.
For example, when using (BPF_F_CPU | BPF_EXIST) flag combination
with bpf_map_update_elem() on a BPF_MAP_TYPE_PERCPU_HASH map, the
BPF_EXIST flag does not prevent new insertions as expected.
Also for BPF_MAP_TYPE_PERCPU_ARRAY map, using the (BPF_F_ALL_CPUS |
BPF_EXIST) flag combination with bpf_map_update_elem() results in an
incorrect EINVAL error response, even though the flag combination is
valid.
This patch fixes the bug by adding proper flag validations and checks.
Fixes: c6936161fd55 ("bpf: Add BPF_F_CPU and BPF_F_ALL_CPUS flags support for percpu_hash and lru_percpu_hash maps")
Fixes: 8eb76cb03f0f ("bpf: Add BPF_F_CPU and BPF_F_ALL_CPUS flags support for percpu_array maps")
Signed-off-by: Masoud Aghasi <maghasi@disroot.org>
---
kernel/bpf/arraymap.c | 4 ++--
kernel/bpf/hashtab.c | 9 ++++++---
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
index 0fe9afd4a591..1be86e9b2e84 100644
--- a/kernel/bpf/arraymap.c
+++ b/kernel/bpf/arraymap.c
@@ -438,7 +438,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
u32 size;
int cpu, off = 0;
- if (unlikely((map_flags & BPF_F_LOCK) || (u32)map_flags > BPF_F_ALL_CPUS))
+ if (unlikely((u32)map_flags & ~(BPF_EXIST | BPF_NOEXIST | BPF_F_CPU | BPF_F_ALL_CPUS)))
/* unknown flags */
return -EINVAL;
@@ -446,7 +446,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
/* all elements were pre-allocated, cannot insert a new one */
return -E2BIG;
- if (unlikely(map_flags == BPF_NOEXIST))
+ if (unlikely(map_flags & BPF_NOEXIST))
/* all elements already exist */
return -EEXIST;
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 53c99fe4f176..648b9aeb917c 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -1196,11 +1196,11 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
static int check_flags(struct bpf_htab *htab, struct htab_elem *l_old,
u64 map_flags)
{
- if (l_old && (map_flags & ~BPF_F_LOCK) == BPF_NOEXIST)
+ if (l_old && (map_flags & BPF_NOEXIST))
/* elem already exists */
return -EEXIST;
- if (!l_old && (map_flags & ~BPF_F_LOCK) == BPF_EXIST)
+ if (!l_old && (map_flags & BPF_EXIST))
/* elem doesn't exist, cannot update it */
return -ENOENT;
@@ -1383,9 +1383,12 @@ static long htab_lru_map_update_elem(struct bpf_map *map, void *key, void *value
static int htab_map_check_update_flags(bool onallcpus, u64 map_flags)
{
+ if (unlikely((map_flags & BPF_EXIST) && (map_flags & BPF_NOEXIST)))
+ return -EINVAL;
if (unlikely(!onallcpus && map_flags > BPF_EXIST))
return -EINVAL;
- if (unlikely(onallcpus && ((map_flags & BPF_F_LOCK) || (u32)map_flags > BPF_F_ALL_CPUS)))
+ if (unlikely(onallcpus &&
+ ((u32)map_flags & ~(BPF_EXIST | BPF_NOEXIST | BPF_F_CPU | BPF_F_ALL_CPUS))))
return -EINVAL;
return 0;
}
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] selftests/bpf: add test for percpu map flags combination
2026-09-28 10:28 [PATCH 0/2] bpf: Fix incorrect handling of user flags by percpu map updates Masoud Aghasi
2026-09-28 10:28 ` [PATCH 1/2] " Masoud Aghasi
@ 2026-09-28 10:28 ` Masoud Aghasi
1 sibling, 0 replies; 5+ messages in thread
From: Masoud Aghasi @ 2026-09-28 10:28 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, leon.hwang,
Masoud Aghasi
Add a test that exercises using a combination of flags for
percpu map update.
Before the fix, this test fails to respect user flags combination of
(BPF_F_CPU | BPF_EXIST). With the fix applied the test passes.
Signed-off-by: Masoud Aghasi <maghasi@disroot.org>
---
.../selftests/bpf/prog_tests/percpu_alloc.c | 20 +++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/percpu_alloc.c b/tools/testing/selftests/bpf/prog_tests/percpu_alloc.c
index 7b4a1e24363b..a0a1fa0e11c0 100644
--- a/tools/testing/selftests/bpf/prog_tests/percpu_alloc.c
+++ b/tools/testing/selftests/bpf/prog_tests/percpu_alloc.c
@@ -537,6 +537,24 @@ static void test_hash_cpu_flag(void)
test_map_op_cpu_flag(BPF_MAP_TYPE_HASH);
}
+static void test_percpu_hash_flags_combination(void)
+{
+ u32 max_entries = 1;
+ u64 flags, val = 0;
+ int err, map_fd, key = 0;
+
+ map_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, "test_flags_combo",
+ sizeof(int), sizeof(u64), max_entries, NULL);
+ if (!ASSERT_GE(map_fd, 0, "bpf_map_create"))
+ return;
+
+ flags = BPF_F_CPU | BPF_EXIST;
+ err = bpf_map_update_elem(map_fd, &key, &val, flags);
+ ASSERT_EQ(err, -ENOENT, "bpf_map_update_elem flags_combo");
+
+ close(map_fd);
+}
+
void test_percpu_alloc(void)
{
if (test__start_subtest("array"))
@@ -565,4 +583,6 @@ void test_percpu_alloc(void)
test_array_cpu_flag();
if (test__start_subtest("cpu_flag_hash"))
test_hash_cpu_flag();
+ if (test__start_subtest("percpu_hash_flags_combination"))
+ test_percpu_hash_flags_combination();
}
--
2.47.3
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] bpf: Fix incorrect handling of user flags by percpu map updates
2026-09-28 10:28 ` [PATCH 1/2] " Masoud Aghasi
@ 2026-09-28 10:41 ` sashiko-bot
2026-09-28 12:53 ` Masoud Aghasi
0 siblings, 1 reply; 5+ messages in thread
From: sashiko-bot @ 2026-09-28 10:41 UTC (permalink / raw)
To: Masoud Aghasi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] bpf: bpf_percpu_array_update() misses validation for mutually exclusive flags
--
commit 41d85d3576867a24ad9b52f72cd4c1d7b23504a6
Author: Masoud Aghasi <maghasi@disroot.org>
bpf: Fix incorrect handling of user flags by percpu map updates
This commit fixes incorrect handling of BPF_EXIST, BPF_NOEXIST, BPF_F_CPU,
and BPF_F_ALL_CPUS flag combinations in BPF_MAP_TYPE_PERCPU_HASH and
BPF_MAP_TYPE_PERCPU_ARRAY map updates.
> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
> index 0ce26b538075e..463f43b19e5cd 100644
> --- a/kernel/bpf/arraymap.c
> +++ b/kernel/bpf/arraymap.c
> @@ -438,7 +438,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
> u32 size;
> int cpu, off = 0;
>
> - if (unlikely((map_flags & BPF_F_LOCK) || (u32)map_flags > BPF_F_ALL_CPUS))
> + if (unlikely((u32)map_flags & ~(BPF_EXIST | BPF_NOEXIST | BPF_F_CPU | BPF_F_ALL_CPUS)))
> /* unknown flags */
> return -EINVAL;
>
> @@ -446,7 +446,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
> /* all elements were pre-allocated, cannot insert a new one */
> return -E2BIG;
>
> - if (unlikely(map_flags == BPF_NOEXIST))
> + if (unlikely(map_flags & BPF_NOEXIST))
[Severity: Low]
Does this validation correctly handle the case where both BPF_EXIST and
BPF_NOEXIST are passed together?
Since the mask check above allows this mutually exclusive combination through,
evaluating `map_flags & BPF_NOEXIST` as true here will return -EEXIST instead
of the expected -EINVAL error code. Should an explicit check for the
combination of BPF_EXIST and BPF_NOEXIST be added here, similar to the one
added for hash maps in htab_map_check_update_flags() in this same patch?
> /* all elements already exist */
> return -EEXIST;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260928102821.995214-1-maghasi@disroot.org?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] bpf: Fix incorrect handling of user flags by percpu map updates
2026-09-28 10:41 ` sashiko-bot
@ 2026-09-28 12:53 ` Masoud Aghasi
0 siblings, 0 replies; 5+ messages in thread
From: Masoud Aghasi @ 2026-09-28 12:53 UTC (permalink / raw)
To: bpf
Cc: andrii, eddyz87, ast, daniel, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai, leon.hwang,
sashiko-reviews
On 28/09/2026 11:41, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Low] bpf: bpf_percpu_array_update() misses validation for mutually exclusive flags
> --
>
> commit 41d85d3576867a24ad9b52f72cd4c1d7b23504a6
> Author: Masoud Aghasi <maghasi@disroot.org>
>
> bpf: Fix incorrect handling of user flags by percpu map updates
>
> This commit fixes incorrect handling of BPF_EXIST, BPF_NOEXIST, BPF_F_CPU,
> and BPF_F_ALL_CPUS flag combinations in BPF_MAP_TYPE_PERCPU_HASH and
> BPF_MAP_TYPE_PERCPU_ARRAY map updates.
>
>> diff --git a/kernel/bpf/arraymap.c b/kernel/bpf/arraymap.c
>> index 0ce26b538075e..463f43b19e5cd 100644
>> --- a/kernel/bpf/arraymap.c
>> +++ b/kernel/bpf/arraymap.c
>> @@ -438,7 +438,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
>> u32 size;
>> int cpu, off = 0;
>>
>> - if (unlikely((map_flags & BPF_F_LOCK) || (u32)map_flags > BPF_F_ALL_CPUS))
>> + if (unlikely((u32)map_flags & ~(BPF_EXIST | BPF_NOEXIST | BPF_F_CPU | BPF_F_ALL_CPUS)))
>> /* unknown flags */
>> return -EINVAL;
>>
>> @@ -446,7 +446,7 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value,
>> /* all elements were pre-allocated, cannot insert a new one */
>> return -E2BIG;
>>
>> - if (unlikely(map_flags == BPF_NOEXIST))
>> + if (unlikely(map_flags & BPF_NOEXIST))
>
> [Severity: Low]
> Does this validation correctly handle the case where both BPF_EXIST and
> BPF_NOEXIST are passed together?
>
> Since the mask check above allows this mutually exclusive combination through,
> evaluating `map_flags & BPF_NOEXIST` as true here will return -EEXIST instead
> of the expected -EINVAL error code. Should an explicit check for the
> combination of BPF_EXIST and BPF_NOEXIST be added here, similar to the one
> added for hash maps in htab_map_check_update_flags() in this same patch?
>
>> /* all elements already exist */
>> return -EEXIST;
>
As there is already a check for "BPF_NOEXIST", it is just a matter of
which error code to return, -EEXIST or -EINVAL. The implementation
currently handles it by prioritizing the BPF_NOEXIST.
There is a similar case for the combination of BPF_F_CPU and
BPF_F_ALL_CPUS, but the implementation already handles it by
prioritizing the BPF_F_CPU.
But let's wait for other reviews as well.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-09-28 12:54 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-28 10:28 [PATCH 0/2] bpf: Fix incorrect handling of user flags by percpu map updates Masoud Aghasi
2026-09-28 10:28 ` [PATCH 1/2] " Masoud Aghasi
2026-09-28 10:41 ` sashiko-bot
2026-09-28 12:53 ` Masoud Aghasi
2026-09-28 10:28 ` [PATCH 2/2] selftests/bpf: add test for percpu map flags combination Masoud Aghasi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox