On 2025/9/30 14:31, David Hildenbrand wrote:
On 30.09.25 08:05, Lance Yang wrote:
From: Lance Yang lance.yang@linux.dev
When splitting an mTHP and replacing a zero-filled subpage with the shared zeropage, try_to_map_unused_to_zeropage() currently drops several important PTE bits.
For userspace tools like CRIU, which rely on the soft-dirty mechanism for incremental snapshots, losing the soft-dirty bit means modified pages are missed, leading to inconsistent memory state after restore.
As pointed out by David, the more critical uffd-wp bit is also dropped. This breaks the userfaultfd write-protection mechanism, causing writes to be silently missed by monitoring applications, which can lead to data corruption.
Preserve both the soft-dirty and uffd-wp bits from the old PTE when creating the new zeropage mapping to ensure they are correctly tracked.
Cc: stable@vger.kernel.org Fixes: b1f202060afe ("mm: remap unused subpages to shared zeropage when splitting isolated thp") Suggested-by: David Hildenbrand david@redhat.com Suggested-by: Dev Jain dev.jain@arm.com Acked-by: David Hildenbrand david@redhat.com Signed-off-by: Lance Yang lance.yang@linux.dev
v2 -> v3: - ptep_get() gets called only once per iteration (per Dev) - https://lore.kernel.org/linux-mm/20250930043351.34927-1- lance.yang@linux.dev/
v1 -> v2: - Avoid calling ptep_get() multiple times (per Dev) - Double-check the uffd-wp bit (per David) - Collect Acked-by from David - thanks! - https://lore.kernel.org/linux-mm/20250928044855.76359-1- lance.yang@linux.dev/
mm/migrate.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-)
diff --git a/mm/migrate.c b/mm/migrate.c index ce83c2c3c287..bafd8cb3bebe 100644 --- a/mm/migrate.c +++ b/mm/migrate.c @@ -297,6 +297,7 @@ bool isolate_folio_to_list(struct folio *folio, struct list_head *list) static bool try_to_map_unused_to_zeropage(struct page_vma_mapped_walk *pvmw, struct folio *folio, + pte_t old_pte, unsigned long idx)
Nit:
static bool try_to_map_unused_to_zeropage(struct page_vma_mapped_walk *pvmw, struct folio *folio, pte_t old_pte, unsigned long idx)
Well, let me clean that up ;p
LGTM, Thanks!
Cheers!