[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