When importing a sync file fence into a timeline syncobj with a non-zero
point, drm_syncobj_import_sync_file_fence() allocates a dma_fence_chain
with dma_fence_chain_alloc(). If that allocation fails the function
returns -ENOMEM directly, leaking the reference on the syncobj taken by
drm_syncobj_find() (and the reference on the fence taken by
sync_file_get_fence()).

Jump to a cleanup path that drops both references before returning the
error.

Fixes: c2d3a7300695 ("drm/syncobj: Extend EXPORT_SYNC_FILE for timeline 
syncobjs")
Cc: [email protected]
Signed-off-by: Wentao Liang <[email protected]>
---
 drivers/gpu/drm/drm_syncobj.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/drm_syncobj.c b/drivers/gpu/drm/drm_syncobj.c
index 8d9fd1917c6e..7e1502cbd852 100644
--- a/drivers/gpu/drm/drm_syncobj.c
+++ b/drivers/gpu/drm/drm_syncobj.c
@@ -742,7 +742,7 @@ static int drm_syncobj_import_sync_file_fence(struct 
drm_file *file_private,
                struct dma_fence_chain *chain = dma_fence_chain_alloc();
 
                if (!chain)
-                       return -ENOMEM;
+                       goto err_put;
 
                drm_syncobj_add_point(syncobj, chain, fence, point);
        } else {
@@ -752,6 +752,10 @@ static int drm_syncobj_import_sync_file_fence(struct 
drm_file *file_private,
        dma_fence_put(fence);
        drm_syncobj_put(syncobj);
        return 0;
+err_put:
+       dma_fence_put(fence);
+       drm_syncobj_put(syncobj);
+       return -ENOMEM;
 }
 
 static int drm_syncobj_export_sync_file(struct drm_file *file_private,
-- 
2.34.1

Reply via email to