mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
@ 2026-06-18 14:03 André Draszik
  2026-06-18 14:53 ` Jani Nikula
  2026-06-18 15:56 ` Philipp Stanner
  0 siblings, 2 replies; 7+ messages in thread
From: André Draszik @ 2026-06-18 14:03 UTC (permalink / raw)
  To: Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Sumit Semwal, Christian König,
	Tvrtko Ursulin, Boris Brezillon, Philipp Stanner
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team,
	André Draszik

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 +++

I see two ways to resolve this:
a) simply drop the BUG_ON(). It can not work anymore since above
   commit, as it is racy now.
b) pass the original 'ops' pointer obtained in dma_fence_driver_name()
   to all callees.

This patch implements option a), as because:
* I don't see much benefit in passing the extra pointer just for this
  BUG_ON() to work.
* Requiring the dma_fence_ops in those callbacks is an implementation
  detail of the drm_crtc driver, and therefore upper layers shouldn't
  have to care about that.
* The existence of the BUG_ON() doesn't appear to be consistent with
  implementations of ::get_driver_name() or ::get_timeline_name() in
  the majority of other DRM drivers in the first place. Those that do
  have a similar BUG_ON() (i915, xe) probably also need an update
  similar to this patch here but I'm not in a position to test those.

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")
Signed-off-by: André Draszik <andre.draszik@linaro.org>
---
 drivers/gpu/drm/drm_crtc.c | 11 +++--------
 1 file changed, 3 insertions(+), 8 deletions(-)

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)
+
 /**
  * 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);
-	return container_of(fence->extern_lock, struct drm_crtc, fence_lock);
-}
-
 static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
 {
 	struct drm_crtc *crtc = fence_to_crtc(fence);

---
base-commit: e2cae00c05d196491c318196792297f2dfbaa02c
change-id: 20260618-linux-drm_crtc_fix2-23a7c354a412

Best regards,
-- 
André Draszik <andre.draszik@linaro.org>


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
  2026-06-18 14:03 [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name() André Draszik
@ 2026-06-18 14:53 ` Jani Nikula
  2026-06-18 15:56 ` Philipp Stanner
  1 sibling, 0 replies; 7+ messages in thread
From: Jani Nikula @ 2026-06-18 14:53 UTC (permalink / raw)
  To: André Draszik, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
	Christian König, Tvrtko Ursulin, Boris Brezillon,
	Philipp Stanner
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team,
	André Draszik

On Thu, 18 Jun 2026, André Draszik <andre.draszik@linaro.org> 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)
> +++ snap +++
>
> I see two ways to resolve this:
> a) simply drop the BUG_ON(). It can not work anymore since above
>    commit, as it is racy now.
> b) pass the original 'ops' pointer obtained in dma_fence_driver_name()
>    to all callees.
>
> This patch implements option a), as because:
> * I don't see much benefit in passing the extra pointer just for this
>   BUG_ON() to work.
> * Requiring the dma_fence_ops in those callbacks is an implementation
>   detail of the drm_crtc driver, and therefore upper layers shouldn't
>   have to care about that.
> * The existence of the BUG_ON() doesn't appear to be consistent with
>   implementations of ::get_driver_name() or ::get_timeline_name() in
>   the majority of other DRM drivers in the first place. Those that do
>   have a similar BUG_ON() (i915, xe) probably also need an update
>   similar to this patch here but I'm not in a position to test those.
>
> 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")
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  drivers/gpu/drm/drm_crtc.c | 11 +++--------
>  1 file changed, 3 insertions(+), 8 deletions(-)
>
> 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)
> +
>  /**
>   * 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);

Whether removing the BUG_ON() turns out to be the right choice or not, I
couldn't say, but please don't turn this function into a macro, at least
not without rationale. (I can't think of any.)

BR,
Jani.

> -	return container_of(fence->extern_lock, struct drm_crtc, fence_lock);
> -}
> -
>  static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
>  {
>  	struct drm_crtc *crtc = fence_to_crtc(fence);
>
> ---
> base-commit: e2cae00c05d196491c318196792297f2dfbaa02c
> change-id: 20260618-linux-drm_crtc_fix2-23a7c354a412
>
> Best regards,

-- 
Jani Nikula, Intel

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
  2026-06-18 14:03 [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name() André Draszik
  2026-06-18 14:53 ` Jani Nikula
@ 2026-06-18 15:56 ` Philipp Stanner
  2026-06-23 11:37   ` André Draszik
  1 sibling, 1 reply; 7+ messages in thread
From: Philipp Stanner @ 2026-06-18 15:56 UTC (permalink / raw)
  To: André Draszik, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
	Christian König, Tvrtko Ursulin, Boris Brezillon,
	Philipp Stanner, Danilo Krummrich
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team

+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@kernel.org/

https://lore.kernel.org/dri-devel/fa0dc9757bf8343516c4b156a2b70ec91b64ef8f.camel@mailbox.org/


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.


That said:

> +++ snap +++
> 
> I see two ways to resolve this:
> a) simply drop the BUG_ON(). It can not work anymore since above
>    commit, as it is racy now.
> b) pass the original 'ops' pointer obtained in dma_fence_driver_name()
>    to all callees.
> 
> This patch implements option a), as because:
> * I don't see much benefit in passing the extra pointer just for this
>   BUG_ON() to work.
> * Requiring the dma_fence_ops in those callbacks is an implementation
>   detail of the drm_crtc driver, and therefore upper layers shouldn't
>   have to care about that.
> * The existence of the BUG_ON() doesn't appear to be consistent with
>   implementations of ::get_driver_name() or ::get_timeline_name() in
>   the majority of other DRM drivers in the first place. Those that do
>   have a similar BUG_ON() (i915, xe) probably also need an update
>   similar to this patch here but I'm not in a position to test those.
> 
> 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")
> Signed-off-by: André Draszik <andre.draszik@linaro.org>
> ---
>  drivers/gpu/drm/drm_crtc.c | 11 +++--------
>  1 file changed, 3 insertions(+), 8 deletions(-)
> 
> 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.

> +
>  /**
>   * 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.


P.

> -	return container_of(fence->extern_lock, struct drm_crtc, fence_lock);
> -}
> -
>  static const char *drm_crtc_fence_get_driver_name(struct dma_fence *fence)
>  {
>  	struct drm_crtc *crtc = fence_to_crtc(fence);
> 
> ---
> base-commit: e2cae00c05d196491c318196792297f2dfbaa02c
> change-id: 20260618-linux-drm_crtc_fix2-23a7c354a412
> 
> Best regards,

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
  2026-06-18 15:56 ` Philipp Stanner
@ 2026-06-23 11:37   ` André Draszik
  2026-06-23 11:58     ` Philipp Stanner
  0 siblings, 1 reply; 7+ messages in thread
From: André Draszik @ 2026-06-23 11:37 UTC (permalink / raw)
  To: phasta, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Sumit Semwal, Christian König,
	Tvrtko Ursulin, Boris Brezillon, Danilo Krummrich
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team

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@kernel.org/
> 
> https://lore.kernel.org/dri-devel/fa0dc9757bf8343516c4b156a2b70ec91b64ef8f.camel@mailbox.org/
> 
> 
> 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@linaro.org?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@linaro.org?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'

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
  2026-06-23 11:37   ` André Draszik
@ 2026-06-23 11:58     ` Philipp Stanner
  2026-06-23 14:33       ` André Draszik
  0 siblings, 1 reply; 7+ messages in thread
From: Philipp Stanner @ 2026-06-23 11:58 UTC (permalink / raw)
  To: André Draszik, phasta, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
	Christian König, Tvrtko Ursulin, Boris Brezillon,
	Danilo Krummrich
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team

On Tue, 2026-06-23 at 12:37 +0100, André Draszik wrote:
> 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@kernel.org/
> > 
> > https://lore.kernel.org/dri-devel/fa0dc9757bf8343516c4b156a2b70ec91b64ef8f.camel@mailbox.org/
> > 
> > 
> > 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@linaro.org?part=1
> 
> I believe Lock synchronization would resolve that (as would adding explicit
> memory barriers).

That is being discussed in the thread I linked, where Gary lists which
barriers you would need for (presumably correct) lockless magic.

However, if my issue were to be solved with barriers, the
test_and_set_bit() in dma_fence_signal_timestamp_locked() would have to
be replaced with the more weakly ordered test_bit() and set_bit(),
maybe creating other pitfalls.

The ordering issue in the get_*_name() functions plays into that.
Setting the bit would then be done after setting the ops-pointer to
NULL. So one would have to try to move the NULL set, too.

Long story short, this is painful and subtle.

But I think what we are realizing over and over again is that dma_fence
has many subtleties to its API contract, and the implementation's
sparring use of spinlocks leads to workarounds where people take locks
manually or have to do an RCU dance.

Note that Christian is strongly opposed to guarding everything with
locks, in part for supposedly occuring deadlocks in the fence callbacks
when the driver needs to take its own locks.

The community discussion regarding that problem is currently in some
sort of dead end, where none of us seems to know what the correct path
forward is.

drm_sched users (and future users in Rust) use intermediate fences
which decouple e.g. userspace from the actual hardware fences. So one
path forward might be to question the callbacks in general and think
about some sort of replacement for them.

> 
> [...]
> > > 
> 
> > 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.

My understanding of the current situation is that as an issuer of
dma_fence's you, in general, should wait for a grace period until you
perform operations like driver unload, or, more generally, have fence-
related resources and such being accessed through callbacks go away.

Danilo has recently mentioned some life-time inconsistencies between
wider kernel device model and DRM device model that might be related to
that discussion, and which made him object against some RCU
requirements.

Maybe he's got the time to share some details with you that are
relevant to your work.


P.

> 
> Cheers,
> Andre'

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
  2026-06-23 11:58     ` Philipp Stanner
@ 2026-06-23 14:33       ` André Draszik
  2026-06-24  7:33         ` Philipp Stanner
  0 siblings, 1 reply; 7+ messages in thread
From: André Draszik @ 2026-06-23 14:33 UTC (permalink / raw)
  To: phasta, Maarten Lankhorst, Maxime Ripard, Thomas Zimmermann,
	David Airlie, Simona Vetter, Sumit Semwal, Christian König,
	Tvrtko Ursulin, Boris Brezillon, Danilo Krummrich
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team

Hi Philipp,

On Tue, 2026-06-23 at 13:58 +0200, Philipp Stanner wrote:
> On Tue, 2026-06-23 at 12:37 +0100, André Draszik wrote:
> > On Thu, 2026-06-18 at 17:56 +0200, Philipp Stanner wrote:
> > > 
> > > 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@linaro.org?part=1
> > 
> > I believe Lock synchronization would resolve that (as would adding explicit
> > memory barriers).
> 
> That is being discussed in the thread I linked, where Gary lists which
> barriers you would need for (presumably correct) lockless magic.

Having read Gary's suggestion, that aligns with what I had in mind.

> However, if my issue were to be solved with barriers, the
> test_and_set_bit() in dma_fence_signal_timestamp_locked() would have to
> be replaced with the more weakly ordered test_bit() and set_bit(),
> maybe creating other pitfalls.

For the avoidance of doubts, I'm not saying that all the issues you raised
can be solved by barriers instead of appropriate locks (I don't know enough
about the code and issues in general here).

I do think however that appropriate locks will fix the ordering issue
highlighted by sashiko (i.e. +1 for your argument). Barriers would fix this
specific issue, too, but that is not a statement about any wider issues. 

> The ordering issue in the get_*_name() functions plays into that.
> Setting the bit would then be done after setting the ops-pointer to
> NULL. So one would have to try to move the NULL set, too.
> 
> Long story short, this is painful and subtle.
> 
> But I think what we are realizing over and over again is that dma_fence
> has many subtleties to its API contract, and the implementation's
> sparring use of spinlocks leads to workarounds where people take locks
> manually or have to do an RCU dance.
> 
> Note that Christian is strongly opposed to guarding everything with
> locks, in part for supposedly occuring deadlocks in the fence callbacks
> when the driver needs to take its own locks.

ww_mutex could help against deadlocks, but might affect performance, in case
these are all critical code paths (IDK),

> The community discussion regarding that problem is currently in some
> sort of dead end, where none of us seems to know what the correct path
> forward is.

Please ignore if the following doesn't make sense, I'm just a bystander :-)
How about at least adding the required barriers and related changes, and
taking it from there? This would solve some immediate and easy to hit
issues on Arm64? If they turn out to be insufficient, code can still
be changed.



> > > 
> [...]
> My understanding of the current situation is that as an issuer of
> dma_fence's you, in general, should wait for a grace period until you
> perform operations like driver unload, or, more generally, have fence-
> related resources and such being accessed through callbacks go away.

If I understand correctly, simply waiting for a grace period in the
driver's unbind should be the way to go.


> Danilo ... Maybe he's got the time to share some details with you that are
> relevant to your work.

Will wait a little :-)



BTW, thanks Philipp for all these details, much appreciated.

Cheers,
A.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name()
  2026-06-23 14:33       ` André Draszik
@ 2026-06-24  7:33         ` Philipp Stanner
  0 siblings, 0 replies; 7+ messages in thread
From: Philipp Stanner @ 2026-06-24  7:33 UTC (permalink / raw)
  To: André Draszik, phasta, Maarten Lankhorst, Maxime Ripard,
	Thomas Zimmermann, David Airlie, Simona Vetter, Sumit Semwal,
	Christian König, Tvrtko Ursulin, Boris Brezillon,
	Danilo Krummrich
  Cc: dri-devel, linux-kernel, linux-media, linaro-mm-sig,
	Peter Griffin, Tudor Ambarus, Juan Yescas, kernel-team

On Tue, 2026-06-23 at 15:33 +0100, André Draszik wrote:
> > However, if my issue were to be solved with barriers, the
> > test_and_set_bit() in dma_fence_signal_timestamp_locked() would have to
> > be replaced with the more weakly ordered test_bit() and set_bit(),
> > maybe creating other pitfalls.
> 
> For the avoidance of doubts, I'm not saying that all the issues you raised
> can be solved by barriers instead of appropriate locks (I don't know enough
> about the code and issues in general here).

I'm not saying that you're saying that. I'm just cautioning you that
this change could be tricky.

> 
> I do think however that appropriate locks will fix the ordering issue
> highlighted by sashiko (i.e. +1 for your argument). Barriers would fix this
> specific issue, too, but that is not a statement about any wider issues. 
> 
> > The ordering issue in the get_*_name() functions plays into that.
> > Setting the bit would then be done after setting the ops-pointer to
> > NULL. So one would have to try to move the NULL set, too.
> > 
> > Long story short, this is painful and subtle.
> > 
> > But I think what we are realizing over and over again is that dma_fence
> > has many subtleties to its API contract, and the implementation's
> > sparring use of spinlocks leads to workarounds where people take locks
> > manually or have to do an RCU dance.
> > 
> > Note that Christian is strongly opposed to guarding everything with
> > locks, in part for supposedly occuring deadlocks in the fence callbacks
> > when the driver needs to take its own locks.
> 
> ww_mutex could help against deadlocks, but might affect performance, in case
> these are all critical code paths (IDK),

You can't use sleepable locks in fences. They fire in interrupt context
left and right ;)

Despite, that wouldn't even solve the reported problem.

The tl;dr is:

there is fence_ops->enable_signaling(), which is currently being called
with the fence lock held. So the driver, in that callback, cannot take
a driver-specific lock IF there is another driver party (like an IRQ)
taking first the driver lock and then the fence lock.

Which is why Christian König wants to remove the fence lock being held
in enable_signaling().

One reason why that, supposedly, is currently not a problem is that
without fence->inline_lock, you can protect the fctx with the same lock
and do fctx list manipulations in enable_signaling() with lock
protection.


If you have a big bowl of popcorn available, you could checkout this
thread:

https://lore.kernel.org/dri-devel/20260608142436.265820-2-phasta@kernel.org/

;p

My own thinking is:
If everyone used inline_lock, and if we could rely on everyone being
able to do the necessary work in enable_signaling() without said lock-
inversion, then we could perfectly synchronize all actions related to
dma_fence, including driver and, thus, fence_ops unload.

The only thing blocking really might be enable_signaling (the other
callbacks already take the lock). The more difficult question would be
how to implement that in a backwards compatible manner, i.e., for those
who don't have inline_lock.

Another idea for the distant future might be to question the existence
of those callbacks. Userspace often is sort of decoupled from the
hardware fences through intermediate fences already.

> 
> > The community discussion regarding that problem is currently in some
> > sort of dead end, where none of us seems to know what the correct path
> > forward is.
> 
> Please ignore if the following doesn't make sense, I'm just a bystander :-)
> How about at least adding the required barriers and related changes, and
> taking it from there? This would solve some immediate and easy to hit
> issues on Arm64? If they turn out to be insufficient, code can still
> be changed.
> 

I am in support of that, which is why I posted that RFC for feedback
about the appropriate memory barriers.

> 
> BTW, thanks Philipp for all these details, much appreciated.

You're welcome. If you'd find a clever solution, probably everyone
would be happy.


P.

> 
> Cheers,
> A.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2026-06-24  7:34 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-18 14:03 [PATCH] drm/drm_crtc: fix race with dma_fence_signal() in ::get_driver_name() André Draszik
2026-06-18 14:53 ` Jani Nikula
2026-06-18 15:56 ` Philipp Stanner
2026-06-23 11:37   ` André Draszik
2026-06-23 11:58     ` Philipp Stanner
2026-06-23 14:33       ` André Draszik
2026-06-24  7:33         ` Philipp Stanner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox