diff options
Diffstat (limited to 'drivers/hid/usbhid/hiddev.c')
| -rw-r--r-- | drivers/hid/usbhid/hiddev.c | 14 |
1 files changed, 10 insertions, 4 deletions
diff --git a/drivers/hid/usbhid/hiddev.c b/drivers/hid/usbhid/hiddev.c index 95cc192bc7af..842e9edb888e 100644 --- a/drivers/hid/usbhid/hiddev.c +++ b/drivers/hid/usbhid/hiddev.c | |||
| @@ -406,6 +406,7 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, | |||
| 406 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); | 406 | uref_multi = kmalloc(sizeof(struct hiddev_usage_ref_multi), GFP_KERNEL); |
| 407 | if (!uref_multi) | 407 | if (!uref_multi) |
| 408 | return -ENOMEM; | 408 | return -ENOMEM; |
| 409 | lock_kernel(); | ||
| 409 | uref = &uref_multi->uref; | 410 | uref = &uref_multi->uref; |
| 410 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { | 411 | if (cmd == HIDIOCGUSAGES || cmd == HIDIOCSUSAGES) { |
| 411 | if (copy_from_user(uref_multi, user_arg, | 412 | if (copy_from_user(uref_multi, user_arg, |
| @@ -501,12 +502,15 @@ static noinline int hiddev_ioctl_usage(struct hiddev *hiddev, unsigned int cmd, | |||
| 501 | } | 502 | } |
| 502 | 503 | ||
| 503 | goodreturn: | 504 | goodreturn: |
| 505 | unlock_kernel(); | ||
| 504 | kfree(uref_multi); | 506 | kfree(uref_multi); |
| 505 | return 0; | 507 | return 0; |
| 506 | fault: | 508 | fault: |
| 509 | unlock_kernel(); | ||
| 507 | kfree(uref_multi); | 510 | kfree(uref_multi); |
| 508 | return -EFAULT; | 511 | return -EFAULT; |
| 509 | inval: | 512 | inval: |
| 513 | unlock_kernel(); | ||
| 510 | kfree(uref_multi); | 514 | kfree(uref_multi); |
| 511 | return -EINVAL; | 515 | return -EINVAL; |
| 512 | } | 516 | } |
| @@ -540,7 +544,7 @@ static noinline int hiddev_ioctl_string(struct hiddev *hiddev, unsigned int cmd, | |||
| 540 | return len; | 544 | return len; |
| 541 | } | 545 | } |
| 542 | 546 | ||
| 543 | static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) | 547 | static long hiddev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 544 | { | 548 | { |
| 545 | struct hiddev_list *list = file->private_data; | 549 | struct hiddev_list *list = file->private_data; |
| 546 | struct hiddev *hiddev = list->hiddev; | 550 | struct hiddev *hiddev = list->hiddev; |
| @@ -555,7 +559,10 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 555 | struct usbhid_device *usbhid = hid->driver_data; | 559 | struct usbhid_device *usbhid = hid->driver_data; |
| 556 | void __user *user_arg = (void __user *)arg; | 560 | void __user *user_arg = (void __user *)arg; |
| 557 | int i; | 561 | int i; |
| 562 | |||
| 563 | /* Called without BKL by compat methods so no BKL taken */ | ||
| 558 | 564 | ||
| 565 | /* FIXME: Who or what stop this racing with a disconnect ?? */ | ||
| 559 | if (!hiddev->exist) | 566 | if (!hiddev->exist) |
| 560 | return -EIO; | 567 | return -EIO; |
| 561 | 568 | ||
| @@ -756,8 +763,7 @@ static int hiddev_ioctl(struct inode *inode, struct file *file, unsigned int cmd | |||
| 756 | #ifdef CONFIG_COMPAT | 763 | #ifdef CONFIG_COMPAT |
| 757 | static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 764 | static long hiddev_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 758 | { | 765 | { |
| 759 | struct inode *inode = file->f_path.dentry->d_inode; | 766 | return hiddev_ioctl(file, cmd, (unsigned long)compat_ptr(arg)); |
| 760 | return hiddev_ioctl(inode, file, cmd, (unsigned long)compat_ptr(arg)); | ||
| 761 | } | 767 | } |
| 762 | #endif | 768 | #endif |
| 763 | 769 | ||
| @@ -768,7 +774,7 @@ static const struct file_operations hiddev_fops = { | |||
| 768 | .poll = hiddev_poll, | 774 | .poll = hiddev_poll, |
| 769 | .open = hiddev_open, | 775 | .open = hiddev_open, |
| 770 | .release = hiddev_release, | 776 | .release = hiddev_release, |
| 771 | .ioctl = hiddev_ioctl, | 777 | .unlocked_ioctl = hiddev_ioctl, |
| 772 | .fasync = hiddev_fasync, | 778 | .fasync = hiddev_fasync, |
| 773 | #ifdef CONFIG_COMPAT | 779 | #ifdef CONFIG_COMPAT |
| 774 | .compat_ioctl = hiddev_compat_ioctl, | 780 | .compat_ioctl = hiddev_compat_ioctl, |
