Skip to content

Commit f7652af

Browse files
committed
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: <[email protected]> Signed-off-by: Thomas Hellstrom <[email protected]> Reviewed-by: Sinclair Yeh <[email protected]>
1 parent d64a047 commit f7652af

File tree

1 file changed

+50
-27
lines changed

1 file changed

+50
-27
lines changed

drivers/gpu/drm/vmwgfx/vmwgfx_fence.c

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

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

703703

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+
*/
717+
static struct ttm_base_object *
718+
vmw_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+
704739
int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
705740
struct drm_file *file_priv)
706741
{
@@ -726,13 +761,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
726761
arg->kernel_cookie = jiffies + wait_timeout;
727762
}
728763

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

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

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

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

782809
fence = &(container_of(base, struct vmw_user_fence, base)->fence);
783810
fman = fman_from_fence(fence);
@@ -1024,6 +1051,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10241051
(struct drm_vmw_fence_event_arg *) data;
10251052
struct vmw_fence_obj *fence = NULL;
10261053
struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
1054+
struct ttm_object_file *tfile = vmw_fp->tfile;
10271055
struct drm_vmw_fence_rep __user *user_fence_rep =
10281056
(struct drm_vmw_fence_rep __user *)(unsigned long)
10291057
arg->fence_rep;
@@ -1037,23 +1065,19 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10371065
*/
10381066
if (arg->handle) {
10391067
struct ttm_base_object *base =
1040-
ttm_base_object_lookup_for_ref(dev_priv->tdev,
1041-
arg->handle);
1042-
1043-
if (unlikely(base == NULL)) {
1044-
DRM_ERROR("Fence event invalid fence object handle "
1045-
"0x%08lx.\n",
1046-
(unsigned long)arg->handle);
1047-
return -EINVAL;
1048-
}
1068+
vmw_fence_obj_lookup(tfile, arg->handle);
1069+
1070+
if (IS_ERR(base))
1071+
return PTR_ERR(base);
1072+
10491073
fence = &(container_of(base, struct vmw_user_fence,
10501074
base)->fence);
10511075
(void) vmw_fence_obj_reference(fence);
10521076

10531077
if (user_fence_rep != NULL) {
10541078
bool existed;
10551079

1056-
ret = ttm_ref_object_add(vmw_fp->tfile, base,
1080+
ret = ttm_ref_object_add(tfile, base,
10571081
TTM_REF_USAGE, &existed);
10581082
if (unlikely(ret != 0)) {
10591083
DRM_ERROR("Failed to reference a fence "
@@ -1097,8 +1121,7 @@ int vmw_fence_event_ioctl(struct drm_device *dev, void *data,
10971121
return 0;
10981122
out_no_create:
10991123
if (user_fence_rep != NULL)
1100-
ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
1101-
handle, TTM_REF_USAGE);
1124+
ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
11021125
out_no_ref_obj:
11031126
vmw_fence_obj_unreference(&fence);
11041127
return ret;

0 commit comments

Comments
 (0)