For AMDGPU_GEM_USERPTR_ANONONLY, amdgpu_ttm_tt_get_user_pages() only
checks the VMA at the start of the range for a backing file, and
amdgpu_hmm_range_get_pages() then faults in the whole range, across any
other VMAs. The check used to reject ranges ending beyond the first VMA
(vma->vm_end < end), which got lost when the code moved to HMM.

An ANONONLY userptr over one page of file-backed memory is
rejected with -EPERM, but one over an anonymous page followed by the
same file-backed page is accepted.

Check every VMA in the range. The second userptr is now rejected too.
Fixes: 6826cb3b92a3 ("drm/amdgpu: support userptr cross VMAs case with HMM")

Signed-off-by: Jesse Zhang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 2103f8d6165d..d113618543a2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -783,10 +783,17 @@ int amdgpu_ttm_tt_get_user_pages(struct amdgpu_bo *bo,
                r = -EFAULT;
                goto out_unlock;
        }
-       if (unlikely((gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) &&
-               vma->vm_file)) {
-               r = -EPERM;
-               goto out_unlock;
+       if (gtt->userflags & AMDGPU_GEM_USERPTR_ANONONLY) {
+               unsigned long end = start + ttm->num_pages * PAGE_SIZE;
+               VMA_ITERATOR(vmi, mm, start);
+
+               /* the range may cover more than the VMA at its start */
+               for_each_vma_range(vmi, vma, end) {
+                       if (unlikely(vma->vm_file)) {
+                               r = -EPERM;
+                               goto out_unlock;
+                       }
+               }
        }
 
        readonly = amdgpu_ttm_tt_is_readonly(ttm);
-- 
2.50.1

Reply via email to