On 10/8/26 08:53, Jesse Zhang wrote:
> 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]>

Reviewed-by: Christian König <[email protected]>

We should probably fix ttm_bo_kmap() to return an error code as well.

Regards,
Christian.

> ---
>  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;
>               }

Reply via email to