diff options
Diffstat (limited to 'drivers/input/joydev.c')
| -rw-r--r-- | drivers/input/joydev.c | 68 |
1 files changed, 41 insertions, 27 deletions
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c index 4cfd084fa897..9a1d55b74d7a 100644 --- a/drivers/input/joydev.c +++ b/drivers/input/joydev.c | |||
| @@ -456,8 +456,11 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
| 456 | unsigned int cmd, void __user *argp) | 456 | unsigned int cmd, void __user *argp) |
| 457 | { | 457 | { |
| 458 | struct input_dev *dev = joydev->handle.dev; | 458 | struct input_dev *dev = joydev->handle.dev; |
| 459 | size_t len; | ||
| 459 | int i, j; | 460 | int i, j; |
| 461 | const char *name; | ||
| 460 | 462 | ||
| 463 | /* Process fixed-sized commands. */ | ||
| 461 | switch (cmd) { | 464 | switch (cmd) { |
| 462 | 465 | ||
| 463 | case JS_SET_CAL: | 466 | case JS_SET_CAL: |
| @@ -499,9 +502,22 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
| 499 | return copy_to_user(argp, joydev->corr, | 502 | return copy_to_user(argp, joydev->corr, |
| 500 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; | 503 | sizeof(joydev->corr[0]) * joydev->nabs) ? -EFAULT : 0; |
| 501 | 504 | ||
| 502 | case JSIOCSAXMAP: | 505 | } |
| 503 | if (copy_from_user(joydev->abspam, argp, | 506 | |
| 504 | sizeof(__u8) * (ABS_MAX + 1))) | 507 | /* |
| 508 | * Process variable-sized commands (the axis and button map commands | ||
| 509 | * are considered variable-sized to decouple them from the values of | ||
| 510 | * ABS_MAX and KEY_MAX). | ||
| 511 | */ | ||
| 512 | switch (cmd & ~IOCSIZE_MASK) { | ||
| 513 | |||
| 514 | case (JSIOCSAXMAP & ~IOCSIZE_MASK): | ||
| 515 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); | ||
| 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)) | ||
| 505 | return -EFAULT; | 521 | return -EFAULT; |
| 506 | 522 | ||
| 507 | for (i = 0; i < joydev->nabs; i++) { | 523 | for (i = 0; i < joydev->nabs; i++) { |
| @@ -511,13 +527,17 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
| 511 | } | 527 | } |
| 512 | return 0; | 528 | return 0; |
| 513 | 529 | ||
| 514 | case JSIOCGAXMAP: | 530 | case (JSIOCGAXMAP & ~IOCSIZE_MASK): |
| 515 | return copy_to_user(argp, joydev->abspam, | 531 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->abspam)); |
| 516 | sizeof(__u8) * (ABS_MAX + 1)) ? -EFAULT : 0; | 532 | return copy_to_user(argp, joydev->abspam, len) ? -EFAULT : 0; |
| 517 | 533 | ||
| 518 | case JSIOCSBTNMAP: | 534 | case (JSIOCSBTNMAP & ~IOCSIZE_MASK): |
| 519 | if (copy_from_user(joydev->keypam, argp, | 535 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); |
| 520 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1))) | 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)) | ||
| 521 | return -EFAULT; | 541 | return -EFAULT; |
| 522 | 542 | ||
| 523 | for (i = 0; i < joydev->nkey; i++) { | 543 | for (i = 0; i < joydev->nkey; i++) { |
| @@ -529,25 +549,19 @@ static int joydev_ioctl_common(struct joydev *joydev, | |||
| 529 | 549 | ||
| 530 | return 0; | 550 | return 0; |
| 531 | 551 | ||
| 532 | case JSIOCGBTNMAP: | 552 | case (JSIOCGBTNMAP & ~IOCSIZE_MASK): |
| 533 | return copy_to_user(argp, joydev->keypam, | 553 | len = min_t(size_t, _IOC_SIZE(cmd), sizeof(joydev->keypam)); |
| 534 | sizeof(__u16) * (KEY_MAX - BTN_MISC + 1)) ? -EFAULT : 0; | 554 | return copy_to_user(argp, joydev->keypam, len) ? -EFAULT : 0; |
| 535 | 555 | ||
| 536 | default: | 556 | case JSIOCGNAME(0): |
| 537 | if ((cmd & ~IOCSIZE_MASK) == JSIOCGNAME(0)) { | 557 | name = dev->name; |
| 538 | int len; | 558 | if (!name) |
| 539 | const char *name = dev->name; | 559 | return 0; |
| 540 | 560 | ||
| 541 | if (!name) | 561 | len = min_t(size_t, _IOC_SIZE(cmd), strlen(name) + 1); |
| 542 | return 0; | 562 | return copy_to_user(argp, name, len) ? -EFAULT : len; |
| 543 | len = strlen(name) + 1; | ||
| 544 | if (len > _IOC_SIZE(cmd)) | ||
| 545 | len = _IOC_SIZE(cmd); | ||
| 546 | if (copy_to_user(argp, name, len)) | ||
| 547 | return -EFAULT; | ||
| 548 | return len; | ||
| 549 | } | ||
| 550 | } | 563 | } |
| 564 | |||
| 551 | return -EINVAL; | 565 | return -EINVAL; |
| 552 | } | 566 | } |
| 553 | 567 | ||
