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

From: Eric Dumazet

Date: Fri Aug 21 2026 - 13:07:49 EST


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

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.

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")
Reported-by: syzbot+0dbf6d295b3350944f0b@xxxxxxxxxxxxxxxxxxxxxxxxx
Closes: https://lore.kernel.org/lkml/6a88837e.ae6ddae5.3da009.0040.GAE@xxxxxxxxxx/T/#u
Signed-off-by: Eric Dumazet <edumazet@xxxxxxxxxx>
---
Cc: David Hildenbrand <david@xxxxxxxxxx>
Cc: Zi Yan <ziy@xxxxxxxxxx>
Cc: Matthew Brost <matthew.brost@xxxxxxxxx>
Cc: Joshua Hahn <joshua.hahnjy@xxxxxxxxx>
Cc: Rakie Kim <rakie.kim@xxxxxx>
Cc: Byungchul Park <byungchul@xxxxxx>
Cc: Gregory Price <gourry@xxxxxxxxxx>
Cc: Ying Huang <ying.huang@xxxxxxxxxxxxxxxxx>
Cc: Alistair Popple <apopple@xxxxxxxxxx>
Cc: linux-mm@xxxxxxxxx
---
mm/mempolicy.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index 501e0b80d7da..1ef50ca37d42 100644
--- 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);
if (!weights)
return total_allocated;


base-commit: 4e69c1856bfd9ffb7e9d335a25842fa211628929
--
2.55.0.766.g2966f0265a-goog