diff options
author | Thomas Hellstrom <thellstrom@vmware.com> | 2017-03-27 05:21:25 -0400 |
---|---|---|
committer | Thomas Hellstrom <thellstrom@vmware.com> | 2017-03-30 05:43:39 -0400 |
commit | fe25deb7737ce6c0879ccf79c99fa1221d428bf2 (patch) | |
tree | 8e5091f95dc74616cb5aab8560f8a0b7d1b8e577 | |
parent | 63774069d9527a1aeaa4aa20e929ef5e8e9ecc38 (diff) |
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: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Sinclair Yeh <syeh@vmware.com>
-rw-r--r-- | drivers/gpu/drm/ttm/ttm_object.c | 10 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | 22 | ||||
-rw-r--r-- | include/drm/ttm/ttm_object.h | 5 |
5 files changed, 24 insertions, 23 deletions
diff --git a/drivers/gpu/drm/ttm/ttm_object.c b/drivers/gpu/drm/ttm/ttm_object.c index fdb451e3ec01..d750140bafbc 100644 --- a/drivers/gpu/drm/ttm/ttm_object.c +++ b/drivers/gpu/drm/ttm/ttm_object.c | |||
@@ -179,7 +179,7 @@ int ttm_base_object_init(struct ttm_object_file *tfile, | |||
179 | if (unlikely(ret != 0)) | 179 | if (unlikely(ret != 0)) |
180 | goto out_err0; | 180 | goto out_err0; |
181 | 181 | ||
182 | ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); | 182 | ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false); |
183 | if (unlikely(ret != 0)) | 183 | if (unlikely(ret != 0)) |
184 | goto out_err1; | 184 | goto out_err1; |
185 | 185 | ||
@@ -318,7 +318,8 @@ EXPORT_SYMBOL(ttm_ref_object_exists); | |||
318 | 318 | ||
319 | int ttm_ref_object_add(struct ttm_object_file *tfile, | 319 | int ttm_ref_object_add(struct ttm_object_file *tfile, |
320 | struct ttm_base_object *base, | 320 | struct ttm_base_object *base, |
321 | enum ttm_ref_type ref_type, bool *existed) | 321 | enum ttm_ref_type ref_type, bool *existed, |
322 | bool require_existed) | ||
322 | { | 323 | { |
323 | struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; | 324 | struct drm_open_hash *ht = &tfile->ref_hash[ref_type]; |
324 | struct ttm_ref_object *ref; | 325 | struct ttm_ref_object *ref; |
@@ -345,6 +346,9 @@ int ttm_ref_object_add(struct ttm_object_file *tfile, | |||
345 | } | 346 | } |
346 | 347 | ||
347 | rcu_read_unlock(); | 348 | rcu_read_unlock(); |
349 | if (require_existed) | ||
350 | return -EPERM; | ||
351 | |||
348 | ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), | 352 | ret = ttm_mem_global_alloc(mem_glob, sizeof(*ref), |
349 | false, false); | 353 | false, false); |
350 | if (unlikely(ret != 0)) | 354 | if (unlikely(ret != 0)) |
@@ -635,7 +639,7 @@ int ttm_prime_fd_to_handle(struct ttm_object_file *tfile, | |||
635 | prime = (struct ttm_prime_object *) dma_buf->priv; | 639 | prime = (struct ttm_prime_object *) dma_buf->priv; |
636 | base = &prime->base; | 640 | base = &prime->base; |
637 | *handle = base->hash.key; | 641 | *handle = base->hash.key; |
638 | ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); | 642 | ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, false); |
639 | 643 | ||
640 | dma_buf_put(dma_buf); | 644 | dma_buf_put(dma_buf); |
641 | 645 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c index 4076063e0fdd..6b2708b4eafe 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | |||
@@ -1075,10 +1075,8 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data, | |||
1075 | (void) vmw_fence_obj_reference(fence); | 1075 | (void) vmw_fence_obj_reference(fence); |
1076 | 1076 | ||
1077 | if (user_fence_rep != NULL) { | 1077 | if (user_fence_rep != NULL) { |
1078 | bool existed; | 1078 | ret = ttm_ref_object_add(vmw_fp->tfile, base, |
1079 | 1079 | TTM_REF_USAGE, NULL, false); | |
1080 | ret = ttm_ref_object_add(tfile, base, | ||
1081 | TTM_REF_USAGE, &existed); | ||
1082 | if (unlikely(ret != 0)) { | 1080 | if (unlikely(ret != 0)) { |
1083 | DRM_ERROR("Failed to reference a fence " | 1081 | DRM_ERROR("Failed to reference a fence " |
1084 | "object.\n"); | 1082 | "object.\n"); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index 65b3f0369636..bf23153d4f55 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |||
@@ -589,7 +589,7 @@ static int vmw_user_dmabuf_synccpu_grab(struct vmw_user_dma_buffer *user_bo, | |||
589 | return ret; | 589 | return ret; |
590 | 590 | ||
591 | ret = ttm_ref_object_add(tfile, &user_bo->prime.base, | 591 | ret = ttm_ref_object_add(tfile, &user_bo->prime.base, |
592 | TTM_REF_SYNCCPU_WRITE, &existed); | 592 | TTM_REF_SYNCCPU_WRITE, &existed, false); |
593 | if (ret != 0 || existed) | 593 | if (ret != 0 || existed) |
594 | ttm_bo_synccpu_write_release(&user_bo->dma.base); | 594 | ttm_bo_synccpu_write_release(&user_bo->dma.base); |
595 | 595 | ||
@@ -773,7 +773,7 @@ int vmw_user_dmabuf_reference(struct ttm_object_file *tfile, | |||
773 | 773 | ||
774 | *handle = user_bo->prime.base.hash.key; | 774 | *handle = user_bo->prime.base.hash.key; |
775 | return ttm_ref_object_add(tfile, &user_bo->prime.base, | 775 | return ttm_ref_object_add(tfile, &user_bo->prime.base, |
776 | TTM_REF_USAGE, NULL); | 776 | TTM_REF_USAGE, NULL, false); |
777 | } | 777 | } |
778 | 778 | ||
779 | /* | 779 | /* |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c index f410502cb075..adc023fe67f3 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_surface.c | |||
@@ -891,17 +891,16 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv, | |||
891 | uint32_t handle; | 891 | uint32_t handle; |
892 | struct ttm_base_object *base; | 892 | struct ttm_base_object *base; |
893 | int ret; | 893 | int ret; |
894 | bool require_exist = false; | ||
894 | 895 | ||
895 | if (handle_type == DRM_VMW_HANDLE_PRIME) { | 896 | if (handle_type == DRM_VMW_HANDLE_PRIME) { |
896 | ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle); | 897 | ret = ttm_prime_fd_to_handle(tfile, u_handle, &handle); |
897 | if (unlikely(ret != 0)) | 898 | if (unlikely(ret != 0)) |
898 | return ret; | 899 | return ret; |
899 | } else { | 900 | } else { |
900 | if (unlikely(drm_is_render_client(file_priv))) { | 901 | if (unlikely(drm_is_render_client(file_priv))) |
901 | DRM_ERROR("Render client refused legacy " | 902 | require_exist = true; |
902 | "surface reference.\n"); | 903 | |
903 | return -EACCES; | ||
904 | } | ||
905 | if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) { | 904 | if (ACCESS_ONCE(vmw_fpriv(file_priv)->locked_master)) { |
906 | DRM_ERROR("Locked master refused legacy " | 905 | DRM_ERROR("Locked master refused legacy " |
907 | "surface reference.\n"); | 906 | "surface reference.\n"); |
@@ -929,17 +928,14 @@ vmw_surface_handle_reference(struct vmw_private *dev_priv, | |||
929 | 928 | ||
930 | /* | 929 | /* |
931 | * Make sure the surface creator has the same | 930 | * Make sure the surface creator has the same |
932 | * authenticating master. | 931 | * authenticating master, or is already registered with us. |
933 | */ | 932 | */ |
934 | if (drm_is_primary_client(file_priv) && | 933 | if (drm_is_primary_client(file_priv) && |
935 | user_srf->master != file_priv->master) { | 934 | user_srf->master != file_priv->master) |
936 | DRM_ERROR("Trying to reference surface outside of" | 935 | require_exist = true; |
937 | " master domain.\n"); | ||
938 | ret = -EACCES; | ||
939 | goto out_bad_resource; | ||
940 | } | ||
941 | 936 | ||
942 | ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL); | 937 | ret = ttm_ref_object_add(tfile, base, TTM_REF_USAGE, NULL, |
938 | require_exist); | ||
943 | if (unlikely(ret != 0)) { | 939 | if (unlikely(ret != 0)) { |
944 | DRM_ERROR("Could not add a reference to a surface.\n"); | 940 | DRM_ERROR("Could not add a reference to a surface.\n"); |
945 | goto out_bad_resource; | 941 | goto out_bad_resource; |
diff --git a/include/drm/ttm/ttm_object.h b/include/drm/ttm/ttm_object.h index ed953f98f0e1..1487011fe057 100644 --- a/include/drm/ttm/ttm_object.h +++ b/include/drm/ttm/ttm_object.h | |||
@@ -229,6 +229,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base); | |||
229 | * @ref_type: The type of reference. | 229 | * @ref_type: The type of reference. |
230 | * @existed: Upon completion, indicates that an identical reference object | 230 | * @existed: Upon completion, indicates that an identical reference object |
231 | * already existed, and the refcount was upped on that object instead. | 231 | * already existed, and the refcount was upped on that object instead. |
232 | * @require_existed: Fail with -EPERM if an identical ref object didn't | ||
233 | * already exist. | ||
232 | * | 234 | * |
233 | * Checks that the base object is shareable and adds a ref object to it. | 235 | * Checks that the base object is shareable and adds a ref object to it. |
234 | * | 236 | * |
@@ -243,7 +245,8 @@ extern void ttm_base_object_unref(struct ttm_base_object **p_base); | |||
243 | */ | 245 | */ |
244 | extern int ttm_ref_object_add(struct ttm_object_file *tfile, | 246 | extern int ttm_ref_object_add(struct ttm_object_file *tfile, |
245 | struct ttm_base_object *base, | 247 | struct ttm_base_object *base, |
246 | enum ttm_ref_type ref_type, bool *existed); | 248 | enum ttm_ref_type ref_type, bool *existed, |
249 | bool require_existed); | ||
247 | 250 | ||
248 | extern bool ttm_ref_object_exists(struct ttm_object_file *tfile, | 251 | extern bool ttm_ref_object_exists(struct ttm_object_file *tfile, |
249 | struct ttm_base_object *base); | 252 | struct ttm_base_object *base); |