[PATCH] drm: Avoid NULL master_priv access in i915 kernel driver

Stéphane Marchesin marcheu at chromium.org
Wed Feb 12 14:24:00 PST 2014


From: Stuart Abercrombie <sabercrombie at chromium.org>

In several places, including the interrupt handler, the i915 driver assumes
it can deref. dev->primary->master->driver_priv if dev->primary->master
is non-NULL.  This wasn't true if drm_open_helper was midway through, so
rearrange the initialization order.

v2: Address this in drm_open_helper instead of the various access points --
basically Stephane's fix.

Signed-off-by: Stuart Abercrombie <sabercrombie at chromium.org>
Signed-off-by: Stéphane Marchesin <marcheu at chromium.org>
---
 drivers/gpu/drm/drm_fops.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 7f2af9a..3df3032 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -260,9 +260,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 	 * any master object for render clients */
 	mutex_lock(&dev->struct_mutex);
 	if (!priv->minor->master && !drm_is_render_client(priv)) {
-		/* create a new master */
-		priv->minor->master = drm_master_create(priv->minor);
-		if (!priv->minor->master) {
+		/* create a new master but don't assign it yet
+		 * to ensure master->driver_priv is set up first
+		 */
+		struct drm_master *master_ptr = drm_master_create(priv->minor);
+		if (!master_ptr) {
 			mutex_unlock(&dev->struct_mutex);
 			ret = -ENOMEM;
 			goto out_close;
@@ -270,7 +272,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 
 		priv->is_master = 1;
 		/* take another reference for the copy in the local file priv */
-		priv->master = drm_master_get(priv->minor->master);
+		priv->master = drm_master_get(master_ptr);
 
 		priv->authenticated = 1;
 
@@ -280,7 +282,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 			if (ret) {
 				mutex_lock(&dev->struct_mutex);
 				/* drop both references if this fails */
-				drm_master_put(&priv->minor->master);
+				drm_master_put(&master_ptr);
 				drm_master_put(&priv->master);
 				mutex_unlock(&dev->struct_mutex);
 				goto out_close;
@@ -291,12 +293,13 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
 			ret = dev->driver->master_set(dev, priv, true);
 			if (ret) {
 				/* drop both references if this fails */
-				drm_master_put(&priv->minor->master);
+				drm_master_put(&master_ptr);
 				drm_master_put(&priv->master);
 				mutex_unlock(&dev->struct_mutex);
 				goto out_close;
 			}
 		}
+		priv->minor->master = master_ptr;
 	} else if (!drm_is_render_client(priv)) {
 		/* get a reference to the master */
 		priv->master = drm_master_get(priv->minor->master);
-- 
1.9.0.rc1.175.g0b1dcb5



More information about the dri-devel mailing list