diff mbox

[3/3] drm: fix error routines in drm_open_helper

Message ID 1372673193-18824-4-git-send-email-sw0312.kim@samsung.com (mailing list archive)
State New, archived
Headers show

Commit Message

Seung-Woo Kim July 1, 2013, 10:06 a.m. UTC
From: YoungJun Cho <yj44.cho@samsung.com>

There are wrong cases 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.
And 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 <yj44.cho@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 drivers/gpu/drm/drm_fops.c |   17 +++++++++++++----
 1 files changed, 13 insertions(+), 4 deletions(-)

Comments

Chris Wilson July 1, 2013, 10:18 a.m. UTC | #1
On Mon, Jul 01, 2013 at 07:06:33PM +0900, Seung-Woo Kim wrote:
> From: YoungJun Cho <yj44.cho@samsung.com>
> 
> There are wrong cases 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.
> And 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 <yj44.cho@samsung.com>
> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com>
> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
> ---
>  drivers/gpu/drm/drm_fops.c |   17 +++++++++++++----
>  1 files changed, 13 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
> index 429e07d..0470261 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 = -ENOMEM;

Elsewhere we use ENODEV for a failure to find the minor inode.

The error path cleanup changes look reasonable. Though require a quick
audit to make sure all of the callees do not expect more state to be
correctly setup before being called.
-Chris
diff mbox

Patch

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 429e07d..0470261 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 = -ENOMEM;
+		goto out_free;
+	}
+
 	priv->ioctl_count = 0;
 	/* for compatibility root is always authenticated */
 	priv->authenticated = capable(CAP_SYS_ADMIN);
@@ -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,11 @@  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_free:
 	kfree(priv);
 	filp->private_data = NULL;
 	return ret;