aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSeung-Woo Kim <sw0312.kim@samsung.com>2013-07-01 20:53:28 -0400
committerDave Airlie <airlied@redhat.com>2013-07-03 20:53:37 -0400
commitdf9b6a9c3333a99d4483e92ca6b225b335567313 (patch)
treef0478c4990796a3843cb863e66c884a5d10f2e80
parentfe2ef780669d9bbd2f921b247dc79266b00b99ab (diff)
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>
-rw-r--r--drivers/gpu/drm/drm_fops.c25
1 files changed, 20 insertions, 5 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index 429e07d0b0f1..3a24385e0368 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,
271 priv->uid = current_euid(); 271 priv->uid = current_euid();
272 priv->pid = get_pid(task_pid(current)); 272 priv->pid = get_pid(task_pid(current));
273 priv->minor = idr_find(&drm_minors_idr, minor_id); 273 priv->minor = idr_find(&drm_minors_idr, minor_id);
274 if (!priv->minor) {
275 ret = -ENODEV;
276 goto out_put_pid;
277 }
278
274 priv->ioctl_count = 0; 279 priv->ioctl_count = 0;
275 /* for compatibility root is always authenticated */ 280 /* for compatibility root is always authenticated */
276 priv->authenticated = capable(CAP_SYS_ADMIN); 281 priv->authenticated = capable(CAP_SYS_ADMIN);
@@ -292,7 +297,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
292 if (dev->driver->open) { 297 if (dev->driver->open) {
293 ret = dev->driver->open(dev, priv); 298 ret = dev->driver->open(dev, priv);
294 if (ret < 0) 299 if (ret < 0)
295 goto out_free; 300 goto out_prime_destroy;
296 } 301 }
297 302
298 303
@@ -304,7 +309,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
304 if (!priv->minor->master) { 309 if (!priv->minor->master) {
305 mutex_unlock(&dev->struct_mutex); 310 mutex_unlock(&dev->struct_mutex);
306 ret = -ENOMEM; 311 ret = -ENOMEM;
307 goto out_free; 312 goto out_close;
308 } 313 }
309 314
310 priv->is_master = 1; 315 priv->is_master = 1;
@@ -322,7 +327,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
322 drm_master_put(&priv->minor->master); 327 drm_master_put(&priv->minor->master);
323 drm_master_put(&priv->master); 328 drm_master_put(&priv->master);
324 mutex_unlock(&dev->struct_mutex); 329 mutex_unlock(&dev->struct_mutex);
325 goto out_free; 330 goto out_close;
326 } 331 }
327 } 332 }
328 mutex_lock(&dev->struct_mutex); 333 mutex_lock(&dev->struct_mutex);
@@ -333,7 +338,7 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
333 drm_master_put(&priv->minor->master); 338 drm_master_put(&priv->minor->master);
334 drm_master_put(&priv->master); 339 drm_master_put(&priv->master);
335 mutex_unlock(&dev->struct_mutex); 340 mutex_unlock(&dev->struct_mutex);
336 goto out_free; 341 goto out_close;
337 } 342 }
338 } 343 }
339 mutex_unlock(&dev->struct_mutex); 344 mutex_unlock(&dev->struct_mutex);
@@ -367,7 +372,17 @@ static int drm_open_helper(struct inode *inode, struct file *filp,
367#endif 372#endif
368 373
369 return 0; 374 return 0;
370 out_free: 375
376out_close:
377 if (dev->driver->postclose)
378 dev->driver->postclose(dev, priv);
379out_prime_destroy:
380 if (drm_core_check_feature(dev, DRIVER_PRIME))
381 drm_prime_destroy_file_private(&priv->prime);
382 if (dev->driver->driver_features & DRIVER_GEM)
383 drm_gem_release(dev, priv);
384out_put_pid:
385 put_pid(priv->pid);
371 kfree(priv); 386 kfree(priv);
372 filp->private_data = NULL; 387 filp->private_data = NULL;
373 return ret; 388 return ret;