]> err.no Git - linux-2.6/blobdiff - drivers/hid/hidraw.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-for-linus
[linux-2.6] / drivers / hid / hidraw.c
index 20ebba1032b8a99b795d5cf9ebf322e388602be9..0c6b4d4e7e2700ee9135d2729b8c388f7d8c6118 100644 (file)
@@ -30,6 +30,7 @@
 #include <linux/major.h>
 #include <linux/hid.h>
 #include <linux/mutex.h>
+#include <linux/smp_lock.h>
 
 #include <linux/hidraw.h>
 
@@ -113,13 +114,13 @@ static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t
 
        if (count > HID_MIN_BUFFER_SIZE) {
                printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
-                               current->pid);
+                               task_pid_nr(current));
                return -EINVAL;
        }
 
        if (count < 2) {
                printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
-                               current->pid);
+                               task_pid_nr(current));
                return -EINVAL;
        }
 
@@ -157,6 +158,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
        struct hidraw_list *list;
        int err = 0;
 
+       lock_kernel();
        if (!(list = kzalloc(sizeof(struct hidraw_list), GFP_KERNEL))) {
                err = -ENOMEM;
                goto out;
@@ -183,6 +185,7 @@ static int hidraw_open(struct inode *inode, struct file *file)
 out_unlock:
        spin_unlock(&minors_lock);
 out:
+       unlock_kernel();
        return err;
 
 }
@@ -229,9 +232,15 @@ static int hidraw_ioctl(struct inode *inode, struct file *file, unsigned int cmd
 
                                if (get_user(len, (int __user *)arg))
                                        return -EFAULT;
-                               if (copy_to_user(*((__u8 **)(user_arg +
-                                                       sizeof(__u32))),
-                                                       dev->hid->rdesc, len))
+
+                               if (len > HID_MAX_DESCRIPTOR_SIZE - 1)
+                                       return -EINVAL;
+
+                               if (copy_to_user(user_arg + offsetof(
+                                                               struct hidraw_report_descriptor,
+                                                               value[0]),
+                                                       dev->hid->rdesc,
+                                                       min(dev->hid->rsize, len)))
                                                return -EFAULT;
                                return 0;
                        }
@@ -282,7 +291,7 @@ EXPORT_SYMBOL_GPL(hidraw_report_event);
 
 int hidraw_connect(struct hid_device *hid)
 {
-       int minor, result = -EINVAL;
+       int minor, result;
        struct hidraw *dev;
 
        /* TODO currently we accept any HID device. This should later
@@ -290,8 +299,11 @@ int hidraw_connect(struct hid_device *hid)
         * non-input applications
         */
 
-       if (!(dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL)))
-               return -1;
+       dev = kzalloc(sizeof(struct hidraw), GFP_KERNEL);
+       if (!dev)
+               return -ENOMEM;
+
+       result = -EINVAL;
 
        spin_lock(&minors_lock);
 
@@ -305,17 +317,21 @@ int hidraw_connect(struct hid_device *hid)
 
        spin_unlock(&minors_lock);
 
-       if (result)
+       if (result) {
+               kfree(dev);
                goto out;
+       }
 
-       dev->dev = device_create(hidraw_class, NULL, MKDEV(hidraw_major, minor),
-                               "%s%d", "hidraw", minor);
+       dev->dev = device_create_drvdata(hidraw_class, NULL,
+                                        MKDEV(hidraw_major, minor), NULL,
+                                        "%s%d", "hidraw", minor);
 
        if (IS_ERR(dev->dev)) {
                spin_lock(&minors_lock);
                hidraw_table[minor] = NULL;
                spin_unlock(&minors_lock);
                result = PTR_ERR(dev->dev);
+               kfree(dev);
                goto out;
        }