diff options
author | Hans Verkuil <hverkuil@xs4all.nl> | 2010-11-26 04:54:53 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-12-01 17:10:20 -0500 |
commit | ca9afe6f87b569cdf8e797395381f18ae23a2905 (patch) | |
tree | 9c5475baf2bb90f05fe25e8ca6fa8f53c2fc05dc | |
parent | 879aa24d6394aa04b690a600a41ff500441ad384 (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.c | 7 |
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 | } |
630 | EXPORT_SYMBOL(video_unregister_device); | 635 | EXPORT_SYMBOL(video_unregister_device); |