diff options
Diffstat (limited to 'drivers/input/misc/uinput.c')
-rw-r--r-- | drivers/input/misc/uinput.c | 48 |
1 files changed, 16 insertions, 32 deletions
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c index 82542a1c1098..364bdf43a381 100644 --- a/drivers/input/misc/uinput.c +++ b/drivers/input/misc/uinput.c | |||
@@ -347,8 +347,7 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
347 | { | 347 | { |
348 | struct uinput_user_dev *user_dev; | 348 | struct uinput_user_dev *user_dev; |
349 | struct input_dev *dev; | 349 | struct input_dev *dev; |
350 | char *name; | 350 | int i; |
351 | int i, size; | ||
352 | int retval; | 351 | int retval; |
353 | 352 | ||
354 | if (count != sizeof(struct uinput_user_dev)) | 353 | if (count != sizeof(struct uinput_user_dev)) |
@@ -362,30 +361,25 @@ static int uinput_setup_device(struct uinput_device *udev, const char __user *bu | |||
362 | 361 | ||
363 | dev = udev->dev; | 362 | dev = udev->dev; |
364 | 363 | ||
365 | user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL); | 364 | user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev)); |
366 | if (!user_dev) | 365 | if (IS_ERR(user_dev)) |
367 | return -ENOMEM; | 366 | return PTR_ERR(user_dev); |
368 | |||
369 | if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) { | ||
370 | retval = -EFAULT; | ||
371 | goto exit; | ||
372 | } | ||
373 | 367 | ||
374 | udev->ff_effects_max = user_dev->ff_effects_max; | 368 | udev->ff_effects_max = user_dev->ff_effects_max; |
375 | 369 | ||
376 | size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1; | 370 | /* Ensure name is filled in */ |
377 | if (!size) { | 371 | if (!user_dev->name[0]) { |
378 | retval = -EINVAL; | 372 | retval = -EINVAL; |
379 | goto exit; | 373 | goto exit; |
380 | } | 374 | } |
381 | 375 | ||
382 | kfree(dev->name); | 376 | kfree(dev->name); |
383 | dev->name = name = kmalloc(size, GFP_KERNEL); | 377 | dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE, |
384 | if (!name) { | 378 | GFP_KERNEL); |
379 | if (!dev->name) { | ||
385 | retval = -ENOMEM; | 380 | retval = -ENOMEM; |
386 | goto exit; | 381 | goto exit; |
387 | } | 382 | } |
388 | strlcpy(name, user_dev->name, size); | ||
389 | 383 | ||
390 | dev->id.bustype = user_dev->id.bustype; | 384 | dev->id.bustype = user_dev->id.bustype; |
391 | dev->id.vendor = user_dev->id.vendor; | 385 | dev->id.vendor = user_dev->id.vendor; |
@@ -622,7 +616,6 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
622 | struct uinput_ff_upload ff_up; | 616 | struct uinput_ff_upload ff_up; |
623 | struct uinput_ff_erase ff_erase; | 617 | struct uinput_ff_erase ff_erase; |
624 | struct uinput_request *req; | 618 | struct uinput_request *req; |
625 | int length; | ||
626 | char *phys; | 619 | char *phys; |
627 | 620 | ||
628 | retval = mutex_lock_interruptible(&udev->mutex); | 621 | retval = mutex_lock_interruptible(&udev->mutex); |
@@ -689,24 +682,15 @@ static long uinput_ioctl_handler(struct file *file, unsigned int cmd, | |||
689 | retval = -EINVAL; | 682 | retval = -EINVAL; |
690 | goto out; | 683 | goto out; |
691 | } | 684 | } |
692 | length = strnlen_user(p, 1024); | 685 | |
693 | if (length <= 0) { | 686 | phys = strndup_user(p, 1024); |
694 | retval = -EFAULT; | 687 | if (IS_ERR(phys)) { |
695 | break; | 688 | retval = PTR_ERR(phys); |
689 | goto out; | ||
696 | } | 690 | } |
691 | |||
697 | kfree(udev->dev->phys); | 692 | kfree(udev->dev->phys); |
698 | udev->dev->phys = phys = kmalloc(length, GFP_KERNEL); | 693 | udev->dev->phys = phys; |
699 | if (!phys) { | ||
700 | retval = -ENOMEM; | ||
701 | break; | ||
702 | } | ||
703 | if (copy_from_user(phys, p, length)) { | ||
704 | udev->dev->phys = NULL; | ||
705 | kfree(phys); | ||
706 | retval = -EFAULT; | ||
707 | break; | ||
708 | } | ||
709 | phys[length - 1] = '\0'; | ||
710 | break; | 694 | break; |
711 | 695 | ||
712 | case UI_BEGIN_FF_UPLOAD: | 696 | case UI_BEGIN_FF_UPLOAD: |