Commit 5c4fa002 authored by Jean-Francois Moine's avatar Jean-Francois Moine Committed by Mauro Carvalho Chehab

V4L/DVB (9690): gspca: Lock the subdrivers via module_get/put.

The previous subdriver protection against rmmod was done via the
file operations table in the device descriptor. On device disconnection
while streaming, the device structure was freed at close time, and the
module_put still used the module name in the freed area.
Now, explicit module get/put are done on open and close.
Signed-off-by: default avatarJean-Francois Moine <moinejf@free.fr>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@redhat.com>
parent 98522a7b
...@@ -874,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file) ...@@ -874,6 +874,13 @@ static int dev_open(struct inode *inode, struct file *file)
ret = -EBUSY; ret = -EBUSY;
goto out; goto out;
} }
/* protect the subdriver against rmmod */
if (!try_module_get(gspca_dev->module)) {
ret = -ENODEV;
goto out;
}
gspca_dev->users++; gspca_dev->users++;
/* one more user */ /* one more user */
...@@ -920,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file) ...@@ -920,6 +927,7 @@ static int dev_close(struct inode *inode, struct file *file)
gspca_dev->memory = GSPCA_MEMORY_NO; gspca_dev->memory = GSPCA_MEMORY_NO;
} }
file->private_data = NULL; file->private_data = NULL;
module_put(gspca_dev->module);
mutex_unlock(&gspca_dev->queue_lock); mutex_unlock(&gspca_dev->queue_lock);
PDEBUG(D_STREAM, "close done"); PDEBUG(D_STREAM, "close done");
...@@ -1870,9 +1878,8 @@ int gspca_dev_probe(struct usb_interface *intf, ...@@ -1870,9 +1878,8 @@ int gspca_dev_probe(struct usb_interface *intf,
/* init video stuff */ /* init video stuff */
memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template); memcpy(&gspca_dev->vdev, &gspca_template, sizeof gspca_template);
gspca_dev->vdev.parent = &dev->dev; gspca_dev->vdev.parent = &dev->dev;
memcpy(&gspca_dev->fops, &dev_fops, sizeof gspca_dev->fops); gspca_dev->vdev.fops = &dev_fops;
gspca_dev->vdev.fops = &gspca_dev->fops; gspca_dev->module = module;
gspca_dev->fops.owner = module; /* module protection */
gspca_dev->present = 1; gspca_dev->present = 1;
ret = video_register_device(&gspca_dev->vdev, ret = video_register_device(&gspca_dev->vdev,
VFL_TYPE_GRABBER, VFL_TYPE_GRABBER,
......
...@@ -121,7 +121,7 @@ struct gspca_frame { ...@@ -121,7 +121,7 @@ struct gspca_frame {
struct gspca_dev { struct gspca_dev {
struct video_device vdev; /* !! must be the first item */ struct video_device vdev; /* !! must be the first item */
struct file_operations fops; struct module *module; /* subdriver handling the device */
struct usb_device *dev; struct usb_device *dev;
struct kref kref; struct kref kref;
struct file *capt_file; /* file doing video capture */ struct file *capt_file; /* file doing video capture */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment