All of lore.kernel.org
 help / color / mirror / Atom feed
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>,
	LKML <linux-kernel@vger.kernel.org>
Cc: kvm@vger.kernel.org, linux-mm@kvack.org,
	linux-arm-kernel@lists.infradead.org,
	linux-samsung-soc@vger.kernel.org, linux-media@vger.kernel.org,
	"Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Daniel Vetter" <daniel.vetter@intel.com>,
	"Christoph Hellwig" <hch@infradead.org>,
	"Jason Gunthorpe" <jgg@ziepe.ca>,
	"Kees Cook" <keescook@chromium.org>,
	"Dan Williams" <dan.j.williams@intel.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Jérôme Glisse" <jglisse@redhat.com>, "Jan Kara" <jack@suse.cz>
Subject: [PATCH v6 17/17] RFC: mm: add mmu_notifier argument to follow_pfn
Date: Thu, 19 Nov 2020 15:41:46 +0100	[thread overview]
Message-ID: <20201119144146.1045202-18-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <20201119144146.1045202-1-daniel.vetter@ffwll.ch>

The only safe way for non core/arch code to use follow_pfn() is
together with an mmu_notifier subscription. follow_pfn() is already
marked as _GPL and the kerneldoc explains this restriction.

This patch here enforces all this by adding a mmu_notifier argument
and verifying that it is registered for the correct mm_struct.

Motivated by discussions with Christoph Hellwig and Jason Gunthorpe.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <keescook@chromium.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Jérôme Glisse <jglisse@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: linux-mm@kvack.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: linux-media@vger.kernel.org
Cc: kvm@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/linux/mm.h  |  3 ++-
 mm/memory.c         | 39 ++++++++++++++++++++++++++-------------
 mm/nommu.c          | 23 ++++++++++++++++++-----
 virt/kvm/kvm_main.c |  4 ++--
 4 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index aa0087feab24..14453f366efd 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1651,6 +1651,7 @@ void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
 		unsigned long start, unsigned long end);
 
 struct mmu_notifier_range;
+struct mmu_notifier;
 
 void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 		unsigned long end, unsigned long floor, unsigned long ceiling);
@@ -1660,7 +1661,7 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
 		   struct mmu_notifier_range *range,
 		   pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn);
+	unsigned long *pfn, struct mmu_notifier *subscription);
 int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 		      unsigned long *pfn);
 int follow_phys(struct vm_area_struct *vma, unsigned long address,
diff --git a/mm/memory.c b/mm/memory.c
index 0db0c5e233fd..51fc0507663a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4789,11 +4789,30 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
 }
 EXPORT_SYMBOL(follow_pte_pmd);
 
+static int __follow_pfn(struct vm_area_struct *vma, unsigned long address,
+			unsigned long *pfn)
+{
+	int ret = -EINVAL;
+	spinlock_t *ptl;
+	pte_t *ptep;
+
+	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+		return ret;
+
+	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
+	if (ret)
+		return ret;
+	*pfn = pte_pfn(*ptep);
+	pte_unmap_unlock(ptep, ptl);
+	return 0;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
  * @address: user virtual address
  * @pfn: location to store found PFN
+ * @subscription: mmu_notifier subscription for the mm @vma is part of
  *
  * Only IO mappings and raw PFN mappings are allowed. Note that callers must
  * ensure coherency with pte updates by using a &mmu_notifier to follow updates.
@@ -4805,21 +4824,15 @@ EXPORT_SYMBOL(follow_pte_pmd);
  * Return: zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn)
+	unsigned long *pfn, struct mmu_notifier *subscription)
 {
-	int ret = -EINVAL;
-	spinlock_t *ptl;
-	pte_t *ptep;
+	if (WARN_ON(!subscription->mm))
+		return -EINVAL;
 
-	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
-		return ret;
+	if (WARN_ON(subscription->mm != vma->vm_mm))
+		return -EINVAL;
 
-	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
-	if (ret)
-		return ret;
-	*pfn = pte_pfn(*ptep);
-	pte_unmap_unlock(ptep, ptl);
-	return 0;
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL_GPL(follow_pfn);
 
@@ -4844,7 +4857,7 @@ int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 	WARN_ONCE(1, "unsafe follow_pfn usage\n");
 	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
 
-	return follow_pfn(vma, address, pfn);
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL(unsafe_follow_pfn);
 
diff --git a/mm/nommu.c b/mm/nommu.c
index 79fc98a6c94a..2a6b46fe1906 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -111,24 +111,37 @@ unsigned int kobjsize(const void *objp)
 	return page_size(page);
 }
 
+static int __follow_pfn(struct vm_area_struct *vma, unsigned long address,
+			unsigned long *pfn)
+{
+	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+		return -EINVAL;
+
+	*pfn = address >> PAGE_SHIFT;
+	return 0;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
  * @address: user virtual address
  * @pfn: location to store found PFN
+ * @subscription: mmu_notifier subscription for the mm @vma is part of
  *
  * Only IO mappings and raw PFN mappings are allowed.
  *
  * Returns zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn)
+	unsigned long *pfn, struct mmu_notifier *subscription)
 {
-	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+	if (WARN_ON(!subscription->mm))
 		return -EINVAL;
 
-	*pfn = address >> PAGE_SHIFT;
-	return 0;
+	if (WARN_ON(subscription->mm != vma->vm_mm))
+		return -EINVAL;
+
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL_GPL(follow_pfn);
 
@@ -153,7 +166,7 @@ int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 	WARN_ONCE(1, "unsafe follow_pfn usage\n");
 	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
 
-	return follow_pfn(vma, address, pfn);
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL(unsafe_follow_pfn);
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 417f3d470c3e..6f6786524eff 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1891,7 +1891,7 @@ static int hva_to_pfn_remapped(struct kvm *kvm, struct vm_area_struct *vma,
 	unsigned long pfn;
 	int r;
 
-	r = follow_pfn(vma, addr, &pfn);
+	r = follow_pfn(vma, addr, &pfn, &kvm->mmu_notifier);
 	if (r) {
 		/*
 		 * get_user_pages fails for VM_IO and VM_PFNMAP vmas and does
@@ -1906,7 +1906,7 @@ static int hva_to_pfn_remapped(struct kvm *kvm, struct vm_area_struct *vma,
 		if (r)
 			return r;
 
-		r = follow_pfn(vma, addr, &pfn);
+		r = follow_pfn(vma, addr, &pfn, &kvm->mmu_notifier);
 		if (r)
 			return r;
 
-- 
2.29.2


WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>,
	LKML <linux-kernel@vger.kernel.org>
Cc: linux-samsung-soc@vger.kernel.org, "Jan Kara" <jack@suse.cz>,
	"Kees Cook" <keescook@chromium.org>,
	kvm@vger.kernel.org, "Jason Gunthorpe" <jgg@ziepe.ca>,
	"Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Christoph Hellwig" <hch@infradead.org>,
	linux-mm@kvack.org, "Jérôme Glisse" <jglisse@redhat.com>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Daniel Vetter" <daniel.vetter@intel.com>,
	"Dan Williams" <dan.j.williams@intel.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	linux-arm-kernel@lists.infradead.org,
	linux-media@vger.kernel.org
Subject: [PATCH v6 17/17] RFC: mm: add mmu_notifier argument to follow_pfn
Date: Thu, 19 Nov 2020 15:41:46 +0100	[thread overview]
Message-ID: <20201119144146.1045202-18-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <20201119144146.1045202-1-daniel.vetter@ffwll.ch>

The only safe way for non core/arch code to use follow_pfn() is
together with an mmu_notifier subscription. follow_pfn() is already
marked as _GPL and the kerneldoc explains this restriction.

This patch here enforces all this by adding a mmu_notifier argument
and verifying that it is registered for the correct mm_struct.

Motivated by discussions with Christoph Hellwig and Jason Gunthorpe.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <keescook@chromium.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Jérôme Glisse <jglisse@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: linux-mm@kvack.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: linux-media@vger.kernel.org
Cc: kvm@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/linux/mm.h  |  3 ++-
 mm/memory.c         | 39 ++++++++++++++++++++++++++-------------
 mm/nommu.c          | 23 ++++++++++++++++++-----
 virt/kvm/kvm_main.c |  4 ++--
 4 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index aa0087feab24..14453f366efd 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1651,6 +1651,7 @@ void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
 		unsigned long start, unsigned long end);
 
 struct mmu_notifier_range;
+struct mmu_notifier;
 
 void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 		unsigned long end, unsigned long floor, unsigned long ceiling);
@@ -1660,7 +1661,7 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
 		   struct mmu_notifier_range *range,
 		   pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn);
+	unsigned long *pfn, struct mmu_notifier *subscription);
 int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 		      unsigned long *pfn);
 int follow_phys(struct vm_area_struct *vma, unsigned long address,
diff --git a/mm/memory.c b/mm/memory.c
index 0db0c5e233fd..51fc0507663a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4789,11 +4789,30 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
 }
 EXPORT_SYMBOL(follow_pte_pmd);
 
+static int __follow_pfn(struct vm_area_struct *vma, unsigned long address,
+			unsigned long *pfn)
+{
+	int ret = -EINVAL;
+	spinlock_t *ptl;
+	pte_t *ptep;
+
+	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+		return ret;
+
+	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
+	if (ret)
+		return ret;
+	*pfn = pte_pfn(*ptep);
+	pte_unmap_unlock(ptep, ptl);
+	return 0;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
  * @address: user virtual address
  * @pfn: location to store found PFN
+ * @subscription: mmu_notifier subscription for the mm @vma is part of
  *
  * Only IO mappings and raw PFN mappings are allowed. Note that callers must
  * ensure coherency with pte updates by using a &mmu_notifier to follow updates.
@@ -4805,21 +4824,15 @@ EXPORT_SYMBOL(follow_pte_pmd);
  * Return: zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn)
+	unsigned long *pfn, struct mmu_notifier *subscription)
 {
-	int ret = -EINVAL;
-	spinlock_t *ptl;
-	pte_t *ptep;
+	if (WARN_ON(!subscription->mm))
+		return -EINVAL;
 
-	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
-		return ret;
+	if (WARN_ON(subscription->mm != vma->vm_mm))
+		return -EINVAL;
 
-	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
-	if (ret)
-		return ret;
-	*pfn = pte_pfn(*ptep);
-	pte_unmap_unlock(ptep, ptl);
-	return 0;
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL_GPL(follow_pfn);
 
@@ -4844,7 +4857,7 @@ int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 	WARN_ONCE(1, "unsafe follow_pfn usage\n");
 	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
 
-	return follow_pfn(vma, address, pfn);
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL(unsafe_follow_pfn);
 
diff --git a/mm/nommu.c b/mm/nommu.c
index 79fc98a6c94a..2a6b46fe1906 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -111,24 +111,37 @@ unsigned int kobjsize(const void *objp)
 	return page_size(page);
 }
 
+static int __follow_pfn(struct vm_area_struct *vma, unsigned long address,
+			unsigned long *pfn)
+{
+	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+		return -EINVAL;
+
+	*pfn = address >> PAGE_SHIFT;
+	return 0;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
  * @address: user virtual address
  * @pfn: location to store found PFN
+ * @subscription: mmu_notifier subscription for the mm @vma is part of
  *
  * Only IO mappings and raw PFN mappings are allowed.
  *
  * Returns zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn)
+	unsigned long *pfn, struct mmu_notifier *subscription)
 {
-	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+	if (WARN_ON(!subscription->mm))
 		return -EINVAL;
 
-	*pfn = address >> PAGE_SHIFT;
-	return 0;
+	if (WARN_ON(subscription->mm != vma->vm_mm))
+		return -EINVAL;
+
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL_GPL(follow_pfn);
 
@@ -153,7 +166,7 @@ int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 	WARN_ONCE(1, "unsafe follow_pfn usage\n");
 	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
 
-	return follow_pfn(vma, address, pfn);
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL(unsafe_follow_pfn);
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 417f3d470c3e..6f6786524eff 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1891,7 +1891,7 @@ static int hva_to_pfn_remapped(struct kvm *kvm, struct vm_area_struct *vma,
 	unsigned long pfn;
 	int r;
 
-	r = follow_pfn(vma, addr, &pfn);
+	r = follow_pfn(vma, addr, &pfn, &kvm->mmu_notifier);
 	if (r) {
 		/*
 		 * get_user_pages fails for VM_IO and VM_PFNMAP vmas and does
@@ -1906,7 +1906,7 @@ static int hva_to_pfn_remapped(struct kvm *kvm, struct vm_area_struct *vma,
 		if (r)
 			return r;
 
-		r = follow_pfn(vma, addr, &pfn);
+		r = follow_pfn(vma, addr, &pfn, &kvm->mmu_notifier);
 		if (r)
 			return r;
 
-- 
2.29.2


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

WARNING: multiple messages have this Message-ID (diff)
From: Daniel Vetter <daniel.vetter@ffwll.ch>
To: DRI Development <dri-devel@lists.freedesktop.org>,
	LKML <linux-kernel@vger.kernel.org>
Cc: linux-samsung-soc@vger.kernel.org, "Jan Kara" <jack@suse.cz>,
	"Kees Cook" <keescook@chromium.org>,
	kvm@vger.kernel.org, "Jason Gunthorpe" <jgg@ziepe.ca>,
	"Daniel Vetter" <daniel.vetter@ffwll.ch>,
	"Christoph Hellwig" <hch@infradead.org>,
	linux-mm@kvack.org, "Jérôme Glisse" <jglisse@redhat.com>,
	"John Hubbard" <jhubbard@nvidia.com>,
	"Daniel Vetter" <daniel.vetter@intel.com>,
	"Dan Williams" <dan.j.williams@intel.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	linux-arm-kernel@lists.infradead.org,
	linux-media@vger.kernel.org
Subject: [PATCH v6 17/17] RFC: mm: add mmu_notifier argument to follow_pfn
Date: Thu, 19 Nov 2020 15:41:46 +0100	[thread overview]
Message-ID: <20201119144146.1045202-18-daniel.vetter@ffwll.ch> (raw)
In-Reply-To: <20201119144146.1045202-1-daniel.vetter@ffwll.ch>

The only safe way for non core/arch code to use follow_pfn() is
together with an mmu_notifier subscription. follow_pfn() is already
marked as _GPL and the kerneldoc explains this restriction.

This patch here enforces all this by adding a mmu_notifier argument
and verifying that it is registered for the correct mm_struct.

Motivated by discussions with Christoph Hellwig and Jason Gunthorpe.

Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Kees Cook <keescook@chromium.org>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Jérôme Glisse <jglisse@redhat.com>
Cc: Jan Kara <jack@suse.cz>
Cc: Dan Williams <dan.j.williams@intel.com>
Cc: linux-mm@kvack.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-samsung-soc@vger.kernel.org
Cc: linux-media@vger.kernel.org
Cc: kvm@vger.kernel.org
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
---
 include/linux/mm.h  |  3 ++-
 mm/memory.c         | 39 ++++++++++++++++++++++++++-------------
 mm/nommu.c          | 23 ++++++++++++++++++-----
 virt/kvm/kvm_main.c |  4 ++--
 4 files changed, 48 insertions(+), 21 deletions(-)

diff --git a/include/linux/mm.h b/include/linux/mm.h
index aa0087feab24..14453f366efd 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1651,6 +1651,7 @@ void unmap_vmas(struct mmu_gather *tlb, struct vm_area_struct *start_vma,
 		unsigned long start, unsigned long end);
 
 struct mmu_notifier_range;
+struct mmu_notifier;
 
 void free_pgd_range(struct mmu_gather *tlb, unsigned long addr,
 		unsigned long end, unsigned long floor, unsigned long ceiling);
@@ -1660,7 +1661,7 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
 		   struct mmu_notifier_range *range,
 		   pte_t **ptepp, pmd_t **pmdpp, spinlock_t **ptlp);
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn);
+	unsigned long *pfn, struct mmu_notifier *subscription);
 int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 		      unsigned long *pfn);
 int follow_phys(struct vm_area_struct *vma, unsigned long address,
diff --git a/mm/memory.c b/mm/memory.c
index 0db0c5e233fd..51fc0507663a 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4789,11 +4789,30 @@ int follow_pte_pmd(struct mm_struct *mm, unsigned long address,
 }
 EXPORT_SYMBOL(follow_pte_pmd);
 
+static int __follow_pfn(struct vm_area_struct *vma, unsigned long address,
+			unsigned long *pfn)
+{
+	int ret = -EINVAL;
+	spinlock_t *ptl;
+	pte_t *ptep;
+
+	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+		return ret;
+
+	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
+	if (ret)
+		return ret;
+	*pfn = pte_pfn(*ptep);
+	pte_unmap_unlock(ptep, ptl);
+	return 0;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
  * @address: user virtual address
  * @pfn: location to store found PFN
+ * @subscription: mmu_notifier subscription for the mm @vma is part of
  *
  * Only IO mappings and raw PFN mappings are allowed. Note that callers must
  * ensure coherency with pte updates by using a &mmu_notifier to follow updates.
@@ -4805,21 +4824,15 @@ EXPORT_SYMBOL(follow_pte_pmd);
  * Return: zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn)
+	unsigned long *pfn, struct mmu_notifier *subscription)
 {
-	int ret = -EINVAL;
-	spinlock_t *ptl;
-	pte_t *ptep;
+	if (WARN_ON(!subscription->mm))
+		return -EINVAL;
 
-	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
-		return ret;
+	if (WARN_ON(subscription->mm != vma->vm_mm))
+		return -EINVAL;
 
-	ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
-	if (ret)
-		return ret;
-	*pfn = pte_pfn(*ptep);
-	pte_unmap_unlock(ptep, ptl);
-	return 0;
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL_GPL(follow_pfn);
 
@@ -4844,7 +4857,7 @@ int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 	WARN_ONCE(1, "unsafe follow_pfn usage\n");
 	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
 
-	return follow_pfn(vma, address, pfn);
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL(unsafe_follow_pfn);
 
diff --git a/mm/nommu.c b/mm/nommu.c
index 79fc98a6c94a..2a6b46fe1906 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -111,24 +111,37 @@ unsigned int kobjsize(const void *objp)
 	return page_size(page);
 }
 
+static int __follow_pfn(struct vm_area_struct *vma, unsigned long address,
+			unsigned long *pfn)
+{
+	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+		return -EINVAL;
+
+	*pfn = address >> PAGE_SHIFT;
+	return 0;
+}
+
 /**
  * follow_pfn - look up PFN at a user virtual address
  * @vma: memory mapping
  * @address: user virtual address
  * @pfn: location to store found PFN
+ * @subscription: mmu_notifier subscription for the mm @vma is part of
  *
  * Only IO mappings and raw PFN mappings are allowed.
  *
  * Returns zero and the pfn at @pfn on success, -ve otherwise.
  */
 int follow_pfn(struct vm_area_struct *vma, unsigned long address,
-	unsigned long *pfn)
+	unsigned long *pfn, struct mmu_notifier *subscription)
 {
-	if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+	if (WARN_ON(!subscription->mm))
 		return -EINVAL;
 
-	*pfn = address >> PAGE_SHIFT;
-	return 0;
+	if (WARN_ON(subscription->mm != vma->vm_mm))
+		return -EINVAL;
+
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL_GPL(follow_pfn);
 
@@ -153,7 +166,7 @@ int unsafe_follow_pfn(struct vm_area_struct *vma, unsigned long address,
 	WARN_ONCE(1, "unsafe follow_pfn usage\n");
 	add_taint(TAINT_USER, LOCKDEP_STILL_OK);
 
-	return follow_pfn(vma, address, pfn);
+	return __follow_pfn(vma, address, pfn);
 }
 EXPORT_SYMBOL(unsafe_follow_pfn);
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 417f3d470c3e..6f6786524eff 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1891,7 +1891,7 @@ static int hva_to_pfn_remapped(struct kvm *kvm, struct vm_area_struct *vma,
 	unsigned long pfn;
 	int r;
 
-	r = follow_pfn(vma, addr, &pfn);
+	r = follow_pfn(vma, addr, &pfn, &kvm->mmu_notifier);
 	if (r) {
 		/*
 		 * get_user_pages fails for VM_IO and VM_PFNMAP vmas and does
@@ -1906,7 +1906,7 @@ static int hva_to_pfn_remapped(struct kvm *kvm, struct vm_area_struct *vma,
 		if (r)
 			return r;
 
-		r = follow_pfn(vma, addr, &pfn);
+		r = follow_pfn(vma, addr, &pfn, &kvm->mmu_notifier);
 		if (r)
 			return r;
 
-- 
2.29.2

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  parent reply	other threads:[~2020-11-19 14:43 UTC|newest]

Thread overview: 117+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-11-19 14:41 [PATCH v6 00/17] follow_pfn and other iomap races Daniel Vetter
2020-11-19 14:41 ` Daniel Vetter
2020-11-19 14:41 ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 01/17] drm/exynos: Stop using frame_vector helpers Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 02/17] drm/exynos: Use FOLL_LONGTERM for g2d cmdlists Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 03/17] misc/habana: Stop using frame_vector helpers Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-21 12:47   ` Oded Gabbay
2020-11-21 12:47     ` Oded Gabbay
2020-11-21 12:47     ` Oded Gabbay
2020-11-19 14:41 ` [PATCH v6 04/17] misc/habana: Use FOLL_LONGTERM for userptr Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-21 10:15   ` Oded Gabbay
2020-11-21 10:15     ` Oded Gabbay
2020-11-21 10:15     ` Oded Gabbay
2020-11-19 14:41 ` [PATCH v6 05/17] mm/frame-vector: Use FOLL_LONGTERM Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 06/17] media: videobuf2: Move frame_vector into media subsystem Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-20  8:07   ` Hans Verkuil
2020-11-20  8:07     ` Hans Verkuil
2020-11-20  8:07     ` Hans Verkuil
2020-11-19 14:41 ` [PATCH v6 07/17] mm: Close race in generic_access_phys Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 08/17] mm: Add unsafe_follow_pfn Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 09/17] media/videbuf1|2: Mark follow_pfn usage as unsafe Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-20  8:06   ` Hans Verkuil
2020-11-20  8:06     ` Hans Verkuil
2020-11-20  8:06     ` Hans Verkuil
2020-11-20  8:28     ` Hans Verkuil
2020-11-20  8:28       ` Hans Verkuil
2020-11-20  8:28       ` Hans Verkuil
2020-11-20  8:32       ` Tomasz Figa
2020-11-20  8:32         ` Tomasz Figa
2020-11-20  8:32         ` Tomasz Figa
2020-11-20  9:18       ` Daniel Vetter
2020-11-20  9:18         ` Daniel Vetter
2020-11-20  9:18         ` Daniel Vetter
2020-11-20 10:38         ` Hans Verkuil
2020-11-20 10:38           ` Hans Verkuil
2020-11-20 10:38           ` Hans Verkuil
2020-11-20 10:51           ` Daniel Vetter
2020-11-20 10:51             ` Daniel Vetter
2020-11-20 10:51             ` Daniel Vetter
2020-11-20 12:08             ` Hans Verkuil
2020-11-20 12:08               ` Hans Verkuil
2020-11-20 12:08               ` Hans Verkuil
2020-11-20 12:23               ` Tomasz Figa
2020-11-20 12:23                 ` Tomasz Figa
2020-11-20 12:23                 ` Tomasz Figa
2020-11-24 14:16                 ` Daniel Vetter
2020-11-24 14:16                   ` Daniel Vetter
2020-11-24 14:16                   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 10/17] vfio/type1: Mark follow_pfn " Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 11/17] PCI: Obey iomem restrictions for procfs mmap Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 12/17] /dev/mem: Only set filp->f_mapping Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 13/17] resource: Move devmem revoke code to resource framework Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 14/17] sysfs: Support zapping of binary attr mmaps Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 15/17] PCI: Revoke mappings like devmem Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41 ` [PATCH v6 16/17] RFC: kvm: pass kvm argument to follow_pfn callsites Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-20 15:33   ` Paolo Bonzini
2020-11-20 15:33     ` Paolo Bonzini
2020-11-20 15:33     ` Paolo Bonzini
2020-11-20 15:44     ` Daniel Vetter
2020-11-20 15:44       ` Daniel Vetter
2020-11-20 15:44       ` Daniel Vetter
2020-11-20 15:55       ` Paolo Bonzini
2020-11-20 15:55         ` Paolo Bonzini
2020-11-20 15:55         ` Paolo Bonzini
2020-11-19 14:41 ` Daniel Vetter [this message]
2020-11-19 14:41   ` [PATCH v6 17/17] RFC: mm: add mmu_notifier argument to follow_pfn Daniel Vetter
2020-11-19 14:41   ` Daniel Vetter
2020-11-20 18:30   ` Jason Gunthorpe
2020-11-20 18:30     ` Jason Gunthorpe
2020-11-20 18:30     ` Jason Gunthorpe
2020-11-24 14:28     ` Daniel Vetter
2020-11-24 14:28       ` Daniel Vetter
2020-11-24 14:28       ` Daniel Vetter
2020-11-24 15:55       ` Jason Gunthorpe
2020-11-24 15:55         ` Jason Gunthorpe
2020-11-24 15:55         ` Jason Gunthorpe
2020-11-25  9:00         ` Daniel Vetter
2020-11-25  9:00           ` Daniel Vetter
2020-11-25  9:00           ` Daniel Vetter
2020-11-27 13:12 ` [PATCH v6 00/17] follow_pfn and other iomap races Jason Gunthorpe
2020-11-27 13:12   ` Jason Gunthorpe
2020-11-27 13:12   ` Jason Gunthorpe
2020-11-27 15:36   ` Daniel Vetter
2020-11-27 15:36     ` Daniel Vetter
2020-11-27 15:36     ` Daniel Vetter

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20201119144146.1045202-18-daniel.vetter@ffwll.ch \
    --to=daniel.vetter@ffwll.ch \
    --cc=akpm@linux-foundation.org \
    --cc=dan.j.williams@intel.com \
    --cc=daniel.vetter@intel.com \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=hch@infradead.org \
    --cc=jack@suse.cz \
    --cc=jgg@ziepe.ca \
    --cc=jglisse@redhat.com \
    --cc=jhubbard@nvidia.com \
    --cc=keescook@chromium.org \
    --cc=kvm@vger.kernel.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-media@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=linux-samsung-soc@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.