Re: [PATCH bpf v2 1/2] bpf: Fix queue/stack map u32 index overflow

Andrii Nakryiko <[email protected]>
Newsgroups org.kernel.vger.bpf
Message-ID <CAEf4BzZj3-qWtBaSQ5PKKji531Qe_EWEsFU4=VsHzHaa775E7g@mail.gmail.com>
On Mon, Aug 10, 2026 at 2:28 AM <[email protected]> wrote:
>
> From: Yuan Chen <[email protected]>
>
> The queue/stack map addresses elements[] with the product of a u32
> head/tail index and value_size, but the storage itself is allocated in
> 64-bit arithmetic. When max_entries * value_size exceeds U32_MAX, the
> product wraps and push/peek/pop operate on the wrong element, corrupting
> map data and leaking stale values to user space.
>
> The original bound check was removed by commit c85d69135a91 ("bpf: move
> memory size checks to bpf_map_charge_init()"), which migrated only the
> bytes-to-pages conversion and dropped the overflow guard, so oversized
> queue/stack maps can be created again.
>
> Restore the bound in queue_stack_map_alloc_check(): reject maps whose
> element storage would exceed U32_MAX bytes, keeping the u32 index
> multiplication overflow-free. Also reject max_entries == U32_MAX, which
> would make the u32 capacity counter qs->size (max_entries + 1) wrap to
> 0 and permanently break the map.
>
> Fixes: c85d69135a91 ("bpf: move memory size checks to bpf_map_charge_init()")
> Signed-off-by: Yuan Chen <[email protected]>
> ---
>  kernel/bpf/queue_stack_maps.c | 10 ++++++++++
>  1 file changed, 10 insertions(+)
>
> diff --git a/kernel/bpf/queue_stack_maps.c b/kernel/bpf/queue_stack_maps.c
> index c1c9dee4dcdd..bb2453693b80 100644
> --- a/kernel/bpf/queue_stack_maps.c
> +++ b/kernel/bpf/queue_stack_maps.c
> @@ -59,6 +59,16 @@ static int queue_stack_map_alloc_check(union bpf_attr *attr)
>                  */
>                 return -E2BIG;
>
> +       /*
> +        * The u32 head/tail index is multiplied by value_size to address
> +        * elements[], and qs->size (max_entries + 1) is stored in a u32.
> +        * Bound the map size so neither the product nor the capacity
> +        * counter can overflow.
> +        */
> +       if ((u64)attr->max_entries * attr->value_size > U32_MAX ||
> +           attr->max_entries == U32_MAX)
> +               return -E2BIG;

maybe just

if (attr->max_entries >= U32_MAX / attr->value_size)
    return -E2BIG;

This will reject any combination of max_entries and value_size (which
we already checked for zero, so we are fine with division here) that
would get us at U32_MAX size or larger. That automatically eliminates
max_entries == U32_MAX as well.

pw-bot: cr

> +
>         return 0;
>  }
>
> --
> 2.54.0
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.