Skip to content

Commit 67695f1

Browse files
SENSEIIIIIakpm00
authored andcommitted
userfaultfd: fix mmap_changing checking in mfill_atomic_hugetlb
In mfill_atomic_hugetlb(), mmap_changing isn't being checked again if we drop mmap_lock and reacquire it. When the lock is not held, mmap_changing could have been incremented. This is also inconsistent with the behavior in mfill_atomic(). Link: https://lkml.kernel.org/r/[email protected] Fixes: df2cc96 ("userfaultfd: prevent non-cooperative events vs mcopy_atomic races") Signed-off-by: Lokesh Gidra <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Mike Rapoport <[email protected]> Cc: Axel Rasmussen <[email protected]> Cc: Brian Geffon <[email protected]> Cc: David Hildenbrand <[email protected]> Cc: Jann Horn <[email protected]> Cc: Kalesh Singh <[email protected]> Cc: Matthew Wilcox (Oracle) <[email protected]> Cc: Nicolas Geoffray <[email protected]> Cc: Peter Xu <[email protected]> Cc: Suren Baghdasaryan <[email protected]> Cc: <[email protected]> Signed-off-by: Andrew Morton <[email protected]>
1 parent d021b44 commit 67695f1

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

mm/userfaultfd.c

+13-2
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,7 @@ static __always_inline ssize_t mfill_atomic_hugetlb(
357357
unsigned long dst_start,
358358
unsigned long src_start,
359359
unsigned long len,
360+
atomic_t *mmap_changing,
360361
uffd_flags_t flags)
361362
{
362363
struct mm_struct *dst_mm = dst_vma->vm_mm;
@@ -472,6 +473,15 @@ static __always_inline ssize_t mfill_atomic_hugetlb(
472473
goto out;
473474
}
474475
mmap_read_lock(dst_mm);
476+
/*
477+
* If memory mappings are changing because of non-cooperative
478+
* operation (e.g. mremap) running in parallel, bail out and
479+
* request the user to retry later
480+
*/
481+
if (mmap_changing && atomic_read(mmap_changing)) {
482+
err = -EAGAIN;
483+
break;
484+
}
475485

476486
dst_vma = NULL;
477487
goto retry;
@@ -506,6 +516,7 @@ extern ssize_t mfill_atomic_hugetlb(struct vm_area_struct *dst_vma,
506516
unsigned long dst_start,
507517
unsigned long src_start,
508518
unsigned long len,
519+
atomic_t *mmap_changing,
509520
uffd_flags_t flags);
510521
#endif /* CONFIG_HUGETLB_PAGE */
511522

@@ -622,8 +633,8 @@ static __always_inline ssize_t mfill_atomic(struct mm_struct *dst_mm,
622633
* If this is a HUGETLB vma, pass off to appropriate routine
623634
*/
624635
if (is_vm_hugetlb_page(dst_vma))
625-
return mfill_atomic_hugetlb(dst_vma, dst_start,
626-
src_start, len, flags);
636+
return mfill_atomic_hugetlb(dst_vma, dst_start, src_start,
637+
len, mmap_changing, flags);
627638

628639
if (!vma_is_anonymous(dst_vma) && !vma_is_shmem(dst_vma))
629640
goto out_unlock;

0 commit comments

Comments
 (0)