lkml.org 
[lkml]   [2017]   [Jul]   [16]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Date
    Subject[PATCH 3.2 55/95] drm/vmwgfx: Type-check lookups of fence objects
    3.2.91-rc1 review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Thomas Hellstrom <thellstrom@vmware.com>

    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>
    [bwh: Backported to 3.2: adjust context]
    Signed-off-by: Ben Hutchings <ben@decadent.org.uk>
    ---
    drivers/gpu/drm/vmwgfx/vmwgfx_fence.c | 77 +++++++++++++++++++++++------------
    1 file changed, 50 insertions(+), 27 deletions(-)

    --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
    +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
    @@ -493,7 +493,7 @@ int vmw_fence_create(struct vmw_fence_ma
    struct vmw_fence_obj **p_fence)
    {
    struct vmw_fence_obj *fence;
    - int ret;
    + int ret;

    fence = kzalloc(sizeof(*fence), GFP_KERNEL);
    if (unlikely(fence == NULL))
    @@ -661,6 +661,41 @@ void vmw_fence_fifo_up(struct vmw_fence_
    }


    +/**
    + * vmw_fence_obj_lookup - Look up a user-space fence object
    + *
    + * @tfile: A struct ttm_object_file identifying the caller.
    + * @handle: A handle identifying the fence object.
    + * @return: A struct vmw_user_fence base ttm object on success or
    + * an error pointer on failure.
    + *
    + * The fence object is looked up and type-checked. The caller needs
    + * to have opened the fence object first, but since that happens on
    + * creation and fence objects aren't shareable, that's not an
    + * issue currently.
    + */
    +static struct ttm_base_object *
    +vmw_fence_obj_lookup(struct ttm_object_file *tfile, u32 handle)
    +{
    + struct ttm_base_object *base = ttm_base_object_lookup(tfile, handle);
    +
    + if (!base) {
    + pr_err("Invalid fence object handle 0x%08lx.\n",
    + (unsigned long)handle);
    + return ERR_PTR(-EINVAL);
    + }
    +
    + if (base->refcount_release != vmw_user_fence_base_release) {
    + pr_err("Invalid fence object handle 0x%08lx.\n",
    + (unsigned long)handle);
    + ttm_base_object_unref(&base);
    + return ERR_PTR(-EINVAL);
    + }
    +
    + return base;
    +}
    +
    +
    int vmw_fence_obj_wait_ioctl(struct drm_device *dev, void *data,
    struct drm_file *file_priv)
    {
    @@ -686,13 +721,9 @@ int vmw_fence_obj_wait_ioctl(struct drm_
    arg->kernel_cookie = jiffies + wait_timeout;
    }

    - base = ttm_base_object_lookup(tfile, arg->handle);
    - if (unlikely(base == NULL)) {
    - printk(KERN_ERR "Wait invalid fence object handle "
    - "0x%08lx.\n",
    - (unsigned long)arg->handle);
    - return -EINVAL;
    - }
    + base = vmw_fence_obj_lookup(tfile, arg->handle);
    + if (IS_ERR(base))
    + return PTR_ERR(base);

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

    @@ -731,13 +762,9 @@ int vmw_fence_obj_signaled_ioctl(struct
    struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
    struct vmw_private *dev_priv = vmw_priv(dev);

    - base = ttm_base_object_lookup(tfile, arg->handle);
    - if (unlikely(base == NULL)) {
    - printk(KERN_ERR "Fence signaled invalid fence object handle "
    - "0x%08lx.\n",
    - (unsigned long)arg->handle);
    - return -EINVAL;
    - }
    + base = vmw_fence_obj_lookup(tfile, arg->handle);
    + if (IS_ERR(base))
    + return PTR_ERR(base);

    fence = &(container_of(base, struct vmw_user_fence, base)->fence);
    fman = fence->fman;
    @@ -987,6 +1014,7 @@ int vmw_fence_event_ioctl(struct drm_dev
    (struct drm_vmw_fence_event_arg *) data;
    struct vmw_fence_obj *fence = NULL;
    struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
    + struct ttm_object_file *tfile = vmw_fp->tfile;
    struct drm_vmw_fence_rep __user *user_fence_rep =
    (struct drm_vmw_fence_rep __user *)(unsigned long)
    arg->fence_rep;
    @@ -1002,14 +1030,11 @@ int vmw_fence_event_ioctl(struct drm_dev
    */
    if (arg->handle) {
    struct ttm_base_object *base =
    - ttm_base_object_lookup(vmw_fp->tfile, arg->handle);
    + vmw_fence_obj_lookup(tfile, arg->handle);
    +
    + if (IS_ERR(base))
    + return PTR_ERR(base);

    - if (unlikely(base == NULL)) {
    - DRM_ERROR("Fence event invalid fence object handle "
    - "0x%08lx.\n",
    - (unsigned long)arg->handle);
    - return -EINVAL;
    - }
    fence = &(container_of(base, struct vmw_user_fence,
    base)->fence);
    (void) vmw_fence_obj_reference(fence);
    @@ -1017,7 +1042,7 @@ int vmw_fence_event_ioctl(struct drm_dev
    if (user_fence_rep != NULL) {
    bool existed;

    - ret = ttm_ref_object_add(vmw_fp->tfile, base,
    + ret = ttm_ref_object_add(tfile, base,
    TTM_REF_USAGE, &existed);
    if (unlikely(ret != 0)) {
    DRM_ERROR("Failed to reference a fence "
    @@ -1099,8 +1124,7 @@ out_no_event:
    spin_unlock_irqrestore(&dev->event_lock, irq_flags);
    out_no_event_space:
    if (user_fence_rep != NULL)
    - ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
    - handle, TTM_REF_USAGE);
    + ttm_ref_object_base_unref(tfile, handle, TTM_REF_USAGE);
    out_no_ref_obj:
    vmw_fence_obj_unreference(&fence);
    return ret;
    \
     
     \ /
      Last update: 2017-07-16 16:56    [W:4.357 / U:0.132 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site