diff options
Diffstat (limited to 'drivers/input/joydev.c')
-rw-r--r-- | drivers/input/joydev.c | 106 |
1 files changed, 74 insertions, 32 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 9a1d55b74d7a..901b2525993e 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
@@ -452,6 +452,76 @@ static unsigned int joydev_poll(struct file *file, poll_table *wait) | |||
452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); | 452 | (joydev->exist ? 0 : (POLLHUP | POLLERR)); |
453 | } | 453 | } |
454 | 454 | ||
455 | static int joydev_handle_JSIOCSAXMAP(struct joydev *joydev, | ||
456 | void __user *argp, size_t len) | ||
457 | { | ||
458 | __u8 *abspam; | ||
459 | int i; | ||
460 | int retval = 0; | ||
461 | |||
462 | len = min(len, sizeof(joydev->abspam)); | ||
463 | |||
464 | /* Validate the map. */ | ||
465 | abspam = kmalloc(len, GFP_KERNEL); | ||
466 | if (!abspam) | ||
467 | return -ENOMEM; | ||
468 | |||
469 | if (copy_from_user(abspam, argp, len)) { | ||
470 | retval = -EFAULT; | ||
471 | goto out; | ||
472 | } | ||
473 | |||
474 | for (i = 0; i < joydev->nabs; i++) { | ||
475 | if (abspam[i] > ABS_MAX) { | ||
476 | retval = -EINVAL; | ||
477 | goto out; | ||
478 | } | ||
479 | } | ||
480 | |||
481 | memcpy(joydev->abspam, abspam, len); | ||
482 | |||
483 | out: | ||
484 | kfree(abspam); | ||
485 | return retval; | ||
486 | } | ||
487 | |||
488 | static int joydev_handle_JSIOCSBTNMAP(struct joydev *joydev, | ||
489 | void __user *argp, size_t len) | ||
490 | { | ||
491 | __u16 *keypam; | ||
492 | int i; | ||
493 | int retval = 0; | ||
494 | |||
495 | len = min(len, sizeof(joydev->keypam)); | ||
496 | |||
497 | /* Validate the map. */ | ||
498 | keypam = kmalloc(len, GFP_KERNEL); | ||
499 | if (!keypam) | ||
500 | return -ENOMEM; | ||
501 | |||
502 | if (copy_from_user(keypam, argp, len)) { | ||
503 | retval = -EFAULT; | ||
504 | goto out; | ||
505 | } | ||
506 | |||
507 | for (i = 0; i < joydev->nkey; i++) { | ||
508 | if (keypam[i] > KEY_MAX || keypam[i] < BTN_MISC) { | ||
509 | retval = -EINVAL; | ||
510 | goto out; | ||
511 | } | ||
512 | } | ||
513 | |||
514 | memcpy(joydev->keypam, keypam, len); | ||
515 | |||
516 | for (i = 0; i < joydev->nkey; i++) | ||
517 | joydev->keymap[keypam[i] - BTN_MISC] = i; | ||
518 | |||
519 | out: | ||
520 | kfree(keypam); | ||
521 | return retval; | ||
522 | } | ||
523 | |||
524 | |||
455 | static int joydev_ioctl_common(struct joydev *joydev, | 525 | static int joydev_ioctl_common(struct joydev *joydev, |
456 | unsigned int cmd, void __user *argp) | 526 | unsigned int cmd, void __user *argp) |
457 | { | 527 | { |
@@ -512,46 +582,18 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
512 | switch (cmd & ~IOCSIZE_MASK) { | 582 | switch (cmd & ~IOCSIZE_MASK) { |
513 | 583 | ||
514 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): | 584 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): |
515 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | 585 | return joydev_handle_JSIOCSAXMAP(joydev, argp, _IOC_SIZE(cmd)); |
516 | /* | ||
517 | * FIXME: we should not copy into our axis map before | ||
518 | * validating the data. | ||
519 | */ | ||
520 | if (copy_from_user(joydev->abspam, argp, len)) | ||
521 | return -EFAULT; | ||
522 | |||
523 | for (i = 0; i < joydev->nabs; i++) { | ||
524 | if (joydev->abspam[i] > ABS_MAX) | ||
525 | return -EINVAL; | ||
526 | joydev->absmap[joydev->abspam[i]] = i; | ||
527 | } | ||
528 | return 0; | ||
529 | 586 | ||
530 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): | 587 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): |
531 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | 588 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); |
532 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; | 589 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : len; |
533 | 590 | ||
534 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): | 591 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): |
535 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | 592 | return joydev_handle_JSIOCSBTNMAP(joydev, argp, _IOC_SIZE(cmd)); |
536 | /* | ||
537 | * FIXME: we should not copy into our keymap before | ||
538 | * validating the data. | ||
539 | */ | ||
540 | if (copy_from_user(joydev->keypam, argp, len)) | ||
541 | return -EFAULT; | ||
542 | |||
543 | for (i = 0; i < joydev->nkey; i++) { | ||
544 | if (joydev->keypam[i] > KEY_MAX || | ||
545 | joydev->keypam[i] < BTN_MISC) | ||
546 | return -EINVAL; | ||
547 | joydev->keymap[joydev->keypam[i] - BTN_MISC] = i; | ||
548 | } | ||
549 | |||
550 | return 0; | ||
551 | 593 | ||
552 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): | 594 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): |
553 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); | 595 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); |
554 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; | 596 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : len; |
555 | 597 | ||
556 | case JSIOCGNAME(0): | 598 | case JSIOCGNAME(0): |
557 | name = dev->name; | 599 | name = dev->name; |