From 339824df70a0e9e08f2a7151b776d72421050f04 Mon Sep 17 00:00:00 2001 From: Puranam V G Tejaswi Date: Thu, 2 Dec 2021 21:27:14 +0530 Subject: [PATCH] msm: kgsl: Signal fence only if last fence refcount was not put Currently there is a chance that release for the fence was already called before we call dma_fence_get during kgsl_timeline_signal and kgsl_ioctl_timeline_destroy. This can cause use-after-free issue as we can access fence after release. Fix this by signalling fence only if the last refcount on the fence was not yet put. This makes sure that release for the fence will not be called until we are done signalling. Change-Id: I6bdcefa1f128febb7a0f7aef133757268a3b9ae3 Signed-off-by: Puranam V G Tejaswi --- drivers/gpu/msm/kgsl_timeline.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/msm/kgsl_timeline.c b/drivers/gpu/msm/kgsl_timeline.c index 817a71f114ee..92b0f5b26ea0 100644 --- a/drivers/gpu/msm/kgsl_timeline.c +++ b/drivers/gpu/msm/kgsl_timeline.c @@ -270,12 +270,10 @@ void kgsl_timeline_signal(struct kgsl_timeline *timeline, u64 seqno) timeline->value = seqno; spin_lock(&timeline->fence_lock); - list_for_each_entry_safe(fence, tmp, &timeline->fences, node) { - if (timeline_fence_signaled(&fence->base)) { - dma_fence_get(&fence->base); + list_for_each_entry_safe(fence, tmp, &timeline->fences, node) + if (timeline_fence_signaled(&fence->base) && + kref_get_unless_zero(&fence->base.refcount)) list_move(&fence->node, &temp); - } - } spin_unlock(&timeline->fence_lock); list_for_each_entry_safe(fence, tmp, &temp, node) { @@ -548,7 +546,8 @@ long kgsl_ioctl_timeline_destroy(struct kgsl_device_private *dev_priv, spin_lock(&timeline->fence_lock); list_for_each_entry_safe(fence, tmp, &timeline->fences, node) - dma_fence_get(&fence->base); + if (!kref_get_unless_zero(&fence->base.refcount)) + list_del_init(&fence->node); list_replace_init(&timeline->fences, &temp); spin_unlock(&timeline->fence_lock);