Skip to content

Commit

Permalink
[media] soc-camera: protect against racing open(2) and rmmod
Browse files Browse the repository at this point in the history
To protect against open() racing with rmmod, hold the list_lock also while
obtaining a reference to the camera host driver and check that the video
device hasn't been unregistered yet.

Signed-off-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
  • Loading branch information
Guennadi Liakhovetski authored and Mauro Carvalho Chehab committed Apr 4, 2013
1 parent 53faa68 commit 2400a1f
Showing 1 changed file with 28 additions and 14 deletions.
42 changes: 28 additions & 14 deletions drivers/media/platform/soc_camera/soc_camera.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,36 +508,49 @@ static int soc_camera_set_fmt(struct soc_camera_device *icd,
static int soc_camera_open(struct file *file)
{
struct video_device *vdev = video_devdata(file);
struct soc_camera_device *icd = dev_get_drvdata(vdev->parent);
struct soc_camera_desc *sdesc = to_soc_camera_desc(icd);
struct soc_camera_device *icd;
struct soc_camera_host *ici;
int ret;

if (!to_soc_camera_control(icd))
/* No device driver attached */
return -ENODEV;

/*
* Don't mess with the host during probe: wait until the loop in
* scan_add_host() completes
* scan_add_host() completes. Also protect against a race with
* soc_camera_host_unregister().
*/
if (mutex_lock_interruptible(&list_lock))
return -ERESTARTSYS;

if (!vdev || !video_is_registered(vdev)) {
mutex_unlock(&list_lock);
return -ENODEV;
}

icd = dev_get_drvdata(vdev->parent);
ici = to_soc_camera_host(icd->parent);

ret = try_module_get(ici->ops->owner) ? 0 : -ENODEV;
mutex_unlock(&list_lock);

if (mutex_lock_interruptible(&ici->host_lock))
return -ERESTARTSYS;
if (!try_module_get(ici->ops->owner)) {
if (ret < 0) {
dev_err(icd->pdev, "Couldn't lock capture bus driver.\n");
ret = -EINVAL;
goto emodule;
return ret;
}

if (!to_soc_camera_control(icd)) {
/* No device driver attached */
ret = -ENODEV;
goto econtrol;
}

if (mutex_lock_interruptible(&ici->host_lock)) {
ret = -ERESTARTSYS;
goto elockhost;
}
icd->use_count++;

/* Now we really have to activate the camera */
if (icd->use_count == 1) {
struct soc_camera_desc *sdesc = to_soc_camera_desc(icd);
/* Restore parameters before the last close() per V4L2 API */
struct v4l2_format f = {
.type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
Expand Down Expand Up @@ -609,9 +622,10 @@ static int soc_camera_open(struct file *file)
ici->ops->remove(icd);
eiciadd:
icd->use_count--;
module_put(ici->ops->owner);
emodule:
mutex_unlock(&ici->host_lock);
elockhost:
econtrol:
module_put(ici->ops->owner);

return ret;
}
Expand Down

0 comments on commit 2400a1f

Please sign in to comment.