aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/media-devnode.c
diff options
context:
space:
mode:
authorShuah Khan <shuahkh@osg.samsung.com>2016-06-10 14:37:23 -0300
committerMauro Carvalho Chehab <mchehab@s-opensource.com>2016-06-15 17:59:28 -0300
commit6f0dd24a084a17f9984dd49dffbf7055bf123993 (patch)
treee50dbdce2f36d2136d956860f21ece4ff25d20ba /drivers/media/media-devnode.c
parent[media] media: fix use-after-free in cdev_put() when app exits after driver unbind (diff)
downloadlinux-dev-6f0dd24a084a17f9984dd49dffbf7055bf123993.tar.xz
linux-dev-6f0dd24a084a17f9984dd49dffbf7055bf123993.zip
[media] media: fix media devnode ioctl/syscall and unregister race
Media devnode open/ioctl could be in progress when media device unregister is initiated. System calls and ioctls check media device registered status at the beginning, however, there is a window where unregister could be in progress without changing the media devnode status to unregistered. process 1 process 2 fd = open(/dev/media0) media_devnode_is_registered() (returns true here) media_device_unregister() (unregister is in progress and devnode isn't unregistered yet) ... ioctl(fd, ...) __media_ioctl() media_devnode_is_registered() (returns true here) ... media_devnode_unregister() ... (driver releases the media device memory) media_device_ioctl() (By this point devnode->media_dev does not point to allocated memory. use-after free in in mutex_lock_nested) BUG: KASAN: use-after-free in mutex_lock_nested+0x79c/0x800 at addr ffff8801ebe914f0 Fix it by clearing register bit when unregister starts to avoid the race. process 1 process 2 fd = open(/dev/media0) media_devnode_is_registered() (could return true here) media_device_unregister() (clear the register bit, then start unregister.) ... ioctl(fd, ...) __media_ioctl() media_devnode_is_registered() (return false here, ioctl returns I/O error, and will not access media device memory) ... media_devnode_unregister() ... (driver releases the media device memory) Signed-off-by: Shuah Khan <shuahkh@osg.samsung.com> Suggested-by: Sakari Ailus <sakari.ailus@linux.intel.com> Reported-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com> Tested-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com>
Diffstat (limited to 'drivers/media/media-devnode.c')
-rw-r--r--drivers/media/media-devnode.c8
1 files changed, 7 insertions, 1 deletions
diff --git a/drivers/media/media-devnode.c b/drivers/media/media-devnode.c
index 5b605ff38daf..f2772ba6f611 100644
--- a/drivers/media/media-devnode.c
+++ b/drivers/media/media-devnode.c
@@ -287,7 +287,7 @@ cdev_add_error:
return ret;
}
-void media_devnode_unregister(struct media_devnode *devnode)
+void media_devnode_unregister_prepare(struct media_devnode *devnode)
{
/* Check if devnode was ever registered at all */
if (!media_devnode_is_registered(devnode))
@@ -295,6 +295,12 @@ void media_devnode_unregister(struct media_devnode *devnode)
mutex_lock(&media_devnode_lock);
clear_bit(MEDIA_FLAG_REGISTERED, &devnode->flags);
+ mutex_unlock(&media_devnode_lock);
+}
+
+void media_devnode_unregister(struct media_devnode *devnode)
+{
+ mutex_lock(&media_devnode_lock);
/* Delete the cdev on this minor as well */
cdev_del(&devnode->cdev);
mutex_unlock(&media_devnode_lock);