Re: [PATCH] mm/mempolicy: Fix sleeping allocation in alloc_pages_bulk_weighted_interleave()

From: Andrew Morton

Date: Fri Aug 21 2026 - 13:44:32 EST


On Fri, 21 Aug 2026 17:04:07 +0000 Eric Dumazet <edumazet@xxxxxxxxxx> wrote:

> syzbot reported a sleeping function called from invalid context splat
> in bucket_table_alloc().

That was quick (7 minutes!). I was just looking at this.

> When rhashtable_insert_slow() rehashes the table under rcu_read_lock(),
> it calls bucket_table_alloc(..., GFP_ATOMIC | __GFP_NOWARN).
> If the bucket table allocation uses vmalloc, __vmalloc_node_range_noprof()
> invokes vm_area_alloc_pages() -> alloc_pages_bulk_mempolicy_noprof() with
> the passed GFP_ATOMIC flags.
>
> If the current task has an MPOL_WEIGHTED_INTERLEAVE mempolicy,
> alloc_pages_bulk_weighted_interleave() is called and currently hardcodes
> GFP_KERNEL when allocating the temporary weights array, triggering
> a might_alloc() splat in atomic/RCU contexts.

2 years ago. Why are we discovering this now?

> Pass the gfp flags (masked with GFP_RECLAIM_MASK to strip page-allocator
> zone modifiers like __GFP_HIGHMEM) received by
> alloc_pages_bulk_weighted_interleave() to kmalloc() instead of
> hardcoding GFP_KERNEL. Since the weights buffer is immediately
> initialized in full, kmalloc() is sufficient.
>
> Fixes: fa3bea4e1f82 ("mm/mempolicy: introduce MPOL_WEIGHTED_INTERLEAVE for weighted interleaving")

I'll add cc:stable

> --- a/mm/mempolicy.c
> +++ b/mm/mempolicy.c
> @@ -2688,7 +2688,7 @@ static unsigned long alloc_pages_bulk_weighted_interleave(gfp_t gfp,
> prev_node = node;
>
> /* create a local copy of node weights to operate on outside rcu */
> - weights = kzalloc(nr_node_ids, GFP_KERNEL);
> + weights = kmalloc(nr_node_ids, gfp & GFP_RECLAIM_MASK);

lgtm, thanks.

I wonder if we *really* need the local copy of state->iw_table.
Perhaps with appropriate care we can directly use state->iw_table in
here.

How much would it hurt to expand the rcu_read_lock() coverage?

A local array of MAX_NUMNODES bytes isn't attractive - 1k of stack.

A spinlock-protected static array would work, if super-rare slowpath.

> if (!weights)
> return total_allocated;