diff options
| -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; |
