Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Input: define separate EVIOCGKEYCODE_V2/EVIOCSKEYCODE_V2

The desire to keep old names for the EVIOCGKEYCODE/EVIOCSKEYCODE while
extending them to support large scancodes was a mistake. While we tried
to keep ABI intact (and we succeeded in doing that, programs compiled
on older kernels will work on newer ones) there is still a problem with
recompiling existing software with newer kernel headers.

New kernel headers will supply updated ioctl numbers and kernel will
expect that userspace will use struct input_keymap_entry to set and
retrieve keymap data. But since the names of ioctls are still the same
userspace will happily compile even if not adjusted to make use of the
new structure and will start miraculously fail in the field.

To avoid this issue let's revert EVIOCGKEYCODE/EVIOCSKEYCODE definitions
and add EVIOCGKEYCODE_V2/EVIOCSKEYCODE_V2 so that userspace can explicitly
select the style of ioctls it wants to employ.

Reviewed-by: Henrik Rydberg <rydberg@euromail.se>
Acked-by: Jarod Wilson <jarod@redhat.com>
Acked-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Signed-off-by: Dmitry Torokhov <dtor@mail.ru>

+69 -64
+65 -62
drivers/input/evdev.c
··· 534 534 } 535 535 #undef OLD_KEY_MAX 536 536 537 - static int evdev_handle_get_keycode(struct input_dev *dev, 538 - void __user *p, size_t size) 537 + static int evdev_handle_get_keycode(struct input_dev *dev, void __user *p) 538 + { 539 + struct input_keymap_entry ke = { 540 + .len = sizeof(unsigned int), 541 + .flags = 0, 542 + }; 543 + int __user *ip = (int __user *)p; 544 + int error; 545 + 546 + /* legacy case */ 547 + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) 548 + return -EFAULT; 549 + 550 + error = input_get_keycode(dev, &ke); 551 + if (error) 552 + return error; 553 + 554 + if (put_user(ke.keycode, ip + 1)) 555 + return -EFAULT; 556 + 557 + return 0; 558 + } 559 + 560 + static int evdev_handle_get_keycode_v2(struct input_dev *dev, void __user *p) 539 561 { 540 562 struct input_keymap_entry ke; 541 563 int error; 542 564 543 - memset(&ke, 0, sizeof(ke)); 565 + if (copy_from_user(&ke, p, sizeof(ke))) 566 + return -EFAULT; 544 567 545 - if (size == sizeof(unsigned int[2])) { 546 - /* legacy case */ 547 - int __user *ip = (int __user *)p; 568 + error = input_get_keycode(dev, &ke); 569 + if (error) 570 + return error; 548 571 549 - if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) 550 - return -EFAULT; 572 + if (copy_to_user(p, &ke, sizeof(ke))) 573 + return -EFAULT; 551 574 552 - ke.len = sizeof(unsigned int); 553 - ke.flags = 0; 554 - 555 - error = input_get_keycode(dev, &ke); 556 - if (error) 557 - return error; 558 - 559 - if (put_user(ke.keycode, ip + 1)) 560 - return -EFAULT; 561 - 562 - } else { 563 - size = min(size, sizeof(ke)); 564 - 565 - if (copy_from_user(&ke, p, size)) 566 - return -EFAULT; 567 - 568 - error = input_get_keycode(dev, &ke); 569 - if (error) 570 - return error; 571 - 572 - if (copy_to_user(p, &ke, size)) 573 - return -EFAULT; 574 - } 575 575 return 0; 576 576 } 577 577 578 - static int evdev_handle_set_keycode(struct input_dev *dev, 579 - void __user *p, size_t size) 578 + static int evdev_handle_set_keycode(struct input_dev *dev, void __user *p) 579 + { 580 + struct input_keymap_entry ke = { 581 + .len = sizeof(unsigned int), 582 + .flags = 0, 583 + }; 584 + int __user *ip = (int __user *)p; 585 + 586 + if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) 587 + return -EFAULT; 588 + 589 + if (get_user(ke.keycode, ip + 1)) 590 + return -EFAULT; 591 + 592 + return input_set_keycode(dev, &ke); 593 + } 594 + 595 + static int evdev_handle_set_keycode_v2(struct input_dev *dev, void __user *p) 580 596 { 581 597 struct input_keymap_entry ke; 582 598 583 - memset(&ke, 0, sizeof(ke)); 599 + if (copy_from_user(&ke, p, sizeof(ke))) 600 + return -EFAULT; 584 601 585 - if (size == sizeof(unsigned int[2])) { 586 - /* legacy case */ 587 - int __user *ip = (int __user *)p; 588 - 589 - if (copy_from_user(ke.scancode, p, sizeof(unsigned int))) 590 - return -EFAULT; 591 - 592 - if (get_user(ke.keycode, ip + 1)) 593 - return -EFAULT; 594 - 595 - ke.len = sizeof(unsigned int); 596 - ke.flags = 0; 597 - 598 - } else { 599 - size = min(size, sizeof(ke)); 600 - 601 - if (copy_from_user(&ke, p, size)) 602 - return -EFAULT; 603 - 604 - if (ke.len > sizeof(ke.scancode)) 605 - return -EINVAL; 606 - } 602 + if (ke.len > sizeof(ke.scancode)) 603 + return -EINVAL; 607 604 608 605 return input_set_keycode(dev, &ke); 609 606 } ··· 666 669 return evdev_grab(evdev, client); 667 670 else 668 671 return evdev_ungrab(evdev, client); 672 + 673 + case EVIOCGKEYCODE: 674 + return evdev_handle_get_keycode(dev, p); 675 + 676 + case EVIOCSKEYCODE: 677 + return evdev_handle_set_keycode(dev, p); 678 + 679 + case EVIOCGKEYCODE_V2: 680 + return evdev_handle_get_keycode_v2(dev, p); 681 + 682 + case EVIOCSKEYCODE_V2: 683 + return evdev_handle_set_keycode_v2(dev, p); 669 684 } 670 685 671 686 size = _IOC_SIZE(cmd); ··· 717 708 return -EFAULT; 718 709 719 710 return error; 720 - 721 - case EVIOC_MASK_SIZE(EVIOCGKEYCODE): 722 - return evdev_handle_get_keycode(dev, p, size); 723 - 724 - case EVIOC_MASK_SIZE(EVIOCSKEYCODE): 725 - return evdev_handle_set_keycode(dev, p, size); 726 711 } 727 712 728 713 /* Multi-number variable-length handlers */
+4 -2
include/linux/input.h
··· 104 104 #define EVIOCGREP _IOR('E', 0x03, unsigned int[2]) /* get repeat settings */ 105 105 #define EVIOCSREP _IOW('E', 0x03, unsigned int[2]) /* set repeat settings */ 106 106 107 - #define EVIOCGKEYCODE _IOR('E', 0x04, struct input_keymap_entry) /* get keycode */ 108 - #define EVIOCSKEYCODE _IOW('E', 0x04, struct input_keymap_entry) /* set keycode */ 107 + #define EVIOCGKEYCODE _IOR('E', 0x04, unsigned int[2]) /* get keycode */ 108 + #define EVIOCGKEYCODE_V2 _IOR('E', 0x04, struct input_keymap_entry) 109 + #define EVIOCSKEYCODE _IOW('E', 0x04, unsigned int[2]) /* set keycode */ 110 + #define EVIOCSKEYCODE_V2 _IOW('E', 0x04, struct input_keymap_entry) 109 111 110 112 #define EVIOCGNAME(len) _IOC(_IOC_READ, 'E', 0x06, len) /* get device name */ 111 113 #define EVIOCGPHYS(len) _IOC(_IOC_READ, 'E', 0x07, len) /* get physical location */