* [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
@ 2025-11-07 10:03 Alexei Safin
2025-11-07 11:35 ` Yafang Shao
2025-11-07 11:41 ` David Laight
0 siblings, 2 replies; 7+ messages in thread
From: Alexei Safin @ 2025-11-07 10:03 UTC (permalink / raw)
To: Alexei Starovoitov
Cc: Alexei Safin, Daniel Borkmann, Andrii Nakryiko, Martin KaFai Lau,
Eduard Zingerman, Song Liu, Yonghong Song, John Fastabend,
KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa, Yafang Shao,
bpf, linux-kernel, lvc-patches, stable
The intermediate product value_size * num_possible_cpus() is evaluated
in 32-bit arithmetic and only then promoted to 64 bits. On systems with
large value_size and many possible CPUs this can overflow and lead to
an underestimated memory usage.
Found by Linux Verification Center (linuxtesting.org) with SVACE.
Fixes: 304849a27b34 ("bpf: hashtab memory usage")
Cc: stable@vger.kernel.org
Suggested-by: Yafang Shao <laoar.shao@gmail.com>
Signed-off-by: Alexei Safin <a.safin@rosa.ru>
---
v2: Promote value_size to u64 at declaration to avoid 32-bit overflow
in all arithmetic using this variable (suggested by Yafang Shao)
kernel/bpf/hashtab.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
index 570e2f723144..1f0add26ba3f 100644
--- a/kernel/bpf/hashtab.c
+++ b/kernel/bpf/hashtab.c
@@ -2252,7 +2252,7 @@ static long bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_
static u64 htab_map_mem_usage(const struct bpf_map *map)
{
struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
- u32 value_size = round_up(htab->map.value_size, 8);
+ u64 value_size = round_up(htab->map.value_size, 8);
bool prealloc = htab_is_prealloc(htab);
bool percpu = htab_is_percpu(htab);
bool lru = htab_is_lru(htab);
--
2.50.1 (Apple Git-155)
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
2025-11-07 10:03 [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation Alexei Safin
@ 2025-11-07 11:35 ` Yafang Shao
2025-11-07 11:41 ` David Laight
1 sibling, 0 replies; 7+ messages in thread
From: Yafang Shao @ 2025-11-07 11:35 UTC (permalink / raw)
To: Alexei Safin
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
bpf, linux-kernel, lvc-patches, stable
On Fri, Nov 7, 2025 at 6:03 PM Alexei Safin <a.safin@rosa.ru> wrote:
>
> The intermediate product value_size * num_possible_cpus() is evaluated
> in 32-bit arithmetic and only then promoted to 64 bits. On systems with
> large value_size and many possible CPUs this can overflow and lead to
> an underestimated memory usage.
>
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
>
> Fixes: 304849a27b34 ("bpf: hashtab memory usage")
> Cc: stable@vger.kernel.org
> Suggested-by: Yafang Shao <laoar.shao@gmail.com>
> Signed-off-by: Alexei Safin <a.safin@rosa.ru>
Acked-by: Yafang Shao <laoar.shao@gmail.com>
> ---
> v2: Promote value_size to u64 at declaration to avoid 32-bit overflow
> in all arithmetic using this variable (suggested by Yafang Shao)
> kernel/bpf/hashtab.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
> index 570e2f723144..1f0add26ba3f 100644
> --- a/kernel/bpf/hashtab.c
> +++ b/kernel/bpf/hashtab.c
> @@ -2252,7 +2252,7 @@ static long bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_
> static u64 htab_map_mem_usage(const struct bpf_map *map)
> {
> struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
> - u32 value_size = round_up(htab->map.value_size, 8);
> + u64 value_size = round_up(htab->map.value_size, 8);
> bool prealloc = htab_is_prealloc(htab);
> bool percpu = htab_is_percpu(htab);
> bool lru = htab_is_lru(htab);
> --
> 2.50.1 (Apple Git-155)
>
--
Regards
Yafang
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
2025-11-07 10:03 [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation Alexei Safin
2025-11-07 11:35 ` Yafang Shao
@ 2025-11-07 11:41 ` David Laight
2025-11-09 3:00 ` Yafang Shao
1 sibling, 1 reply; 7+ messages in thread
From: David Laight @ 2025-11-07 11:41 UTC (permalink / raw)
To: Alexei Safin
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
Yafang Shao, bpf, linux-kernel, lvc-patches, stable
On Fri, 7 Nov 2025 13:03:05 +0300
Alexei Safin <a.safin@rosa.ru> wrote:
> The intermediate product value_size * num_possible_cpus() is evaluated
> in 32-bit arithmetic and only then promoted to 64 bits. On systems with
> large value_size and many possible CPUs this can overflow and lead to
> an underestimated memory usage.
>
> Found by Linux Verification Center (linuxtesting.org) with SVACE.
That code is insane.
The size being calculated looks like a kernel memory size.
You really don't want to be allocating single structures that exceed 4GB.
David
>
> Fixes: 304849a27b34 ("bpf: hashtab memory usage")
> Cc: stable@vger.kernel.org
> Suggested-by: Yafang Shao <laoar.shao@gmail.com>
> Signed-off-by: Alexei Safin <a.safin@rosa.ru>
> ---
> v2: Promote value_size to u64 at declaration to avoid 32-bit overflow
> in all arithmetic using this variable (suggested by Yafang Shao)
> kernel/bpf/hashtab.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/hashtab.c b/kernel/bpf/hashtab.c
> index 570e2f723144..1f0add26ba3f 100644
> --- a/kernel/bpf/hashtab.c
> +++ b/kernel/bpf/hashtab.c
> @@ -2252,7 +2252,7 @@ static long bpf_for_each_hash_elem(struct bpf_map *map, bpf_callback_t callback_
> static u64 htab_map_mem_usage(const struct bpf_map *map)
> {
> struct bpf_htab *htab = container_of(map, struct bpf_htab, map);
> - u32 value_size = round_up(htab->map.value_size, 8);
> + u64 value_size = round_up(htab->map.value_size, 8);
> bool prealloc = htab_is_prealloc(htab);
> bool percpu = htab_is_percpu(htab);
> bool lru = htab_is_lru(htab);
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
2025-11-07 11:41 ` David Laight
@ 2025-11-09 3:00 ` Yafang Shao
2025-11-09 8:20 ` Yafang Shao
0 siblings, 1 reply; 7+ messages in thread
From: Yafang Shao @ 2025-11-09 3:00 UTC (permalink / raw)
To: David Laight
Cc: Alexei Safin, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
Hao Luo, Jiri Olsa, bpf, linux-kernel, lvc-patches, stable
On Fri, Nov 7, 2025 at 7:41 PM David Laight
<david.laight.linux@gmail.com> wrote:
>
> On Fri, 7 Nov 2025 13:03:05 +0300
> Alexei Safin <a.safin@rosa.ru> wrote:
>
> > The intermediate product value_size * num_possible_cpus() is evaluated
> > in 32-bit arithmetic and only then promoted to 64 bits. On systems with
> > large value_size and many possible CPUs this can overflow and lead to
> > an underestimated memory usage.
> >
> > Found by Linux Verification Center (linuxtesting.org) with SVACE.
>
> That code is insane.
> The size being calculated looks like a kernel memory size.
> You really don't want to be allocating single structures that exceed 4GB.
I failed to get your point.
The calculation `value_size * num_possible_cpus() * num_entries` can
overflow. While the creation of a hashmap limits `value_size *
num_entries` to U32_MAX, this new formula can easily exceed that
limit. For example, on my test server with just 64 CPUs, the following
operation will trigger an overflow:
map_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, "count_map", 4, 4,
1 << 27, &map_opts)
--
Regards
Yafang
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
2025-11-09 3:00 ` Yafang Shao
@ 2025-11-09 8:20 ` Yafang Shao
2025-11-09 11:00 ` Алексей Сафин
0 siblings, 1 reply; 7+ messages in thread
From: Yafang Shao @ 2025-11-09 8:20 UTC (permalink / raw)
To: David Laight, Alexei Safin
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
bpf, linux-kernel, lvc-patches, stable
On Sun, Nov 9, 2025 at 11:00 AM Yafang Shao <laoar.shao@gmail.com> wrote:
>
> On Fri, Nov 7, 2025 at 7:41 PM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Fri, 7 Nov 2025 13:03:05 +0300
> > Alexei Safin <a.safin@rosa.ru> wrote:
> >
> > > The intermediate product value_size * num_possible_cpus() is evaluated
> > > in 32-bit arithmetic and only then promoted to 64 bits. On systems with
> > > large value_size and many possible CPUs this can overflow and lead to
> > > an underestimated memory usage.
> > >
> > > Found by Linux Verification Center (linuxtesting.org) with SVACE.
> >
> > That code is insane.
> > The size being calculated looks like a kernel memory size.
> > You really don't want to be allocating single structures that exceed 4GB.
>
> I failed to get your point.
> The calculation `value_size * num_possible_cpus() * num_entries` can
> overflow. While the creation of a hashmap limits `value_size *
> num_entries` to U32_MAX, this new formula can easily exceed that
> limit. For example, on my test server with just 64 CPUs, the following
> operation will trigger an overflow:
>
> map_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, "count_map", 4, 4,
> 1 << 27, &map_opts)
Upon reviewing the code, I see that `num_entries` is declared as u64,
which prevents overflow in the calculation `value_size *
num_possible_cpus() * num_entries`. Therefore, this change is
unnecessary.
It seems that the Linux Verification Center (linuxtesting.org) needs
to be improved ;-)
--
Regards
Yafang
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
2025-11-09 8:20 ` Yafang Shao
@ 2025-11-09 11:00 ` Алексей Сафин
2025-11-09 12:10 ` Yafang Shao
0 siblings, 1 reply; 7+ messages in thread
From: Алексей Сафин @ 2025-11-09 11:00 UTC (permalink / raw)
To: Yafang Shao, David Laight
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Martin KaFai Lau, Eduard Zingerman, Song Liu, Yonghong Song,
John Fastabend, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
bpf, linux-kernel, lvc-patches, stable
Thanks for the follow-up.
Just to clarify: the overflow happens before the multiplication by
num_entries. In C, the * operator is left-associative, so the expression is
evaluated as (value_size * num_possible_cpus()) * num_entries. Since
value_size was u32 and num_possible_cpus() returns int, the first product is
performed in 32-bit arithmetic due to usual integer promotions. If that
intermediate product overflows, the result is already incorrect before it is
promoted when multiplied by u64 num_entries.
A concrete example within allowed limits:
value_size = 1,048,576 (1 MiB), num_possible_cpus() = 4096
=> 1,048,576 * 4096 = 2^32 => wraps to 0 in 32 bits, even with
num_entries = 1.
This isn’t about a single >4GiB allocation - it’s about aggregated memory
usage (percpu), which can legitimately exceed 4GiB in total.
v2 promotes value_size to u64 at declaration, which avoids the 32-bit
intermediate overflow cleanly.
09.11.2025 11:20, Yafang Shao пишет:
> On Sun, Nov 9, 2025 at 11:00 AM Yafang Shao <laoar.shao@gmail.com> wrote:
>> On Fri, Nov 7, 2025 at 7:41 PM David Laight
>> <david.laight.linux@gmail.com> wrote:
>>> On Fri, 7 Nov 2025 13:03:05 +0300
>>> Alexei Safin <a.safin@rosa.ru> wrote:
>>>
>>>> The intermediate product value_size * num_possible_cpus() is evaluated
>>>> in 32-bit arithmetic and only then promoted to 64 bits. On systems with
>>>> large value_size and many possible CPUs this can overflow and lead to
>>>> an underestimated memory usage.
>>>>
>>>> Found by Linux Verification Center (linuxtesting.org) with SVACE.
>>> That code is insane.
>>> The size being calculated looks like a kernel memory size.
>>> You really don't want to be allocating single structures that exceed 4GB.
>> I failed to get your point.
>> The calculation `value_size * num_possible_cpus() * num_entries` can
>> overflow. While the creation of a hashmap limits `value_size *
>> num_entries` to U32_MAX, this new formula can easily exceed that
>> limit. For example, on my test server with just 64 CPUs, the following
>> operation will trigger an overflow:
>>
>> map_fd = bpf_map_create(BPF_MAP_TYPE_PERCPU_HASH, "count_map", 4, 4,
>> 1 << 27, &map_opts)
> Upon reviewing the code, I see that `num_entries` is declared as u64,
> which prevents overflow in the calculation `value_size *
> num_possible_cpus() * num_entries`. Therefore, this change is
> unnecessary.
>
> It seems that the Linux Verification Center (linuxtesting.org) needs
> to be improved ;-)
>
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation
2025-11-09 11:00 ` Алексей Сафин
@ 2025-11-09 12:10 ` Yafang Shao
0 siblings, 0 replies; 7+ messages in thread
From: Yafang Shao @ 2025-11-09 12:10 UTC (permalink / raw)
To: Алексей Сафин
Cc: David Laight, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, John Fastabend, KP Singh, Stanislav Fomichev,
Hao Luo, Jiri Olsa, bpf, linux-kernel, lvc-patches, stable
On Sun, Nov 9, 2025 at 7:00 PM Алексей Сафин <a.safin@rosa.ru> wrote:
>
> Thanks for the follow-up.
>
> Just to clarify: the overflow happens before the multiplication by
> num_entries. In C, the * operator is left-associative, so the expression is
> evaluated as (value_size * num_possible_cpus()) * num_entries. Since
> value_size was u32 and num_possible_cpus() returns int, the first product is
> performed in 32-bit arithmetic due to usual integer promotions. If that
> intermediate product overflows, the result is already incorrect before it is
> promoted when multiplied by u64 num_entries.
>
> A concrete example within allowed limits:
> value_size = 1,048,576 (1 MiB), num_possible_cpus() = 4096
> => 1,048,576 * 4096 = 2^32 => wraps to 0 in 32 bits, even with
> num_entries = 1.
Thank you for the clarification.
Based on my understanding, the maximum value_size for a percpu hashmap
appears to be constrained by PCPU_MIN_UNIT_SIZE (32768), as referenced
in htab_map_alloc_check():
https://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git/tree/kernel/bpf/hashtab.c#n457
This would require num_possible_cpus() to reach 131072 to potentially
cause an overflow. However, the maximum number of CPUs supported on
x86_64 is typically 8192 in standard kernel configurations. I'm
uncertain if any architectures actually support systems at this scale.
>
> This isn’t about a single >4GiB allocation - it’s about aggregated memory
> usage (percpu), which can legitimately exceed 4GiB in total.
>
> v2 promotes value_size to u64 at declaration, which avoids the 32-bit
> intermediate overflow cleanly.
--
Regards
Yafang
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2025-11-09 12:11 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-07 10:03 [PATCH v2] bpf: hashtab: fix 32-bit overflow in memory usage calculation Alexei Safin
2025-11-07 11:35 ` Yafang Shao
2025-11-07 11:41 ` David Laight
2025-11-09 3:00 ` Yafang Shao
2025-11-09 8:20 ` Yafang Shao
2025-11-09 11:00 ` Алексей Сафин
2025-11-09 12:10 ` Yafang Shao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).