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 <yj44.cho@samsung.com> Signed-off-by: Seung-Woo Kim <sw0312.kim@samsung.com> Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Reviewed-by: Chris Wilson <chris-wilson.co.uk> Signed-off-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
fe2ef78066
commit
df9b6a9c33
|
@ -271,6 +271,11 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||||
priv->uid = current_euid();
|
priv->uid = current_euid();
|
||||||
priv->pid = get_pid(task_pid(current));
|
priv->pid = get_pid(task_pid(current));
|
||||||
priv->minor = idr_find(&drm_minors_idr, minor_id);
|
priv->minor = idr_find(&drm_minors_idr, minor_id);
|
||||||
|
if (!priv->minor) {
|
||||||
|
ret = -ENODEV;
|
||||||
|
goto out_put_pid;
|
||||||
|
}
|
||||||
|
|
||||||
priv->ioctl_count = 0;
|
priv->ioctl_count = 0;
|
||||||
/* for compatibility root is always authenticated */
|
/* for compatibility root is always authenticated */
|
||||||
priv->authenticated = capable(CAP_SYS_ADMIN);
|
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) {
|
if (dev->driver->open) {
|
||||||
ret = dev->driver->open(dev, priv);
|
ret = dev->driver->open(dev, priv);
|
||||||
if (ret < 0)
|
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) {
|
if (!priv->minor->master) {
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
ret = -ENOMEM;
|
ret = -ENOMEM;
|
||||||
goto out_free;
|
goto out_close;
|
||||||
}
|
}
|
||||||
|
|
||||||
priv->is_master = 1;
|
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->minor->master);
|
||||||
drm_master_put(&priv->master);
|
drm_master_put(&priv->master);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
goto out_free;
|
goto out_close;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_lock(&dev->struct_mutex);
|
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->minor->master);
|
||||||
drm_master_put(&priv->master);
|
drm_master_put(&priv->master);
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
goto out_free;
|
goto out_close;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mutex_unlock(&dev->struct_mutex);
|
mutex_unlock(&dev->struct_mutex);
|
||||||
|
@ -367,7 +372,17 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return 0;
|
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);
|
kfree(priv);
|
||||||
filp->private_data = NULL;
|
filp->private_data = NULL;
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in a new issue