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: syzbot+cba1a1f459230395a076@syzkaller.appspotmail.com mailto:syzbot%2Bcba1a1f459230395a076@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cba1a1f459230395a076 https://syzkaller.appspot.com/bug?extid=cba1a1f459230395a076 Signed-off-by: Kirtikumar Anandrao Ramchandani <kirtiar15502@gmail.com mailto:kirtiar15502@gmail.com>
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
linaro-mm-sig@lists.linaro.org