If a buffer is pinned successfully but the mapping is never recorded in job->unpins, host1x_job_unpin() cannot release it. This happens when a relocation buffer is discontiguous (map->chunks > 1) and when alloc_iova() or iommu_map_sgtable() fail while mapping a gather buffer's IOVA, leaking the mapping and the buffer object reference it holds. Unpin the mapping before jumping to the shared error labels. Fixes: c6aeaf56f468 ("drm/tegra: Implement correct DMA-BUF semantics") Cc: stable@vger.kernel.org Signed-off-by: Wentao Liang --- drivers/gpu/host1x/job.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/gpu/host1x/job.c b/drivers/gpu/host1x/job.c index 3ed49e1fd933..675e7dde7e38 100644 --- a/drivers/gpu/host1x/job.c +++ b/drivers/gpu/host1x/job.c @@ -193,6 +193,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) * contiguous chunk of I/O virtual memory. */ if (map->chunks > 1) { + host1x_bo_unpin(map); err = -EINVAL; goto unpin; } @@ -244,6 +245,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) alloc = alloc_iova(&host->iova, gather_size >> shift, host->iova_end >> shift, true); if (!alloc) { + host1x_bo_unpin(map); err = -ENOMEM; goto put; } @@ -252,6 +254,7 @@ static unsigned int pin_job(struct host1x *host, struct host1x_job *job) map->sgt, IOMMU_READ); if (err == 0) { __free_iova(&host->iova, alloc); + host1x_bo_unpin(map); err = -EINVAL; goto put; } -- 2.34.1