[media] uvcvideo: Remove sysadmin requirements for UVCIOC_CTRL_MAP
authorMartin Rubli <martin_rubli@logitech.com>
Wed, 8 Sep 2010 07:15:23 +0000 (04:15 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Thu, 21 Oct 2010 03:18:22 +0000 (01:18 -0200)
This patch removes the sysadmin requirements for UVCIOC_CTRL_MAP (and the stub
implementation of UVCIOC_CTRL_ADD). This requirement no longer makes sense with
the new XU control access mechanisms since XU controls can be accessed without
adding control mappings first.

A maximum number (currently 1024) of control mappings per device is enforced to
avoid excess memory consumption caused by careless user space applications.

Signed-off-by: Martin Rubli <martin_rubli@logitech.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
drivers/media/video/uvc/uvc_ctrl.c
drivers/media/video/uvc/uvc_driver.c
drivers/media/video/uvc/uvc_v4l2.c
drivers/media/video/uvc/uvcvideo.h

index 2c81b7f355519f195f1397badb2a3bc13c5a0619..531a3e1a6d178d0e9ea169e1447e87161c8c46f6 100644 (file)
@@ -1435,6 +1435,7 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
        struct uvc_entity *entity;
        struct uvc_control *ctrl;
        int found = 0;
+       int ret;
 
        if (mapping->id & ~V4L2_CTRL_ID_MASK) {
                uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', control "
@@ -1478,7 +1479,20 @@ int uvc_ctrl_add_mapping(struct uvc_video_chain *chain,
                }
        }
 
+       /* Prevent excess memory consumption */
+       if (atomic_inc_return(&dev->nmappings) > UVC_MAX_CONTROL_MAPPINGS) {
+               atomic_dec(&dev->nmappings);
+               uvc_trace(UVC_TRACE_CONTROL, "Can't add mapping '%s', maximum "
+                       "mappings count (%u) exceeded.\n", mapping->name,
+                       UVC_MAX_CONTROL_MAPPINGS);
+               ret = -ENOMEM;
+               goto done;
+       }
+
        ret = __uvc_ctrl_add_mapping(dev, ctrl, mapping);
+       if (ret < 0)
+               atomic_dec(&dev->nmappings);
+
 done:
        mutex_unlock(&chain->ctrl_mutex);
        return ret;
index 71efda76cc73f5a74cb041fb25af03ed1e050244..a1e9dfb52f6986fc189279f1b3d03e6927124a61 100644 (file)
@@ -1760,6 +1760,7 @@ static int uvc_probe(struct usb_interface *intf,
        INIT_LIST_HEAD(&dev->streams);
        atomic_set(&dev->nstreams, 0);
        atomic_set(&dev->users, 0);
+       atomic_set(&dev->nmappings, 0);
 
        dev->udev = usb_get_dev(udev);
        dev->intf = usb_get_intf(intf);
index 4a510483f7c54a34903d6c912dbc2cd6b702d856..6d15de9b520437a4440dc8da2071efd0b91fe306 100644 (file)
@@ -1025,16 +1025,10 @@ static long uvc_v4l2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
        /* Dynamic controls. */
        case UVCIOC_CTRL_ADD:
                /* Legacy ioctl, kept for API compatibility reasons */
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-
                return -EEXIST;
 
        case UVCIOC_CTRL_MAP_OLD:
        case UVCIOC_CTRL_MAP:
-               if (!capable(CAP_SYS_ADMIN))
-                       return -EPERM;
-
                return uvc_ioctl_ctrl_map(chain, arg,
                                          cmd == UVCIOC_CTRL_MAP_OLD);
 
index 34637fbbbd61ce455ea3d94885f6c50ff09d4444..39e9e36e8839647b84c135128f432c6d3ae8205f 100644 (file)
@@ -172,6 +172,9 @@ struct uvc_xu_control {
 #define UVC_CTRL_CONTROL_TIMEOUT       300
 #define UVC_CTRL_STREAMING_TIMEOUT     5000
 
+/* Maximum allowed number of control mappings per device */
+#define UVC_MAX_CONTROL_MAPPINGS       1024
+
 /* Devices quirks */
 #define UVC_QUIRK_STATUS_INTERVAL      0x00000001
 #define UVC_QUIRK_PROBE_MINMAX         0x00000002
@@ -472,6 +475,7 @@ struct uvc_device {
 
        enum uvc_device_state state;
        atomic_t users;
+       atomic_t nmappings;
 
        /* Video control interface */
        __u16 uvc_version;