[PATCH v3 2/2] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()

From: André Draszik

Date: Tue Jul 21 2026 - 04:28:55 EST


Since commit 541c8f2468b9 ("dma-buf: detach fence ops on signal v3"),
I'm seeing the BUG_ON() triggering in drm_crtc's fence_to_crtc() via
drm_crtc_fence_get_driver_name() regularly:

Call trace:
panic+0x58/0x5c
die+0x160/0x178
bug_brk_handler+0x70/0xa4
call_el1_break_hook+0x3c/0x1a0
do_el1_brk64+0x24/0x74
el1_brk64+0x34/0x54
el1h_64_sync_handler+0x80/0xfc
el1h_64_sync+0x84/0x88
drm_crtc_fence_get_driver_name+0x60/0x68 (P)
sync_file_get_name+0x184/0x45c
sync_file_ioctl+0x404/0xf70
__arm64_sys_ioctl+0x124/0x1dc

This looks to be caused by a code flow similar to the following:

+++ snip +++
thread A thread B

ioctl(SYNC_IOC_FILE_INFO)
sync_file_ioctl()
sync_file_get_name()
dma_fence_signal_timestamp_locked() dma_fence_driver_name()
ops = rcu_dereference(fence->ops)
if (!dma_fence_test_signaled_flag())
ops->get_driver_name(fence) i.e.
drm_crtc_fence_get_driver_name()
test_and_set_bit(SIGNALED)
RCU_INIT_POINTER(fence->ops, NULL)
drm_crtc_fence_get_driver_name()
BUG_ON(rcu_access_pointer(fence->ops)
!= &drm_crtc_fence_ops)
+++ snap +++

In other words, a fence's ops pointer can now change to NULL on signal,
which wasn't the case before the culprit commit and hence the BUG_ON()
triggers.

Simply drop the BUG_ON() as it's usage of fence ops is invalid now, and
because using BUG_ON() and friends to take down the system is an
unacceptable way to handle a failure.

Note that the adjacent drm_crtc_fence_get_timeline_name() has the same
problem and is fixed by this patch as well.

Fixes: 541c8f2468b9 ("dma-buf: detach fence ops on signal v3")
Cc: stable@xxxxxxxxxxxxxxx
Reviewed-by: Philipp Stanner <phasta@xxxxxxxxxx>
Signed-off-by: André Draszik <andre.draszik@xxxxxxxxxx>
---
v3:
- Philipp:
- shorten commit message
- explicitly Cc: stable
- collect tag

v2:
- don't turn fence_to_crtc() into macro
- update commit message to include reference to unacceptable use of BUG
---
drivers/gpu/drm/drm_crtc.c | 3 ---
1 file changed, 3 deletions(-)

diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
index e8e80c936852..5295ec122e0d 100644
--- a/drivers/gpu/drm/drm_crtc.c
+++ b/drivers/gpu/drm/drm_crtc.c
@@ -154,11 +154,8 @@ static void drm_crtc_crc_fini(struct drm_crtc *crtc)
#endif
}

-static const struct dma_fence_ops drm_crtc_fence_ops;
-
static struct drm_crtc *fence_to_crtc(struct dma_fence *fence)
{
- BUG_ON(rcu_access_pointer(fence->ops) != &drm_crtc_fence_ops);
return container_of(fence->extern_lock, struct drm_crtc, fence_lock);
}


--
2.55.0.229.g6434b31f56-goog