The GFX12 user queue private fault woker loads
the relevnt user queue from the userq doorbell xarray.
However it does not hold the spin_lock of the xarray
when walking the xarray, and does not increase the
kref of the user queue, so it races with queue
destruction path and may run into an use-after-free
userq problem.

This commit fixes this UAF problem by utilizing
amdgpu_lookup_queue_by_doorbell helper, which
properly hoding the xarray spin lock and the kref
of the user queue.

Signed-off-by: Zhu Lingshan <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c 
b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index fdfee88e41e3..b6ae15066205 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -5070,9 +5070,12 @@ static void gfx_v12_0_userq_priv_fault_work(struct 
work_struct *work)
 
                doorbell = (db_ctrl & 
CP_RB_DOORBELL_CONTROL__DOORBELL_OFFSET_MASK) >>
                           CP_RB_DOORBELL_CONTROL__DOORBELL_OFFSET__SHIFT;
-               q = xa_load(&adev->userq_doorbell_xa, doorbell);
-               if (q)
+               q = amdgpu_lookup_queue_by_doorbell(&adev->userq_doorbell_xa,
+                                                   doorbell);
+               if (q) {
                        amdgpu_userq_start_hang_detect_work(q);
+                       amdgpu_userq_put(q);
+               }
        }
 }
 
-- 
2.53.0

Reply via email to