kvm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages()
       [not found] <cover.1681508038.git.lstoakes@gmail.com>
@ 2023-04-14 23:27 ` Lorenzo Stoakes
  2023-04-15  5:27   ` Greg Kroah-Hartman
  2023-04-17 13:01   ` Jason Gunthorpe
  2023-04-14 23:27 ` [PATCH 2/7] mm/gup: remove unused vmas parameter from pin_user_pages_remote() Lorenzo Stoakes
                   ` (2 subsequent siblings)
  3 siblings, 2 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-14 23:27 UTC (permalink / raw)
  To: linux-mm, linux-kernel, Andrew Morton
  Cc: Matthew Wilcox, David Hildenbrand, x86, linux-sgx, amd-gfx,
	dri-devel, kvm, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Jarkko Sakkinen, H . Peter Anvin, Xinhui Pan, David Airlie,
	Daniel Vetter, Dimitri Sivanich, Arnd Bergmann,
	Greg Kroah-Hartman, Paolo Bonzini, Lorenzo Stoakes

No invocation of get_user_pages() uses the vmas parameter, so remove
it.

The GUP API is confusing and caveated. Recent changes have done much to
improve that, however there is more we can do. Exporting vmas is a prime
target as the caller has to be extremely careful to preclude their use
after the mmap_lock has expired or otherwise be left with dangling
pointers.

Removing the vmas parameter focuses the GUP functions upon their primary
purpose - pinning (and outputting) pages as well as performing the actions
implied by the input flags.

This is part of a patch series aiming to remove the vmas parameter
altogether.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
Suggested-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
 arch/x86/kernel/cpu/sgx/ioctl.c     | 2 +-
 drivers/gpu/drm/radeon/radeon_ttm.c | 2 +-
 drivers/misc/sgi-gru/grufault.c     | 2 +-
 include/linux/mm.h                  | 3 +--
 mm/gup.c                            | 9 +++------
 mm/gup_test.c                       | 5 ++---
 virt/kvm/kvm_main.c                 | 4 ++--
 7 files changed, 11 insertions(+), 16 deletions(-)

diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 21ca0a831b70..5d390df21440 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -214,7 +214,7 @@ static int __sgx_encl_add_page(struct sgx_encl *encl,
 	if (!(vma->vm_flags & VM_MAYEXEC))
 		return -EACCES;
 
-	ret = get_user_pages(src, 1, 0, &src_page, NULL);
+	ret = get_user_pages(src, 1, 0, &src_page);
 	if (ret < 1)
 		return -EFAULT;
 
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 1e8e287e113c..0597540f0dde 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -362,7 +362,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_device *bdev, struct ttm_tt *ttm
 		struct page **pages = ttm->pages + pinned;
 
 		r = get_user_pages(userptr, num_pages, write ? FOLL_WRITE : 0,
-				   pages, NULL);
+				   pages);
 		if (r < 0)
 			goto release_pages;
 
diff --git a/drivers/misc/sgi-gru/grufault.c b/drivers/misc/sgi-gru/grufault.c
index b836936e9747..378cf02a2aa1 100644
--- a/drivers/misc/sgi-gru/grufault.c
+++ b/drivers/misc/sgi-gru/grufault.c
@@ -185,7 +185,7 @@ static int non_atomic_pte_lookup(struct vm_area_struct *vma,
 #else
 	*pageshift = PAGE_SHIFT;
 #endif
-	if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page, NULL) <= 0)
+	if (get_user_pages(vaddr, 1, write ? FOLL_WRITE : 0, &page) <= 0)
 		return -EFAULT;
 	*paddr = page_to_phys(page);
 	put_page(page);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 5d5ba1556ae9..faeed36c2d04 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2380,8 +2380,7 @@ long pin_user_pages_remote(struct mm_struct *mm,
 			   unsigned int gup_flags, struct page **pages,
 			   struct vm_area_struct **vmas, int *locked);
 long get_user_pages(unsigned long start, unsigned long nr_pages,
-			    unsigned int gup_flags, struct page **pages,
-			    struct vm_area_struct **vmas);
+		    unsigned int gup_flags, struct page **pages);
 long pin_user_pages(unsigned long start, unsigned long nr_pages,
 		    unsigned int gup_flags, struct page **pages,
 		    struct vm_area_struct **vmas);
diff --git a/mm/gup.c b/mm/gup.c
index 1f72a717232b..7e454d6b157e 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2251,8 +2251,6 @@ long get_user_pages_remote(struct mm_struct *mm,
  * @pages:      array that receives pointers to the pages pinned.
  *              Should be at least nr_pages long. Or NULL, if caller
  *              only intends to ensure the pages are faulted in.
- * @vmas:       array of pointers to vmas corresponding to each page.
- *              Or NULL if the caller does not require them.
  *
  * This is the same as get_user_pages_remote(), just with a less-flexible
  * calling convention where we assume that the mm being operated on belongs to
@@ -2260,16 +2258,15 @@ long get_user_pages_remote(struct mm_struct *mm,
  * obviously don't pass FOLL_REMOTE in here.
  */
 long get_user_pages(unsigned long start, unsigned long nr_pages,
-		unsigned int gup_flags, struct page **pages,
-		struct vm_area_struct **vmas)
+		    unsigned int gup_flags, struct page **pages)
 {
 	int locked = 1;
 
-	if (!is_valid_gup_args(pages, vmas, NULL, &gup_flags, FOLL_TOUCH))
+	if (!is_valid_gup_args(pages, NULL, NULL, &gup_flags, FOLL_TOUCH))
 		return -EINVAL;
 
 	return __get_user_pages_locked(current->mm, start, nr_pages, pages,
-				       vmas, &locked, gup_flags);
+				       NULL, &locked, gup_flags);
 }
 EXPORT_SYMBOL(get_user_pages);
 
diff --git a/mm/gup_test.c b/mm/gup_test.c
index 8ae7307a1bb6..9ba8ea23f84e 100644
--- a/mm/gup_test.c
+++ b/mm/gup_test.c
@@ -139,8 +139,7 @@ static int __gup_test_ioctl(unsigned int cmd,
 						 pages + i);
 			break;
 		case GUP_BASIC_TEST:
-			nr = get_user_pages(addr, nr, gup->gup_flags, pages + i,
-					    NULL);
+			nr = get_user_pages(addr, nr, gup->gup_flags, pages + i);
 			break;
 		case PIN_FAST_BENCHMARK:
 			nr = pin_user_pages_fast(addr, nr, gup->gup_flags,
@@ -161,7 +160,7 @@ static int __gup_test_ioctl(unsigned int cmd,
 						    pages + i, NULL);
 			else
 				nr = get_user_pages(addr, nr, gup->gup_flags,
-						    pages + i, NULL);
+						    pages + i);
 			break;
 		default:
 			ret = -EINVAL;
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index d255964ec331..2d2446df0900 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2474,7 +2474,7 @@ static inline int check_user_page_hwpoison(unsigned long addr)
 {
 	int rc, flags = FOLL_HWPOISON | FOLL_WRITE;
 
-	rc = get_user_pages(addr, 1, flags, NULL, NULL);
+	rc = get_user_pages(addr, 1, flags, NULL);
 	return rc == -EHWPOISON;
 }
 
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 2/7] mm/gup: remove unused vmas parameter from pin_user_pages_remote()
       [not found] <cover.1681508038.git.lstoakes@gmail.com>
  2023-04-14 23:27 ` [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages() Lorenzo Stoakes
@ 2023-04-14 23:27 ` Lorenzo Stoakes
  2023-04-17 13:02   ` Jason Gunthorpe
  2023-04-14 23:27 ` [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote() Lorenzo Stoakes
  2023-04-14 23:27 ` [PATCH 6/7] mm/gup: remove vmas parameter from pin_user_pages() Lorenzo Stoakes
  3 siblings, 1 reply; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-14 23:27 UTC (permalink / raw)
  To: linux-mm, linux-kernel, Andrew Morton, iommu
  Cc: Matthew Wilcox, David Hildenbrand, kvm, Jason Gunthorpe,
	Kevin Tian, Joerg Roedel, Will Deacon, Robin Murphy,
	Alex Williamson, Lorenzo Stoakes

No invocation of pin_user_pages_remote() uses the vmas parameter, so remove
it. This forms part of a larger patch set eliminating the use of the vmas
parameters altogether.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 drivers/iommu/iommufd/pages.c   | 4 ++--
 drivers/vfio/vfio_iommu_type1.c | 2 +-
 include/linux/mm.h              | 2 +-
 mm/gup.c                        | 8 +++-----
 mm/process_vm_access.c          | 2 +-
 5 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/drivers/iommu/iommufd/pages.c b/drivers/iommu/iommufd/pages.c
index f8d92c9bb65b..9d55a2188a64 100644
--- a/drivers/iommu/iommufd/pages.c
+++ b/drivers/iommu/iommufd/pages.c
@@ -786,7 +786,7 @@ static int pfn_reader_user_pin(struct pfn_reader_user *user,
 			user->locked = 1;
 		}
 		rc = pin_user_pages_remote(pages->source_mm, uptr, npages,
-					   user->gup_flags, user->upages, NULL,
+					   user->gup_flags, user->upages,
 					   &user->locked);
 	}
 	if (rc <= 0) {
@@ -1787,7 +1787,7 @@ static int iopt_pages_rw_page(struct iopt_pages *pages, unsigned long index,
 	rc = pin_user_pages_remote(
 		pages->source_mm, (uintptr_t)(pages->uptr + index * PAGE_SIZE),
 		1, (flags & IOMMUFD_ACCESS_RW_WRITE) ? FOLL_WRITE : 0, &page,
-		NULL, NULL);
+		NULL);
 	mmap_read_unlock(pages->source_mm);
 	if (rc != 1) {
 		if (WARN_ON(rc >= 0))
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 493c31de0edb..e6dc8fec3ed5 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -562,7 +562,7 @@ static int vaddr_get_pfns(struct mm_struct *mm, unsigned long vaddr,
 
 	mmap_read_lock(mm);
 	ret = pin_user_pages_remote(mm, vaddr, npages, flags | FOLL_LONGTERM,
-				    pages, NULL, NULL);
+				    pages, NULL);
 	if (ret > 0) {
 		int i;
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index faeed36c2d04..513d5fab02f1 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2378,7 +2378,7 @@ long get_user_pages_remote(struct mm_struct *mm,
 long pin_user_pages_remote(struct mm_struct *mm,
 			   unsigned long start, unsigned long nr_pages,
 			   unsigned int gup_flags, struct page **pages,
-			   struct vm_area_struct **vmas, int *locked);
+			   int *locked);
 long get_user_pages(unsigned long start, unsigned long nr_pages,
 		    unsigned int gup_flags, struct page **pages);
 long pin_user_pages(unsigned long start, unsigned long nr_pages,
diff --git a/mm/gup.c b/mm/gup.c
index 7e454d6b157e..931c805bc32b 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -3093,8 +3093,6 @@ EXPORT_SYMBOL_GPL(pin_user_pages_fast);
  * @gup_flags:	flags modifying lookup behaviour
  * @pages:	array that receives pointers to the pages pinned.
  *		Should be at least nr_pages long.
- * @vmas:	array of pointers to vmas corresponding to each page.
- *		Or NULL if the caller does not require them.
  * @locked:	pointer to lock flag indicating whether lock is held and
  *		subsequently whether VM_FAULT_RETRY functionality can be
  *		utilised. Lock must initially be held.
@@ -3109,14 +3107,14 @@ EXPORT_SYMBOL_GPL(pin_user_pages_fast);
 long pin_user_pages_remote(struct mm_struct *mm,
 			   unsigned long start, unsigned long nr_pages,
 			   unsigned int gup_flags, struct page **pages,
-			   struct vm_area_struct **vmas, int *locked)
+			   int *locked)
 {
 	int local_locked = 1;
 
-	if (!is_valid_gup_args(pages, vmas, locked, &gup_flags,
+	if (!is_valid_gup_args(pages, NULL, locked, &gup_flags,
 			       FOLL_PIN | FOLL_TOUCH | FOLL_REMOTE))
 		return 0;
-	return __gup_longterm_locked(mm, start, nr_pages, pages, vmas,
+	return __gup_longterm_locked(mm, start, nr_pages, pages, NULL,
 				     locked ? locked : &local_locked,
 				     gup_flags);
 }
diff --git a/mm/process_vm_access.c b/mm/process_vm_access.c
index 78dfaf9e8990..0523edab03a6 100644
--- a/mm/process_vm_access.c
+++ b/mm/process_vm_access.c
@@ -104,7 +104,7 @@ static int process_vm_rw_single_vec(unsigned long addr,
 		mmap_read_lock(mm);
 		pinned_pages = pin_user_pages_remote(mm, pa, pinned_pages,
 						     flags, process_pages,
-						     NULL, &locked);
+						     &locked);
 		if (locked)
 			mmap_read_unlock(mm);
 		if (pinned_pages <= 0)
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
       [not found] <cover.1681508038.git.lstoakes@gmail.com>
  2023-04-14 23:27 ` [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages() Lorenzo Stoakes
  2023-04-14 23:27 ` [PATCH 2/7] mm/gup: remove unused vmas parameter from pin_user_pages_remote() Lorenzo Stoakes
@ 2023-04-14 23:27 ` Lorenzo Stoakes
  2023-04-15  0:25   ` Tetsuo Handa
  2023-04-17 13:09   ` Jason Gunthorpe
  2023-04-14 23:27 ` [PATCH 6/7] mm/gup: remove vmas parameter from pin_user_pages() Lorenzo Stoakes
  3 siblings, 2 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-14 23:27 UTC (permalink / raw)
  To: linux-mm, linux-kernel, Andrew Morton
  Cc: Matthew Wilcox, David Hildenbrand, linux-arm-kernel, kvm,
	linux-s390, linux-fsdevel, linux-perf-users,
	linux-security-module, Catalin Marinas, Will Deacon,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Sven Schnelle,
	Eric Biederman, Kees Cook, Alexander Viro, Christian Brauner,
	Peter Zijlstra, Ingo Molnar, Arnaldo Carvalho de Melo,
	Mark Rutland, Alexander Shishkin, Jiri Olsa, Namhyung Kim,
	Ian Rogers, Adrian Hunter, Kentaro Takeda, Tetsuo Handa,
	Paul Moore, James Morris, Serge E . Hallyn, Paolo Bonzini,
	Lorenzo Stoakes

The only instances of get_user_pages_remote() invocations which used the
vmas parameter were for a single page which can instead simply look up the
VMA directly. In particular:-

- __update_ref_ctr() looked up the VMA but did nothing with it so we simply
  remove it.

- __access_remote_vm() was already using vma_lookup() when the original
  lookup failed so by doing the lookup directly this also de-duplicates the
  code.

This forms part of a broader set of patches intended to eliminate the vmas
parameter altogether.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 arch/arm64/kernel/mte.c   |  5 +++--
 arch/s390/kvm/interrupt.c |  2 +-
 fs/exec.c                 |  2 +-
 include/linux/mm.h        |  2 +-
 kernel/events/uprobes.c   | 10 +++++-----
 mm/gup.c                  | 12 ++++--------
 mm/memory.c               |  9 +++++----
 mm/rmap.c                 |  2 +-
 security/tomoyo/domain.c  |  2 +-
 virt/kvm/async_pf.c       |  3 +--
 10 files changed, 23 insertions(+), 26 deletions(-)

diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
index f5bcb0dc6267..74d8d4007dec 100644
--- a/arch/arm64/kernel/mte.c
+++ b/arch/arm64/kernel/mte.c
@@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
 		struct page *page = NULL;
 
 		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
-					    &vma, NULL);
-		if (ret <= 0)
+					    NULL);
+		vma = vma_lookup(mm, addr);
+		if (ret <= 0 || !vma)
 			break;
 
 		/*
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 9250fde1f97d..c19d0cb7d2f2 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -2777,7 +2777,7 @@ static struct page *get_map_page(struct kvm *kvm, u64 uaddr)
 
 	mmap_read_lock(kvm->mm);
 	get_user_pages_remote(kvm->mm, uaddr, 1, FOLL_WRITE,
-			      &page, NULL, NULL);
+			      &page, NULL);
 	mmap_read_unlock(kvm->mm);
 	return page;
 }
diff --git a/fs/exec.c b/fs/exec.c
index 87cf3a2f0e9a..d8d48ee15aac 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -219,7 +219,7 @@ static struct page *get_arg_page(struct linux_binprm *bprm, unsigned long pos,
 	 */
 	mmap_read_lock(bprm->mm);
 	ret = get_user_pages_remote(bprm->mm, pos, 1, gup_flags,
-			&page, NULL, NULL);
+			&page, NULL);
 	mmap_read_unlock(bprm->mm);
 	if (ret <= 0)
 		return NULL;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 513d5fab02f1..8dfa236cfb58 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2374,7 +2374,7 @@ extern int __access_remote_vm(struct mm_struct *mm, unsigned long addr,
 long get_user_pages_remote(struct mm_struct *mm,
 			    unsigned long start, unsigned long nr_pages,
 			    unsigned int gup_flags, struct page **pages,
-			    struct vm_area_struct **vmas, int *locked);
+			    int *locked);
 long pin_user_pages_remote(struct mm_struct *mm,
 			   unsigned long start, unsigned long nr_pages,
 			   unsigned int gup_flags, struct page **pages,
diff --git a/kernel/events/uprobes.c b/kernel/events/uprobes.c
index 59887c69d54c..35e8a7ec884c 100644
--- a/kernel/events/uprobes.c
+++ b/kernel/events/uprobes.c
@@ -365,7 +365,6 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
 {
 	void *kaddr;
 	struct page *page;
-	struct vm_area_struct *vma;
 	int ret;
 	short *ptr;
 
@@ -373,7 +372,7 @@ __update_ref_ctr(struct mm_struct *mm, unsigned long vaddr, short d)
 		return -EINVAL;
 
 	ret = get_user_pages_remote(mm, vaddr, 1,
-			FOLL_WRITE, &page, &vma, NULL);
+				    FOLL_WRITE, &page, NULL);
 	if (unlikely(ret <= 0)) {
 		/*
 		 * We are asking for 1 page. If get_user_pages_remote() fails,
@@ -475,8 +474,9 @@ int uprobe_write_opcode(struct arch_uprobe *auprobe, struct mm_struct *mm,
 		gup_flags |= FOLL_SPLIT_PMD;
 	/* Read the page with vaddr into memory */
 	ret = get_user_pages_remote(mm, vaddr, 1, gup_flags,
-				    &old_page, &vma, NULL);
-	if (ret <= 0)
+				    &old_page, NULL);
+	vma = vma_lookup(mm, vaddr);
+	if (ret <= 0 || !vma)
 		return ret;
 
 	ret = verify_opcode(old_page, vaddr, &opcode);
@@ -2028,7 +2028,7 @@ static int is_trap_at_addr(struct mm_struct *mm, unsigned long vaddr)
 	 * essentially a kernel access to the memory.
 	 */
 	result = get_user_pages_remote(mm, vaddr, 1, FOLL_FORCE, &page,
-			NULL, NULL);
+				       NULL);
 	if (result < 0)
 		return result;
 
diff --git a/mm/gup.c b/mm/gup.c
index 931c805bc32b..9440aa54c741 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -2165,8 +2165,6 @@ static bool is_valid_gup_args(struct page **pages, struct vm_area_struct **vmas,
  * @pages:	array that receives pointers to the pages pinned.
  *		Should be at least nr_pages long. Or NULL, if caller
  *		only intends to ensure the pages are faulted in.
- * @vmas:	array of pointers to vmas corresponding to each page.
- *		Or NULL if the caller does not require them.
  * @locked:	pointer to lock flag indicating whether lock is held and
  *		subsequently whether VM_FAULT_RETRY functionality can be
  *		utilised. Lock must initially be held.
@@ -2181,8 +2179,6 @@ static bool is_valid_gup_args(struct page **pages, struct vm_area_struct **vmas,
  *
  * The caller is responsible for releasing returned @pages, via put_page().
  *
- * @vmas are valid only as long as mmap_lock is held.
- *
  * Must be called with mmap_lock held for read or write.
  *
  * get_user_pages_remote walks a process's page tables and takes a reference
@@ -2219,15 +2215,15 @@ static bool is_valid_gup_args(struct page **pages, struct vm_area_struct **vmas,
 long get_user_pages_remote(struct mm_struct *mm,
 		unsigned long start, unsigned long nr_pages,
 		unsigned int gup_flags, struct page **pages,
-		struct vm_area_struct **vmas, int *locked)
+		int *locked)
 {
 	int local_locked = 1;
 
-	if (!is_valid_gup_args(pages, vmas, locked, &gup_flags,
+	if (!is_valid_gup_args(pages, NULL, locked, &gup_flags,
 			       FOLL_TOUCH | FOLL_REMOTE))
 		return -EINVAL;
 
-	return __get_user_pages_locked(mm, start, nr_pages, pages, vmas,
+	return __get_user_pages_locked(mm, start, nr_pages, pages, NULL,
 				       locked ? locked : &local_locked,
 				       gup_flags);
 }
@@ -2237,7 +2233,7 @@ EXPORT_SYMBOL(get_user_pages_remote);
 long get_user_pages_remote(struct mm_struct *mm,
 			   unsigned long start, unsigned long nr_pages,
 			   unsigned int gup_flags, struct page **pages,
-			   struct vm_area_struct **vmas, int *locked)
+			   int *locked)
 {
 	return 0;
 }
diff --git a/mm/memory.c b/mm/memory.c
index ea8fdca35df3..43426147f9f7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -5596,7 +5596,11 @@ int __access_remote_vm(struct mm_struct *mm, unsigned long addr, void *buf,
 		struct page *page = NULL;
 
 		ret = get_user_pages_remote(mm, addr, 1,
-				gup_flags, &page, &vma, NULL);
+				gup_flags, &page, NULL);
+		vma = vma_lookup(mm, addr);
+		if (!vma)
+			break;
+
 		if (ret <= 0) {
 #ifndef CONFIG_HAVE_IOREMAP_PROT
 			break;
@@ -5605,9 +5609,6 @@ int __access_remote_vm(struct mm_struct *mm, unsigned long addr, void *buf,
 			 * Check if this is a VM_IO | VM_PFNMAP VMA, which
 			 * we can access using slightly different code.
 			 */
-			vma = vma_lookup(mm, addr);
-			if (!vma)
-				break;
 			if (vma->vm_ops && vma->vm_ops->access)
 				ret = vma->vm_ops->access(vma, addr, buf,
 							  len, write);
diff --git a/mm/rmap.c b/mm/rmap.c
index ba901c416785..756ea8a9bb90 100644
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -2324,7 +2324,7 @@ int make_device_exclusive_range(struct mm_struct *mm, unsigned long start,
 
 	npages = get_user_pages_remote(mm, start, npages,
 				       FOLL_GET | FOLL_WRITE | FOLL_SPLIT_PMD,
-				       pages, NULL, NULL);
+				       pages, NULL);
 	if (npages < 0)
 		return npages;
 
diff --git a/security/tomoyo/domain.c b/security/tomoyo/domain.c
index 31af29f669d2..ac20c0bdff9d 100644
--- a/security/tomoyo/domain.c
+++ b/security/tomoyo/domain.c
@@ -916,7 +916,7 @@ bool tomoyo_dump_page(struct linux_binprm *bprm, unsigned long pos,
 	 */
 	mmap_read_lock(bprm->mm);
 	ret = get_user_pages_remote(bprm->mm, pos, 1,
-				    FOLL_FORCE, &page, NULL, NULL);
+				    FOLL_FORCE, &page, NULL);
 	mmap_read_unlock(bprm->mm);
 	if (ret <= 0)
 		return false;
diff --git a/virt/kvm/async_pf.c b/virt/kvm/async_pf.c
index 9bfe1d6f6529..e033c79d528e 100644
--- a/virt/kvm/async_pf.c
+++ b/virt/kvm/async_pf.c
@@ -61,8 +61,7 @@ static void async_pf_execute(struct work_struct *work)
 	 * access remotely.
 	 */
 	mmap_read_lock(mm);
-	get_user_pages_remote(mm, addr, 1, FOLL_WRITE, NULL, NULL,
-			&locked);
+	get_user_pages_remote(mm, addr, 1, FOLL_WRITE, NULL, &locked);
 	if (locked)
 		mmap_read_unlock(mm);
 
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* [PATCH 6/7] mm/gup: remove vmas parameter from pin_user_pages()
       [not found] <cover.1681508038.git.lstoakes@gmail.com>
                   ` (2 preceding siblings ...)
  2023-04-14 23:27 ` [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote() Lorenzo Stoakes
@ 2023-04-14 23:27 ` Lorenzo Stoakes
  3 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-14 23:27 UTC (permalink / raw)
  To: linux-mm, linux-kernel, Andrew Morton
  Cc: Matthew Wilcox, David Hildenbrand, Michael Ellerman,
	Nicholas Piggin, Christophe Leroy, Dennis Dalessandro,
	Jason Gunthorpe, Leon Romanovsky, Christian Benvenuti,
	Nelson Escobar, Bernard Metzler, Mauro Carvalho Chehab,
	Michael S . Tsirkin, Jason Wang, Jens Axboe, Pavel Begunkov,
	Bjorn Topel, Magnus Karlsson, Maciej Fijalkowski, Jonathan Lemon,
	David S . Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
	Alexei Starovoitov, Daniel Borkmann, Jesper Dangaard Brouer,
	John Fastabend, linuxppc-dev, linux-rdma, linux-media,
	virtualization, kvm, netdev, io-uring, bpf, Lorenzo Stoakes

After the introduction of FOLL_SAME_FILE we no longer require vmas for any
invocation of pin_user_pages(), so eliminate this parameter from the
function and all callers.

This clears the way to removing the vmas parameter from GUP altogether.

Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
---
 arch/powerpc/mm/book3s64/iommu_api.c       | 2 +-
 drivers/infiniband/hw/qib/qib_user_pages.c | 2 +-
 drivers/infiniband/hw/usnic/usnic_uiom.c   | 2 +-
 drivers/infiniband/sw/siw/siw_mem.c        | 2 +-
 drivers/media/v4l2-core/videobuf-dma-sg.c  | 2 +-
 drivers/vdpa/vdpa_user/vduse_dev.c         | 2 +-
 drivers/vhost/vdpa.c                       | 2 +-
 include/linux/mm.h                         | 3 +--
 io_uring/rsrc.c                            | 2 +-
 mm/gup.c                                   | 9 +++------
 mm/gup_test.c                              | 9 ++++-----
 net/xdp/xdp_umem.c                         | 2 +-
 12 files changed, 17 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/mm/book3s64/iommu_api.c b/arch/powerpc/mm/book3s64/iommu_api.c
index 81d7185e2ae8..d19fb1f3007d 100644
--- a/arch/powerpc/mm/book3s64/iommu_api.c
+++ b/arch/powerpc/mm/book3s64/iommu_api.c
@@ -105,7 +105,7 @@ static long mm_iommu_do_alloc(struct mm_struct *mm, unsigned long ua,
 
 		ret = pin_user_pages(ua + (entry << PAGE_SHIFT), n,
 				FOLL_WRITE | FOLL_LONGTERM,
-				mem->hpages + entry, NULL);
+				mem->hpages + entry);
 		if (ret == n) {
 			pinned += n;
 			continue;
diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c
index f693bc753b6b..1bb7507325bc 100644
--- a/drivers/infiniband/hw/qib/qib_user_pages.c
+++ b/drivers/infiniband/hw/qib/qib_user_pages.c
@@ -111,7 +111,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages,
 		ret = pin_user_pages(start_page + got * PAGE_SIZE,
 				     num_pages - got,
 				     FOLL_LONGTERM | FOLL_WRITE,
-				     p + got, NULL);
+				     p + got);
 		if (ret < 0) {
 			mmap_read_unlock(current->mm);
 			goto bail_release;
diff --git a/drivers/infiniband/hw/usnic/usnic_uiom.c b/drivers/infiniband/hw/usnic/usnic_uiom.c
index 2a5cac2658ec..84e0f41e7dfa 100644
--- a/drivers/infiniband/hw/usnic/usnic_uiom.c
+++ b/drivers/infiniband/hw/usnic/usnic_uiom.c
@@ -140,7 +140,7 @@ static int usnic_uiom_get_pages(unsigned long addr, size_t size, int writable,
 		ret = pin_user_pages(cur_base,
 				     min_t(unsigned long, npages,
 				     PAGE_SIZE / sizeof(struct page *)),
-				     gup_flags, page_list, NULL);
+				     gup_flags, page_list);
 
 		if (ret < 0)
 			goto out;
diff --git a/drivers/infiniband/sw/siw/siw_mem.c b/drivers/infiniband/sw/siw/siw_mem.c
index f51ab2ccf151..e6e25f15567d 100644
--- a/drivers/infiniband/sw/siw/siw_mem.c
+++ b/drivers/infiniband/sw/siw/siw_mem.c
@@ -422,7 +422,7 @@ struct siw_umem *siw_umem_get(u64 start, u64 len, bool writable)
 		umem->page_chunk[i].plist = plist;
 		while (nents) {
 			rv = pin_user_pages(first_page_va, nents, foll_flags,
-					    plist, NULL);
+					    plist);
 			if (rv < 0)
 				goto out_sem_up;
 
diff --git a/drivers/media/v4l2-core/videobuf-dma-sg.c b/drivers/media/v4l2-core/videobuf-dma-sg.c
index 53001532e8e3..405b89ea1054 100644
--- a/drivers/media/v4l2-core/videobuf-dma-sg.c
+++ b/drivers/media/v4l2-core/videobuf-dma-sg.c
@@ -180,7 +180,7 @@ static int videobuf_dma_init_user_locked(struct videobuf_dmabuf *dma,
 		data, size, dma->nr_pages);
 
 	err = pin_user_pages(data & PAGE_MASK, dma->nr_pages, gup_flags,
-			     dma->pages, NULL);
+			     dma->pages);
 
 	if (err != dma->nr_pages) {
 		dma->nr_pages = (err >= 0) ? err : 0;
diff --git a/drivers/vdpa/vdpa_user/vduse_dev.c b/drivers/vdpa/vdpa_user/vduse_dev.c
index 0c3b48616a9f..1f80254604f0 100644
--- a/drivers/vdpa/vdpa_user/vduse_dev.c
+++ b/drivers/vdpa/vdpa_user/vduse_dev.c
@@ -995,7 +995,7 @@ static int vduse_dev_reg_umem(struct vduse_dev *dev,
 		goto out;
 
 	pinned = pin_user_pages(uaddr, npages, FOLL_LONGTERM | FOLL_WRITE,
-				page_list, NULL);
+				page_list);
 	if (pinned != npages) {
 		ret = pinned < 0 ? pinned : -ENOMEM;
 		goto out;
diff --git a/drivers/vhost/vdpa.c b/drivers/vhost/vdpa.c
index 7be9d9d8f01c..4317128c1c62 100644
--- a/drivers/vhost/vdpa.c
+++ b/drivers/vhost/vdpa.c
@@ -952,7 +952,7 @@ static int vhost_vdpa_pa_map(struct vhost_vdpa *v,
 	while (npages) {
 		sz2pin = min_t(unsigned long, npages, list_size);
 		pinned = pin_user_pages(cur_base, sz2pin,
-					gup_flags, page_list, NULL);
+					gup_flags, page_list);
 		if (sz2pin != pinned) {
 			if (pinned < 0) {
 				ret = pinned;
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 8dfa236cfb58..3f7d36ad7de7 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2382,8 +2382,7 @@ long pin_user_pages_remote(struct mm_struct *mm,
 long get_user_pages(unsigned long start, unsigned long nr_pages,
 		    unsigned int gup_flags, struct page **pages);
 long pin_user_pages(unsigned long start, unsigned long nr_pages,
-		    unsigned int gup_flags, struct page **pages,
-		    struct vm_area_struct **vmas);
+		    unsigned int gup_flags, struct page **pages);
 long get_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
 		    struct page **pages, unsigned int gup_flags);
 long pin_user_pages_unlocked(unsigned long start, unsigned long nr_pages,
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index adc860bcbd4f..92d0d47e322c 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -1157,7 +1157,7 @@ struct page **io_pin_pages(unsigned long ubuf, unsigned long len, int *npages)
 
 	pret = pin_user_pages(ubuf, nr_pages,
 			      FOLL_WRITE | FOLL_LONGTERM | FOLL_SAME_FILE,
-			      pages, NULL);
+			      pages);
 	if (pret == nr_pages) {
 		/*
 		 * lookup the first VMA, we require that all VMAs in range
diff --git a/mm/gup.c b/mm/gup.c
index 3954ce499a4a..714970ef3b30 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -3132,8 +3132,6 @@ EXPORT_SYMBOL(pin_user_pages_remote);
  * @gup_flags:	flags modifying lookup behaviour
  * @pages:	array that receives pointers to the pages pinned.
  *		Should be at least nr_pages long.
- * @vmas:	array of pointers to vmas corresponding to each page.
- *		Or NULL if the caller does not require them.
  *
  * Nearly the same as get_user_pages(), except that FOLL_TOUCH is not set, and
  * FOLL_PIN is set.
@@ -3142,15 +3140,14 @@ EXPORT_SYMBOL(pin_user_pages_remote);
  * see Documentation/core-api/pin_user_pages.rst for details.
  */
 long pin_user_pages(unsigned long start, unsigned long nr_pages,
-		    unsigned int gup_flags, struct page **pages,
-		    struct vm_area_struct **vmas)
+		    unsigned int gup_flags, struct page **pages)
 {
 	int locked = 1;
 
-	if (!is_valid_gup_args(pages, vmas, NULL, &gup_flags, FOLL_PIN))
+	if (!is_valid_gup_args(pages, NULL, NULL, &gup_flags, FOLL_PIN))
 		return 0;
 	return __gup_longterm_locked(current->mm, start, nr_pages,
-				     pages, vmas, &locked, gup_flags);
+				     pages, NULL, &locked, gup_flags);
 }
 EXPORT_SYMBOL(pin_user_pages);
 
diff --git a/mm/gup_test.c b/mm/gup_test.c
index 9ba8ea23f84e..1668ce0e0783 100644
--- a/mm/gup_test.c
+++ b/mm/gup_test.c
@@ -146,18 +146,17 @@ static int __gup_test_ioctl(unsigned int cmd,
 						 pages + i);
 			break;
 		case PIN_BASIC_TEST:
-			nr = pin_user_pages(addr, nr, gup->gup_flags, pages + i,
-					    NULL);
+			nr = pin_user_pages(addr, nr, gup->gup_flags, pages + i);
 			break;
 		case PIN_LONGTERM_BENCHMARK:
 			nr = pin_user_pages(addr, nr,
 					    gup->gup_flags | FOLL_LONGTERM,
-					    pages + i, NULL);
+					    pages + i);
 			break;
 		case DUMP_USER_PAGES_TEST:
 			if (gup->test_flags & GUP_TEST_FLAG_DUMP_PAGES_USE_PIN)
 				nr = pin_user_pages(addr, nr, gup->gup_flags,
-						    pages + i, NULL);
+						    pages + i);
 			else
 				nr = get_user_pages(addr, nr, gup->gup_flags,
 						    pages + i);
@@ -270,7 +269,7 @@ static inline int pin_longterm_test_start(unsigned long arg)
 							gup_flags, pages);
 		else
 			cur_pages = pin_user_pages(addr, remaining_pages,
-						   gup_flags, pages, NULL);
+						   gup_flags, pages);
 		if (cur_pages < 0) {
 			pin_longterm_test_stop();
 			ret = cur_pages;
diff --git a/net/xdp/xdp_umem.c b/net/xdp/xdp_umem.c
index 02207e852d79..06cead2b8e34 100644
--- a/net/xdp/xdp_umem.c
+++ b/net/xdp/xdp_umem.c
@@ -103,7 +103,7 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem, unsigned long address)
 
 	mmap_read_lock(current->mm);
 	npgs = pin_user_pages(address, umem->npgs,
-			      gup_flags | FOLL_LONGTERM, &umem->pgs[0], NULL);
+			      gup_flags | FOLL_LONGTERM, &umem->pgs[0]);
 	mmap_read_unlock(current->mm);
 
 	if (npgs != umem->npgs) {
-- 
2.40.0


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-14 23:27 ` [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote() Lorenzo Stoakes
@ 2023-04-15  0:25   ` Tetsuo Handa
  2023-04-17 13:09   ` Jason Gunthorpe
  1 sibling, 0 replies; 14+ messages in thread
From: Tetsuo Handa @ 2023-04-15  0:25 UTC (permalink / raw)
  To: Lorenzo Stoakes, Andrew Morton; +Cc: linux-mm, linux-kernel

On 2023/04/15 8:27, Lorenzo Stoakes wrote:
> diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> index f5bcb0dc6267..74d8d4007dec 100644
> --- a/arch/arm64/kernel/mte.c
> +++ b/arch/arm64/kernel/mte.c
> @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
>  		struct page *page = NULL;
>  
>  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
> -					    &vma, NULL);
> -		if (ret <= 0)
> +					    NULL);
> +		vma = vma_lookup(mm, addr);
> +		if (ret <= 0 || !vma)
>  			break;

This conversion looks wrong. When get_user_pages_remote(&page) returned > 0,
put_page(page) is needed even if vma_lookup() returned NULL, isn't it?


^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages()
  2023-04-14 23:27 ` [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages() Lorenzo Stoakes
@ 2023-04-15  5:27   ` Greg Kroah-Hartman
  2023-04-17 13:01   ` Jason Gunthorpe
  1 sibling, 0 replies; 14+ messages in thread
From: Greg Kroah-Hartman @ 2023-04-15  5:27 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, Andrew Morton, Matthew Wilcox,
	David Hildenbrand, x86, linux-sgx, amd-gfx, dri-devel, kvm,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Jarkko Sakkinen,
	H . Peter Anvin, Xinhui Pan, David Airlie, Daniel Vetter,
	Dimitri Sivanich, Arnd Bergmann, Paolo Bonzini

On Sat, Apr 15, 2023 at 12:27:13AM +0100, Lorenzo Stoakes wrote:
> No invocation of get_user_pages() uses the vmas parameter, so remove
> it.
> 
> The GUP API is confusing and caveated. Recent changes have done much to
> improve that, however there is more we can do. Exporting vmas is a prime
> target as the caller has to be extremely careful to preclude their use
> after the mmap_lock has expired or otherwise be left with dangling
> pointers.
> 
> Removing the vmas parameter focuses the GUP functions upon their primary
> purpose - pinning (and outputting) pages as well as performing the actions
> implied by the input flags.
> 
> This is part of a patch series aiming to remove the vmas parameter
> altogether.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> Suggested-by: Matthew Wilcox (Oracle) <willy@infradead.org>

Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages()
  2023-04-14 23:27 ` [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages() Lorenzo Stoakes
  2023-04-15  5:27   ` Greg Kroah-Hartman
@ 2023-04-17 13:01   ` Jason Gunthorpe
  1 sibling, 0 replies; 14+ messages in thread
From: Jason Gunthorpe @ 2023-04-17 13:01 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, Andrew Morton, Matthew Wilcox,
	David Hildenbrand, x86, linux-sgx, amd-gfx, dri-devel, kvm,
	Thomas Gleixner, Ingo Molnar, Borislav Petkov, Jarkko Sakkinen,
	H . Peter Anvin, Xinhui Pan, David Airlie, Daniel Vetter,
	Dimitri Sivanich, Arnd Bergmann, Greg Kroah-Hartman,
	Paolo Bonzini

On Sat, Apr 15, 2023 at 12:27:13AM +0100, Lorenzo Stoakes wrote:
> No invocation of get_user_pages() uses the vmas parameter, so remove
> it.
> 
> The GUP API is confusing and caveated. Recent changes have done much to
> improve that, however there is more we can do. Exporting vmas is a prime
> target as the caller has to be extremely careful to preclude their use
> after the mmap_lock has expired or otherwise be left with dangling
> pointers.
> 
> Removing the vmas parameter focuses the GUP functions upon their primary
> purpose - pinning (and outputting) pages as well as performing the actions
> implied by the input flags.
> 
> This is part of a patch series aiming to remove the vmas parameter
> altogether.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> Suggested-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> ---
>  arch/x86/kernel/cpu/sgx/ioctl.c     | 2 +-
>  drivers/gpu/drm/radeon/radeon_ttm.c | 2 +-
>  drivers/misc/sgi-gru/grufault.c     | 2 +-
>  include/linux/mm.h                  | 3 +--
>  mm/gup.c                            | 9 +++------
>  mm/gup_test.c                       | 5 ++---
>  virt/kvm/kvm_main.c                 | 4 ++--
>  7 files changed, 11 insertions(+), 16 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>

Jason

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 2/7] mm/gup: remove unused vmas parameter from pin_user_pages_remote()
  2023-04-14 23:27 ` [PATCH 2/7] mm/gup: remove unused vmas parameter from pin_user_pages_remote() Lorenzo Stoakes
@ 2023-04-17 13:02   ` Jason Gunthorpe
  0 siblings, 0 replies; 14+ messages in thread
From: Jason Gunthorpe @ 2023-04-17 13:02 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, Andrew Morton, iommu, Matthew Wilcox,
	David Hildenbrand, kvm, Kevin Tian, Joerg Roedel, Will Deacon,
	Robin Murphy, Alex Williamson

On Sat, Apr 15, 2023 at 12:27:23AM +0100, Lorenzo Stoakes wrote:
> No invocation of pin_user_pages_remote() uses the vmas parameter, so remove
> it. This forms part of a larger patch set eliminating the use of the vmas
> parameters altogether.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> ---
>  drivers/iommu/iommufd/pages.c   | 4 ++--
>  drivers/vfio/vfio_iommu_type1.c | 2 +-
>  include/linux/mm.h              | 2 +-
>  mm/gup.c                        | 8 +++-----
>  mm/process_vm_access.c          | 2 +-
>  5 files changed, 8 insertions(+), 10 deletions(-)

Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>

Jason

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-14 23:27 ` [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote() Lorenzo Stoakes
  2023-04-15  0:25   ` Tetsuo Handa
@ 2023-04-17 13:09   ` Jason Gunthorpe
  2023-04-17 13:13     ` Lorenzo Stoakes
  1 sibling, 1 reply; 14+ messages in thread
From: Jason Gunthorpe @ 2023-04-17 13:09 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, Andrew Morton, Matthew Wilcox,
	David Hildenbrand, linux-arm-kernel, kvm, linux-s390,
	linux-fsdevel, linux-perf-users, linux-security-module,
	Catalin Marinas, Will Deacon, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Sven Schnelle, Eric Biederman, Kees Cook,
	Alexander Viro, Christian Brauner, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Ian Rogers, Adrian Hunter,
	Kentaro Takeda, Tetsuo Handa, Paul Moore, James Morris,
	Serge E . Hallyn, Paolo Bonzini

On Sat, Apr 15, 2023 at 12:27:31AM +0100, Lorenzo Stoakes wrote:
> The only instances of get_user_pages_remote() invocations which used the
> vmas parameter were for a single page which can instead simply look up the
> VMA directly. In particular:-
> 
> - __update_ref_ctr() looked up the VMA but did nothing with it so we simply
>   remove it.
> 
> - __access_remote_vm() was already using vma_lookup() when the original
>   lookup failed so by doing the lookup directly this also de-duplicates the
>   code.
> 
> This forms part of a broader set of patches intended to eliminate the vmas
> parameter altogether.
> 
> Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> ---
>  arch/arm64/kernel/mte.c   |  5 +++--
>  arch/s390/kvm/interrupt.c |  2 +-
>  fs/exec.c                 |  2 +-
>  include/linux/mm.h        |  2 +-
>  kernel/events/uprobes.c   | 10 +++++-----
>  mm/gup.c                  | 12 ++++--------
>  mm/memory.c               |  9 +++++----
>  mm/rmap.c                 |  2 +-
>  security/tomoyo/domain.c  |  2 +-
>  virt/kvm/async_pf.c       |  3 +--
>  10 files changed, 23 insertions(+), 26 deletions(-)
> 
> diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> index f5bcb0dc6267..74d8d4007dec 100644
> --- a/arch/arm64/kernel/mte.c
> +++ b/arch/arm64/kernel/mte.c
> @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
>  		struct page *page = NULL;
>  
>  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
> -					    &vma, NULL);
> -		if (ret <= 0)
> +					    NULL);
> +		vma = vma_lookup(mm, addr);
> +		if (ret <= 0 || !vma)
>  			break;

Given the slightly tricky error handling, it would make sense to turn
this pattern into a helper function:

page = get_single_user_page_locked(mm, addr, gup_flags, &vma);
if (IS_ERR(page))
  [..]

static inline struct page *get_single_user_page_locked(struct mm_struct *mm,
   unsigned long addr, int gup_flags, struct vm_area_struct **vma)
{
	struct page *page;
	int ret;

	ret = get_user_pages_remote(*mm, addr, 1, gup_flags, &page, NULL, NULL);
	if (ret < 0)
	   return ERR_PTR(ret);
	if (WARN_ON(ret == 0))
	   return ERR_PTR(-EINVAL);
        *vma = vma_lookup(mm, addr);
	if (WARN_ON(!*vma) {
	   put_user_page(page);
	   return ERR_PTR(-EINVAL);
        }
	return page;
}

It could be its own patch so this change was just a mechanical removal
of NULL

Jason

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-17 13:09   ` Jason Gunthorpe
@ 2023-04-17 13:13     ` Lorenzo Stoakes
  2023-04-17 13:16       ` Jason Gunthorpe
  0 siblings, 1 reply; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-17 13:13 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: linux-mm, linux-kernel, Andrew Morton, Matthew Wilcox,
	David Hildenbrand, linux-arm-kernel, kvm, linux-s390,
	linux-fsdevel, linux-perf-users, linux-security-module,
	Catalin Marinas, Will Deacon, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Sven Schnelle, Eric Biederman, Kees Cook,
	Alexander Viro, Christian Brauner, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Ian Rogers, Adrian Hunter,
	Kentaro Takeda, Tetsuo Handa, Paul Moore, James Morris,
	Serge E . Hallyn, Paolo Bonzini

On Mon, Apr 17, 2023 at 10:09:36AM -0300, Jason Gunthorpe wrote:
> On Sat, Apr 15, 2023 at 12:27:31AM +0100, Lorenzo Stoakes wrote:
> > The only instances of get_user_pages_remote() invocations which used the
> > vmas parameter were for a single page which can instead simply look up the
> > VMA directly. In particular:-
> >
> > - __update_ref_ctr() looked up the VMA but did nothing with it so we simply
> >   remove it.
> >
> > - __access_remote_vm() was already using vma_lookup() when the original
> >   lookup failed so by doing the lookup directly this also de-duplicates the
> >   code.
> >
> > This forms part of a broader set of patches intended to eliminate the vmas
> > parameter altogether.
> >
> > Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> > ---
> >  arch/arm64/kernel/mte.c   |  5 +++--
> >  arch/s390/kvm/interrupt.c |  2 +-
> >  fs/exec.c                 |  2 +-
> >  include/linux/mm.h        |  2 +-
> >  kernel/events/uprobes.c   | 10 +++++-----
> >  mm/gup.c                  | 12 ++++--------
> >  mm/memory.c               |  9 +++++----
> >  mm/rmap.c                 |  2 +-
> >  security/tomoyo/domain.c  |  2 +-
> >  virt/kvm/async_pf.c       |  3 +--
> >  10 files changed, 23 insertions(+), 26 deletions(-)
> >
> > diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> > index f5bcb0dc6267..74d8d4007dec 100644
> > --- a/arch/arm64/kernel/mte.c
> > +++ b/arch/arm64/kernel/mte.c
> > @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
> >  		struct page *page = NULL;
> >
> >  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
> > -					    &vma, NULL);
> > -		if (ret <= 0)
> > +					    NULL);
> > +		vma = vma_lookup(mm, addr);
> > +		if (ret <= 0 || !vma)
> >  			break;
>
> Given the slightly tricky error handling, it would make sense to turn
> this pattern into a helper function:
>
> page = get_single_user_page_locked(mm, addr, gup_flags, &vma);
> if (IS_ERR(page))
>   [..]
>
> static inline struct page *get_single_user_page_locked(struct mm_struct *mm,
>    unsigned long addr, int gup_flags, struct vm_area_struct **vma)
> {
> 	struct page *page;
> 	int ret;
>
> 	ret = get_user_pages_remote(*mm, addr, 1, gup_flags, &page, NULL, NULL);
> 	if (ret < 0)
> 	   return ERR_PTR(ret);
> 	if (WARN_ON(ret == 0))
> 	   return ERR_PTR(-EINVAL);
>         *vma = vma_lookup(mm, addr);
> 	if (WARN_ON(!*vma) {
> 	   put_user_page(page);
> 	   return ERR_PTR(-EINVAL);
>         }
> 	return page;
> }
>
> It could be its own patch so this change was just a mechanical removal
> of NULL
>
> Jason
>

Agreed, I think this would work better as a follow up patch however so as
not to distract too much from the core change. I feel like there are quite
a few things we can follow up on including assessing whether we might be
able to use _fast() paths in places (I haven't assessed this yet).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-17 13:13     ` Lorenzo Stoakes
@ 2023-04-17 13:16       ` Jason Gunthorpe
  2023-04-17 13:23         ` Lorenzo Stoakes
  0 siblings, 1 reply; 14+ messages in thread
From: Jason Gunthorpe @ 2023-04-17 13:16 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: linux-mm, linux-kernel, Andrew Morton, Matthew Wilcox,
	David Hildenbrand, linux-arm-kernel, kvm, linux-s390,
	linux-fsdevel, linux-perf-users, linux-security-module,
	Catalin Marinas, Will Deacon, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Sven Schnelle, Eric Biederman, Kees Cook,
	Alexander Viro, Christian Brauner, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Ian Rogers, Adrian Hunter,
	Kentaro Takeda, Tetsuo Handa, Paul Moore, James Morris,
	Serge E . Hallyn, Paolo Bonzini

On Mon, Apr 17, 2023 at 02:13:39PM +0100, Lorenzo Stoakes wrote:
> On Mon, Apr 17, 2023 at 10:09:36AM -0300, Jason Gunthorpe wrote:
> > On Sat, Apr 15, 2023 at 12:27:31AM +0100, Lorenzo Stoakes wrote:
> > > The only instances of get_user_pages_remote() invocations which used the
> > > vmas parameter were for a single page which can instead simply look up the
> > > VMA directly. In particular:-
> > >
> > > - __update_ref_ctr() looked up the VMA but did nothing with it so we simply
> > >   remove it.
> > >
> > > - __access_remote_vm() was already using vma_lookup() when the original
> > >   lookup failed so by doing the lookup directly this also de-duplicates the
> > >   code.
> > >
> > > This forms part of a broader set of patches intended to eliminate the vmas
> > > parameter altogether.
> > >
> > > Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> > > ---
> > >  arch/arm64/kernel/mte.c   |  5 +++--
> > >  arch/s390/kvm/interrupt.c |  2 +-
> > >  fs/exec.c                 |  2 +-
> > >  include/linux/mm.h        |  2 +-
> > >  kernel/events/uprobes.c   | 10 +++++-----
> > >  mm/gup.c                  | 12 ++++--------
> > >  mm/memory.c               |  9 +++++----
> > >  mm/rmap.c                 |  2 +-
> > >  security/tomoyo/domain.c  |  2 +-
> > >  virt/kvm/async_pf.c       |  3 +--
> > >  10 files changed, 23 insertions(+), 26 deletions(-)
> > >
> > > diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> > > index f5bcb0dc6267..74d8d4007dec 100644
> > > --- a/arch/arm64/kernel/mte.c
> > > +++ b/arch/arm64/kernel/mte.c
> > > @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
> > >  		struct page *page = NULL;
> > >
> > >  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
> > > -					    &vma, NULL);
> > > -		if (ret <= 0)
> > > +					    NULL);
> > > +		vma = vma_lookup(mm, addr);
> > > +		if (ret <= 0 || !vma)
> > >  			break;
> >
> > Given the slightly tricky error handling, it would make sense to turn
> > this pattern into a helper function:
> >
> > page = get_single_user_page_locked(mm, addr, gup_flags, &vma);
> > if (IS_ERR(page))
> >   [..]
> >
> > static inline struct page *get_single_user_page_locked(struct mm_struct *mm,
> >    unsigned long addr, int gup_flags, struct vm_area_struct **vma)
> > {
> > 	struct page *page;
> > 	int ret;
> >
> > 	ret = get_user_pages_remote(*mm, addr, 1, gup_flags, &page, NULL, NULL);
> > 	if (ret < 0)
> > 	   return ERR_PTR(ret);
> > 	if (WARN_ON(ret == 0))
> > 	   return ERR_PTR(-EINVAL);
> >         *vma = vma_lookup(mm, addr);
> > 	if (WARN_ON(!*vma) {
> > 	   put_user_page(page);
> > 	   return ERR_PTR(-EINVAL);
> >         }
> > 	return page;
> > }
> >
> > It could be its own patch so this change was just a mechanical removal
> > of NULL
> >
> > Jason
> >
> 
> Agreed, I think this would work better as a follow up patch however so as
> not to distract too much from the core change. 

I don't think you should open code sketchy error handling in several
places and then clean it up later. Just do it right from the start.

Jason

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-17 13:16       ` Jason Gunthorpe
@ 2023-04-17 13:23         ` Lorenzo Stoakes
  2023-04-17 15:07           ` Eric W. Biederman
  0 siblings, 1 reply; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-17 13:23 UTC (permalink / raw)
  To: Jason Gunthorpe
  Cc: linux-mm, linux-kernel, Andrew Morton, Matthew Wilcox,
	David Hildenbrand, linux-arm-kernel, kvm, linux-s390,
	linux-fsdevel, linux-perf-users, linux-security-module,
	Catalin Marinas, Will Deacon, Christian Borntraeger,
	Janosch Frank, Claudio Imbrenda, Heiko Carstens, Vasily Gorbik,
	Alexander Gordeev, Sven Schnelle, Eric Biederman, Kees Cook,
	Alexander Viro, Christian Brauner, Peter Zijlstra, Ingo Molnar,
	Arnaldo Carvalho de Melo, Mark Rutland, Alexander Shishkin,
	Jiri Olsa, Namhyung Kim, Ian Rogers, Adrian Hunter,
	Kentaro Takeda, Tetsuo Handa, Paul Moore, James Morris,
	Serge E . Hallyn, Paolo Bonzini

On Mon, Apr 17, 2023 at 10:16:28AM -0300, Jason Gunthorpe wrote:
> On Mon, Apr 17, 2023 at 02:13:39PM +0100, Lorenzo Stoakes wrote:
> > On Mon, Apr 17, 2023 at 10:09:36AM -0300, Jason Gunthorpe wrote:
> > > On Sat, Apr 15, 2023 at 12:27:31AM +0100, Lorenzo Stoakes wrote:
> > > > The only instances of get_user_pages_remote() invocations which used the
> > > > vmas parameter were for a single page which can instead simply look up the
> > > > VMA directly. In particular:-
> > > >
> > > > - __update_ref_ctr() looked up the VMA but did nothing with it so we simply
> > > >   remove it.
> > > >
> > > > - __access_remote_vm() was already using vma_lookup() when the original
> > > >   lookup failed so by doing the lookup directly this also de-duplicates the
> > > >   code.
> > > >
> > > > This forms part of a broader set of patches intended to eliminate the vmas
> > > > parameter altogether.
> > > >
> > > > Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> > > > ---
> > > >  arch/arm64/kernel/mte.c   |  5 +++--
> > > >  arch/s390/kvm/interrupt.c |  2 +-
> > > >  fs/exec.c                 |  2 +-
> > > >  include/linux/mm.h        |  2 +-
> > > >  kernel/events/uprobes.c   | 10 +++++-----
> > > >  mm/gup.c                  | 12 ++++--------
> > > >  mm/memory.c               |  9 +++++----
> > > >  mm/rmap.c                 |  2 +-
> > > >  security/tomoyo/domain.c  |  2 +-
> > > >  virt/kvm/async_pf.c       |  3 +--
> > > >  10 files changed, 23 insertions(+), 26 deletions(-)
> > > >
> > > > diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> > > > index f5bcb0dc6267..74d8d4007dec 100644
> > > > --- a/arch/arm64/kernel/mte.c
> > > > +++ b/arch/arm64/kernel/mte.c
> > > > @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
> > > >  		struct page *page = NULL;
> > > >
> > > >  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
> > > > -					    &vma, NULL);
> > > > -		if (ret <= 0)
> > > > +					    NULL);
> > > > +		vma = vma_lookup(mm, addr);
> > > > +		if (ret <= 0 || !vma)
> > > >  			break;
> > >
> > > Given the slightly tricky error handling, it would make sense to turn
> > > this pattern into a helper function:
> > >
> > > page = get_single_user_page_locked(mm, addr, gup_flags, &vma);
> > > if (IS_ERR(page))
> > >   [..]
> > >
> > > static inline struct page *get_single_user_page_locked(struct mm_struct *mm,
> > >    unsigned long addr, int gup_flags, struct vm_area_struct **vma)
> > > {
> > > 	struct page *page;
> > > 	int ret;
> > >
> > > 	ret = get_user_pages_remote(*mm, addr, 1, gup_flags, &page, NULL, NULL);
> > > 	if (ret < 0)
> > > 	   return ERR_PTR(ret);
> > > 	if (WARN_ON(ret == 0))
> > > 	   return ERR_PTR(-EINVAL);
> > >         *vma = vma_lookup(mm, addr);
> > > 	if (WARN_ON(!*vma) {
> > > 	   put_user_page(page);
> > > 	   return ERR_PTR(-EINVAL);
> > >         }
> > > 	return page;
> > > }
> > >
> > > It could be its own patch so this change was just a mechanical removal
> > > of NULL
> > >
> > > Jason
> > >
> >
> > Agreed, I think this would work better as a follow up patch however so as
> > not to distract too much from the core change.
>
> I don't think you should open code sketchy error handling in several
> places and then clean it up later. Just do it right from the start.
>

Intent was to do smallest change possible (though through review that grew
of course), but I see your point, in this instance this is fiddly stuff and
probably better to abstract it to enforce correct handling.

I'll respin + add something like this.

> Jason

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-17 13:23         ` Lorenzo Stoakes
@ 2023-04-17 15:07           ` Eric W. Biederman
  2023-04-17 15:14             ` Lorenzo Stoakes
  0 siblings, 1 reply; 14+ messages in thread
From: Eric W. Biederman @ 2023-04-17 15:07 UTC (permalink / raw)
  To: Lorenzo Stoakes
  Cc: Jason Gunthorpe, linux-mm, linux-kernel, Andrew Morton,
	Matthew Wilcox, David Hildenbrand, linux-arm-kernel, kvm,
	linux-s390, linux-fsdevel, linux-perf-users,
	linux-security-module, Catalin Marinas, Will Deacon,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Sven Schnelle,
	Kees Cook, Alexander Viro, Christian Brauner, Peter Zijlstra,
	Ingo Molnar, Arnaldo Carvalho de Melo, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Namhyung Kim, Ian Rogers,
	Adrian Hunter, Kentaro Takeda, Tetsuo Handa, Paul Moore,
	James Morris, Serge E . Hallyn, Paolo Bonzini

Lorenzo Stoakes <lstoakes@gmail.com> writes:

> On Mon, Apr 17, 2023 at 10:16:28AM -0300, Jason Gunthorpe wrote:
>> On Mon, Apr 17, 2023 at 02:13:39PM +0100, Lorenzo Stoakes wrote:
>> > On Mon, Apr 17, 2023 at 10:09:36AM -0300, Jason Gunthorpe wrote:
>> > > On Sat, Apr 15, 2023 at 12:27:31AM +0100, Lorenzo Stoakes wrote:
>> > > > The only instances of get_user_pages_remote() invocations which used the
>> > > > vmas parameter were for a single page which can instead simply look up the
>> > > > VMA directly. In particular:-
>> > > >
>> > > > - __update_ref_ctr() looked up the VMA but did nothing with it so we simply
>> > > >   remove it.
>> > > >
>> > > > - __access_remote_vm() was already using vma_lookup() when the original
>> > > >   lookup failed so by doing the lookup directly this also de-duplicates the
>> > > >   code.
>> > > >
>> > > > This forms part of a broader set of patches intended to eliminate the vmas
>> > > > parameter altogether.
>> > > >
>> > > > Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
>> > > > ---
>> > > >  arch/arm64/kernel/mte.c   |  5 +++--
>> > > >  arch/s390/kvm/interrupt.c |  2 +-
>> > > >  fs/exec.c                 |  2 +-
>> > > >  include/linux/mm.h        |  2 +-
>> > > >  kernel/events/uprobes.c   | 10 +++++-----
>> > > >  mm/gup.c                  | 12 ++++--------
>> > > >  mm/memory.c               |  9 +++++----
>> > > >  mm/rmap.c                 |  2 +-
>> > > >  security/tomoyo/domain.c  |  2 +-
>> > > >  virt/kvm/async_pf.c       |  3 +--
>> > > >  10 files changed, 23 insertions(+), 26 deletions(-)
>> > > >
>> > > > diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
>> > > > index f5bcb0dc6267..74d8d4007dec 100644
>> > > > --- a/arch/arm64/kernel/mte.c
>> > > > +++ b/arch/arm64/kernel/mte.c
>> > > > @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
>> > > >  		struct page *page = NULL;
>> > > >
>> > > >  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
>> > > > -					    &vma, NULL);
>> > > > -		if (ret <= 0)
>> > > > +					    NULL);
>> > > > +		vma = vma_lookup(mm, addr);
>> > > > +		if (ret <= 0 || !vma)
>> > > >  			break;
>> > >
>> > > Given the slightly tricky error handling, it would make sense to turn
>> > > this pattern into a helper function:
>> > >
>> > > page = get_single_user_page_locked(mm, addr, gup_flags, &vma);
>> > > if (IS_ERR(page))
>> > >   [..]
>> > >
>> > > static inline struct page *get_single_user_page_locked(struct mm_struct *mm,
>> > >    unsigned long addr, int gup_flags, struct vm_area_struct **vma)
>> > > {
>> > > 	struct page *page;
>> > > 	int ret;
>> > >
>> > > 	ret = get_user_pages_remote(*mm, addr, 1, gup_flags, &page, NULL, NULL);
>> > > 	if (ret < 0)
>> > > 	   return ERR_PTR(ret);
>> > > 	if (WARN_ON(ret == 0))
>> > > 	   return ERR_PTR(-EINVAL);
>> > >         *vma = vma_lookup(mm, addr);
>> > > 	if (WARN_ON(!*vma) {
>> > > 	   put_user_page(page);
>> > > 	   return ERR_PTR(-EINVAL);
>> > >         }
>> > > 	return page;
>> > > }
>> > >
>> > > It could be its own patch so this change was just a mechanical removal
>> > > of NULL
>> > >
>> > > Jason
>> > >
>> >
>> > Agreed, I think this would work better as a follow up patch however so as
>> > not to distract too much from the core change.
>>
>> I don't think you should open code sketchy error handling in several
>> places and then clean it up later. Just do it right from the start.
>>
>
> Intent was to do smallest change possible (though through review that grew
> of course), but I see your point, in this instance this is fiddly stuff and
> probably better to abstract it to enforce correct handling.
>
> I'll respin + add something like this.

Could you include in your description why looking up the vma after
getting the page does not introduce a race?

I am probably silly and just looking at this quickly but it does not
seem immediately obvious why the vma and the page should match.

I would not be surprised if you hold the appropriate mutex over the
entire operation but it just isn't apparent from the diff.

I am concerned because it is an easy mistake to refactor something into
two steps and then discover you have introduced a race.

Eric

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote()
  2023-04-17 15:07           ` Eric W. Biederman
@ 2023-04-17 15:14             ` Lorenzo Stoakes
  0 siblings, 0 replies; 14+ messages in thread
From: Lorenzo Stoakes @ 2023-04-17 15:14 UTC (permalink / raw)
  To: Eric W. Biederman
  Cc: Jason Gunthorpe, linux-mm, linux-kernel, Andrew Morton,
	Matthew Wilcox, David Hildenbrand, linux-arm-kernel, kvm,
	linux-s390, linux-fsdevel, linux-perf-users,
	linux-security-module, Catalin Marinas, Will Deacon,
	Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
	Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Sven Schnelle,
	Kees Cook, Alexander Viro, Christian Brauner, Peter Zijlstra,
	Ingo Molnar, Arnaldo Carvalho de Melo, Mark Rutland,
	Alexander Shishkin, Jiri Olsa, Namhyung Kim, Ian Rogers,
	Adrian Hunter, Kentaro Takeda, Tetsuo Handa, Paul Moore,
	James Morris, Serge E . Hallyn, Paolo Bonzini

On Mon, Apr 17, 2023 at 10:07:53AM -0500, Eric W. Biederman wrote:
> Lorenzo Stoakes <lstoakes@gmail.com> writes:
>
> > On Mon, Apr 17, 2023 at 10:16:28AM -0300, Jason Gunthorpe wrote:
> >> On Mon, Apr 17, 2023 at 02:13:39PM +0100, Lorenzo Stoakes wrote:
> >> > On Mon, Apr 17, 2023 at 10:09:36AM -0300, Jason Gunthorpe wrote:
> >> > > On Sat, Apr 15, 2023 at 12:27:31AM +0100, Lorenzo Stoakes wrote:
> >> > > > The only instances of get_user_pages_remote() invocations which used the
> >> > > > vmas parameter were for a single page which can instead simply look up the
> >> > > > VMA directly. In particular:-
> >> > > >
> >> > > > - __update_ref_ctr() looked up the VMA but did nothing with it so we simply
> >> > > >   remove it.
> >> > > >
> >> > > > - __access_remote_vm() was already using vma_lookup() when the original
> >> > > >   lookup failed so by doing the lookup directly this also de-duplicates the
> >> > > >   code.
> >> > > >
> >> > > > This forms part of a broader set of patches intended to eliminate the vmas
> >> > > > parameter altogether.
> >> > > >
> >> > > > Signed-off-by: Lorenzo Stoakes <lstoakes@gmail.com>
> >> > > > ---
> >> > > >  arch/arm64/kernel/mte.c   |  5 +++--
> >> > > >  arch/s390/kvm/interrupt.c |  2 +-
> >> > > >  fs/exec.c                 |  2 +-
> >> > > >  include/linux/mm.h        |  2 +-
> >> > > >  kernel/events/uprobes.c   | 10 +++++-----
> >> > > >  mm/gup.c                  | 12 ++++--------
> >> > > >  mm/memory.c               |  9 +++++----
> >> > > >  mm/rmap.c                 |  2 +-
> >> > > >  security/tomoyo/domain.c  |  2 +-
> >> > > >  virt/kvm/async_pf.c       |  3 +--
> >> > > >  10 files changed, 23 insertions(+), 26 deletions(-)
> >> > > >
> >> > > > diff --git a/arch/arm64/kernel/mte.c b/arch/arm64/kernel/mte.c
> >> > > > index f5bcb0dc6267..74d8d4007dec 100644
> >> > > > --- a/arch/arm64/kernel/mte.c
> >> > > > +++ b/arch/arm64/kernel/mte.c
> >> > > > @@ -437,8 +437,9 @@ static int __access_remote_tags(struct mm_struct *mm, unsigned long addr,
> >> > > >  		struct page *page = NULL;
> >> > > >
> >> > > >  		ret = get_user_pages_remote(mm, addr, 1, gup_flags, &page,
> >> > > > -					    &vma, NULL);
> >> > > > -		if (ret <= 0)
> >> > > > +					    NULL);
> >> > > > +		vma = vma_lookup(mm, addr);
> >> > > > +		if (ret <= 0 || !vma)
> >> > > >  			break;
> >> > >
> >> > > Given the slightly tricky error handling, it would make sense to turn
> >> > > this pattern into a helper function:
> >> > >
> >> > > page = get_single_user_page_locked(mm, addr, gup_flags, &vma);
> >> > > if (IS_ERR(page))
> >> > >   [..]
> >> > >
> >> > > static inline struct page *get_single_user_page_locked(struct mm_struct *mm,
> >> > >    unsigned long addr, int gup_flags, struct vm_area_struct **vma)
> >> > > {
> >> > > 	struct page *page;
> >> > > 	int ret;
> >> > >
> >> > > 	ret = get_user_pages_remote(*mm, addr, 1, gup_flags, &page, NULL, NULL);
> >> > > 	if (ret < 0)
> >> > > 	   return ERR_PTR(ret);
> >> > > 	if (WARN_ON(ret == 0))
> >> > > 	   return ERR_PTR(-EINVAL);
> >> > >         *vma = vma_lookup(mm, addr);
> >> > > 	if (WARN_ON(!*vma) {
> >> > > 	   put_user_page(page);
> >> > > 	   return ERR_PTR(-EINVAL);
> >> > >         }
> >> > > 	return page;
> >> > > }
> >> > >
> >> > > It could be its own patch so this change was just a mechanical removal
> >> > > of NULL
> >> > >
> >> > > Jason
> >> > >
> >> >
> >> > Agreed, I think this would work better as a follow up patch however so as
> >> > not to distract too much from the core change.
> >>
> >> I don't think you should open code sketchy error handling in several
> >> places and then clean it up later. Just do it right from the start.
> >>
> >
> > Intent was to do smallest change possible (though through review that grew
> > of course), but I see your point, in this instance this is fiddly stuff and
> > probably better to abstract it to enforce correct handling.
> >
> > I'll respin + add something like this.
>
> Could you include in your description why looking up the vma after
> getting the page does not introduce a race?
>
> I am probably silly and just looking at this quickly but it does not
> seem immediately obvious why the vma and the page should match.
>
> I would not be surprised if you hold the appropriate mutex over the
> entire operation but it just isn't apparent from the diff.
>
> I am concerned because it is an easy mistake to refactor something into
> two steps and then discover you have introduced a race.
>
> Eric
>

The mmap_lock is held so VMAs cannot be altered and no such race can
occur. get_user_pages_remote() requires that the user calls it under the
lock so it is implicitly assured that this cannot happen.

I'll update the description to make this clear on the next spin!

(side-note: here is another irritating issue with GUP, we don't suffix with
_locked() consistently)

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-04-17 18:33 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <cover.1681508038.git.lstoakes@gmail.com>
2023-04-14 23:27 ` [PATCH 1/7] mm/gup: remove unused vmas parameter from get_user_pages() Lorenzo Stoakes
2023-04-15  5:27   ` Greg Kroah-Hartman
2023-04-17 13:01   ` Jason Gunthorpe
2023-04-14 23:27 ` [PATCH 2/7] mm/gup: remove unused vmas parameter from pin_user_pages_remote() Lorenzo Stoakes
2023-04-17 13:02   ` Jason Gunthorpe
2023-04-14 23:27 ` [PATCH 3/7] mm/gup: remove vmas parameter from get_user_pages_remote() Lorenzo Stoakes
2023-04-15  0:25   ` Tetsuo Handa
2023-04-17 13:09   ` Jason Gunthorpe
2023-04-17 13:13     ` Lorenzo Stoakes
2023-04-17 13:16       ` Jason Gunthorpe
2023-04-17 13:23         ` Lorenzo Stoakes
2023-04-17 15:07           ` Eric W. Biederman
2023-04-17 15:14             ` Lorenzo Stoakes
2023-04-14 23:27 ` [PATCH 6/7] mm/gup: remove vmas parameter from pin_user_pages() Lorenzo Stoakes

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).