lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250429014754.1479118-1-Liam.Howlett@oracle.com>
Date: Mon, 28 Apr 2025 21:47:54 -0400
From: "Liam R. Howlett" <Liam.Howlett@...cle.com>
To: "Liam R . Howlett" <Liam.Howlett@...cle.com>
Cc: maple-tree@...ts.infradead.org, linux-mm@...ck.org,
        linux-kernel@...r.kernel.org,
        Zhaoyang Huang <zhaoyang.huang@...soc.com>,
        Hailong Liu <hailong.liu@...o.com>,
        Lorenzo Stoakes <lorenzo.stoakes@...cle.com>,
        Suren Baghdasaryan <surenb@...gle.com>,
        "zhangpeng . 00 @ bytedance . com" <zhangpeng.00@...edance.com>,
        Steve Kang <Steve.Kang@...soc.com>,
        Matthew Wilcox <willy@...radead.org>,
        Sidhartha Kumar <sidhartha.kumar@...cle.com>
Subject: [RFC PATCH v6.6] maple_tree: Fix MA_STATE_PREALLOC flag in mas_preallocate()

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@...soc.com>
Reported-by: Hailong Liu <hailong.liu@...o.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@...cle.com>
Cc: Suren Baghdasaryan <surenb@...gle.com>
Cc: Hailong Liu <hailong.liu@...o.com>
Cc: zhangpeng.00@...edance.com <zhangpeng.00@...edance.com>
Cc: Steve Kang <Steve.Kang@...soc.com>
Cc: Matthew Wilcox <willy@...radead.org>
Cc: Sidhartha Kumar <sidhartha.kumar@...cle.com>
Signed-off-by: Liam R. Howlett <Liam.Howlett@...cle.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


Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ