aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/pwc
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2009-08-14 01:22:52 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2009-09-12 11:19:13 -0400
commit89dec01b7e251697720ac3d6a5310d72359eba69 (patch)
tree786097673e8e60fdc5442c1fc2ac2d65185eb1c1 /drivers/media/video/pwc
parent35c3057bb71ba0683e6f1268f3663099d8454e5f (diff)
V4L/DVB (12489): pwc - fix few use-after-free and memory leaks
I just happen to peek inside the PWC driver and did not like what I saw there. Please consider applying the patch below. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/pwc')
-rw-r--r--drivers/media/video/pwc/pwc-if.c78
-rw-r--r--drivers/media/video/pwc/pwc.h1
2 files changed, 36 insertions, 43 deletions
diff --git a/drivers/media/video/pwc/pwc-if.c b/drivers/media/video/pwc/pwc-if.c
index 8d17cf613306..f976df452a34 100644
--- a/drivers/media/video/pwc/pwc-if.c
+++ b/drivers/media/video/pwc/pwc-if.c
@@ -1057,7 +1057,8 @@ static int pwc_create_sysfs_files(struct video_device *vdev)
1057 goto err; 1057 goto err;
1058 if (pdev->features & FEATURE_MOTOR_PANTILT) { 1058 if (pdev->features & FEATURE_MOTOR_PANTILT) {
1059 rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt); 1059 rc = device_create_file(&vdev->dev, &dev_attr_pan_tilt);
1060 if (rc) goto err_button; 1060 if (rc)
1061 goto err_button;
1061 } 1062 }
1062 1063
1063 return 0; 1064 return 0;
@@ -1072,6 +1073,7 @@ err:
1072static void pwc_remove_sysfs_files(struct video_device *vdev) 1073static void pwc_remove_sysfs_files(struct video_device *vdev)
1073{ 1074{
1074 struct pwc_device *pdev = video_get_drvdata(vdev); 1075 struct pwc_device *pdev = video_get_drvdata(vdev);
1076
1075 if (pdev->features & FEATURE_MOTOR_PANTILT) 1077 if (pdev->features & FEATURE_MOTOR_PANTILT)
1076 device_remove_file(&vdev->dev, &dev_attr_pan_tilt); 1078 device_remove_file(&vdev->dev, &dev_attr_pan_tilt);
1077 device_remove_file(&vdev->dev, &dev_attr_button); 1079 device_remove_file(&vdev->dev, &dev_attr_button);
@@ -1229,13 +1231,11 @@ static void pwc_cleanup(struct pwc_device *pdev)
1229 video_unregister_device(pdev->vdev); 1231 video_unregister_device(pdev->vdev);
1230 1232
1231#ifdef CONFIG_USB_PWC_INPUT_EVDEV 1233#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1232 if (pdev->button_dev) { 1234 if (pdev->button_dev)
1233 input_unregister_device(pdev->button_dev); 1235 input_unregister_device(pdev->button_dev);
1234 input_free_device(pdev->button_dev);
1235 kfree(pdev->button_dev->phys);
1236 pdev->button_dev = NULL;
1237 }
1238#endif 1236#endif
1237
1238 kfree(pdev);
1239} 1239}
1240 1240
1241/* Note that all cleanup is done in the reverse order as in _open */ 1241/* Note that all cleanup is done in the reverse order as in _open */
@@ -1281,8 +1281,6 @@ static int pwc_video_close(struct file *file)
1281 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen); 1281 PWC_DEBUG_OPEN("<< video_close() vopen=%d\n", pdev->vopen);
1282 } else { 1282 } else {
1283 pwc_cleanup(pdev); 1283 pwc_cleanup(pdev);
1284 /* Free memory (don't set pdev to 0 just yet) */
1285 kfree(pdev);
1286 /* search device_hint[] table if we occupy a slot, by any chance */ 1284 /* search device_hint[] table if we occupy a slot, by any chance */
1287 for (hint = 0; hint < MAX_DEV_HINTS; hint++) 1285 for (hint = 0; hint < MAX_DEV_HINTS; hint++)
1288 if (device_hint[hint].pdev == pdev) 1286 if (device_hint[hint].pdev == pdev)
@@ -1499,13 +1497,10 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1499 struct usb_device *udev = interface_to_usbdev(intf); 1497 struct usb_device *udev = interface_to_usbdev(intf);
1500 struct pwc_device *pdev = NULL; 1498 struct pwc_device *pdev = NULL;
1501 int vendor_id, product_id, type_id; 1499 int vendor_id, product_id, type_id;
1502 int i, hint, rc; 1500 int hint, rc;
1503 int features = 0; 1501 int features = 0;
1504 int video_nr = -1; /* default: use next available device */ 1502 int video_nr = -1; /* default: use next available device */
1505 char serial_number[30], *name; 1503 char serial_number[30], *name;
1506#ifdef CONFIG_USB_PWC_INPUT_EVDEV
1507 char *phys = NULL;
1508#endif
1509 1504
1510 vendor_id = le16_to_cpu(udev->descriptor.idVendor); 1505 vendor_id = le16_to_cpu(udev->descriptor.idVendor);
1511 product_id = le16_to_cpu(udev->descriptor.idProduct); 1506 product_id = le16_to_cpu(udev->descriptor.idProduct);
@@ -1757,8 +1752,7 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1757 pdev->vframes = default_fps; 1752 pdev->vframes = default_fps;
1758 strcpy(pdev->serial, serial_number); 1753 strcpy(pdev->serial, serial_number);
1759 pdev->features = features; 1754 pdev->features = features;
1760 if (vendor_id == 0x046D && product_id == 0x08B5) 1755 if (vendor_id == 0x046D && product_id == 0x08B5) {
1761 {
1762 /* Logitech QuickCam Orbit 1756 /* Logitech QuickCam Orbit
1763 The ranges have been determined experimentally; they may differ from cam to cam. 1757 The ranges have been determined experimentally; they may differ from cam to cam.
1764 Also, the exact ranges left-right and up-down are different for my cam 1758 Also, the exact ranges left-right and up-down are different for my cam
@@ -1780,8 +1774,8 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1780 pdev->vdev = video_device_alloc(); 1774 pdev->vdev = video_device_alloc();
1781 if (!pdev->vdev) { 1775 if (!pdev->vdev) {
1782 PWC_ERROR("Err, cannot allocate video_device struture. Failing probe."); 1776 PWC_ERROR("Err, cannot allocate video_device struture. Failing probe.");
1783 kfree(pdev); 1777 rc = -ENOMEM;
1784 return -ENOMEM; 1778 goto err_free_mem;
1785 } 1779 }
1786 memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template)); 1780 memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
1787 pdev->vdev->parent = &intf->dev; 1781 pdev->vdev->parent = &intf->dev;
@@ -1806,25 +1800,23 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1806 } 1800 }
1807 1801
1808 pdev->vdev->release = video_device_release; 1802 pdev->vdev->release = video_device_release;
1809 i = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr); 1803 rc = video_register_device(pdev->vdev, VFL_TYPE_GRABBER, video_nr);
1810 if (i < 0) { 1804 if (rc < 0) {
1811 PWC_ERROR("Failed to register as video device (%d).\n", i); 1805 PWC_ERROR("Failed to register as video device (%d).\n", rc);
1812 rc = i; 1806 goto err_video_release;
1813 goto err;
1814 }
1815 else {
1816 PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num);
1817 } 1807 }
1818 1808
1809 PWC_INFO("Registered as /dev/video%d.\n", pdev->vdev->num);
1810
1819 /* occupy slot */ 1811 /* occupy slot */
1820 if (hint < MAX_DEV_HINTS) 1812 if (hint < MAX_DEV_HINTS)
1821 device_hint[hint].pdev = pdev; 1813 device_hint[hint].pdev = pdev;
1822 1814
1823 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev); 1815 PWC_DEBUG_PROBE("probe() function returning struct at 0x%p.\n", pdev);
1824 usb_set_intfdata (intf, pdev); 1816 usb_set_intfdata(intf, pdev);
1825 rc = pwc_create_sysfs_files(pdev->vdev); 1817 rc = pwc_create_sysfs_files(pdev->vdev);
1826 if (rc) 1818 if (rc)
1827 goto err_unreg; 1819 goto err_video_unreg;
1828 1820
1829 /* Set the leds off */ 1821 /* Set the leds off */
1830 pwc_set_leds(pdev, 0, 0); 1822 pwc_set_leds(pdev, 0, 0);
@@ -1835,16 +1827,16 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1835 pdev->button_dev = input_allocate_device(); 1827 pdev->button_dev = input_allocate_device();
1836 if (!pdev->button_dev) { 1828 if (!pdev->button_dev) {
1837 PWC_ERROR("Err, insufficient memory for webcam snapshot button device."); 1829 PWC_ERROR("Err, insufficient memory for webcam snapshot button device.");
1838 return -ENOMEM; 1830 rc = -ENOMEM;
1831 pwc_remove_sysfs_files(pdev->vdev);
1832 goto err_video_unreg;
1839 } 1833 }
1840 1834
1835 usb_make_path(udev, pdev->button_phys, sizeof(pdev->button_phys));
1836 strlcat(pdev->button_phys, "/input0", sizeof(pdev->button_phys));
1837
1841 pdev->button_dev->name = "PWC snapshot button"; 1838 pdev->button_dev->name = "PWC snapshot button";
1842 phys = kasprintf(GFP_KERNEL,"usb-%s-%s", pdev->udev->bus->bus_name, pdev->udev->devpath); 1839 pdev->button_dev->phys = pdev->button_phys;
1843 if (!phys) {
1844 input_free_device(pdev->button_dev);
1845 return -ENOMEM;
1846 }
1847 pdev->button_dev->phys = phys;
1848 usb_to_input_id(pdev->udev, &pdev->button_dev->id); 1840 usb_to_input_id(pdev->udev, &pdev->button_dev->id);
1849 pdev->button_dev->dev.parent = &pdev->udev->dev; 1841 pdev->button_dev->dev.parent = &pdev->udev->dev;
1850 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY); 1842 pdev->button_dev->evbit[0] = BIT_MASK(EV_KEY);
@@ -1853,25 +1845,27 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
1853 rc = input_register_device(pdev->button_dev); 1845 rc = input_register_device(pdev->button_dev);
1854 if (rc) { 1846 if (rc) {
1855 input_free_device(pdev->button_dev); 1847 input_free_device(pdev->button_dev);
1856 kfree(pdev->button_dev->phys);
1857 pdev->button_dev = NULL; 1848 pdev->button_dev = NULL;
1858 return rc; 1849 pwc_remove_sysfs_files(pdev->vdev);
1850 goto err_video_unreg;
1859 } 1851 }
1860#endif 1852#endif
1861 1853
1862 return 0; 1854 return 0;
1863 1855
1864err_unreg: 1856err_video_unreg:
1865 if (hint < MAX_DEV_HINTS) 1857 if (hint < MAX_DEV_HINTS)
1866 device_hint[hint].pdev = NULL; 1858 device_hint[hint].pdev = NULL;
1867 video_unregister_device(pdev->vdev); 1859 video_unregister_device(pdev->vdev);
1868err: 1860 pdev->vdev = NULL; /* So we don't try to release it below */
1869 video_device_release(pdev->vdev); /* Drip... drip... drip... */ 1861err_video_release:
1870 kfree(pdev); /* Oops, no memory leaks please */ 1862 video_device_release(pdev->vdev);
1863err_free_mem:
1864 kfree(pdev);
1871 return rc; 1865 return rc;
1872} 1866}
1873 1867
1874/* The user janked out the cable... */ 1868/* The user yanked out the cable... */
1875static void usb_pwc_disconnect(struct usb_interface *intf) 1869static void usb_pwc_disconnect(struct usb_interface *intf)
1876{ 1870{
1877 struct pwc_device *pdev; 1871 struct pwc_device *pdev;
@@ -1902,7 +1896,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
1902 /* Alert waiting processes */ 1896 /* Alert waiting processes */
1903 wake_up_interruptible(&pdev->frameq); 1897 wake_up_interruptible(&pdev->frameq);
1904 /* Wait until device is closed */ 1898 /* Wait until device is closed */
1905 if(pdev->vopen) { 1899 if (pdev->vopen) {
1906 mutex_lock(&pdev->modlock); 1900 mutex_lock(&pdev->modlock);
1907 pdev->unplugged = 1; 1901 pdev->unplugged = 1;
1908 mutex_unlock(&pdev->modlock); 1902 mutex_unlock(&pdev->modlock);
@@ -1911,8 +1905,6 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
1911 /* Device is closed, so we can safely unregister it */ 1905 /* Device is closed, so we can safely unregister it */
1912 PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n"); 1906 PWC_DEBUG_PROBE("Unregistering video device in disconnect().\n");
1913 pwc_cleanup(pdev); 1907 pwc_cleanup(pdev);
1914 /* Free memory (don't set pdev to 0 just yet) */
1915 kfree(pdev);
1916 1908
1917disconnect_out: 1909disconnect_out:
1918 /* search device_hint[] table if we occupy a slot, by any chance */ 1910 /* search device_hint[] table if we occupy a slot, by any chance */
diff --git a/drivers/media/video/pwc/pwc.h b/drivers/media/video/pwc/pwc.h
index 844565bde53b..0902355dfa77 100644
--- a/drivers/media/video/pwc/pwc.h
+++ b/drivers/media/video/pwc/pwc.h
@@ -253,6 +253,7 @@ struct pwc_device
253 int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */ 253 int snapshot_button_status; /* set to 1 when the user push the button, reset to 0 when this value is read */
254#ifdef CONFIG_USB_PWC_INPUT_EVDEV 254#ifdef CONFIG_USB_PWC_INPUT_EVDEV
255 struct input_dev *button_dev; /* webcam snapshot button input */ 255 struct input_dev *button_dev; /* webcam snapshot button input */
256 char button_phys[64];
256#endif 257#endif
257 258
258 /*** Misc. data ***/ 259 /*** Misc. data ***/