Skip to content

Commit f39edcf

Browse files
Qi Zhengakpm00
authored andcommitted
mm: pgtable: fix incorrect reclaim of non-empty PTE pages
In zap_pte_range(), if the pte lock was released midway, the pte entries may be refilled with physical pages by another thread, which may cause a non-empty PTE page to be reclaimed and eventually cause the system to crash. To fix it, fall back to the slow path in this case to recheck if all pte entries are still none. Link: https://lkml.kernel.org/r/[email protected] Fixes: 6375e95 ("mm: pgtable: reclaim empty PTE page in madvise(MADV_DONTNEED)") Signed-off-by: Qi Zheng <[email protected]> Reported-by: Christian Brauner <[email protected]> Closes: https://lore.kernel.org/all/20250207-anbot-bankfilialen-acce9d79a2c7@brauner/ Reported-by: Qu Wenruo <[email protected]> Closes: https://lore.kernel.org/all/[email protected]/ Tested-by: Zi Yan <[email protected]> Cc: <[email protected]> Cc: "Darrick J. Wong" <[email protected]> Cc: Dave Chinner <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Jann Horn <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: Muchun Song <[email protected]> Cc: Zi Yan <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent b016d08 commit f39edcf

File tree

1 file changed

+14
-3
lines changed

1 file changed

+14
-3
lines changed

mm/memory.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1719,7 +1719,7 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
17191719
pmd_t pmdval;
17201720
unsigned long start = addr;
17211721
bool can_reclaim_pt = reclaim_pt_is_enabled(start, end, details);
1722-
bool direct_reclaim = false;
1722+
bool direct_reclaim = true;
17231723
int nr;
17241724

17251725
retry:
@@ -1734,20 +1734,31 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb,
17341734
do {
17351735
bool any_skipped = false;
17361736

1737-
if (need_resched())
1737+
if (need_resched()) {
1738+
direct_reclaim = false;
17381739
break;
1740+
}
17391741

17401742
nr = do_zap_pte_range(tlb, vma, pte, addr, end, details, rss,
17411743
&force_flush, &force_break, &any_skipped);
17421744
if (any_skipped)
17431745
can_reclaim_pt = false;
17441746
if (unlikely(force_break)) {
17451747
addr += nr * PAGE_SIZE;
1748+
direct_reclaim = false;
17461749
break;
17471750
}
17481751
} while (pte += nr, addr += PAGE_SIZE * nr, addr != end);
17491752

1750-
if (can_reclaim_pt && addr == end)
1753+
/*
1754+
* Fast path: try to hold the pmd lock and unmap the PTE page.
1755+
*
1756+
* If the pte lock was released midway (retry case), or if the attempt
1757+
* to hold the pmd lock failed, then we need to recheck all pte entries
1758+
* to ensure they are still none, thereby preventing the pte entries
1759+
* from being repopulated by another thread.
1760+
*/
1761+
if (can_reclaim_pt && direct_reclaim && addr == end)
17511762
direct_reclaim = try_get_and_clear_pmd(mm, pmd, &pmdval);
17521763

17531764
add_mm_rss_vec(mm, rss);

0 commit comments

Comments
 (0)