The vm pointer returned from amdgpu_vm_get_vm_from_pasid() is only
valid while the lock is still being held. Once xa_unlock_irqrestore is
called and returned, the pointer is no longer under lock and is subject
to modification. Since, the caller still dereferences vm->task_info in
amdgpu_vm_get_task_info_vm() after the lock is removed, this causes a
use after unlock problem.

Remove the lifetime issue present in amdgpu_vm_get_task_info_pasid()
through removing the amdgpu_vm_get_vm_from_pasid() function from
amdgpu_vm.c and making the relevant code inline to hold the lock while
it is still in use.

Signed-off-by: Shahyan Soltani <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 25 ++++++++++---------------
 1 file changed, 10 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 32719f31b6c9..180d694323e8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -2460,19 +2460,6 @@ static void amdgpu_vm_destroy_task_info(struct kref 
*kref)
        kfree(ti);
 }
 
-static inline struct amdgpu_vm *
-amdgpu_vm_get_vm_from_pasid(struct amdgpu_device *adev, u32 pasid)
-{
-       struct amdgpu_vm *vm;
-       unsigned long flags;
-
-       xa_lock_irqsave(&adev->vm_manager.pasids, flags);
-       vm = xa_load(&adev->vm_manager.pasids, pasid);
-       xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
-
-       return vm;
-}
-
 /**
  * amdgpu_vm_put_task_info - reference down the vm task_info ptr
  *
@@ -2519,8 +2506,16 @@ amdgpu_vm_get_task_info_vm(struct amdgpu_vm *vm)
 struct amdgpu_task_info *
 amdgpu_vm_get_task_info_pasid(struct amdgpu_device *adev, u32 pasid)
 {
-       return amdgpu_vm_get_task_info_vm(
-                       amdgpu_vm_get_vm_from_pasid(adev, pasid));
+       struct amdgpu_task_info *ti;
+       struct amdgpu_vm *vm;
+       unsigned long flags;
+
+       xa_lock_irqsave(&adev->vm_manager.pasids, flags);
+       vm = xa_load(&adev->vm_manager.pasids, pasid);
+       ti = amdgpu_vm_get_task_info_vm(vm);
+       xa_unlock_irqrestore(&adev->vm_manager.pasids, flags);
+
+       return ti;
 }
 
 static int amdgpu_vm_create_task_info(struct amdgpu_vm *vm)
-- 
2.54.0

Reply via email to