Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

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 <zackr@vmware.com>
Fixes: 8afa13a0583f ("drm/vmwgfx: Implement DRIVER_GEM")
Reviewed-by: Martin Krastev <krastevm@vmware.com>
Reviewed-by: Maaz Mombasawala <mombasawalam@vmware.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20230211050514.2431155-1-zack@kde.org
(cherry picked from commit 9ef8d83e8e25d5f1811b3a38eb1484f85f64296c)
Cc: <stable@vger.kernel.org> # v5.17+

+20 -10
+5 -3
drivers/gpu/drm/vmwgfx/vmwgfx_bo.c
··· 598 598 ttm_bo_put(&vmw_bo->base); 599 599 } 600 600 601 + drm_gem_object_put(&vmw_bo->base.base); 601 602 return ret; 602 603 } 603 604 ··· 639 638 640 639 ret = vmw_user_bo_synccpu_grab(vbo, arg->flags); 641 640 vmw_bo_unreference(&vbo); 641 + drm_gem_object_put(&vbo->base.base); 642 642 if (unlikely(ret != 0)) { 643 643 if (ret == -ERESTARTSYS || ret == -EBUSY) 644 644 return -EBUSY; ··· 697 695 * struct vmw_buffer_object should be placed. 698 696 * Return: Zero on success, Negative error code on error. 699 697 * 700 - * The vmw buffer object pointer will be refcounted. 698 + * The vmw buffer object pointer will be refcounted (both ttm and gem) 701 699 */ 702 700 int vmw_user_bo_lookup(struct drm_file *filp, 703 701 uint32_t handle, ··· 714 712 715 713 *out = gem_to_vmw_bo(gobj); 716 714 ttm_bo_get(&(*out)->base); 717 - drm_gem_object_put(gobj); 718 715 719 716 return 0; 720 717 } ··· 794 793 ret = vmw_gem_object_create_with_handle(dev_priv, file_priv, 795 794 args->size, &args->handle, 796 795 &vbo); 797 - 796 + /* drop reference from allocate - handle holds it now */ 797 + drm_gem_object_put(&vbo->base.base); 798 798 return ret; 799 799 } 800 800
+2
drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c
··· 1160 1160 } 1161 1161 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, true, false); 1162 1162 ttm_bo_put(&vmw_bo->base); 1163 + drm_gem_object_put(&vmw_bo->base.base); 1163 1164 if (unlikely(ret != 0)) 1164 1165 return ret; 1165 1166 ··· 1215 1214 } 1216 1215 ret = vmw_validation_add_bo(sw_context->ctx, vmw_bo, false, false); 1217 1216 ttm_bo_put(&vmw_bo->base); 1217 + drm_gem_object_put(&vmw_bo->base.base); 1218 1218 if (unlikely(ret != 0)) 1219 1219 return ret; 1220 1220
+2 -2
drivers/gpu/drm/vmwgfx/vmwgfx_gem.c
··· 152 152 (*p_vbo)->base.base.funcs = &vmw_gem_object_funcs; 153 153 154 154 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); 157 155 out_no_bo: 158 156 return ret; 159 157 } ··· 178 180 rep->map_handle = drm_vma_node_offset_addr(&vbo->base.base.vma_node); 179 181 rep->cur_gmr_id = handle; 180 182 rep->cur_gmr_offset = 0; 183 + /* drop reference from allocate - handle holds it now */ 184 + drm_gem_object_put(&vbo->base.base); 181 185 out_no_bo: 182 186 return ret; 183 187 }
+3 -1
drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
··· 1815 1815 1816 1816 err_out: 1817 1817 /* vmw_user_lookup_handle takes one ref so does new_fb */ 1818 - if (bo) 1818 + if (bo) { 1819 1819 vmw_bo_unreference(&bo); 1820 + drm_gem_object_put(&bo->base.base); 1821 + } 1820 1822 if (surface) 1821 1823 vmw_surface_unreference(&surface); 1822 1824
+1
drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c
··· 458 458 ret = vmw_overlay_update_stream(dev_priv, buf, arg, true); 459 459 460 460 vmw_bo_unreference(&buf); 461 + drm_gem_object_put(&buf->base.base); 461 462 462 463 out_unlock: 463 464 mutex_unlock(&overlay->mutex);
+1
drivers/gpu/drm/vmwgfx/vmwgfx_shader.c
··· 807 807 num_output_sig, tfile, shader_handle); 808 808 out_bad_arg: 809 809 vmw_bo_unreference(&buffer); 810 + drm_gem_object_put(&buffer->base.base); 810 811 return ret; 811 812 } 812 813
+6 -4
drivers/gpu/drm/vmwgfx/vmwgfx_surface.c
··· 683 683 container_of(base, struct vmw_user_surface, prime.base); 684 684 struct vmw_resource *res = &user_srf->srf.res; 685 685 686 - if (base->shareable && res && res->backup) 686 + if (res && res->backup) 687 687 drm_gem_object_put(&res->backup->base.base); 688 688 689 689 *p_base = NULL; ··· 864 864 goto out_unlock; 865 865 } 866 866 vmw_bo_reference(res->backup); 867 - drm_gem_object_get(&res->backup->base.base); 867 + /* 868 + * We don't expose the handle to the userspace and surface 869 + * already holds a gem reference 870 + */ 871 + drm_gem_handle_delete(file_priv, backup_handle); 868 872 } 869 873 870 874 tmp = vmw_resource_reference(&srf->res); ··· 1572 1568 drm_vma_node_offset_addr(&res->backup->base.base.vma_node); 1573 1569 rep->buffer_size = res->backup->base.base.size; 1574 1570 rep->buffer_handle = backup_handle; 1575 - if (user_srf->prime.base.shareable) 1576 - drm_gem_object_get(&res->backup->base.base); 1577 1571 } else { 1578 1572 rep->buffer_map_handle = 0; 1579 1573 rep->buffer_size = 0;