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

From: André Draszik

Date: Tue Jun 23 2026 - 07:37:34 EST


Hi,

On Thu, 2026-06-18 at 17:56 +0200, Philipp Stanner wrote:
> +Cc Danilo
>
> On Thu, 2026-06-18 at 15:03 +0100, André Draszik wrote:
> > 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)
>
> Now this looks like a very similar problem that I have recently been
> concerned with:
>
> https://lore.kernel.org/dri-devel/20260612104251.2264707-2-phasta@xxxxxxxxxx/
>
> https://lore.kernel.org/dri-devel/fa0dc9757bf8343516c4b156a2b70ec91b64ef8f.camel@xxxxxxxxxxx/
>
>
> I continue to believe because of bugs like this and the ones I have
> quoted in the threads above the robustness of the kernel could be
> greatly improved if we could get dma_fence fully synchronized with its
> lock.

On top of that, sashiko highlighted (via my other patch) that the existing
code is missing some memory barriers:

https://sashiko.dev/#/patchset/20260618-linux-drm_crtc_fix-v1-1-801f29c9853d@xxxxxxxxxx?part=1

I believe Lock synchronization would resolve that (as would adding explicit
memory barriers).

[...]

> > diff --git a/drivers/gpu/drm/drm_crtc.c b/drivers/gpu/drm/drm_crtc.c
> > index 63ead8ba6756..31c8636e7467 100644
> > --- a/drivers/gpu/drm/drm_crtc.c
> > +++ b/drivers/gpu/drm/drm_crtc.c
> > @@ -73,6 +73,9 @@
> >   * &drm_mode_config_funcs.atomic_check.
> >   */
> >  
> > +#define fence_to_crtc(f) container_of((f)->extern_lock, \
> > +       struct drm_crtc, fence_lock)
>
> I agree that macros should be avoided if possible.

No problem, I'll change that.

>
> > +
> >  /**
> >   * drm_crtc_from_index - find the registered CRTC at an index
> >   * @dev: DRM device
> > @@ -154,14 +157,6 @@ 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);
>
> +1
>
> BUG_ON is more or less deprecated and should not be used anymore. There
> needs to be bombastic justification for shooting down the entire
> kernel.

Yes, I meant to mention that in my commit message as well.

Now, you might have seen that sashiko highlighted that the existing
BUG_ON() is masking a potential use-after-free during driver removal which
I believe to be a correct observation. It suggests two alternative ways to
resolve it:

https://sashiko.dev/#/patchset/20260618-linux-drm_crtc_fix2-v1-1-c03e77b36f34@xxxxxxxxxx?part=1

> Does the CRTC or DRM device need to be kept alive for the RCU grace period,
> or should the fence hold a proper reference to prevent the use-after-free
> when get_driver_name() and get_timeline_name() access the freed CRTC
> structure?

Do you guys have any preference on that? It appears the use-after-free
should be resolved before merging the removal of the BUG_ON(), and I'd like
to progress on this.

Cheers,
Andre'