OSDN Git Service

dma-buf/sync_file: Don't leak fences on merge failure
authorJason Ekstrand <jason@jlekstrand.net>
Thu, 24 Jun 2021 17:47:32 +0000 (12:47 -0500)
committerChristian König <christian.koenig@amd.com>
Mon, 12 Jul 2021 11:34:49 +0000 (13:34 +0200)
Each add_fence() call does a dma_fence_get() on the relevant fence.  In
the error path, we weren't calling dma_fence_put() so all those fences
got leaked.  Also, in the krealloc_array failure case, we weren't
freeing the fences array.  Instead, ensure that i and fences are always
zero-initialized and dma_fence_put() all the fences and kfree(fences) on
every error path.

Signed-off-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Christian König <christian.koenig@amd.com>
Fixes: a02b9dc90d84 ("dma-buf/sync_file: refactor fence storage in struct sync_file")
Cc: Gustavo Padovan <gustavo.padovan@collabora.co.uk>
Cc: Christian König <christian.koenig@amd.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20210624174732.1754546-1-jason@jlekstrand.net
Signed-off-by: Christian König <christian.koenig@amd.com>
drivers/dma-buf/sync_file.c

index 20d9bdd..394e6e1 100644 (file)
@@ -211,8 +211,8 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
                                         struct sync_file *b)
 {
        struct sync_file *sync_file;
-       struct dma_fence **fences, **nfences, **a_fences, **b_fences;
-       int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
+       struct dma_fence **fences = NULL, **nfences, **a_fences, **b_fences;
+       int i = 0, i_a, i_b, num_fences, a_num_fences, b_num_fences;
 
        sync_file = sync_file_alloc();
        if (!sync_file)
@@ -236,7 +236,7 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
         * If a sync_file can only be created with sync_file_merge
         * and sync_file_create, this is a reasonable assumption.
         */
-       for (i = i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
+       for (i_a = i_b = 0; i_a < a_num_fences && i_b < b_num_fences; ) {
                struct dma_fence *pt_a = a_fences[i_a];
                struct dma_fence *pt_b = b_fences[i_b];
 
@@ -277,15 +277,16 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
                fences = nfences;
        }
 
-       if (sync_file_set_fence(sync_file, fences, i) < 0) {
-               kfree(fences);
+       if (sync_file_set_fence(sync_file, fences, i) < 0)
                goto err;
-       }
 
        strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
        return sync_file;
 
 err:
+       while (i)
+               dma_fence_put(fences[--i]);
+       kfree(fences);
        fput(sync_file->file);
        return NULL;