aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hverkuil@xs4all.nl>2010-11-26 04:54:53 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-01 17:10:20 -0500
commitca9afe6f87b569cdf8e797395381f18ae23a2905 (patch)
tree9c5475baf2bb90f05fe25e8ca6fa8f53c2fc05dc
parent879aa24d6394aa04b690a600a41ff500441ad384 (diff)
[media] v4l2-dev: fix race condition
The unregister function had a race condition with the v4l2_open function. Ensure that both functions test and clear the REGISTER flag from within a critical section. Thanks to Laurent Pinchart for finding this race. Signed-off-by: Hans Verkuil <hverkuil@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/video/v4l2-dev.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c
index 6b64fd607b20..359e23290a7e 100644
--- a/drivers/media/video/v4l2-dev.c
+++ b/drivers/media/video/v4l2-dev.c
@@ -309,7 +309,7 @@ static int v4l2_open(struct inode *inode, struct file *filp)
309 mutex_lock(&videodev_lock); 309 mutex_lock(&videodev_lock);
310 vdev = video_devdata(filp); 310 vdev = video_devdata(filp);
311 /* return ENODEV if the video device has already been removed. */ 311 /* return ENODEV if the video device has already been removed. */
312 if (vdev == NULL) { 312 if (vdev == NULL || !video_is_registered(vdev)) {
313 mutex_unlock(&videodev_lock); 313 mutex_unlock(&videodev_lock);
314 return -ENODEV; 314 return -ENODEV;
315 } 315 }
@@ -624,7 +624,12 @@ void video_unregister_device(struct video_device *vdev)
624 if (!vdev || !video_is_registered(vdev)) 624 if (!vdev || !video_is_registered(vdev))
625 return; 625 return;
626 626
627 mutex_lock(&videodev_lock);
628 /* This must be in a critical section to prevent a race with v4l2_open.
629 * Once this bit has been cleared video_get may never be called again.
630 */
627 clear_bit(V4L2_FL_REGISTERED, &vdev->flags); 631 clear_bit(V4L2_FL_REGISTERED, &vdev->flags);
632 mutex_unlock(&videodev_lock);
628 device_unregister(&vdev->dev); 633 device_unregister(&vdev->dev);
629} 634}
630EXPORT_SYMBOL(video_unregister_device); 635EXPORT_SYMBOL(video_unregister_device);