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 ;-)