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 | ||