Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Seung-Woo Kim and committed by
Dave Airlie
df9b6a9c fe2ef780

+20 -5
+20 -5
drivers/gpu/drm/drm_fops.c
··· 271 271 priv->uid = current_euid(); 272 272 priv->pid = get_pid(task_pid(current)); 273 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 279 priv->ioctl_count = 0; 275 280 /* for compatibility root is always authenticated */ 276 281 priv->authenticated = capable(CAP_SYS_ADMIN); ··· 297 292 if (dev->driver->open) { 298 293 ret = dev->driver->open(dev, priv); 299 294 if (ret < 0) 300 - goto out_free; 295 + goto out_prime_destroy; 301 296 } 302 297 303 298 ··· 309 304 if (!priv->minor->master) { 310 305 mutex_unlock(&dev->struct_mutex); 311 306 ret = -ENOMEM; 312 - goto out_free; 307 + goto out_close; 313 308 } 314 309 315 310 priv->is_master = 1; ··· 327 322 drm_master_put(&priv->minor->master); 328 323 drm_master_put(&priv->master); 329 324 mutex_unlock(&dev->struct_mutex); 330 - goto out_free; 325 + goto out_close; 331 326 } 332 327 } 333 328 mutex_lock(&dev->struct_mutex); ··· 338 333 drm_master_put(&priv->minor->master); 339 334 drm_master_put(&priv->master); 340 335 mutex_unlock(&dev->struct_mutex); 341 - goto out_free; 336 + goto out_close; 342 337 } 343 338 } 344 339 mutex_unlock(&dev->struct_mutex); ··· 372 367 #endif 373 368 374 369 return 0; 375 - out_free: 370 + 371 + out_close: 372 + if (dev->driver->postclose) 373 + dev->driver->postclose(dev, priv); 374 + out_prime_destroy: 375 + if (drm_core_check_feature(dev, DRIVER_PRIME)) 376 + drm_prime_destroy_file_private(&priv->prime); 377 + if (dev->driver->driver_features & DRIVER_GEM) 378 + drm_gem_release(dev, priv); 379 + out_put_pid: 380 + put_pid(priv->pid); 376 381 kfree(priv); 377 382 filp->private_data = NULL; 378 383 return ret;