Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 5d8ddc81 authored by Jason Gunthorpe's avatar Jason Gunthorpe Committed by Greg Kroah-Hartman
Browse files

vfio: Use get_user_pages_longterm correctly



commit bb94b55af3461e26b32f0e23d455abeae0cfca5d upstream.

The patch noted in the fixes below converted get_user_pages_fast() to
get_user_pages_longterm(), however the two calls differ in a few ways.

First _fast() is documented to not require the mmap_sem, while _longterm()
is documented to need it. Hold the mmap sem as required.

Second, _fast accepts an 'int write' while _longterm uses 'unsigned int
gup_flags', so the expression '!!(prot & IOMMU_WRITE)' is only working by
luck as FOLL_WRITE is currently == 0x1. Use the expected FOLL_WRITE
constant instead.

Fixes: 94db151dc892 ("vfio: disable filesystem-dax page pinning")
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
Acked-by: default avatarDan Williams <dan.j.williams@intel.com>
Signed-off-by: default avatarAlex Williamson <alex.williamson@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0ce6c464
Loading
Loading
Loading
Loading
+7 −9
Original line number Diff line number Diff line
@@ -339,18 +339,16 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
	struct page *page[1];
	struct vm_area_struct *vma;
	struct vm_area_struct *vmas[1];
	int ret;

	if (mm == current->mm) {
		ret = get_user_pages_longterm(vaddr, 1, !!(prot & IOMMU_WRITE),
					      page, vmas);
	} else {
	unsigned int flags = 0;
	int ret;

	if (prot & IOMMU_WRITE)
		flags |= FOLL_WRITE;

	down_read(&mm->mmap_sem);
	if (mm == current->mm) {
		ret = get_user_pages_longterm(vaddr, 1, flags, page, vmas);
	} else {
		ret = get_user_pages_remote(NULL, mm, vaddr, 1, flags, page,
					    vmas, NULL);
		/*
@@ -364,8 +362,8 @@ static int vaddr_get_pfn(struct mm_struct *mm, unsigned long vaddr,
			ret = -EOPNOTSUPP;
			put_page(page[0]);
		}
		up_read(&mm->mmap_sem);
	}
	up_read(&mm->mmap_sem);

	if (ret == 1) {
		*pfn = page_to_pfn(page[0]);