From: Liam R. Howlett Date: Mon, 27 Oct 2025 19:12:54 +0000 (-0400) Subject: mm/userfaultfd: Move global dst checks to uffd_ctx_lock_and_validate_dst() X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=49ae1f77f6b04bef462ca26c2a3a6cf6f6d7a3c6;p=users%2Fjedix%2Flinux-maple.git mm/userfaultfd: Move global dst checks to uffd_ctx_lock_and_validate_dst() Reduce mfill_atomic() further by exporting logic checks to the lock_and_validate_dst(). Signed-off-by: Liam R. Howlett --- diff --git a/mm/shmem.c b/mm/shmem.c index a08311bebfa3..28c679130f68 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3153,14 +3153,6 @@ static inline struct inode *shmem_get_inode(struct mnt_idmap *idmap, static ssize_t shmem_is_dst_valid(struct vm_area_struct *dst_vma, unsigned long dst_start, unsigned long len) { - /* - * shmem_zero_setup is invoked in mmap for MAP_ANONYMOUS|MAP_SHARED but - * it will overwrite vm_ops, so vma_is_anonymous must return false. - */ - if (WARN_ON_ONCE(vma_is_anonymous(dst_vma) && - dst_vma->vm_flags & VM_SHARED)) - return -EINVAL; - return 0; } diff --git a/mm/userfaultfd.c b/mm/userfaultfd.c index c64c63a80e0f..ca716bef7a50 100644 --- a/mm/userfaultfd.c +++ b/mm/userfaultfd.c @@ -517,10 +517,13 @@ static inline const struct vm_uffd_ops *vma_get_uffd_ops(struct vm_area_struct * return &default_uffd_ops; } +/* + * Global checks live here, specific checks are in the callback. + */ static inline ssize_t uffd_ctx_lock_and_validate_dst(struct userfaultfd_ctx *ctx, struct vm_area_struct *dst_vma, unsigned long dst_start, - unsigned long len) + unsigned long len, uffd_flags_t flags) { const struct vm_uffd_ops *uffd_ops; @@ -533,6 +536,20 @@ uffd_ctx_lock_and_validate_dst(struct userfaultfd_ctx *ctx, if (atomic_read(&ctx->mmap_changing)) return -EAGAIN; + /* + * shmem_zero_setup is invoked in mmap for MAP_ANONYMOUS|MAP_SHARED but + * it will overwrite vm_ops, so vma_is_anonymous must return false. + */ + if (WARN_ON_ONCE(vma_is_anonymous(dst_vma) && + dst_vma->vm_flags & VM_SHARED)) + return -EINVAL; + /* + * validate 'mode' now that we know the dst_vma: don't allow + * a wrprotect copy if the userfaultfd didn't register as WP. + */ + if ((flags & MFILL_ATOMIC_WP) && !(dst_vma->vm_flags & VM_UFFD_WP)) + return -EINVAL; + uffd_ops = vma_get_uffd_ops(dst_vma); WARN_ON_ONCE(!uffd_ops || !uffd_ops->is_dst_valid); return uffd_ops->is_dst_valid(dst_vma, dst_start, len); @@ -600,7 +617,8 @@ retry: goto out; } - err = uffd_ctx_lock_and_validate_dst(ctx, dst_vma, dst_start, len); + err = uffd_ctx_lock_and_validate_dst(ctx, dst_vma, dst_start, + len, flags); if (err) goto out_unlock; } @@ -763,26 +781,11 @@ retry: increment = uffd_ops->increment(dst_vma); } - err = uffd_ctx_lock_and_validate_dst(ctx, dst_vma, dst_start, len); + err = uffd_ctx_lock_and_validate_dst(ctx, dst_vma, dst_start, len, + flags); if (err) goto out_unlock; - err = -EINVAL; - /* - * shmem_zero_setup is invoked in mmap for MAP_ANONYMOUS|MAP_SHARED but - * it will overwrite vm_ops, so vma_is_anonymous must return false. - */ - if (WARN_ON_ONCE(vma_is_anonymous(dst_vma) && - dst_vma->vm_flags & VM_SHARED)) - goto out_unlock; - - /* - * validate 'mode' now that we know the dst_vma: don't allow - * a wrprotect copy if the userfaultfd didn't register as WP. - */ - if ((flags & MFILL_ATOMIC_WP) && !(dst_vma->vm_flags & VM_UFFD_WP)) - goto out_unlock; - /* * If this is a HUGETLB vma, pass off to appropriate routine */ @@ -790,6 +793,7 @@ retry: return mfill_atomic_hugetlb(ctx, dst_vma, dst_start, src_start, len, flags); + err = -EINVAL; if (!vma_is_anonymous(dst_vma) && !vma_is_shmem(dst_vma)) goto out_unlock; if (!vma_is_shmem(dst_vma) &&