Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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>

authored by

Prike Liang and committed by
Alex Deucher
34f31fe4 05ce4441

+28 -52
-5
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 1045 1045 struct amdgpu_mqd mqds[AMDGPU_HW_IP_NUM]; 1046 1046 const struct amdgpu_userq_funcs *userq_funcs[AMDGPU_HW_IP_NUM]; 1047 1047 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; 1053 1048 /** 1054 1049 * @userq_doorbell_xa: Global user queue map (doorbell index → queue) 1055 1050 * Key: doorbell_index (unique global identifier for the queue)
+1 -3
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
··· 3757 3757 spin_lock_init(&adev->virt.rlcg_reg_lock); 3758 3758 spin_lock_init(&adev->wb.lock); 3759 3759 3760 - xa_init_flags(&adev->userq_xa, XA_FLAGS_LOCK_IRQ); 3761 - 3762 3760 INIT_LIST_HEAD(&adev->reset_list); 3763 3761 3764 3762 INIT_LIST_HEAD(&adev->ras_list); 3765 3763 3766 3764 INIT_LIST_HEAD(&adev->pm.od_kobj_list); 3767 3765 3768 - xa_init(&adev->userq_doorbell_xa); 3766 + xa_init_flags(&adev->userq_doorbell_xa, XA_FLAGS_LOCK_IRQ); 3769 3767 3770 3768 INIT_DELAYED_WORK(&adev->delayed_init_work, 3771 3769 amdgpu_device_delayed_init_work_handler);
+1 -19
drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
··· 81 81 struct amdgpu_usermode_queue *userq) 82 82 { 83 83 struct amdgpu_userq_fence_driver *fence_drv; 84 - unsigned long flags; 85 84 int r; 86 85 87 86 fence_drv = kzalloc_obj(*fence_drv); ··· 103 104 fence_drv->context = dma_fence_context_alloc(1); 104 105 get_task_comm(fence_drv->timeline_name, current); 105 106 106 - xa_lock_irqsave(&adev->userq_xa, flags); 107 - r = xa_err(__xa_store(&adev->userq_xa, userq->doorbell_index, 108 - fence_drv, GFP_KERNEL)); 109 - xa_unlock_irqrestore(&adev->userq_xa, flags); 110 - if (r) 111 - goto free_seq64; 112 - 113 107 userq->fence_drv = fence_drv; 114 108 115 109 return 0; 116 110 117 - free_seq64: 118 - amdgpu_seq64_free(adev, fence_drv->va); 119 111 free_fence_drv: 120 112 kfree(fence_drv); 121 113 ··· 177 187 struct amdgpu_userq_fence_driver *fence_drv = container_of(ref, 178 188 struct amdgpu_userq_fence_driver, 179 189 refcount); 180 - struct amdgpu_userq_fence_driver *xa_fence_drv; 181 190 struct amdgpu_device *adev = fence_drv->adev; 182 191 struct amdgpu_userq_fence *fence, *tmp; 183 - struct xarray *xa = &adev->userq_xa; 184 - unsigned long index, flags; 192 + unsigned long flags; 185 193 struct dma_fence *f; 186 194 187 195 spin_lock_irqsave(&fence_drv->fence_list_lock, flags); ··· 195 207 dma_fence_put(f); 196 208 } 197 209 spin_unlock_irqrestore(&fence_drv->fence_list_lock, flags); 198 - 199 - xa_lock_irqsave(xa, flags); 200 - xa_for_each(xa, index, xa_fence_drv) 201 - if (xa_fence_drv == fence_drv) 202 - __xa_erase(xa, index); 203 - xa_unlock_irqrestore(xa, flags); 204 210 205 211 /* Free seq64 memory */ 206 212 amdgpu_seq64_free(adev, fence_drv->va);
+5 -5
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
··· 6502 6502 DRM_DEBUG("IH: CP EOP\n"); 6503 6503 6504 6504 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; 6507 6507 unsigned long flags; 6508 6508 6509 6509 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); 6513 6513 xa_unlock_irqrestore(xa, flags); 6514 6514 } else { 6515 6515 me_id = (entry->ring_id & 0x0c) >> 2;
+5 -5
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
··· 4854 4854 DRM_DEBUG("IH: CP EOP\n"); 4855 4855 4856 4856 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; 4859 4859 unsigned long flags; 4860 4860 4861 4861 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); 4865 4865 xa_unlock_irqrestore(xa, flags); 4866 4866 } else { 4867 4867 me_id = (entry->ring_id & 0x0c) >> 2;
+6 -5
drivers/gpu/drm/amd/amdgpu/gfx_v12_1.c
··· 3643 3643 DRM_DEBUG("IH: CP EOP\n"); 3644 3644 3645 3645 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; 3648 3648 unsigned long flags; 3649 3649 3650 3650 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 + 3654 3655 xa_unlock_irqrestore(xa, flags); 3655 3656 } else { 3656 3657 me_id = (entry->ring_id & 0x0c) >> 2;
+5 -5
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
··· 1662 1662 u32 doorbell_offset = entry->src_data[0]; 1663 1663 1664 1664 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; 1667 1667 unsigned long flags; 1668 1668 1669 1669 doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT; 1670 1670 1671 1671 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); 1675 1675 xa_unlock_irqrestore(xa, flags); 1676 1676 } 1677 1677
+5 -5
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
··· 1594 1594 u32 doorbell_offset = entry->src_data[0]; 1595 1595 1596 1596 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; 1599 1599 unsigned long flags; 1600 1600 1601 1601 doorbell_offset >>= SDMA0_QUEUE0_DOORBELL_OFFSET__OFFSET__SHIFT; 1602 1602 1603 1603 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); 1607 1607 xa_unlock_irqrestore(xa, flags); 1608 1608 } 1609 1609