USERQ_SIGNAL reads the WPTR through amdgpu_bo_kmap(). A dma-buf from
another exporter (e.g. udmabuf) is imported as an sg BO without a page
array, so ttm_bo_kmap() dereferences a NULL ttm->pages:

  BUG: kernel NULL pointer dereference, address: 0000000000000000
  RIP: 0010:ttm_bo_kmap+0x26c/0x300 [ttm]
  Call Trace:
   amdgpu_bo_kmap+0x89/0xb0 [amdgpu]
   amdgpu_userq_fence_read_wptr+0x116/0x170 [amdgpu]
   amdgpu_userq_signal_ioctl+0x3fe/0xbb0 [amdgpu]

Queue creation accepts such a BO too, and warns in amdgpu_bo_gpu_offset()
because the BO is still in the system domain when its GART address is
taken.

Reject imported BOs when the WPTR mapping is set up at creation time and
when the WPTR is read in USERQ_SIGNAL, since userspace can replace the
mapping under the WPTR VA after the queue was created.

Fixes: 5fb2f7fc21a3 ("drm/amdgpu: map wptr BO into GART")
Fixes: a292fdecd728 ("drm/amdgpu: Implement userqueue signal/wait IOCTL")
Signed-off-by: Jesse Zhang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c | 4 +++-
 drivers/gpu/drm/amd/amdgpu/mes_userqueue.c      | 7 ++++++-
 2 files changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 118db0306559..a2fa59a9609e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -386,7 +386,9 @@ static int amdgpu_userq_fence_read_wptr(struct 
amdgpu_device *adev,
                        goto lock_error;
 
                mapping = amdgpu_vm_bo_lookup_mapping(queue->vm, addr);
-               if (!mapping || !mapping->bo_va->base.bo) {
+               /* Imported dma-bufs can't be CPU mapped with amdgpu_bo_kmap(). 
*/
+               if (!mapping || !mapping->bo_va->base.bo ||
+                   drm_gem_is_imported(&mapping->bo_va->base.bo->tbo.base)) {
                        ret = -EINVAL;
                        goto lock_error;
                }
diff --git a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c 
b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
index 1b76c10d1ac2..7abb9d95ef59 100644
--- a/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
+++ b/drivers/gpu/drm/amd/amdgpu/mes_userqueue.c
@@ -54,7 +54,12 @@ mes_userq_create_wptr_mapping(struct amdgpu_device *adev,
                        goto fail_lock;
 
                wptr_mapping = amdgpu_vm_bo_lookup_mapping(vm, wptr);
-               if (!wptr_mapping || !wptr_mapping->bo_va->base.bo) {
+               /*
+                * The WPTR is read through a kernel CPU mapping, which imported
+                * dma-bufs don't support.
+                */
+               if (!wptr_mapping || !wptr_mapping->bo_va->base.bo ||
+                   
drm_gem_is_imported(&wptr_mapping->bo_va->base.bo->tbo.base)) {
                        ret = -EINVAL;
                        goto fail_lock;
                }
-- 
2.50.1

Reply via email to