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