Commit fe25deb7 authored by Thomas Hellstrom's avatar Thomas Hellstrom

drm/ttm, drm/vmwgfx: Relax permission checking when opening surfaces

Previously, when a surface was opened using a legacy (non prime) handle,
it was verified to have been created by a client in the same master realm.
Relax this so that opening is also allowed recursively if the client
already has the surface open.

This works around a regression in svga mesa where opening of a shared
surface is used recursively to obtain surface information.

Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarThomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: default avatarSinclair Yeh <syeh@vmware.com>
parent 63774069
...@@ -179,7 +179,7 @@ int ttm_base_object_init(struct ttm_object_file *tfile, ...@@ -179,7 +179,7 @@ int ttm_base_object_init(struct ttm_object_file *tfile,
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out_err0; goto out_err0;
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
goto out_err1; goto out_err1;
...@@ -318,7 +318,8 @@ EXPORT_SYMBOL(ttm_ref_object_exists); ...@@ -318,7 +318,8 @@ EXPORT_SYMBOL(ttm_ref_object_exists);
int ttm_ref_object_add(struct ttm_object_file *tfile, int ttm_ref_object_add(struct ttm_object_file *tfile,
struct ttm_base_object *base, struct ttm_base_object *base,
enum ttm_ref_type ref_type, bool *existed) enum ttm_ref_type ref_type, bool *existed,
bool require_existed)
{ {
struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; struct drm_open_hash *ht = &tfile->ref_hash[ref_type];
struct ttm_ref_object *ref; struct ttm_ref_object *ref;
...@@ -345,6 +346,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, ...@@ -345,6 +346,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile,
} }
rcu_read_unlock(); rcu_read_unlock();
if (require_existed)
return -EPERM;
ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref),
false, false); false, false);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
...@@ -635,7 +639,7 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile, ...@@ -635,7 +639,7 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile,
prime = (struct ttm_prime_object *) dma_buf->priv; prime = (struct ttm_prime_object *) dma_buf->priv;
base = &prime->base; base = &prime->base;
*handle = base->hash.key; *handle = base->hash.key;
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false);
dma_buf_put(dma_buf); dma_buf_put(dma_buf);
......
...@@ -1075,10 +1075,8 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, ...@@ -1075,10 +1075,8 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
(void) vmw_fence_obj_reference(fence); (void) vmw_fence_obj_reference(fence);
if (user_fence_rep != NULL) { if (user_fence_rep != NULL) {
bool existed; ret = ttm_ref_object_add(vmw_fp->tfile, base,
TTM_REF_USAGE, NULL, false);
ret = ttm_ref_object_add(tfile, base,
TTM_REF_USAGE, &existed);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
DRM_ERROR("Failed to reference a fence " DRM_ERROR("Failed to reference a fence "
"object.\n"); "object.\n");
......
...@@ -589,7 +589,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, ...@@ -589,7 +589,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo,
return ret; return ret;
ret = ttm_ref_object_add(tfile, &user_bo->prime.base, ret = ttm_ref_object_add(tfile, &user_bo->prime.base,
TTM_REF_SYNCCPU_WRITE, &existed); TTM_REF_SYNCCPU_WRITE, &existed, false);
if (ret != 0 || existed) if (ret != 0 || existed)
ttm_bo_synccpu_write_release(&user_bo->dma.base); ttm_bo_synccpu_write_release(&user_bo->dma.base);
...@@ -773,7 +773,7 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, ...@@ -773,7 +773,7 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile,
*handle = user_bo->prime.base.hash.key; *handle = user_bo->prime.base.hash.key;
return ttm_ref_object_add(tfile, &user_bo->prime.base, return ttm_ref_object_add(tfile, &user_bo->prime.base,
TTM_REF_USAGE, NULL); TTM_REF_USAGE, NULL, false);
} }
/* /*
......
...@@ -891,17 +891,16 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv, ...@@ -891,17 +891,16 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
uint32_t handle; uint32_t handle;
struct ttm_base_object *base; struct ttm_base_object *base;
int ret; int ret;
bool require_exist = false;
if (handle_type == DRM_VMW_HANDLE_PRIME) { if (handle_type == DRM_VMW_HANDLE_PRIME) {
ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle); ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle);
if (unlikely(ret != 0)) if (unlikely(ret != 0))
return ret; return ret;
} else { } else {
if (unlikely(drm_is_render_client(file_priv))) { if (unlikely(drm_is_render_client(file_priv)))
DRM_ERROR("Render client refused legacy " require_exist = true;
"surface reference.\n");
return -EACCES;
}
if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) { if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) {
DRM_ERROR("Locked master refused legacy " DRM_ERROR("Locked master refused legacy "
"surface reference.\n"); "surface reference.\n");
...@@ -929,17 +928,14 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv, ...@@ -929,17 +928,14 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv,
/* /*
* Make sure the surface creator has the same * Make sure the surface creator has the same
* authenticating master. * authenticating master, or is already registered with us.
*/ */
if (drm_is_primary_client(file_priv) && if (drm_is_primary_client(file_priv) &&
user_srf->master != file_priv->master) { user_srf->master != file_priv->master)
DRM_ERROR("Trying to reference surface outside of" require_exist = true;
" master domain.\n");
ret = -EACCES;
goto out_bad_resource;
}
ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL,
require_exist);
if (unlikely(ret != 0)) { if (unlikely(ret != 0)) {
DRM_ERROR("Could not add a reference to a surface.\n"); DRM_ERROR("Could not add a reference to a surface.\n");
goto out_bad_resource; goto out_bad_resource;
......
...@@ -229,6 +229,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base); ...@@ -229,6 +229,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);
* @ref_type: The type of reference. * @ref_type: The type of reference.
* @existed: Upon completion, indicates that an identical reference object * @existed: Upon completion, indicates that an identical reference object
* already existed, and the refcount was upped on that object instead. * already existed, and the refcount was upped on that object instead.
* @require_existed: Fail with -EPERM if an identical ref object didn't
* already exist.
* *
* Checks that the base object is shareable and adds a ref object to it. * Checks that the base object is shareable and adds a ref object to it.
* *
...@@ -243,7 +245,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base); ...@@ -243,7 +245,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base);
*/ */
extern int ttm_ref_object_add(struct ttm_object_file *tfile, extern int ttm_ref_object_add(struct ttm_object_file *tfile,
struct ttm_base_object *base, struct ttm_base_object *base,
enum ttm_ref_type ref_type, bool *existed); enum ttm_ref_type ref_type, bool *existed,
bool require_existed);
extern bool ttm_ref_object_exists(struct ttm_object_file *tfile, extern bool ttm_ref_object_exists(struct ttm_object_file *tfile,
struct ttm_base_object *base); struct ttm_base_object *base);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment