Skip to content

Commit 9ef8d83

Browse files
committed
drm/vmwgfx: Do not drop the reference to the handle too soon
v3: Fix vmw_user_bo_lookup which was also dropping the gem reference before the kernel was done with buffer depending on userspace doing the right thing. Same bug, different spot. It is possible for userspace to predict the next buffer handle and to destroy the buffer while it's still used by the kernel. Delay dropping the internal reference on the buffers until kernel is done with them. Instead of immediately dropping the gem reference in vmw_user_bo_lookup and vmw_gem_object_create_with_handle let the callers decide when they're ready give the control back to userspace. Also fixes the second usage of vmw_gem_object_create_with_handle in vmwgfx_surface.c which wasn't grabbing an explicit reference to the gem object which could have been destroyed by the userspace on the owning surface at any point. Signed-off-by: Zack Rusin <[email protected]> Fixes: 8afa13a ("drm/vmwgfx: Implement DRIVER_GEM") Reviewed-by: Martin Krastev <[email protected]> Reviewed-by: Maaz Mombasawala <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 36d421e commit 9ef8d83

File tree

7 files changed

+20
-10
lines changed

7 files changed

+20
-10
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_bo.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -500,6 +500,7 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp,
500500
ttm_bo_put(&vmw_bo->tbo);
501501
}
502502

503+
drm_gem_object_put(&vmw_bo->tbo.base);
503504
return ret;
504505
}
505506

@@ -540,6 +541,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
540541

541542
ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
542543
vmw_bo_unreference(&vbo);
544+
drm_gem_object_put(&vbo->tbo.base);
543545
if (unlikely(ret != 0)) {
544546
if (ret == -ERESTARTSYS || ret == -EBUSY)
545547
return -EBUSY;
@@ -596,7 +598,7 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data,
596598
* struct vmw_bo should be placed.
597599
* Return: Zero on success, Negative error code on error.
598600
*
599-
* The vmw buffer object pointer will be refcounted.
601+
* The vmw buffer object pointer will be refcounted (both ttm and gem)
600602
*/
601603
int vmw_user_bo_lookup(struct drm_file *filp,
602604
u32 handle,
@@ -613,7 +615,6 @@ int vmw_user_bo_lookup(struct drm_file *filp,
613615

614616
*out = to_vmw_bo(gobj);
615617
ttm_bo_get(&(*out)->tbo);
616-
drm_gem_object_put(gobj);
617618

618619
return 0;
619620
}
@@ -693,7 +694,8 @@ int vmw_dumb_create(struct drm_file *file_priv,
693694
ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
694695
args->size, &args->handle,
695696
&vbo);
696-
697+
/* drop reference from allocate - handle holds it now */
698+
drm_gem_object_put(&vbo->tbo.base);
697699
return ret;
698700
}
699701

drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1165,6 +1165,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
11651165
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_MOB, VMW_BO_DOMAIN_MOB);
11661166
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
11671167
ttm_bo_put(&vmw_bo->tbo);
1168+
drm_gem_object_put(&vmw_bo->tbo.base);
11681169
if (unlikely(ret != 0))
11691170
return ret;
11701171

@@ -1221,6 +1222,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
12211222
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
12221223
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
12231224
ttm_bo_put(&vmw_bo->tbo);
1225+
drm_gem_object_put(&vmw_bo->tbo.base);
12241226
if (unlikely(ret != 0))
12251227
return ret;
12261228

drivers/gpu/drm/vmwgfx/vmwgfx_gem.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,8 +133,6 @@ int vmw_gem_object_create_with_handle(struct vmw_private *dev_priv,
133133
(*p_vbo)->tbo.base.funcs = &vmw_gem_object_funcs;
134134

135135
ret = drm_gem_handle_create(filp, &(*p_vbo)->tbo.base, handle);
136-
/* drop reference from allocate - handle holds it now */
137-
drm_gem_object_put(&(*p_vbo)->tbo.base);
138136
out_no_bo:
139137
return ret;
140138
}
@@ -161,6 +159,8 @@ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
161159
rep->map_handle = drm_vma_node_offset_addr(&vbo->tbo.base.vma_node);
162160
rep->cur_gmr_id = handle;
163161
rep->cur_gmr_offset = 0;
162+
/* drop reference from allocate - handle holds it now */
163+
drm_gem_object_put(&vbo->tbo.base);
164164
out_no_bo:
165165
return ret;
166166
}

drivers/gpu/drm/vmwgfx/vmwgfx_kms.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1725,8 +1725,10 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
17251725

17261726
err_out:
17271727
/* vmw_user_lookup_handle takes one ref so does new_fb */
1728-
if (bo)
1728+
if (bo) {
17291729
vmw_bo_unreference(&bo);
1730+
drm_gem_object_put(&bo->tbo.base);
1731+
}
17301732
if (surface)
17311733
vmw_surface_unreference(&surface);
17321734

drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -458,6 +458,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data,
458458
ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
459459

460460
vmw_bo_unreference(&buf);
461+
drm_gem_object_put(&buf->tbo.base);
461462

462463
out_unlock:
463464
mutex_unlock(&overlay->mutex);

drivers/gpu/drm/vmwgfx/vmwgfx_shader.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
810810
num_output_sig, tfile, shader_handle);
811811
out_bad_arg:
812812
vmw_bo_unreference(&buffer);
813+
drm_gem_object_put(&buffer->tbo.base);
813814
return ret;
814815
}
815816

drivers/gpu/drm/vmwgfx/vmwgfx_surface.c

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -686,7 +686,7 @@ static void vmw_user_surface_base_release(struct ttm_base_object **p_base)
686686
container_of(base, struct vmw_user_surface, prime.base);
687687
struct vmw_resource *res = &user_srf->srf.res;
688688

689-
if (base->shareable && res && res->guest_memory_bo)
689+
if (res->guest_memory_bo)
690690
drm_gem_object_put(&res->guest_memory_bo->tbo.base);
691691

692692
*p_base = NULL;
@@ -867,7 +867,11 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
867867
goto out_unlock;
868868
}
869869
vmw_bo_reference(res->guest_memory_bo);
870-
drm_gem_object_get(&res->guest_memory_bo->tbo.base);
870+
/*
871+
* We don't expose the handle to the userspace and surface
872+
* already holds a gem reference
873+
*/
874+
drm_gem_handle_delete(file_priv, backup_handle);
871875
}
872876

873877
tmp = vmw_resource_reference(&srf->res);
@@ -1571,8 +1575,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
15711575
drm_vma_node_offset_addr(&res->guest_memory_bo->tbo.base.vma_node);
15721576
rep->buffer_size = res->guest_memory_bo->tbo.base.size;
15731577
rep->buffer_handle = backup_handle;
1574-
if (user_srf->prime.base.shareable)
1575-
drm_gem_object_get(&res->guest_memory_bo->tbo.base);
15761578
} else {
15771579
rep->buffer_map_handle = 0;
15781580
rep->buffer_size = 0;

0 commit comments

Comments
 (0)