Skip to content

Commit f9e96bf

Browse files
committed
drm/vmwgfx: Fix possible invalid drm gem put calls
vmw_bo_unreference sets the input buffer to null on exit, resulting in null ptr deref's on the subsequent drm gem put calls. This went unnoticed because only very old userspace would be exercising those paths but it wouldn't be hard to hit on old distros with brand new kernels. Introduce a new function that abstracts unrefing of user bo's to make the code cleaner and more explicit. Signed-off-by: Zack Rusin <zackr@vmware.com> Reported-by: Ian Forbes <iforbes@vmware.com> Fixes: 9ef8d83 ("drm/vmwgfx: Do not drop the reference to the handle too soon") Cc: <stable@vger.kernel.org> # v6.4+ Reviewed-by: Maaz Mombasawala<mombasawalam@vmware.com> Link: https://patchwork.freedesktop.org/patch/msgid/20230818041301.407636-1-zack@kde.org
1 parent 14abdfa commit f9e96bf

File tree

6 files changed

+16
-16
lines changed

6 files changed

+16
-16
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_bo.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -497,10 +497,9 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp,
497497
if (!(flags & drm_vmw_synccpu_allow_cs)) {
498498
atomic_dec(&vmw_bo->cpu_writers);
499499
}
500-
ttm_bo_put(&vmw_bo->tbo);
500+
vmw_user_bo_unref(vmw_bo);
501501
}
502502

503-
drm_gem_object_put(&vmw_bo->tbo.base);
504503
return ret;
505504
}
506505

@@ -540,8 +539,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
540539
return ret;
541540

542541
ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
543-
vmw_bo_unreference(&vbo);
544-
drm_gem_object_put(&vbo->tbo.base);
542+
vmw_user_bo_unref(vbo);
545543
if (unlikely(ret != 0)) {
546544
if (ret == -ERESTARTSYS || ret == -EBUSY)
547545
return -EBUSY;

drivers/gpu/drm/vmwgfx/vmwgfx_bo.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,14 @@ static inline struct vmw_bo *vmw_bo_reference(struct vmw_bo *buf)
195195
return buf;
196196
}
197197

198+
static inline void vmw_user_bo_unref(struct vmw_bo *vbo)
199+
{
200+
if (vbo) {
201+
ttm_bo_put(&vbo->tbo);
202+
drm_gem_object_put(&vbo->tbo.base);
203+
}
204+
}
205+
198206
static inline struct vmw_bo *to_vmw_bo(struct drm_gem_object *gobj)
199207
{
200208
return container_of((gobj), struct vmw_bo, tbo.base);

drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1164,8 +1164,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
11641164
}
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);
1167-
ttm_bo_put(&vmw_bo->tbo);
1168-
drm_gem_object_put(&vmw_bo->tbo.base);
1167+
vmw_user_bo_unref(vmw_bo);
11691168
if (unlikely(ret != 0))
11701169
return ret;
11711170

@@ -1221,8 +1220,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
12211220
vmw_bo_placement_set(vmw_bo, VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM,
12221221
VMW_BO_DOMAIN_GMR | VMW_BO_DOMAIN_VRAM);
12231222
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo);
1224-
ttm_bo_put(&vmw_bo->tbo);
1225-
drm_gem_object_put(&vmw_bo->tbo.base);
1223+
vmw_user_bo_unref(vmw_bo);
12261224
if (unlikely(ret != 0))
12271225
return ret;
12281226

drivers/gpu/drm/vmwgfx/vmwgfx_kms.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,10 +1665,8 @@ static struct drm_framebuffer *vmw_kms_fb_create(struct drm_device *dev,
16651665

16661666
err_out:
16671667
/* vmw_user_lookup_handle takes one ref so does new_fb */
1668-
if (bo) {
1669-
vmw_bo_unreference(&bo);
1670-
drm_gem_object_put(&bo->tbo.base);
1671-
}
1668+
if (bo)
1669+
vmw_user_bo_unref(bo);
16721670
if (surface)
16731671
vmw_surface_unreference(&surface);
16741672

drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -451,8 +451,7 @@ int vmw_overlay_ioctl(struct drm_device *dev, void *data,
451451

452452
ret = vmw_overlay_update_stream(dev_priv, buf, arg, true);
453453

454-
vmw_bo_unreference(&buf);
455-
drm_gem_object_put(&buf->tbo.base);
454+
vmw_user_bo_unref(buf);
456455

457456
out_unlock:
458457
mutex_unlock(&overlay->mutex);

drivers/gpu/drm/vmwgfx/vmwgfx_shader.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -809,8 +809,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
809809
shader_type, num_input_sig,
810810
num_output_sig, tfile, shader_handle);
811811
out_bad_arg:
812-
vmw_bo_unreference(&buffer);
813-
drm_gem_object_put(&buffer->tbo.base);
812+
vmw_user_bo_unref(buffer);
814813
return ret;
815814
}
816815

0 commit comments

Comments
 (0)