aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2017-03-27 05:09:08 -0400
committerThomas Hellstrom <thellstrom@vmware.com>2017-03-30 05:42:54 -0400
commitf7652afa8eadb416b23eb57dec6f158529942041 (patch)
treeb96ae6140a414f7eb0577da2c6b20270ff3483f8
parentd64a04720b0e64c1cd0726a3a27b360822fbee22 (diff)
drm/vmwgfx: Type-check lookups of fence objects
A malicious caller could otherwise hand over handles to other objects causing all sorts of interesting problems. Testing done: Ran a Fedora 25 desktop using both Xorg and gnome-shell/Wayland. 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/vmwgfx/vmwgfx_fence.c77
1 files changed, 50 insertions, 27 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
index 6541dd8b82dc..4076063e0fdd 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
@@ -538,7 +538,7 @@ int vmw_fence_create(struct vmw_fence_manager *fman,
538 struct vmw_fence_obj **p_fence) 538 struct vmw_fence_obj **p_fence)
539{ 539{
540 struct vmw_fence_obj *fence; 540 struct vmw_fence_obj *fence;
541 int ret; 541 int ret;
542 542
543 fence = kzalloc(sizeof(*fence), GFP_KERNEL); 543 fence = kzalloc(sizeof(*fence), GFP_KERNEL);
544 if (unlikely(fence == NULL)) 544 if (unlikely(fence == NULL))
@@ -701,6 +701,41 @@ void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
701} 701}
702 702
703 703
704/**
705 * vmw_fence_obj_lookup - Look up a user-space fence object
706 *
707 * @tfile: A struct ttm_object_file identifying the caller.
708 * @handle: A handle identifying the fence object.
709 * @return: A struct vmw_user_fence base ttm object on success or
710 * an error pointer on failure.
711 *
712 * The fence object is looked up and type-checked. The caller needs
713 * to have opened the fence object first, but since that happens on
714 * creation and fence objects aren't shareable, that's not an
715 * issue currently.
716 */
717static struct ttm_base_object *
718vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle)
719{
720 struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle);
721
722 if (!base) {
723 pr_err("Invalid fence object handle 0x%08lx.\n",
724 (unsigned long)handle);
725 return ERR_PTR(-EINVAL);
726 }
727
728 if (base->refcount_release != vmw_user_fence_base_release) {
729 pr_err("Invalid fence object handle 0x%08lx.\n",
730 (unsigned long)handle);
731 ttm_base_object_unref(&base);
732 return ERR_PTR(-EINVAL);
733 }
734
735 return base;
736}
737
738
704int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data, 739int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
705 struct drm_file *file_priv) 740 struct drm_file *file_priv)
706{ 741{
@@ -726,13 +761,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
726 arg->kernel_cookie = jiffies + wait_timeout; 761 arg->kernel_cookie = jiffies + wait_timeout;
727 } 762 }
728 763
729 base = ttm_base_object_lookup(tfile, arg->handle); 764 base = vmw_fence_obj_lookup(tfile, arg->handle);
730 if (unlikely(base == NULL)) { 765 if (IS_ERR(base))
731 printk(KERN_ERR "Wait invalid fence object handle " 766 return PTR_ERR(base);
732 "0x%08lx.\n",
733 (unsigned long)arg->handle);
734 return -EINVAL;
735 }
736 767
737 fence = &(container_of(base, struct vmw_user_fence, base)->fence); 768 fence = &(container_of(base, struct vmw_user_fence, base)->fence);
738 769
@@ -771,13 +802,9 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
771 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile; 802 struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
772 struct vmw_private *dev_priv = vmw_priv(dev); 803 struct vmw_private *dev_priv = vmw_priv(dev);
773 804
774 base = ttm_base_object_lookup(tfile, arg->handle); 805 base = vmw_fence_obj_lookup(tfile, arg->handle);
775 if (unlikely(base == NULL)) { 806 if (IS_ERR(base))
776 printk(KERN_ERR "Fence signaled invalid fence object handle " 807 return PTR_ERR(base);
777 "0x%08lx.\n",
778 (unsigned long)arg->handle);
779 return -EINVAL;
780 }
781 808
782 fence = &(container_of(base, struct vmw_user_fence, base)->fence); 809 fence = &(container_of(base, struct vmw_user_fence, base)->fence);
783 fman = fman_from_fence(fence); 810 fman = fman_from_fence(fence);
@@ -1024,6 +1051,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
1024 (struct drm_vmw_fence_event_arg *) data; 1051 (struct drm_vmw_fence_event_arg *) data;
1025 struct vmw_fence_obj *fence = NULL; 1052 struct vmw_fence_obj *fence = NULL;
1026 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv); 1053 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
1054 struct ttm_object_file *tfile = vmw_fp->tfile;
1027 struct drm_vmw_fence_rep __user *user_fence_rep = 1055 struct drm_vmw_fence_rep __user *user_fence_rep =
1028 (struct drm_vmw_fence_rep __user *)(unsigned long) 1056 (struct drm_vmw_fence_rep __user *)(unsigned long)
1029 arg->fence_rep; 1057 arg->fence_rep;
@@ -1037,15 +1065,11 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
1037 */ 1065 */
1038 if (arg->handle) { 1066 if (arg->handle) {
1039 struct ttm_base_object *base = 1067 struct ttm_base_object *base =
1040 ttm_base_object_lookup_for_ref(dev_priv->tdev, 1068 vmw_fence_obj_lookup(tfile, arg->handle);
1041 arg->handle); 1069
1042 1070 if (IS_ERR(base))
1043 if (unlikely(base == NULL)) { 1071 return PTR_ERR(base);
1044 DRM_ERROR("Fence event invalid fence object handle " 1072
1045 "0x%08lx.\n",
1046 (unsigned long)arg->handle);
1047 return -EINVAL;
1048 }
1049 fence = &(container_of(base, struct vmw_user_fence, 1073 fence = &(container_of(base, struct vmw_user_fence,
1050 base)->fence); 1074 base)->fence);
1051 (void) vmw_fence_obj_reference(fence); 1075 (void) vmw_fence_obj_reference(fence);
@@ -1053,7 +1077,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
1053 if (user_fence_rep != NULL) { 1077 if (user_fence_rep != NULL) {
1054 bool existed; 1078 bool existed;
1055 1079
1056 ret = ttm_ref_object_add(vmw_fp->tfile, base, 1080 ret = ttm_ref_object_add(tfile, base,
1057 TTM_REF_USAGE, &existed); 1081 TTM_REF_USAGE, &existed);
1058 if (unlikely(ret != 0)) { 1082 if (unlikely(ret != 0)) {
1059 DRM_ERROR("Failed to reference a fence " 1083 DRM_ERROR("Failed to reference a fence "
@@ -1097,8 +1121,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
1097 return 0; 1121 return 0;
1098out_no_create: 1122out_no_create:
1099 if (user_fence_rep != NULL) 1123 if (user_fence_rep != NULL)
1100 ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile, 1124 ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
1101 handle, TTM_REF_USAGE);
1102out_no_ref_obj: 1125out_no_ref_obj:
1103 vmw_fence_obj_unreference(&fence); 1126 vmw_fence_obj_unreference(&fence);
1104 return ret; 1127 return ret;