diff options
| -rw-r--r-- | drivers/hid/hidraw.c | 41 |
1 files changed, 25 insertions, 16 deletions
diff --git a/drivers/hid/hidraw.c b/drivers/hid/hidraw.c index d04476700b7b..589dac5b5f56 100644 --- a/drivers/hid/hidraw.c +++ b/drivers/hid/hidraw.c | |||
| @@ -105,38 +105,48 @@ out: | |||
| 105 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) | 105 | static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos) |
| 106 | { | 106 | { |
| 107 | unsigned int minor = iminor(file->f_path.dentry->d_inode); | 107 | unsigned int minor = iminor(file->f_path.dentry->d_inode); |
| 108 | /* FIXME: What stops hidraw_table going NULL */ | 108 | struct hid_device *dev; |
| 109 | struct hid_device *dev = hidraw_table[minor]->hid; | ||
| 110 | __u8 *buf; | 109 | __u8 *buf; |
| 111 | int ret = 0; | 110 | int ret = 0; |
| 112 | 111 | ||
| 113 | if (!dev->hid_output_raw_report) | 112 | mutex_lock(&minors_lock); |
| 114 | return -ENODEV; | 113 | dev = hidraw_table[minor]->hid; |
| 114 | |||
| 115 | if (!dev->hid_output_raw_report) { | ||
| 116 | ret = -ENODEV; | ||
| 117 | goto out; | ||
| 118 | } | ||
| 115 | 119 | ||
| 116 | if (count > HID_MAX_BUFFER_SIZE) { | 120 | if (count > HID_MAX_BUFFER_SIZE) { |
| 117 | printk(KERN_WARNING "hidraw: pid %d passed too large report\n", | 121 | printk(KERN_WARNING "hidraw: pid %d passed too large report\n", |
| 118 | task_pid_nr(current)); | 122 | task_pid_nr(current)); |
| 119 | return -EINVAL; | 123 | ret = -EINVAL; |
| 124 | goto out; | ||
| 120 | } | 125 | } |
| 121 | 126 | ||
| 122 | if (count < 2) { | 127 | if (count < 2) { |
| 123 | printk(KERN_WARNING "hidraw: pid %d passed too short report\n", | 128 | printk(KERN_WARNING "hidraw: pid %d passed too short report\n", |
| 124 | task_pid_nr(current)); | 129 | task_pid_nr(current)); |
| 125 | return -EINVAL; | 130 | ret = -EINVAL; |
| 131 | goto out; | ||
| 126 | } | 132 | } |
| 127 | 133 | ||
| 128 | buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); | 134 | buf = kmalloc(count * sizeof(__u8), GFP_KERNEL); |
| 129 | if (!buf) | 135 | if (!buf) { |
| 130 | return -ENOMEM; | 136 | ret = -ENOMEM; |
| 137 | goto out; | ||
| 138 | } | ||
| 131 | 139 | ||
| 132 | if (copy_from_user(buf, buffer, count)) { | 140 | if (copy_from_user(buf, buffer, count)) { |
| 133 | ret = -EFAULT; | 141 | ret = -EFAULT; |
| 134 | goto out; | 142 | goto out_free; |
| 135 | } | 143 | } |
| 136 | 144 | ||
| 137 | ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); | 145 | ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT); |
| 138 | out: | 146 | out_free: |
| 139 | kfree(buf); | 147 | kfree(buf); |
| 148 | out: | ||
| 149 | mutex_unlock(&minors_lock); | ||
| 140 | return ret; | 150 | return ret; |
| 141 | } | 151 | } |
| 142 | 152 | ||
| @@ -164,7 +174,6 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
| 164 | goto out; | 174 | goto out; |
| 165 | } | 175 | } |
| 166 | 176 | ||
| 167 | lock_kernel(); | ||
| 168 | mutex_lock(&minors_lock); | 177 | mutex_lock(&minors_lock); |
| 169 | if (!hidraw_table[minor]) { | 178 | if (!hidraw_table[minor]) { |
| 170 | printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", | 179 | printk(KERN_EMERG "hidraw device with minor %d doesn't exist\n", |
| @@ -196,7 +205,6 @@ static int hidraw_open(struct inode *inode, struct file *file) | |||
| 196 | 205 | ||
| 197 | out_unlock: | 206 | out_unlock: |
| 198 | mutex_unlock(&minors_lock); | 207 | mutex_unlock(&minors_lock); |
| 199 | unlock_kernel(); | ||
| 200 | out: | 208 | out: |
| 201 | return err; | 209 | return err; |
| 202 | 210 | ||
| @@ -237,11 +245,12 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
| 237 | struct inode *inode = file->f_path.dentry->d_inode; | 245 | struct inode *inode = file->f_path.dentry->d_inode; |
| 238 | unsigned int minor = iminor(inode); | 246 | unsigned int minor = iminor(inode); |
| 239 | long ret = 0; | 247 | long ret = 0; |
| 240 | /* FIXME: What stops hidraw_table going NULL */ | 248 | struct hidraw *dev; |
| 241 | struct hidraw *dev = hidraw_table[minor]; | ||
| 242 | void __user *user_arg = (void __user*) arg; | 249 | void __user *user_arg = (void __user*) arg; |
| 243 | 250 | ||
| 244 | lock_kernel(); | 251 | mutex_lock(&minors_lock); |
| 252 | dev = hidraw_table[minor]; | ||
| 253 | |||
| 245 | switch (cmd) { | 254 | switch (cmd) { |
| 246 | case HIDIOCGRDESCSIZE: | 255 | case HIDIOCGRDESCSIZE: |
| 247 | if (put_user(dev->hid->rsize, (int __user *)arg)) | 256 | if (put_user(dev->hid->rsize, (int __user *)arg)) |
| @@ -314,7 +323,7 @@ static long hidraw_ioctl(struct file *file, unsigned int cmd, | |||
| 314 | 323 | ||
| 315 | ret = -ENOTTY; | 324 | ret = -ENOTTY; |
| 316 | } | 325 | } |
| 317 | unlock_kernel(); | 326 | mutex_unlock(&minors_lock); |
| 318 | return ret; | 327 | return ret; |
| 319 | } | 328 | } |
| 320 | 329 | ||
