amdgpu_vm_pt_alloc() links a new page table into its parent entry and
the VM with amdgpu_vm_bo_base_init() before clearing it. When clearing
fails, it only drops the reference to the page table: the parent entry
keeps pointing to the freed page table and the VM status list keeps its
entry, so walking the page tables later uses freed memory.
On navi31, opening the render node with failing allocations, where the
CWSR trap mapping of the new file updates the page tables and failing
the open frees the VM again:
BUG: KASAN: slab-out-of-bounds in amdgpu_vm_pt_free+0x288/0x330 [amdgpu]
amdgpu_vm_pt_free+0x288/0x330 [amdgpu]
amdgpu_vm_pt_free_root+0xd5/0x140 [amdgpu]
amdgpu_vm_fini+0x8ab/0x14f0 [amdgpu]
amdgpu_driver_open_kms+0x6c6/0xd60 [amdgpu]
BUG: KASAN: slab-out-of-bounds in amdgpu_vm_pt_descendant+0x27e/0x330 [amdgpu]
Oops: general protection fault, probably for non-canonical address
0xe0b3bcb1a00000fb: 0000 [#1] SMP KASAN NOPTI
Undo the linking with amdgpu_vm_pt_free(), which also unpins the page
table of NPA VMs. With that the same test shows no KASAN reports.
Fixes: 0ce15d6f7d3f ("drm/amdgpu: allocate VM PDs/PTs on demand")
Signed-off-by: Jesse Zhang <[email protected]>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 9 +++++++--
1 file changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index c73eb416c0e2..55de3c414deb 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -502,6 +502,8 @@ int amdgpu_vm_pt_create(struct amdgpu_device *adev, struct
amdgpu_vm *vm,
return 0;
}
+static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry);
+
/**
* amdgpu_vm_pt_alloc - Allocate a specific page table
*
@@ -544,8 +546,11 @@ static int amdgpu_vm_pt_alloc(struct
amdgpu_vm_update_params *p,
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);
- if (r)
- goto error_unpin;
+ if (r) {
+ /* The entry points to the PT now, take it out again */
+ amdgpu_vm_pt_free(entry);
+ return r;
+ }
return 0;
--
2.50.1