In msm_gem_vm_sm_step_remap(), a temporary reference on vm_bo is acquired via drm_gpuvm_bo_get() to keep the object alive during vma close and creation. On success, the reference is released with drm_gpuvm_bo_put(). However, when vma_from_op() fails for prev_vma or next_vma, the function returns directly without releasing the reference, causing a leak.
Fix by converting the error returns to a common error path that releases the temporary reference before returning. Cc: [email protected] Fixes: 2e6a8a1fe2b2 ("drm/msm: Add VM_BIND ioctl") Signed-off-by: Wentao Liang <[email protected]> --- drivers/gpu/drm/msm/msm_gem_vma.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c b/drivers/gpu/drm/msm/msm_gem_vma.c index 1a952b171ed7..69289bea7a66 100644 --- a/drivers/gpu/drm/msm/msm_gem_vma.c +++ b/drivers/gpu/drm/msm/msm_gem_vma.c @@ -602,8 +602,10 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg) if (op->remap.prev) { prev_vma = vma_from_op(arg, op->remap.prev); - if (WARN_ON(IS_ERR(prev_vma))) - return PTR_ERR(prev_vma); + if (WARN_ON(IS_ERR(prev_vma))) { + ret = PTR_ERR(prev_vma); + goto drop_ref; + } vm_dbg("prev_vma: %p:%p: %016llx %016llx", vm, prev_vma, prev_vma->va.addr, prev_vma->va.range); to_msm_vma(prev_vma)->mapped = mapped; @@ -612,8 +614,10 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg) if (op->remap.next) { next_vma = vma_from_op(arg, op->remap.next); - if (WARN_ON(IS_ERR(next_vma))) - return PTR_ERR(next_vma); + if (WARN_ON(IS_ERR(next_vma))) { + ret = PTR_ERR(next_vma); + goto drop_ref; + } vm_dbg("next_vma: %p:%p: %016llx %016llx", vm, next_vma, next_vma->va.addr, next_vma->va.range); to_msm_vma(next_vma)->mapped = mapped; @@ -623,6 +627,7 @@ msm_gem_vm_sm_step_remap(struct drm_gpuva_op *op, void *arg) if (!mapped) drm_gpuvm_bo_evict(vm_bo, true); +drop_ref: /* Drop the previous ref: */ drm_gpuvm_bo_put(vm_bo); -- 2.34.1
