[PATCH 3/3] mm/rmap: fix PTE table overruns during batched reference checks

From: David Hildenbrand (Arm)

Date: Wed Nov 11 2026 - 17:15:28 EST


With a folded PMD, pmd_addr_end() simply returns the supplied end.
folio_referenced_one() can therefore walk past the PTE table when
checking references to a large folio.

Folded PMDs are uncommon, but can occur even on arm64, for example
with 64K pages and a 42-bit virtual address space.

Use pte_table_clamped_end() to clamp the range to the PTE table and
VMA boundaries.

Fixes: 52e054f71840 ("mm: rmap: support batched checks of the references for large folios")
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Chris Mason <mason@xxxxxxxxxx>
Signed-off-by: David Hildenbrand (Arm) <david@xxxxxxxxxx>
---
mm/rmap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/mm/rmap.c b/mm/rmap.c
index 491a954b7fa44..65646ed6fc453 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -973,7 +973,7 @@ static bool folio_referenced_one(struct folio *folio,
pteval = ptep_get(pvmw.pte);

if (pvmw.pte && pte_present(pteval) && folio_test_large(folio)) {
- const unsigned long end_addr = pmd_addr_end(address, vma->vm_end);
+ const unsigned long end_addr = pte_table_clamped_end(address, vma->vm_end);
const unsigned int max_nr = (end_addr - address) >> PAGE_SHIFT;

nr = folio_pte_batch(folio, pvmw.pte, pteval, max_nr);

--
2.43.0