]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
drm/msm: Fix obj leak in VM_BIND error path
authorRob Clark <robin.clark@oss.qualcomm.com>
Thu, 21 Aug 2025 00:04:25 +0000 (17:04 -0700)
committerRob Clark <robin.clark@oss.qualcomm.com>
Sat, 6 Sep 2025 15:58:11 +0000 (08:58 -0700)
If we fail a handle-lookup part way thru, we need to drop the already
obtained obj references.

Fixes: 2e6a8a1fe2b2 ("drm/msm: Add VM_BIND ioctl")
Signed-off-by: Rob Clark <robin.clark@oss.qualcomm.com>
Tested-by: Connor Abbott <cwabbott0@gmail.com>
Patchwork: https://patchwork.freedesktop.org/patch/669784/

drivers/gpu/drm/msm/msm_gem_vma.c

index 00d0f3b7ba327d7ab2f8edd5af79f0d78b27a10a..209154be5efcc00b6f69bf199810305d8d037dc0 100644 (file)
@@ -1023,6 +1023,7 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
        struct drm_device *dev = job->vm->drm;
        int ret = 0;
        int cnt = 0;
+       int i = -1;
 
        if (args->nr_ops == 1) {
                /* Single op case, the op is inlined: */
@@ -1056,11 +1057,12 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
 
        spin_lock(&file->table_lock);
 
-       for (unsigned i = 0; i < args->nr_ops; i++) {
+       for (i = 0; i < args->nr_ops; i++) {
+               struct msm_vm_bind_op *op = &job->ops[i];
                struct drm_gem_object *obj;
 
-               if (!job->ops[i].handle) {
-                       job->ops[i].obj = NULL;
+               if (!op->handle) {
+                       op->obj = NULL;
                        continue;
                }
 
@@ -1068,15 +1070,15 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
                 * normally use drm_gem_object_lookup(), but for bulk lookup
                 * all under single table_lock just hit object_idr directly:
                 */
-               obj = idr_find(&file->object_idr, job->ops[i].handle);
+               obj = idr_find(&file->object_idr, op->handle);
                if (!obj) {
-                       ret = UERR(EINVAL, dev, "invalid handle %u at index %u\n", job->ops[i].handle, i);
+                       ret = UERR(EINVAL, dev, "invalid handle %u at index %u\n", op->handle, i);
                        goto out_unlock;
                }
 
                drm_gem_object_get(obj);
 
-               job->ops[i].obj = obj;
+               op->obj = obj;
                cnt++;
        }
 
@@ -1085,6 +1087,17 @@ vm_bind_job_lookup_ops(struct msm_vm_bind_job *job, struct drm_msm_vm_bind *args
 out_unlock:
        spin_unlock(&file->table_lock);
 
+       if (ret) {
+               for (; i >= 0; i--) {
+                       struct msm_vm_bind_op *op = &job->ops[i];
+
+                       if (!op->obj)
+                               continue;
+
+                       drm_gem_object_put(op->obj);
+                       op->obj = NULL;
+               }
+       }
 out:
        return ret;
 }