Commit 610ad5064cb90aec35f5837bbde3d316fe02aca7

Authored by Uwe Kleine-König
Committed by Greg Kroah-Hartman
1 parent b54f2863a2

UIO: hold a reference to the device's owner while the device is open

Otherwise the device might just disappear while /dev/uioX is being used
which results in an Oops.

Signed-off-by: Uwe Kleine-König <Uwe.Kleine-Koenig@digi.com>
Signed-off-by: Hans J Koch <hjk@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

Showing 1 changed file with 21 additions and 15 deletions Side-by-side Diff

... ... @@ -301,24 +301,34 @@
301 301 if (!idev)
302 302 return -ENODEV;
303 303  
  304 + if (!try_module_get(idev->owner))
  305 + return -ENODEV;
  306 +
304 307 listener = kmalloc(sizeof(*listener), GFP_KERNEL);
305   - if (!listener)
306   - return -ENOMEM;
  308 + if (!listener) {
  309 + ret = -ENOMEM;
  310 + goto err_alloc_listener;
  311 + }
307 312  
308 313 listener->dev = idev;
309 314 listener->event_count = atomic_read(&idev->event);
310 315 filep->private_data = listener;
311 316  
312 317 if (idev->info->open) {
313   - if (!try_module_get(idev->owner))
314   - return -ENODEV;
315 318 ret = idev->info->open(idev->info, inode);
316   - module_put(idev->owner);
  319 + if (ret)
  320 + goto err_infoopen;
317 321 }
318 322  
319   - if (ret)
320   - kfree(listener);
  323 + return 0;
321 324  
  325 +err_infoopen:
  326 +
  327 + kfree(listener);
  328 +err_alloc_listener:
  329 +
  330 + module_put(idev->owner);
  331 +
322 332 return ret;
323 333 }
324 334  
325 335  
... ... @@ -336,12 +346,11 @@
336 346 struct uio_listener *listener = filep->private_data;
337 347 struct uio_device *idev = listener->dev;
338 348  
339   - if (idev->info->release) {
340   - if (!try_module_get(idev->owner))
341   - return -ENODEV;
  349 + if (idev->info->release)
342 350 ret = idev->info->release(idev->info, inode);
343   - module_put(idev->owner);
344   - }
  351 +
  352 + module_put(idev->owner);
  353 +
345 354 if (filep->f_flags & FASYNC)
346 355 ret = uio_fasync(-1, filep, 0);
347 356 kfree(listener);
348 357  
... ... @@ -510,10 +519,7 @@
510 519 return -EINVAL;
511 520  
512 521 if (idev->info->mmap) {
513   - if (!try_module_get(idev->owner))
514   - return -ENODEV;
515 522 ret = idev->info->mmap(idev->info, vma);
516   - module_put(idev->owner);
517 523 return ret;
518 524 }
519 525