Skip to content

Commit 75cb1cc

Browse files
Barry Songakpm00
Barry Song
authored andcommitted
mm: userfaultfd: correct dirty flags set for both present and swap pte
As David pointed out, what truly matters for mremap and userfaultfd move operations is the soft dirty bit. The current comment and implementation—which always sets the dirty bit for present PTEs and fails to set the soft dirty bit for swap PTEs—are incorrect. This could break features like Checkpoint-Restore in Userspace (CRIU). This patch updates the behavior to correctly set the soft dirty bit for both present and swap PTEs in accordance with mremap. Link: https://lkml.kernel.org/r/[email protected] Fixes: adef440 ("userfaultfd: UFFDIO_MOVE uABI") Signed-off-by: Barry Song <[email protected]> Reported-by: David Hildenbrand <[email protected]> Closes: https://lore.kernel.org/linux-mm/[email protected]/ Acked-by: Peter Xu <[email protected]> Reviewed-by: Suren Baghdasaryan <[email protected]> Cc: Lokesh Gidra <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent 02f5bf8 commit 75cb1cc

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

mm/userfaultfd.c

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1064,8 +1064,13 @@ static int move_present_pte(struct mm_struct *mm,
10641064
src_folio->index = linear_page_index(dst_vma, dst_addr);
10651065

10661066
orig_dst_pte = mk_pte(&src_folio->page, dst_vma->vm_page_prot);
1067-
/* Follow mremap() behavior and treat the entry dirty after the move */
1068-
orig_dst_pte = pte_mkwrite(pte_mkdirty(orig_dst_pte), dst_vma);
1067+
/* Set soft dirty bit so userspace can notice the pte was moved */
1068+
#ifdef CONFIG_MEM_SOFT_DIRTY
1069+
orig_dst_pte = pte_mksoft_dirty(orig_dst_pte);
1070+
#endif
1071+
if (pte_dirty(orig_src_pte))
1072+
orig_dst_pte = pte_mkdirty(orig_dst_pte);
1073+
orig_dst_pte = pte_mkwrite(orig_dst_pte, dst_vma);
10691074

10701075
set_pte_at(mm, dst_addr, dst_pte, orig_dst_pte);
10711076
out:
@@ -1100,6 +1105,9 @@ static int move_swap_pte(struct mm_struct *mm, struct vm_area_struct *dst_vma,
11001105
}
11011106

11021107
orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte);
1108+
#ifdef CONFIG_MEM_SOFT_DIRTY
1109+
orig_src_pte = pte_swp_mksoft_dirty(orig_src_pte);
1110+
#endif
11031111
set_pte_at(mm, dst_addr, dst_pte, orig_src_pte);
11041112
double_pt_unlock(dst_ptl, src_ptl);
11051113

0 commit comments

Comments
 (0)