[RFC PATCH v6.6] maple_tree: Fix MA_STATE_PREALLOC flag in mas_preallocate()

Liam R. Howlett Liam.Howlett at oracle.com
Mon Apr 28 18:47:54 PDT 2025


Temporarily clear the preallocation flag when explicitly requesting
allocations.  Pre-existing allocations are already counted against the
request through mas_node_count_gfp(), but the allocations will not
happen if the MA_STATE_PREALLOC flag is set.  This flag is meant to
avoid re-allocating in bulk allocation mode, and to detect issues with
preallocation calculations.

The MA_STATE_PREALLOC flag should also always be set on zero allocations
so that detection of underflow allocations will print a WARN_ON() during
consumption.

User visible effect of this flaw is a WARN_ON() followed by a null
pointer dereference when subsequent requests for larger number of nodes
is ignored, such as the vma merge retry in mmap_region() caused by
drivers altering the vma flags.

Reported-by: Zhaoyang Huang <zhaoyang.huang at unisoc.com>
Reported-by: Hailong Liu <hailong.liu at oppo.com>
Fixes: 54a611b605901 ("Maple Tree: add new data structure")
Link: https://lore.kernel.org/all/1652f7eb-a51b-4fee-8058-c73af63bacd1@oppo.com/
Link: https://lore.kernel.org/all/20250428184058.1416274-1-Liam.Howlett@oracle.com/
Cc: Lorenzo Stoakes <lorenzo.stoakes at oracle.com>
Cc: Suren Baghdasaryan <surenb at google.com>
Cc: Hailong Liu <hailong.liu at oppo.com>
Cc: zhangpeng.00 at bytedance.com <zhangpeng.00 at bytedance.com>
Cc: Steve Kang <Steve.Kang at unisoc.com>
Cc: Matthew Wilcox <willy at infradead.org>
Cc: Sidhartha Kumar <sidhartha.kumar at oracle.com>
Signed-off-by: Liam R. Howlett <Liam.Howlett at oracle.com>
---
 lib/maple_tree.c | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

Only the MA_STATE_PREALLOC flag needs to be fixed to avoid the vma
iterator issue.  Doing the minimum change here mitigates risk in the
stable kernels.

If this fixes the issue, I'll resend without the RFC and add Stable to
the Cc list.

Thanks again, Hailong for the work on this issue.  Your testcase helped
me narrow the bug down in the end.  I appreciate all the work and
support provided by the Android partners, especially the involvement on
the mailing list!

diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 4eda949063602..d9975b870dadc 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -5508,7 +5508,7 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
 	/* At this point, we are at the leaf node that needs to be altered. */
 	/* Exact fit, no nodes needed. */
 	if (wr_mas.r_min == mas->index && wr_mas.r_max == mas->last)
-		return 0;
+		goto ask_zero;
 
 	mas_wr_end_piv(&wr_mas);
 	node_size = mas_wr_new_end(&wr_mas);
@@ -5517,10 +5517,11 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
 	if (node_size == wr_mas.node_end) {
 		/* reuse node */
 		if (!mt_in_rcu(mas->tree))
-			return 0;
+			goto ask_zero;
+
 		/* shifting boundary */
 		if (wr_mas.offset_end - mas->offset == 1)
-			return 0;
+			goto ask_zero;
 	}
 
 	if (node_size >= mt_slots[wr_mas.type]) {
@@ -5539,10 +5540,13 @@ int mas_preallocate(struct ma_state *mas, void *entry, gfp_t gfp)
 
 	/* node store, slot store needs one node */
 ask_now:
+	mas->mas_flags &= ~MA_STATE_PREALLOC;
 	mas_node_count_gfp(mas, request, gfp);
-	mas->mas_flags |= MA_STATE_PREALLOC;
-	if (likely(!mas_is_err(mas)))
+	if (likely(!mas_is_err(mas))) {
+ask_zero:
+		mas->mas_flags |= MA_STATE_PREALLOC;
 		return 0;
+	}
 
 	mas_set_alloc_req(mas, 0);
 	ret = xa_err(mas->node);
-- 
2.47.2




More information about the maple-tree mailing list