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

drm/xe: Make dma-fences compliant with the safe access rules

Xe can free some of the data pointed to by the dma-fences it exports. Most
notably the timeline name can get freed if userspace closes the associated
submit queue. At the same time the fence could have been exported to a
third party (for example a sync_fence fd) which will then cause an use-
after-free on subsequent access.

To make this safe we need to make the driver compliant with the newly
documented dma-fence rules. Driver has to ensure a RCU grace period
between signalling a fence and freeing any data pointed to by said fence.

For the timeline name we simply make the queue be freed via kfree_rcu and
for the shared lock associated with multiple queues we add a RCU grace
period before freeing the per GT structure holding the lock.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Acked-by: Lucas De Marchi <lucas.demarchi@intel.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20250610164226.10817-5-tvrtko.ursulin@igalia.com

authored by

Tvrtko Ursulin and committed by
Tvrtko Ursulin
6bd90e70 506aa8b0

+11 -1
+2
drivers/gpu/drm/xe/xe_guc_exec_queue_types.h
··· 20 20 struct xe_guc_exec_queue { 21 21 /** @q: Backpointer to parent xe_exec_queue */ 22 22 struct xe_exec_queue *q; 23 + /** @rcu: For safe freeing of exported dma fences */ 24 + struct rcu_head rcu; 23 25 /** @sched: GPU scheduler for this xe_exec_queue */ 24 26 struct xe_gpu_scheduler sched; 25 27 /** @entity: Scheduler entity for this xe_exec_queue */
+6 -1
drivers/gpu/drm/xe/xe_guc_submit.c
··· 1285 1285 xe_sched_entity_fini(&ge->entity); 1286 1286 xe_sched_fini(&ge->sched); 1287 1287 1288 - kfree(ge); 1288 + /* 1289 + * RCU free due sched being exported via DRM scheduler fences 1290 + * (timeline name). 1291 + */ 1292 + kfree_rcu(ge, rcu); 1289 1293 xe_exec_queue_fini(q); 1290 1294 xe_pm_runtime_put(guc_to_xe(guc)); 1291 1295 } ··· 1472 1468 1473 1469 q->guc = ge; 1474 1470 ge->q = q; 1471 + init_rcu_head(&ge->rcu); 1475 1472 init_waitqueue_head(&ge->suspend_wait); 1476 1473 1477 1474 for (i = 0; i < MAX_STATIC_MSG_TYPE; ++i)
+3
drivers/gpu/drm/xe/xe_hw_fence.c
··· 100 100 spin_unlock_irqrestore(&irq->lock, flags); 101 101 dma_fence_end_signalling(tmp); 102 102 } 103 + 104 + /* Safe release of the irq->lock used in dma_fence_init. */ 105 + synchronize_rcu(); 103 106 } 104 107 105 108 void xe_hw_fence_irq_run(struct xe_hw_fence_irq *irq)