linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/1] mm/thp: fix MTE tag mismatch when replacing zero-filled subpages
@ 2025-09-22  2:14 Lance Yang
  2025-09-22  2:36 ` Zi Yan
                   ` (4 more replies)
  0 siblings, 5 replies; 22+ messages in thread
From: Lance Yang @ 2025-09-22  2:14 UTC (permalink / raw)
  To: akpm, david, lorenzo.stoakes
  Cc: usamaarif642, yuzhao, ziy, baolin.wang, baohua, voidice,
	Liam.Howlett, catalin.marinas, cerasuolodomenico, hannes,
	kaleshsingh, npache, riel, roman.gushchin, rppt, ryan.roberts,
	dev.jain, ryncsn, shakeel.butt, surenb, hughd, willy,
	matthew.brost, joshua.hahnjy, rakie.kim, byungchul, gourry,
	ying.huang, apopple, qun-wei.lin, Andrew.Yang, casper.li,
	chinwen.chang, linux-arm-kernel, linux-kernel, linux-mediatek,
	linux-mm, ioworker0, stable, Qun-wei Lin, Lance Yang

From: Lance Yang <lance.yang@linux.dev>

When both THP and MTE are enabled, splitting a THP and replacing its
zero-filled subpages with the shared zeropage can cause MTE tag mismatch
faults in userspace.

Remapping zero-filled subpages to the shared zeropage is unsafe, as the
zeropage has a fixed tag of zero, which may not match the tag expected by
the userspace pointer.

KSM already avoids this problem by using memcmp_pages(), which on arm64
intentionally reports MTE-tagged pages as non-identical to prevent unsafe
merging.

As suggested by David[1], this patch adopts the same pattern, replacing the
memchr_inv() byte-level check with a call to pages_identical(). This
leverages existing architecture-specific logic to determine if a page is
truly identical to the shared zeropage.

Having both the THP shrinker and KSM rely on pages_identical() makes the
design more future-proof, IMO. Instead of handling quirks in generic code,
we just let the architecture decide what makes two pages identical.

[1] https://lore.kernel.org/all/ca2106a3-4bb2-4457-81af-301fd99fbef4@redhat.com

Cc: <stable@vger.kernel.org>
Reported-by: Qun-wei Lin <Qun-wei.Lin@mediatek.com>
Closes: https://lore.kernel.org/all/a7944523fcc3634607691c35311a5d59d1a3f8d4.camel@mediatek.com
Fixes: b1f202060afe ("mm: remap unused subpages to shared zeropage when splitting isolated thp")
Suggested-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Lance Yang <lance.yang@linux.dev>
---
Tested on x86_64 and on QEMU for arm64 (with and without MTE support),
and the fix works as expected.

 mm/huge_memory.c | 15 +++------------
 mm/migrate.c     |  8 +-------
 2 files changed, 4 insertions(+), 19 deletions(-)

diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 32e0ec2dde36..28d4b02a1aa5 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -4104,29 +4104,20 @@ static unsigned long deferred_split_count(struct shrinker *shrink,
 static bool thp_underused(struct folio *folio)
 {
 	int num_zero_pages = 0, num_filled_pages = 0;
-	void *kaddr;
 	int i;
 
 	for (i = 0; i < folio_nr_pages(folio); i++) {
-		kaddr = kmap_local_folio(folio, i * PAGE_SIZE);
-		if (!memchr_inv(kaddr, 0, PAGE_SIZE)) {
-			num_zero_pages++;
-			if (num_zero_pages > khugepaged_max_ptes_none) {
-				kunmap_local(kaddr);
+		if (pages_identical(folio_page(folio, i), ZERO_PAGE(0))) {
+			if (++num_zero_pages > khugepaged_max_ptes_none)
 				return true;
-			}
 		} else {
 			/*
 			 * Another path for early exit once the number
 			 * of non-zero filled pages exceeds threshold.
 			 */
-			num_filled_pages++;
-			if (num_filled_pages >= HPAGE_PMD_NR - khugepaged_max_ptes_none) {
-				kunmap_local(kaddr);
+			if (++num_filled_pages >= HPAGE_PMD_NR - khugepaged_max_ptes_none)
 				return false;
-			}
 		}
-		kunmap_local(kaddr);
 	}
 	return false;
 }
diff --git a/mm/migrate.c b/mm/migrate.c
index aee61a980374..ce83c2c3c287 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -300,9 +300,7 @@ static bool try_to_map_unused_to_zeropage(struct page_vma_mapped_walk *pvmw,
 					  unsigned long idx)
 {
 	struct page *page = folio_page(folio, idx);
-	bool contains_data;
 	pte_t newpte;
-	void *addr;
 
 	if (PageCompound(page))
 		return false;
@@ -319,11 +317,7 @@ static bool try_to_map_unused_to_zeropage(struct page_vma_mapped_walk *pvmw,
 	 * this subpage has been non present. If the subpage is only zero-filled
 	 * then map it to the shared zeropage.
 	 */
-	addr = kmap_local_page(page);
-	contains_data = memchr_inv(addr, 0, PAGE_SIZE);
-	kunmap_local(addr);
-
-	if (contains_data)
+	if (!pages_identical(page, ZERO_PAGE(0)))
 		return false;
 
 	newpte = pte_mkspecial(pfn_pte(my_zero_pfn(pvmw->address),
-- 
2.49.0



^ permalink raw reply	[flat|nested] 22+ messages in thread

end of thread, other threads:[~2025-09-24 10:02 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-09-22  2:14 [PATCH 1/1] mm/thp: fix MTE tag mismatch when replacing zero-filled subpages Lance Yang
2025-09-22  2:36 ` Zi Yan
2025-09-22  3:36   ` Lance Yang
2025-09-22  7:41 ` David Hildenbrand
2025-09-22  8:24 ` Usama Arif
2025-09-22 17:24 ` Catalin Marinas
2025-09-22 17:59   ` David Hildenbrand
2025-09-23  1:48     ` Lance Yang
2025-09-23 11:52     ` Catalin Marinas
2025-09-23 12:00       ` David Hildenbrand
2025-09-23 12:04         ` Lance Yang
2025-09-23 12:51         ` Catalin Marinas
2025-09-23 17:20         ` Lance Yang
2025-09-23 16:14       ` Catalin Marinas
2025-09-23 16:40         ` David Hildenbrand
2025-09-24  2:49         ` Lance Yang
2025-09-24  8:50           ` Catalin Marinas
2025-09-24  9:13             ` David Hildenbrand
2025-09-24  9:34               ` Catalin Marinas
2025-09-24  9:44                 ` David Hildenbrand
2025-09-24  9:59                   ` Catalin Marinas
2025-09-23  2:10 ` Wei Yang

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox