dma-buf/sync_file: Don't leak fences on merge failure
commit ffe000217c5068c5da07ccb1c0f8cce7ad767435 upstream.
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: a02b9dc90d
("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>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:

committed by
Greg Kroah-Hartman

parent
f33605908a
commit
0d514185ae
@@ -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 *b)
|
||||||
{
|
{
|
||||||
struct sync_file *sync_file;
|
struct sync_file *sync_file;
|
||||||
struct dma_fence **fences, **nfences, **a_fences, **b_fences;
|
struct dma_fence **fences = NULL, **nfences, **a_fences, **b_fences;
|
||||||
int i, i_a, i_b, num_fences, a_num_fences, b_num_fences;
|
int i = 0, i_a, i_b, num_fences, a_num_fences, b_num_fences;
|
||||||
|
|
||||||
sync_file = sync_file_alloc();
|
sync_file = sync_file_alloc();
|
||||||
if (!sync_file)
|
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
|
* If a sync_file can only be created with sync_file_merge
|
||||||
* and sync_file_create, this is a reasonable assumption.
|
* 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_a = a_fences[i_a];
|
||||||
struct dma_fence *pt_b = b_fences[i_b];
|
struct dma_fence *pt_b = b_fences[i_b];
|
||||||
|
|
||||||
@@ -278,15 +278,16 @@ static struct sync_file *sync_file_merge(const char *name, struct sync_file *a,
|
|||||||
fences = nfences;
|
fences = nfences;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sync_file_set_fence(sync_file, fences, i) < 0) {
|
if (sync_file_set_fence(sync_file, fences, i) < 0)
|
||||||
kfree(fences);
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
|
||||||
|
|
||||||
strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
|
strlcpy(sync_file->user_name, name, sizeof(sync_file->user_name));
|
||||||
return sync_file;
|
return sync_file;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
while (i)
|
||||||
|
dma_fence_put(fences[--i]);
|
||||||
|
kfree(fences);
|
||||||
fput(sync_file->file);
|
fput(sync_file->file);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user