[PATCH] mm/mempolicy: Fix sleeping allocation in alloc_pages_bulk_weighted_interleave()
Eric Dumazet <[email protected]>
| Newsgroups | org.kvack.linux-mm,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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: [email protected]
Closes: https://lore.kernel.org/lkml/[email protected]/T/#u
Signed-off-by: Eric Dumazet <[email protected]>
---
Cc: David Hildenbrand <[email protected]>
Cc: Zi Yan <[email protected]>
Cc: Matthew Brost <[email protected]>
Cc: Joshua Hahn <[email protected]>
Cc: Rakie Kim <[email protected]>
Cc: Byungchul Park <[email protected]>
Cc: Gregory Price <[email protected]>
Cc: Ying Huang <[email protected]>
Cc: Alistair Popple <[email protected]>
Cc: [email protected]
---
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