Skip to content

Commit 34f31fe

Browse files
prliangpubalexdeucher
authored andcommitted
drm/amdgpu: rework userq fence driver alloc/destroy
The correct fix is to tie the global xa entry lifetime to the queue lifetime: insert in amdgpu_userq_create() and erase in amdgpu_userq_cleanup(), both at the well-defined doorbell_index key, making the operation O(1) and resolve the fence driver UAF problem by binding the userq driver fence to per queue. v2: clean up the local variables initialization. (Christian) Signed-off-by: Prike Liang <Prike.Liang@amd.com> Reviewed-by: Christian König <christian.koenig@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
1 parent 05ce444 commit 34f31fe

8 files changed

Lines changed: 28 additions & 52 deletions

File tree

drivers/gpu/drm/amd/amdgpu/amdgpu.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1045,11 +1045,6 @@ struct amdgpu_device {
10451045
struct amdgpu_mqd mqds[AMDGPU_HW_IP_NUM];
10461046
const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM];
10471047

1048-
/* xarray used to retrieve the user queue fence driver reference
1049-
* in the EOP interrupt handler to signal the particular user
1050-
* queue fence.
1051-
*/
1052-
struct xarray userq_xa;
10531048
/**
10541049
* @userq_doorbell_xa: Global user queue map (doorbell index → queue)
10551050
* Key: doorbell_index (unique global identifier for the queue)

drivers/gpu/drm/amd/amdgpu/amdgpu_device.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3757,15 +3757,13 @@ int amdgpu_device_init(struct amdgpu_device *adev,
37573757
spin_lock_init(&adev->virt.rlcg_reg_lock);
37583758
spin_lock_init(&adev->wb.lock);
37593759

3760-
xa_init_flags(&adev->userq_xa, XA_FLAGS_LOCK_IRQ);
3761-
37623760
INIT_LIST_HEAD(&adev->reset_list);
37633761

37643762
INIT_LIST_HEAD(&adev->ras_list);
37653763

37663764
INIT_LIST_HEAD(&adev->pm.od_kobj_list);
37673765

3768-
xa_init(&adev->userq_doorbell_xa);
3766+
xa_init_flags(&adev->userq_doorbell_xa, XA_FLAGS_LOCK_IRQ);
37693767

37703768
INIT_DELAYED_WORK(&adev->delayed_init_work,
37713769
amdgpu_device_delayed_init_work_handler);

drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
8181
struct amdgpu_usermode_queue *userq)
8282
{
8383
struct amdgpu_userq_fence_driver *fence_drv;
84-
unsigned long flags;
8584
int r;
8685

8786
fence_drv = kzalloc_obj(*fence_drv);
@@ -104,19 +103,10 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
104103
fence_drv->context = dma_fence_context_alloc(1);
105104
get_task_comm(fence_drv->timeline_name, current);
106105

107-
xa_lock_irqsave(&adev->userq_xa, flags);
108-
r = xa_err(__xa_store(&adev->userq_xa, userq->doorbell_index,
109-
fence_drv, GFP_KERNEL));
110-
xa_unlock_irqrestore(&adev->userq_xa, flags);
111-
if (r)
112-
goto free_seq64;
113-
114106
userq->fence_drv = fence_drv;
115107

116108
return 0;
117109

118-
free_seq64:
119-
amdgpu_seq64_free(adev, fence_drv->va);
120110
free_fence_drv:
121111
kfree(fence_drv);
122112

@@ -187,11 +177,9 @@ void amdgpu_userq_fence_driver_destroy(struct kref *ref)
187177
struct amdgpu_userq_fence_driver *fence_drv = container_of(ref,
188178
struct amdgpu_userq_fence_driver,
189179
refcount);
190-
struct amdgpu_userq_fence_driver *xa_fence_drv;
191180
struct amdgpu_device *adev = fence_drv->adev;
192181
struct amdgpu_userq_fence *fence, *tmp;
193-
struct xarray *xa = &adev->userq_xa;
194-
unsigned long index, flags;
182+
unsigned long flags;
195183
struct dma_fence *f;
196184

197185
spin_lock_irqsave(&fence_drv->fence_list_lock, flags);
@@ -208,12 +196,6 @@ void amdgpu_userq_fence_driver_destroy(struct kref *ref)
208196
}
209197
spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags);
210198

211-
xa_lock_irqsave(xa, flags);
212-
xa_for_each(xa, index, xa_fence_drv)
213-
if (xa_fence_drv == fence_drv)
214-
__xa_erase(xa, index);
215-
xa_unlock_irqrestore(xa, flags);
216-
217199
/* Free seq64 memory */
218200
amdgpu_seq64_free(adev, fence_drv->va);
219201
kfree(fence_drv);

drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6502,14 +6502,14 @@ static int gfx_v11_0_eop_irq(struct amdgpu_device *adev,
65026502
DRM_DEBUG("IH: CP EOP\n");
65036503

65046504
if (adev->enable_mes && doorbell_offset) {
6505-
struct amdgpu_userq_fence_driver *fence_drv = NULL;
6506-
struct xarray *xa = &adev->userq_xa;
6505+
struct amdgpu_usermode_queue *queue;
6506+
struct xarray *xa = &adev->userq_doorbell_xa;
65076507
unsigned long flags;
65086508

65096509
xa_lock_irqsave(xa, flags);
6510-
fence_drv = xa_load(xa, doorbell_offset);
6511-
if (fence_drv)
6512-
amdgpu_userq_fence_driver_process(fence_drv);
6510+
queue = xa_load(xa, doorbell_offset);
6511+
if (queue)
6512+
amdgpu_userq_fence_driver_process(queue->fence_drv);
65136513
xa_unlock_irqrestore(xa, flags);
65146514
} else {
65156515
me_id = (entry->ring_id & 0x0c) >> 2;

drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4854,14 +4854,14 @@ static int gfx_v12_0_eop_irq(struct amdgpu_device *adev,
48544854
DRM_DEBUG("IH: CP EOP\n");
48554855

48564856
if (adev->enable_mes && doorbell_offset) {
4857-
struct amdgpu_userq_fence_driver *fence_drv = NULL;
4858-
struct xarray *xa = &adev->userq_xa;
4857+
struct xarray *xa = &adev->userq_doorbell_xa;
4858+
struct amdgpu_usermode_queue *queue;
48594859
unsigned long flags;
48604860

48614861
xa_lock_irqsave(xa, flags);
4862-
fence_drv = xa_load(xa, doorbell_offset);
4863-
if (fence_drv)
4864-
amdgpu_userq_fence_driver_process(fence_drv);
4862+
queue = xa_load(xa, doorbell_offset);
4863+
if (queue)
4864+
amdgpu_userq_fence_driver_process(queue->fence_drv);
48654865
xa_unlock_irqrestore(xa, flags);
48664866
} else {
48674867
me_id = (entry->ring_id & 0x0c) >> 2;

drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3643,14 +3643,15 @@ static int gfx_v12_1_eop_irq(struct amdgpu_device *adev,
36433643
DRM_DEBUG("IH: CP EOP\n");
36443644

36453645
if (adev->enable_mes && doorbell_offset) {
3646-
struct amdgpu_userq_fence_driver *fence_drv = NULL;
3647-
struct xarray *xa = &adev->userq_xa;
3646+
struct xarray *xa = &adev->userq_doorbell_xa;
3647+
struct amdgpu_usermode_queue *queue;
36483648
unsigned long flags;
36493649

36503650
xa_lock_irqsave(xa, flags);
3651-
fence_drv = xa_load(xa, doorbell_offset);
3652-
if (fence_drv)
3653-
amdgpu_userq_fence_driver_process(fence_drv);
3651+
queue = xa_load(xa, doorbell_offset);
3652+
if (queue)
3653+
amdgpu_userq_fence_driver_process(queue->fence_drv);
3654+
36543655
xa_unlock_irqrestore(xa, flags);
36553656
} else {
36563657
me_id = (entry->ring_id & 0x0c) >> 2;

drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1662,16 +1662,16 @@ static int sdma_v6_0_process_fence_irq(struct amdgpu_device *adev,
16621662
u32 doorbell_offset = entry->src_data[0];
16631663

16641664
if (adev->enable_mes && doorbell_offset) {
1665-
struct amdgpu_userq_fence_driver *fence_drv = NULL;
1666-
struct xarray *xa = &adev->userq_xa;
1665+
struct amdgpu_usermode_queue *queue;
1666+
struct xarray *xa = &adev->userq_doorbell_xa;
16671667
unsigned long flags;
16681668

16691669
doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
16701670

16711671
xa_lock_irqsave(xa, flags);
1672-
fence_drv = xa_load(xa, doorbell_offset);
1673-
if (fence_drv)
1674-
amdgpu_userq_fence_driver_process(fence_drv);
1672+
queue = xa_load(xa, doorbell_offset);
1673+
if (queue)
1674+
amdgpu_userq_fence_driver_process(queue->fence_drv);
16751675
xa_unlock_irqrestore(xa, flags);
16761676
}
16771677

drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,16 +1594,16 @@ static int sdma_v7_0_process_fence_irq(struct amdgpu_device *adev,
15941594
u32 doorbell_offset = entry->src_data[0];
15951595

15961596
if (adev->enable_mes && doorbell_offset) {
1597-
struct amdgpu_userq_fence_driver *fence_drv = NULL;
1598-
struct xarray *xa = &adev->userq_xa;
1597+
struct xarray *xa = &adev->userq_doorbell_xa;
1598+
struct amdgpu_usermode_queue *queue;
15991599
unsigned long flags;
16001600

16011601
doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT;
16021602

16031603
xa_lock_irqsave(xa, flags);
1604-
fence_drv = xa_load(xa, doorbell_offset);
1605-
if (fence_drv)
1606-
amdgpu_userq_fence_driver_process(fence_drv);
1604+
queue = xa_load(xa, doorbell_offset);
1605+
if (queue)
1606+
amdgpu_userq_fence_driver_process(queue->fence_drv);
16071607
xa_unlock_irqrestore(xa, flags);
16081608
}
16091609

0 commit comments

Comments
 (0)