Commit 610ad5064cb90aec35f5837bbde3d316fe02aca7
Committed by
Greg Kroah-Hartman
1 parent
b54f2863a2
Exists in
master
and in
4 other branches
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
drivers/uio/uio.c
... | ... | @@ -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 |