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: stable@vger.kernel.org
Fixes: 2e6a8a1fe2b2 ("drm/msm: Add VM_BIND ioctl")
Signed-off-by: Wentao Liang <vulab@iscas.ac.cn>
---
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