From df9b6a9c3333a99d4483e92ca6b225b335567313 Mon Sep 17 00:00:00 2001 From: Seung-Woo Kim Date: Tue, 2 Jul 2013 09:53:28 +0900 Subject: [PATCH] drm: fix error routines in drm_open_helper There are missing parts to handle error in drm_open_helper(). The priv->minor, assigned by idr_find() which can return NULL, should be checked whether it is NULL or not before referencing it. put_pid(), drm_gem_release(), and drm_prime_destory_file_private() should be called when error happens after their pair functions are called. If an error occurs after executing dev->driver->open() which allocates driver specific per-file private data, then the private data should be released. Signed-off-by: YoungJun Cho Signed-off-by: Seung-Woo Kim Signed-off-by: Kyungmin Park Reviewed-by: Chris Wilson Signed-off-by: Dave Airlie --- drivers/gpu/drm/drm_fops.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c index 429e07d..3a24385 100644 --- a/drivers/gpu/drm/drm_fops.c +++ b/drivers/gpu/drm/drm_fops.c @@ -271,6 +271,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp, priv->uid = current_euid(); priv->pid = get_pid(task_pid(current)); priv->minor = idr_find(&drm_minors_idr, minor_id); + if (!priv->minor) { + ret = -ENODEV; + goto out_put_pid; + } + priv->ioctl_count = 0; /* for compatibility root is always authenticated */ priv->authenticated = capable(CAP_SYS_ADMIN); @@ -292,7 +297,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (dev->driver->open) { ret = dev->driver->open(dev, priv); if (ret < 0) - goto out_free; + goto out_prime_destroy; } @@ -304,7 +309,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, if (!priv->minor->master) { mutex_unlock(&dev->struct_mutex); ret = -ENOMEM; - goto out_free; + goto out_close; } priv->is_master = 1; @@ -322,7 +327,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, drm_master_put(&priv->minor->master); drm_master_put(&priv->master); mutex_unlock(&dev->struct_mutex); - goto out_free; + goto out_close; } } mutex_lock(&dev->struct_mutex); @@ -333,7 +338,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp, drm_master_put(&priv->minor->master); drm_master_put(&priv->master); mutex_unlock(&dev->struct_mutex); - goto out_free; + goto out_close; } } mutex_unlock(&dev->struct_mutex); @@ -367,7 +372,17 @@ static int drm_open_helper(struct inode *inode, struct file *filp, #endif return 0; - out_free: + +out_close: + if (dev->driver->postclose) + dev->driver->postclose(dev, priv); +out_prime_destroy: + if (drm_core_check_feature(dev, DRIVER_PRIME)) + drm_prime_destroy_file_private(&priv->prime); + if (dev->driver->driver_features & DRIVER_GEM) + drm_gem_release(dev, priv); +out_put_pid: + put_pid(priv->pid); kfree(priv); filp->private_data = NULL; return ret; -- 2.7.4