When mremap is used to create a new mapping, we should not return -EFAULT for VMAs with VM_DONTEXPAND or VM_PFNMAP flags set because the old VMA would neither be expanded nor shrunk in this case. This is particularly useful when trying to create a new VMA using other existing VMAs that have these flags set, such as the ones associated with VFIO devices. Specifically, there are use-cases where a VMM such as Qemu would want to map a non-contiguous buffer associated with a VFIO device in the following way: void *start, *cur; int i; start = mmap(NULL, size, PROT_NONE, MAP_SHARED, -1, 0); if (start == MAP_FAILED) { return start; } cur = start; for (i = 0; i < iov_cnt; i++) { if (mremap(iov[i].iov_base, 0, iov[i].iov_len, MREMAP_FIXED | MREMAP_MAYMOVE, cur) == MAP_FAILED) { goto err; } cur += iov[i].iov_len; } return start; The above code currently works when mapping buffers backed by shmem (memfd) but fails with -EFAULT when mapping VFIO backed buffers because the VMAs associated with iov[i].iov_base addresses have VM_DONTEXPAND and VM_PFNMAP flags set. Therefore, fix this issue by not returning -EFAULT when a new mapping is being created. Cc: Andrew Morton Cc: Liam R. Howlett Cc: Lorenzo Stoakes Cc: Vlastimil Babka Cc: Jann Horn Cc: Pedro Falcato Cc: David Hildenbrand Cc: Akihiko Odaki Signed-off-by: Vivek Kasireddy --- mm/mremap.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mm/mremap.c b/mm/mremap.c index fdb0485ede74..d3868d941f72 100644 --- a/mm/mremap.c +++ b/mm/mremap.c @@ -1736,7 +1736,8 @@ static int check_prep_vma(struct vma_remap_struct *vrm) if (pgoff + (new_len >> PAGE_SHIFT) < pgoff) return -EINVAL; - if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP)) + if (vma->vm_flags & (VM_DONTEXPAND | VM_PFNMAP) && + !vrm_implies_new_addr(vrm)) return -EFAULT; if (!mlock_future_ok(mm, vma->vm_flags, vrm->delta)) -- 2.50.1