Commit 05abb3be authored by Ville Syrjälä's avatar Ville Syrjälä Committed by Christian König
Browse files

dma-buf/dma-resv: Stop leaking on krealloc() failure



Currently dma_resv_get_fences() will leak the previously
allocated array if the fence iteration got restarted and
the krealloc_array() fails.

Free the old array by hand, and make sure we still clear
the returned *fences so the caller won't end up accessing
freed memory. Some (but not all) of the callers of
dma_resv_get_fences() seem to still trawl through the
array even when dma_resv_get_fences() failed. And let's
zero out *num_fences as well for good measure.

Cc: Sumit Semwal <sumit.semwal@linaro.org>
Cc: Christian König <christian.koenig@amd.com>
Cc: linux-media@vger.kernel.org
Cc: dri-devel@lists.freedesktop.org
Cc: linaro-mm-sig@lists.linaro.org
Fixes: d3c80698 ("dma-buf: use new iterator in dma_resv_get_fences v3")
Signed-off-by: default avatarVille Syrjälä <ville.syrjala@linux.intel.com>
Reviewed-by: default avatarChristian König <christian.koenig@amd.com>
Cc: stable@vger.kernel.org
Link: https://patchwork.freedesktop.org/patch/msgid/20230713194745.1751-1-ville.syrjala@linux.intel.com


Signed-off-by: default avatarChristian König <christian.koenig@amd.com>
parent 73274c33
Loading
Loading
Loading
Loading
+9 −4
Original line number Diff line number Diff line
@@ -571,6 +571,7 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
	dma_resv_for_each_fence_unlocked(&cursor, fence) {

		if (dma_resv_iter_is_restarted(&cursor)) {
			struct dma_fence **new_fences;
			unsigned int count;

			while (*num_fences)
@@ -579,13 +580,17 @@ int dma_resv_get_fences(struct dma_resv *obj, enum dma_resv_usage usage,
			count = cursor.num_fences + 1;

			/* Eventually re-allocate the array */
			*fences = krealloc_array(*fences, count,
			new_fences = krealloc_array(*fences, count,
						    sizeof(void *),
						    GFP_KERNEL);
			if (count && !*fences) {
			if (count && !new_fences) {
				kfree(*fences);
				*fences = NULL;
				*num_fences = 0;
				dma_resv_iter_end(&cursor);
				return -ENOMEM;
			}
			*fences = new_fences;
		}

		(*fences)[(*num_fences)++] = dma_fence_get(fence);