Skip to content

Commit 0a127ac

Browse files
zackrgregkh
authored andcommitted
drm/vmwgfx: Do not drop the reference to the handle too soon
commit a950b98 upstream. 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] (cherry picked from commit 9ef8d83) Cc: <[email protected]> # v5.17+ Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 14a14da commit 0a127ac

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
@@ -598,6 +598,7 @@ static int vmw_user_bo_synccpu_release(struct drm_file *filp,
598598
ttm_bo_put(&vmw_bo->base);
599599
}
600600

601+
drm_gem_object_put(&vmw_bo->base.base);
601602
return ret;
602603
}
603604

@@ -638,6 +639,7 @@ int vmw_user_bo_synccpu_ioctl(struct drm_device *dev, void *data,
638639

639640
ret = vmw_user_bo_synccpu_grab(vbo, arg->flags);
640641
vmw_bo_unreference(&vbo);
642+
drm_gem_object_put(&vbo->base.base);
641643
if (unlikely(ret != 0)) {
642644
if (ret == -ERESTARTSYS || ret == -EBUSY)
643645
return -EBUSY;
@@ -695,7 +697,7 @@ int vmw_bo_unref_ioctl(struct drm_device *dev, void *data,
695697
* struct vmw_buffer_object should be placed.
696698
* Return: Zero on success, Negative error code on error.
697699
*
698-
* The vmw buffer object pointer will be refcounted.
700+
* The vmw buffer object pointer will be refcounted (both ttm and gem)
699701
*/
700702
int vmw_user_bo_lookup(struct drm_file *filp,
701703
uint32_t handle,
@@ -712,7 +714,6 @@ int vmw_user_bo_lookup(struct drm_file *filp,
712714

713715
*out = gem_to_vmw_bo(gobj);
714716
ttm_bo_get(&(*out)->base);
715-
drm_gem_object_put(gobj);
716717

717718
return 0;
718719
}
@@ -779,7 +780,8 @@ int vmw_dumb_create(struct drm_file *file_priv,
779780
ret = vmw_gem_object_create_with_handle(dev_priv, file_priv,
780781
args->size, &args->handle,
781782
&vbo);
782-
783+
/* drop reference from allocate - handle holds it now */
784+
drm_gem_object_put(&vbo->base.base);
783785
return ret;
784786
}
785787

drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,6 +1160,7 @@ static int vmw_translate_mob_ptr(struct vmw_private *dev_priv,
11601160
}
11611161
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false);
11621162
ttm_bo_put(&vmw_bo->base);
1163+
drm_gem_object_put(&vmw_bo->base.base);
11631164
if (unlikely(ret != 0))
11641165
return ret;
11651166

@@ -1214,6 +1215,7 @@ static int vmw_translate_guest_ptr(struct vmw_private *dev_priv,
12141215
}
12151216
ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false);
12161217
ttm_bo_put(&vmw_bo->base);
1218+
drm_gem_object_put(&vmw_bo->base.base);
12171219
if (unlikely(ret != 0))
12181220
return ret;
12191221

drivers/gpu/drm/vmwgfx/vmwgfx_gem.c

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

154154
ret = drm_gem_handle_create(filp, &(*p_vbo)->base.base, handle);
155-
/* drop reference from allocate - handle holds it now */
156-
drm_gem_object_put(&(*p_vbo)->base.base);
157155
out_no_bo:
158156
return ret;
159157
}
@@ -180,6 +178,8 @@ int vmw_gem_object_create_ioctl(struct drm_device *dev, void *data,
180178
rep->map_handle = drm_vma_node_offset_addr(&vbo->base.base.vma_node);
181179
rep->cur_gmr_id = handle;
182180
rep->cur_gmr_offset = 0;
181+
/* drop reference from allocate - handle holds it now */
182+
drm_gem_object_put(&vbo->base.base);
183183
out_no_bo:
184184
return ret;
185185
}

drivers/gpu/drm/vmwgfx/vmwgfx_kms.c

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

16701670
err_out:
16711671
/* vmw_user_lookup_handle takes one ref so does new_fb */
1672-
if (bo)
1672+
if (bo) {
16731673
vmw_bo_unreference(&bo);
1674+
drm_gem_object_put(&bo->base.base);
1675+
}
16741676
if (surface)
16751677
vmw_surface_unreference(&surface);
16761678

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->base.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
@@ -807,6 +807,7 @@ static int vmw_shader_define(struct drm_device *dev, struct drm_file *file_priv,
807807
num_output_sig, tfile, shader_handle);
808808
out_bad_arg:
809809
vmw_bo_unreference(&buffer);
810+
drm_gem_object_put(&buffer->base.base);
810811
return ret;
811812
}
812813

drivers/gpu/drm/vmwgfx/vmwgfx_surface.c

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

686-
if (base->shareable && res && res->backup)
686+
if (res && res->backup)
687687
drm_gem_object_put(&res->backup->base.base);
688688

689689
*p_base = NULL;
@@ -860,7 +860,11 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data,
860860
goto out_unlock;
861861
}
862862
vmw_bo_reference(res->backup);
863-
drm_gem_object_get(&res->backup->base.base);
863+
/*
864+
* We don't expose the handle to the userspace and surface
865+
* already holds a gem reference
866+
*/
867+
drm_gem_handle_delete(file_priv, backup_handle);
864868
}
865869

866870
tmp = vmw_resource_reference(&srf->res);
@@ -1564,8 +1568,6 @@ vmw_gb_surface_define_internal(struct drm_device *dev,
15641568
drm_vma_node_offset_addr(&res->backup->base.base.vma_node);
15651569
rep->buffer_size = res->backup->base.base.size;
15661570
rep->buffer_handle = backup_handle;
1567-
if (user_srf->prime.base.shareable)
1568-
drm_gem_object_get(&res->backup->base.base);
15691571
} else {
15701572
rep->buffer_map_handle = 0;
15711573
rep->buffer_size = 0;

0 commit comments

Comments
 (0)