Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e0355a0a authored by Jason Ekstrand's avatar Jason Ekstrand Committed by Greg Kroah-Hartman
Browse files

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: default avatarJason Ekstrand <jason@jlekstrand.net>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Fixes: a02b9dc9 ("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: default avatarChristian König <christian.koenig@amd.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 8bb1589c
Loading
Loading
Loading
Loading
+7 −6
Original line number Diff line number Diff line
@@ -220,8 +220,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)
@@ -245,7 +245,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];

@@ -286,15 +286,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;