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: [email protected] > Closes: https://syzkaller.appspot.com/bug?extid=cba1a1f459230395a076 > Signed-off-by: Kirtikumar Anandrao Ramchandani <[email protected]>
Reviewed-by: Christian König <[email protected]> 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
