mirror of
https://kernel.googlesource.com/pub/scm/linux/kernel/git/stable/linux-stable.git
synced 2025-10-26 17:04:24 +10:00
mm: userfaultfd: correct dirty flags set for both present and swap pte
commit75cb1cca2cupstream. 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/20250508220912.7275-1-21cnbao@gmail.com Fixes:adef440691("userfaultfd: UFFDIO_MOVE uABI") Signed-off-by: Barry Song <v-songbaohua@oppo.com> Reported-by: David Hildenbrand <david@redhat.com> Closes: https://lore.kernel.org/linux-mm/02f14ee1-923f-47e3-a994-4950afb9afcc@redhat.com/ Acked-by: Peter Xu <peterx@redhat.com> Reviewed-by: Suren Baghdasaryan <surenb@google.com> Cc: Lokesh Gidra <lokeshgidra@google.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
d005c81665
commit
fe0756daad
@ -1059,8 +1059,13 @@ static int move_present_pte(struct mm_struct *mm,
|
||||
src_folio->index = linear_page_index(dst_vma, dst_addr);
|
||||
|
||||
orig_dst_pte = mk_pte(&src_folio->page, dst_vma->vm_page_prot);
|
||||
/* Follow mremap() behavior and treat the entry dirty after the move */
|
||||
orig_dst_pte = pte_mkwrite(pte_mkdirty(orig_dst_pte), dst_vma);
|
||||
/* Set soft dirty bit so userspace can notice the pte was moved */
|
||||
#ifdef CONFIG_MEM_SOFT_DIRTY
|
||||
orig_dst_pte = pte_mksoft_dirty(orig_dst_pte);
|
||||
#endif
|
||||
if (pte_dirty(orig_src_pte))
|
||||
orig_dst_pte = pte_mkdirty(orig_dst_pte);
|
||||
orig_dst_pte = pte_mkwrite(orig_dst_pte, dst_vma);
|
||||
|
||||
set_pte_at(mm, dst_addr, dst_pte, orig_dst_pte);
|
||||
out:
|
||||
@ -1094,6 +1099,9 @@ static int move_swap_pte(struct mm_struct *mm, struct vm_area_struct *dst_vma,
|
||||
}
|
||||
|
||||
orig_src_pte = ptep_get_and_clear(mm, src_addr, src_pte);
|
||||
#ifdef CONFIG_MEM_SOFT_DIRTY
|
||||
orig_src_pte = pte_swp_mksoft_dirty(orig_src_pte);
|
||||
#endif
|
||||
set_pte_at(mm, dst_addr, dst_pte, orig_src_pte);
|
||||
double_pt_unlock(dst_ptl, src_ptl);
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user