On 11/4/26 23:18, Kirtikumar Anandrao Ramchandani wrote:
> The last dma_fence_put() can drop a sync point's reference count to
> zero before timeline_fence_release() acquires the timeline lock to
> remove it from pt_list. If sync_timeline_signal() acquires the lock in
> that window, dma_fence_get() attempts to increment a zero reference
> count and triggers a refcount warning.
>
> Use dma_fence_get_rcu() to acquire the temporary signaling reference
> only if the fence is still referenced, as sync_pt_create() already
> does when looking up an existing point. Skip a point whose reference
> count has reached zero: its release callback will remove it from the
> list and tree once the timeline lock is released.
>
> The timeline lock prevents the release callback from removing or
> freeing a listed point during this check. For a live point, retain the
> temporary reference until after dropping the lock, preserving the
> protection against recursive locking from signaling callbacks.
Please add this explanation as code comment to the patch.
>
> Fixes: e531fdb5cd5e ("dma-buf/sw_sync: Avoid recursive lock during fence
> signal")
Drop that here. SW_SYNC is a unit testing functionality which can intentionally
crash the kernel.
You get literally tons of warnings and a tainted kernel when it is
enabled/used. So bugs like those are generally not backported.
Apart from that the patch looks good to me,
Christian.
> Reported-by: [email protected]
> <mailto:syzbot%[email protected]>
> Closes: https://syzkaller.appspot.com/bug?extid=cba1a1f459230395a076
> <https://syzkaller.appspot.com/bug?extid=cba1a1f459230395a076>
> Signed-off-by: Kirtikumar Anandrao Ramchandani <[email protected]
> <mailto:[email protected]>>
> ---
>
> drivers/dma-buf/sw_sync.c | 3 ++-
> 1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c
> index 8df20b0218a9..7f1eadee4cdf 100644
> --- a/drivers/dma-buf/sw_sync.c
> +++ b/drivers/dma-buf/sw_sync.c
> @@ -221,7 +221,8 @@
> if (!timeline_fence_signaled(&pt->base))
> break;
>
> - dma_fence_get(&pt->base);
> + if (!dma_fence_get_rcu(&pt->base))
> + continue;
>
> list_move_tail(&pt->link, &signalled);
> rb_erase(&pt->node, &obj->pt_tree);
>
> base-commit: 05441d697f7f9a927264f4058cbbc6a03dfcac9d