eCryptfs: Remove mmap from directory operations
[safe/jmp/linux-2.6] / drivers / media / video / v4l2-compat-ioctl32.c
index d0e1bd3..c4150bd 100644 (file)
@@ -222,9 +222,9 @@ static int get_microcode32(struct video_code *kp, struct video_code32 __user *up
 
 #endif
 
-static int native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       int ret = -ENOIOCTLCMD;
+       long ret = -ENOIOCTLCMD;
 
        if (file->f_op->unlocked_ioctl)
                ret = file->f_op->unlocked_ioctl(file, cmd, arg);
@@ -600,9 +600,37 @@ struct v4l2_ext_controls32 {
        compat_caddr_t controls; /* actually struct v4l2_ext_control32 * */
 };
 
+struct v4l2_ext_control32 {
+       __u32 id;
+       __u32 size;
+       __u32 reserved2[1];
+       union {
+               __s32 value;
+               __s64 value64;
+               compat_caddr_t string; /* actually char * */
+       };
+} __attribute__ ((packed));
+
+/* The following function really belong in v4l2-common, but that causes
+   a circular dependency between modules. We need to think about this, but
+   for now this will do. */
+
+/* Return non-zero if this control is a pointer type. Currently only
+   type STRING is a pointer type. */
+static inline int ctrl_is_pointer(u32 id)
+{
+       switch (id) {
+       case V4L2_CID_RDS_TX_PS_NAME:
+       case V4L2_CID_RDS_TX_RADIO_TEXT:
+               return 1;
+       default:
+               return 0;
+       }
+}
+
 static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
 {
-       struct v4l2_ext_control __user *ucontrols;
+       struct v4l2_ext_control32 __user *ucontrols;
        struct v4l2_ext_control __user *kcontrols;
        int n;
        compat_caddr_t p;
@@ -626,15 +654,17 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
        kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
        kp->controls = kcontrols;
        while (--n >= 0) {
-               if (copy_in_user(&kcontrols->id, &ucontrols->id, sizeof(__u32)))
-                       return -EFAULT;
-               if (copy_in_user(&kcontrols->reserved2, &ucontrols->reserved2, sizeof(ucontrols->reserved2)))
-                       return -EFAULT;
-               /* Note: if the void * part of the union ever becomes relevant
-                  then we need to know the type of the control in order to do
-                  the right thing here. Luckily, that is not yet an issue. */
-               if (copy_in_user(&kcontrols->value, &ucontrols->value, sizeof(ucontrols->value)))
+               if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols)))
                        return -EFAULT;
+               if (ctrl_is_pointer(kcontrols->id)) {
+                       void __user *s;
+
+                       if (get_user(p, &ucontrols->string))
+                               return -EFAULT;
+                       s = compat_ptr(p);
+                       if (put_user(s, &kcontrols->string))
+                               return -EFAULT;
+               }
                ucontrols++;
                kcontrols++;
        }
@@ -643,7 +673,7 @@ static int get_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 
 static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext_controls32 __user *up)
 {
-       struct v4l2_ext_control __user *ucontrols;
+       struct v4l2_ext_control32 __user *ucontrols;
        struct v4l2_ext_control __user *kcontrols = kp->controls;
        int n = kp->count;
        compat_caddr_t p;
@@ -664,15 +694,14 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
                return -EFAULT;
 
        while (--n >= 0) {
-               if (copy_in_user(&ucontrols->id, &kcontrols->id, sizeof(__u32)))
-                       return -EFAULT;
-               if (copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
-                                       sizeof(ucontrols->reserved2)))
-                       return -EFAULT;
-               /* Note: if the void * part of the union ever becomes relevant
-                  then we need to know the type of the control in order to do
-                  the right thing here. Luckily, that is not yet an issue. */
-               if (copy_in_user(&ucontrols->value, &kcontrols->value, sizeof(ucontrols->value)))
+               unsigned size = sizeof(*ucontrols);
+
+               /* Do not modify the pointer when copying a pointer control.
+                  The contents of the pointer was changed, not the pointer
+                  itself. */
+               if (ctrl_is_pointer(kcontrols->id))
+                       size -= sizeof(ucontrols->value64);
+               if (copy_in_user(ucontrols, kcontrols, size))
                        return -EFAULT;
                ucontrols++;
                kcontrols++;
@@ -705,7 +734,7 @@ static int put_v4l2_ext_controls32(struct v4l2_ext_controls *kp, struct v4l2_ext
 #define VIDIOC_G_OUTPUT32      _IOR ('V', 46, s32)
 #define VIDIOC_S_OUTPUT32      _IOWR('V', 47, s32)
 
-static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        union {
 #ifdef CONFIG_VIDEO_V4L1_COMPAT
@@ -726,7 +755,7 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        } karg;
        void __user *up = compat_ptr(arg);
        int compatible_arg = 1;
-       int err = 0;
+       long err = 0;
 
        /* First, convert the command. */
        switch (cmd) {
@@ -937,9 +966,9 @@ static int do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg
        return err;
 }
 
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
+long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
 {
-       int ret = -ENOIOCTLCMD;
+       long ret = -ENOIOCTLCMD;
 
        if (!file->f_op->ioctl && !file->f_op->unlocked_ioctl)
                return ret;
@@ -1046,8 +1075,14 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_TRY_ENCODER_CMD:
        case VIDIOC_DBG_S_REGISTER:
        case VIDIOC_DBG_G_REGISTER:
-       case VIDIOC_G_CHIP_IDENT:
+       case VIDIOC_DBG_G_CHIP_IDENT:
        case VIDIOC_S_HW_FREQ_SEEK:
+       case VIDIOC_ENUM_DV_PRESETS:
+       case VIDIOC_S_DV_PRESET:
+       case VIDIOC_G_DV_PRESET:
+       case VIDIOC_QUERY_DV_PRESET:
+       case VIDIOC_S_DV_TIMINGS:
+       case VIDIOC_G_DV_TIMINGS:
                ret = do_video_ioctl(file, cmd, arg);
                break;
 
@@ -1065,18 +1100,14 @@ long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
                break;
 #endif
        default:
-               v4l_print_ioctl("compat_ioctl32", cmd);
-               printk(KERN_CONT "\n");
+               printk(KERN_WARNING "compat_ioctl32: "
+                       "unknown ioctl '%c', dir=%d, #%d (0x%08x)\n",
+                       _IOC_TYPE(cmd), _IOC_DIR(cmd), _IOC_NR(cmd), cmd);
                break;
        }
        return ret;
 }
-#else
-long v4l_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
-{
-       return -ENOIOCTLCMD;
-}
+EXPORT_SYMBOL_GPL(v4l2_compat_ioctl32);
 #endif
-EXPORT_SYMBOL_GPL(v4l_compat_ioctl32);
 
 MODULE_LICENSE("GPL");