Re: [PATCH v3 1/2] drm/drm_crtc: ensure dma_fence_ops remain valid during device unbind

Christian König <[email protected]> Mon, 3 Aug 2026 14:26:26 +0200
Newsgroups org.kernel.vger.linux-media,org.freedesktop.lists.dri-devel,org.kernel.vger.linux-kernel,org.kernel.vger.stable
Message-ID <[email protected]>
On 7/21/26 13:20, Philipp Stanner wrote:
> On Tue, 2026-07-21 at 09:21 +0100, André Draszik wrote:
>> In [1], sashiko reported the following issue:
>>
>> === snip ===
>> Looking at how these fences are managed, drm_crtc_create_fence()
>> creates a dma_fence without taking a reference to the drm_device or
>> drm_crtc. Because the sync_file framework exposes this fence to
>> userspace, the fence can outlive the CRTC.
>>
>> The dma_fence contract requires that data accessed by dma_fence_ops
>> (like get_driver_name) must remain valid for an RCU grace period after
>> the fence is signaled. However, drm_crtc_cleanup() and the subsequent
>> freeing of the device do not wait for an RCU grace period via
>> synchronize_rcu().
>>
>> If userspace calls ioctl(SYNC_IOC_FILE_INFO) concurrently with a device
>> hot-unplug:
>>
>> CPU1 (Userspace)
>> sync_file_get_name()
>>   ops = rcu_dereference(fence->ops);
>>   if (!dma_fence_test_signaled_flag())
>>     // Preempted or delayed here
> 
> nit: no one will be preempted here since the RCU read lock must be
> held. The Sashiko tool misses the point, which is simply that someone
> illegally frees up stuff that might be still in use, with or without
> delay or preemption, that's all irrelevant for the issue.
> 
> Anyways, thanks for fixing this:

Seconded.

> 
>>
>>
> 
> […]
> 
>> Link: https://sashiko.dev/#/patchset/[email protected]?part=1
>> Fixes: 6d6003c4b613 ("drm/fence: add fence timeline to drm_crtc")
>> Cc: [email protected]
>> Signed-off-by: André Draszik <[email protected]>
> 
> Reviewed-by: Philipp Stanner <[email protected]>

Reviewed-by: Christian König <[email protected]> for both patches.

> 
>>
>> ---
>> v3:
>> - Philipp: update kerneldoc, add Fixes:
>>
>> v2: new patch
>> ---
>>  drivers/gpu/drm/drm_crtc.c | 15 ++++++++++++---
>>  1 file changed, 12 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
>> index 63ead8ba6756..e8e80c936852 100644
>> --- a/drivers/gpu/drm/drm_crtc.c
>> +++ b/drivers/gpu/drm/drm_crtc.c
>> @@ -493,14 +493,23 @@ EXPORT_SYMBOL(__drmm_crtc_alloc_with_planes);
>>   * drm_crtc_cleanup - Clean up the core crtc usage
>>   * @crtc: CRTC to cleanup
>>   *
>> - * This function cleans up @crtc and removes it from the DRM mode setting
>> - * core. Note that the function does *not* free the crtc structure itself,
>> - * this is the responsibility of the caller.
>> + * This function cleans up @crtc and removes it from the DRM mode setting core,
>> + * after first waiting an RCU grace period to ensure @crtc->dev can safely be
>> + * dereferenced by our dma_fence_ops.
>> + *
>> + * Note that the function does *not* free the crtc structure itself, this is the
>> + * responsibility of the caller.
>>   */
>>  void drm_crtc_cleanup(struct drm_crtc *crtc)
>>  {
>>  	struct drm_device *dev = crtc->dev;
>>  
>> +	/* Ensure our dma_fence_ops remain valid for an RCU grace period after
>> +	 * the fence is signaled. This is necessary because our dma_fence_ops
>> +	 * dereference crtc->dev.
>> +	 */
>> +	synchronize_rcu();
>> +
>>  	/* Note that the crtc_list is considered to be static; should we
>>  	 * remove the drm_crtc at runtime we would have to decrement all
>>  	 * the indices on the drm_crtc after us in the crtc_list.