mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 00:51:51 -04:00
drm/msm: Fix obj leak in VM_BIND error path
If we fail a handle-lookup part way thru, we need to drop the already
obtained obj references.
Fixes: 2e6a8a1fe2 ("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/
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user