]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
dma-fence: Fix potential tracepoint null pointer dereferences
authorTvrtko Ursulin <tvrtko.ursulin@igalia.com>
Wed, 15 Apr 2026 08:32:07 +0000 (09:32 +0100)
committerTvrtko Ursulin <tursulin@ursulin.net>
Wed, 15 Apr 2026 10:52:23 +0000 (11:52 +0100)
Trace_dma_fence_signaled, trace_dma_fence_wait_end and
trace_dma_fence_destroy can all currently dereference a null fence->ops
pointer after it has been reset on fence signalling.

Lets use the safe string getters for most tracepoints to avoid this class
of a problem, while for the signal tracepoint we move it to before ops are
cleared to avoid losing the driver and timeline name information. Apart
from moving it we also need to add a new tracepoint class to bypass the
safe name getters since the signaled bit is already set.

For dma_fence_init we also need to use the new tracepoint class since the
rcu read lock is not held there, and we can do the same for the enable
signaling since there we are certain the fence cannot be signaled while
we are holding the lock and have even validated the fence->ops.

Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Fixes: 541c8f2468b9 ("dma-buf: detach fence ops on signal v3")
Cc: Christian König <christian.koenig@amd.com>
Cc: Philipp Stanner <phasta@kernel.org>
Cc: Boris Brezillon <boris.brezillon@collabora.com>
Cc: linux-media@vger.kernel.org
Cc: linaro-mm-sig@lists.linaro.org
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Tvrtko Ursulin <tursulin@ursulin.net>
Link: https://lore.kernel.org/r/20260415083207.40513-2-tvrtko.ursulin@igalia.com
drivers/dma-buf/dma-fence.c
include/trace/events/dma_fence.h

index 1826ba73094c8baa2d6d095657f2ded3e4becd59..1c1eaecaf1b091f15de2ea0c6ee5e1aa5a8797bf 100644 (file)
@@ -363,6 +363,8 @@ void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
                                      &fence->flags)))
                return;
 
+       trace_dma_fence_signaled(fence);
+
        /*
         * When neither a release nor a wait operation is specified set the ops
         * pointer to NULL to allow the fence structure to become independent
@@ -377,7 +379,6 @@ void dma_fence_signal_timestamp_locked(struct dma_fence *fence,
 
        fence->timestamp = timestamp;
        set_bit(DMA_FENCE_FLAG_TIMESTAMP_BIT, &fence->flags);
-       trace_dma_fence_signaled(fence);
 
        list_for_each_entry_safe(cur, tmp, &cb_list, node) {
                INIT_LIST_HEAD(&cur->node);
index 3abba45c0601a49103e470d88950929934b6f3a8..5b10a9e06fb4ec97ce15b1fb47ec0ddad46eea1f 100644 (file)
@@ -9,12 +9,40 @@
 
 struct dma_fence;
 
+DECLARE_EVENT_CLASS(dma_fence,
+
+       TP_PROTO(struct dma_fence *fence),
+
+       TP_ARGS(fence),
+
+       TP_STRUCT__entry(
+               __string(driver, dma_fence_driver_name(fence))
+               __string(timeline, dma_fence_timeline_name(fence))
+               __field(unsigned int, context)
+               __field(unsigned int, seqno)
+       ),
+
+       TP_fast_assign(
+               __assign_str(driver);
+               __assign_str(timeline);
+               __entry->context = fence->context;
+               __entry->seqno = fence->seqno;
+       ),
+
+       TP_printk("driver=%s timeline=%s context=%u seqno=%u",
+                 __get_str(driver), __get_str(timeline), __entry->context,
+                 __entry->seqno)
+);
+
 /*
  * Safe only for call sites which are guaranteed to not race with fence
- * signaling,holding the fence->lock and having checked for not signaled, or the
- * signaling path itself.
+ * signaling, holding the fence->lock and having checked for not signaled, or
+ * the signaling path itself.
+ *
+ * TODO: Remove the need for this event class when drivers switch to independent
+ *       fences.
  */
-DECLARE_EVENT_CLASS(dma_fence,
+DECLARE_EVENT_CLASS(dma_fence_ops,
 
        TP_PROTO(struct dma_fence *fence),
 
@@ -46,7 +74,7 @@ DEFINE_EVENT(dma_fence, dma_fence_emit,
        TP_ARGS(fence)
 );
 
-DEFINE_EVENT(dma_fence, dma_fence_init,
+DEFINE_EVENT(dma_fence_ops, dma_fence_init,
 
        TP_PROTO(struct dma_fence *fence),
 
@@ -60,14 +88,14 @@ DEFINE_EVENT(dma_fence, dma_fence_destroy,
        TP_ARGS(fence)
 );
 
-DEFINE_EVENT(dma_fence, dma_fence_enable_signal,
+DEFINE_EVENT(dma_fence_ops, dma_fence_enable_signal,
 
        TP_PROTO(struct dma_fence *fence),
 
        TP_ARGS(fence)
 );
 
-DEFINE_EVENT(dma_fence, dma_fence_signaled,
+DEFINE_EVENT(dma_fence_ops, dma_fence_signaled,
 
        TP_PROTO(struct dma_fence *fence),