On 11/5/26 15:26, 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. If sync_timeline_signal() takes the lock in that window, dma_fence_get() attempts to increment a zero reference count.
Use dma_fence_get_rcu() for the temporary signaling reference and skip a point whose reference count has reached zero. The timeline lock serializes with timeline_fence_release(), keeping the point allocated while its reference count is examined. The release callback removes the point from the list and tree after acquiring the lock.
For a live point, retain the temporary reference until after dropping the lock, avoiding recursive locking through signaling callbacks.
Reported-by: syzbot+cba1a1f459230395a076@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=cba1a1f459230395a076 Signed-off-by: Kirtikumar Anandrao Ramchandani kirtiar15502@gmail.com
Reviewed-by: Christian König christian.koenig@amd.com
I will push this to drm-misc-next soon.
Thanks, Christian.
Changes in v4:
- Document why the timeline lock makes the conditional reference acquisition safe without an RCU read-side critical section.
- Leave list and rb-tree removal to timeline_fence_release().
- Drop the Fixes tag because SW_SYNC fixes are not intended for stable.
Changes in v3:
- Unlink zero-reference points from both indexes while holding the timeline lock.
drivers/dma-buf/sw_sync.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/dma-buf/sw_sync.c b/drivers/dma-buf/sw_sync.c index 8df20b021..8aa3ed777 100644 --- a/drivers/dma-buf/sw_sync.c +++ b/drivers/dma-buf/sw_sync.c @@ -221,7 +221,12 @@ static void sync_timeline_signal(struct sync_timeline *obj, unsigned int inc) if (!timeline_fence_signaled(&pt->base)) break;
dma_fence_get(&pt->base);
/** The timeline lock prevents timeline_fence_release() from* removing and freeing pt while its reference count is examined.*/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