Skip to content

Commit ed52892

Browse files
thomashvmwgregkh
authored andcommitted
drm/vmwgfx: Type-check lookups of fence objects
commit f7652afa8eadb416b23eb57dec6f158529942041 upstream. 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. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Sinclair Yeh <syeh@vmware.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent 8f8ee97 commit ed52892

1 file changed

Lines changed: 50 additions & 27 deletions

File tree

drivers/gpu/drm/vmwgfx/vmwgfx_fence.c

Lines changed: 50 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -539,7 +539,7 @@ int vmw_fence_create(struct vmw_fence_manager *fman,
539539
struct vmw_fence_obj **p_fence)
540540
{
541541
struct vmw_fence_obj *fence;
542-
int ret;
542+
int ret;
543543

544544
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
545545
if (unlikely(fence == NULL))
@@ -702,6 +702,41 @@ void vmw_fence_fifo_up(struct vmw_fence_manager *fman)
702702
}
703703

704704

705+
/**
706+
* vmw_fence_obj_lookup - Look up a user-space fence object
707+
*
708+
* @tfile: A struct ttm_object_file identifying the caller.
709+
* @handle: A handle identifying the fence object.
710+
* @return: A struct vmw_user_fence base ttm object on success or
711+
* an error pointer on failure.
712+
*
713+
* The fence object is looked up and type-checked. The caller needs
714+
* to have opened the fence object first, but since that happens on
715+
* creation and fence objects aren't shareable, that's not an
716+
* issue currently.
717+
*/
718+
static struct ttm_base_object *
719+
vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle)
720+
{
721+
struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle);
722+
723+
if (!base) {
724+
pr_err("Invalid fence object handle 0x%08lx.\n",
725+
(unsigned long)handle);
726+
return ERR_PTR(-EINVAL);
727+
}
728+
729+
if (base->refcount_release != vmw_user_fence_base_release) {
730+
pr_err("Invalid fence object handle 0x%08lx.\n",
731+
(unsigned long)handle);
732+
ttm_base_object_unref(&base);
733+
return ERR_PTR(-EINVAL);
734+
}
735+
736+
return base;
737+
}
738+
739+
705740
int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
706741
struct drm_file *file_priv)
707742
{
@@ -727,13 +762,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
727762
arg->kernel_cookie = jiffies + wait_timeout;
728763
}
729764

730-
base = ttm_base_object_lookup(tfile, arg->handle);
731-
if (unlikely(base == NULL)) {
732-
printk(KERN_ERR "Wait invalid fence object handle "
733-
"0x%08lx.\n",
734-
(unsigned long)arg->handle);
735-
return -EINVAL;
736-
}
765+
base = vmw_fence_obj_lookup(tfile, arg->handle);
766+
if (IS_ERR(base))
767+
return PTR_ERR(base);
737768

738769
fence = &(container_of(base, struct vmw_user_fence, base)->fence);
739770

@@ -772,13 +803,9 @@ int vmw_fence_obj_signaled_ioctl(struct drm_device *dev, void *data,
772803
struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
773804
struct vmw_private *dev_priv = vmw_priv(dev);
774805

775-
base = ttm_base_object_lookup(tfile, arg->handle);
776-
if (unlikely(base == NULL)) {
777-
printk(KERN_ERR "Fence signaled invalid fence object handle "
778-
"0x%08lx.\n",
779-
(unsigned long)arg->handle);
780-
return -EINVAL;
781-
}
806+
base = vmw_fence_obj_lookup(tfile, arg->handle);
807+
if (IS_ERR(base))
808+
return PTR_ERR(base);
782809

783810
fence = &(container_of(base, struct vmw_user_fence, base)->fence);
784811
fman = fman_from_fence(fence);
@@ -1093,6 +1120,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10931120
(struct drm_vmw_fence_event_arg *) data;
10941121
struct vmw_fence_obj *fence = NULL;
10951122
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
1123+
struct ttm_object_file *tfile = vmw_fp->tfile;
10961124
struct drm_vmw_fence_rep __user *user_fence_rep =
10971125
(struct drm_vmw_fence_rep __user *)(unsigned long)
10981126
arg->fence_rep;
@@ -1106,23 +1134,19 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
11061134
*/
11071135
if (arg->handle) {
11081136
struct ttm_base_object *base =
1109-
ttm_base_object_lookup_for_ref(dev_priv->tdev,
1110-
arg->handle);
1111-
1112-
if (unlikely(base == NULL)) {
1113-
DRM_ERROR("Fence event invalid fence object handle "
1114-
"0x%08lx.\n",
1115-
(unsigned long)arg->handle);
1116-
return -EINVAL;
1117-
}
1137+
vmw_fence_obj_lookup(tfile, arg->handle);
1138+
1139+
if (IS_ERR(base))
1140+
return PTR_ERR(base);
1141+
11181142
fence = &(container_of(base, struct vmw_user_fence,
11191143
base)->fence);
11201144
(void) vmw_fence_obj_reference(fence);
11211145

11221146
if (user_fence_rep != NULL) {
11231147
bool existed;
11241148

1125-
ret = ttm_ref_object_add(vmw_fp->tfile, base,
1149+
ret = ttm_ref_object_add(tfile, base,
11261150
TTM_REF_USAGE, &existed);
11271151
if (unlikely(ret != 0)) {
11281152
DRM_ERROR("Failed to reference a fence "
@@ -1166,8 +1190,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
11661190
return 0;
11671191
out_no_create:
11681192
if (user_fence_rep != NULL)
1169-
ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
1170-
handle, TTM_REF_USAGE);
1193+
ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
11711194
out_no_ref_obj:
11721195
vmw_fence_obj_unreference(&fence);
11731196
return ret;

0 commit comments

Comments
 (0)