On 10/9/26 03:56, Jesse Zhang wrote:
> amdgpu_vm_pt_alloc() drops the eviction lock while it creates the new
> page table. When the VM started to get evicted in the meantime,
> amdgpu_vm_begin_critical() returns -EBUSY and we jump to error_free_pt
> before pt_bo is assigned. That unreferences an uninitialized pointer,
> leaks the new page table (still pinned for NPA VMs) and returns 0 since
> r is the result of the successful page table creation.
>
> With vm->evicting set right after amdgpu_vm_pt_create() (what
> amdgpu_vm_evictable() does when TTM evicts one of the VM page tables in
> that window), the first GEM_VA map that needs a new page table oopses:
>
> BUG: kernel NULL pointer dereference, address: 0000000000000460
> RIP: 0010:amdgpu_bo_unref+0x27/0x70 [amdgpu]
> Call Trace:
> amdgpu_vm_ptes_update+0xa4e/0xa60 [amdgpu]
> amdgpu_vm_update_range+0x2eb/0x970 [amdgpu]
> amdgpu_vm_bo_update+0x325/0x6d0 [amdgpu]
> amdgpu_gem_va_update_vm+0xdb/0x1c0 [amdgpu]
> amdgpu_gem_va_ioctl+0x86c/0x940 [amdgpu]
>
> Assign pt_bo first, unpin and free the new page table and return the
> error from amdgpu_vm_begin_critical().
>
> Fixes: 1e0041e2ac56 ("drm/amdgpu: rework eviction lock handling into critical
> section v3")
> Signed-off-by: Jesse Zhang <[email protected]>
Reviewed-by: Christian König <[email protected]>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 10 ++++++----
> 1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
> index c03327f1242d..599c0085cdd9 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
> @@ -531,13 +531,16 @@ static int amdgpu_vm_pt_alloc(struct
> amdgpu_vm_update_params *p,
> r2 = amdgpu_vm_begin_critical(p);
> if (r)
> return r;
> - if (r2)
> - goto error_free_pt;
> +
> + pt_bo = &pt->bo;
> + if (r2) {
> + r = r2;
> + goto error_unpin;
> + }
>
> /* Keep a reference to the root directory to avoid
> * freeing them up in the wrong order.
> */
> - pt_bo = &pt->bo;
> pt_bo->parent = amdgpu_bo_ref(cursor->parent->bo);
> amdgpu_vm_bo_base_init(entry, p->vm, pt_bo);
> r = amdgpu_vm_pt_clear(p->adev, p->vm, pt, p->immediate);
> @@ -549,7 +552,6 @@ static int amdgpu_vm_pt_alloc(struct
> amdgpu_vm_update_params *p,
> error_unpin:
> if (p->vm->is_npa)
> amdgpu_bo_unpin(pt_bo);
> -error_free_pt:
> amdgpu_bo_unref(&pt_bo);
> return r;
> }