From: YoungJun Cho <yj44....@samsung.com>

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 <yj44....@samsung.com>
Signed-off-by: Seung-Woo Kim <sw0312....@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.p...@samsung.com>
---
change from v3
- fix typo
change from v2
- adds put_pid, drm_gem_release, drm_prime_destroy_file_private as Chris's 
review
change from v1
- replaces error value for failure to find the minor as ENODEV as Chris 
commented

 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..33b1125 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;
-- 
1.7.9.5

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/dri-devel

Reply via email to