diff options
| author | Ingo Molnar <mingo@elte.hu> | 2008-09-04 07:02:35 -0400 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2008-09-04 07:02:35 -0400 |
| commit | 42390cdec5f6e6e2ee54f308474a6ef7dd16aa5c (patch) | |
| tree | e9684c84f53272319a5acd4b9c86503f30274a51 /drivers/input/evdev.c | |
| parent | 11c231a962c740b3216eb6565149ae5a7944cba7 (diff) | |
| parent | d210baf53b699fc61aa891c177b71d7082d3b957 (diff) | |
Merge branch 'linus' into x86/x2apic
Conflicts:
arch/x86/kernel/cpu/cyrix.c
include/asm-x86/cpufeature.h
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'drivers/input/evdev.c')
| -rw-r--r-- | drivers/input/evdev.c | 63 |
1 files changed, 43 insertions, 20 deletions
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c index 2d65411f6763..3524bef62be6 100644 --- a/drivers/input/evdev.c +++ b/drivers/input/evdev.c | |||
| @@ -647,6 +647,47 @@ static int str_to_user(const char *str, unsigned int maxlen, void __user *p) | |||
| 647 | return copy_to_user(p, str, len) ? -EFAULT : len; | 647 | return copy_to_user(p, str, len) ? -EFAULT : len; |
| 648 | } | 648 | } |
| 649 | 649 | ||
| 650 | #define OLD_KEY_MAX 0x1ff | ||
| 651 | static int handle_eviocgbit(struct input_dev *dev, unsigned int cmd, void __user *p, int compat_mode) | ||
| 652 | { | ||
| 653 | static unsigned long keymax_warn_time; | ||
| 654 | unsigned long *bits; | ||
| 655 | int len; | ||
| 656 | |||
| 657 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
| 658 | |||
| 659 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
| 660 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
| 661 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
| 662 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
| 663 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
| 664 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
| 665 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
| 666 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
| 667 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
| 668 | default: return -EINVAL; | ||
| 669 | } | ||
| 670 | |||
| 671 | /* | ||
| 672 | * Work around bugs in userspace programs that like to do | ||
| 673 | * EVIOCGBIT(EV_KEY, KEY_MAX) and not realize that 'len' | ||
| 674 | * should be in bytes, not in bits. | ||
| 675 | */ | ||
| 676 | if ((_IOC_NR(cmd) & EV_MAX) == EV_KEY && _IOC_SIZE(cmd) == OLD_KEY_MAX) { | ||
| 677 | len = OLD_KEY_MAX; | ||
| 678 | if (printk_timed_ratelimit(&keymax_warn_time, 10 * 1000)) | ||
| 679 | printk(KERN_WARNING | ||
| 680 | "evdev.c(EVIOCGBIT): Suspicious buffer size %u, " | ||
| 681 | "limiting output to %zu bytes. See " | ||
| 682 | "http://userweb.kernel.org/~dtor/eviocgbit-bug.html\n", | ||
| 683 | OLD_KEY_MAX, | ||
| 684 | BITS_TO_LONGS(OLD_KEY_MAX) * sizeof(long)); | ||
| 685 | } | ||
| 686 | |||
| 687 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
| 688 | } | ||
| 689 | #undef OLD_KEY_MAX | ||
| 690 | |||
| 650 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, | 691 | static long evdev_do_ioctl(struct file *file, unsigned int cmd, |
| 651 | void __user *p, int compat_mode) | 692 | void __user *p, int compat_mode) |
| 652 | { | 693 | { |
| @@ -733,26 +774,8 @@ static long evdev_do_ioctl(struct file *file, unsigned int cmd, | |||
| 733 | 774 | ||
| 734 | if (_IOC_DIR(cmd) == _IOC_READ) { | 775 | if (_IOC_DIR(cmd) == _IOC_READ) { |
| 735 | 776 | ||
| 736 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) { | 777 | if ((_IOC_NR(cmd) & ~EV_MAX) == _IOC_NR(EVIOCGBIT(0, 0))) |
| 737 | 778 | return handle_eviocgbit(dev, cmd, p, compat_mode); | |
| 738 | unsigned long *bits; | ||
| 739 | int len; | ||
| 740 | |||
| 741 | switch (_IOC_NR(cmd) & EV_MAX) { | ||
| 742 | |||
| 743 | case 0: bits = dev->evbit; len = EV_MAX; break; | ||
| 744 | case EV_KEY: bits = dev->keybit; len = KEY_MAX; break; | ||
| 745 | case EV_REL: bits = dev->relbit; len = REL_MAX; break; | ||
| 746 | case EV_ABS: bits = dev->absbit; len = ABS_MAX; break; | ||
| 747 | case EV_MSC: bits = dev->mscbit; len = MSC_MAX; break; | ||
| 748 | case EV_LED: bits = dev->ledbit; len = LED_MAX; break; | ||
| 749 | case EV_SND: bits = dev->sndbit; len = SND_MAX; break; | ||
| 750 | case EV_FF: bits = dev->ffbit; len = FF_MAX; break; | ||
| 751 | case EV_SW: bits = dev->swbit; len = SW_MAX; break; | ||
| 752 | default: return -EINVAL; | ||
| 753 | } | ||
| 754 | return bits_to_user(bits, len, _IOC_SIZE(cmd), p, compat_mode); | ||
| 755 | } | ||
| 756 | 779 | ||
| 757 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) | 780 | if (_IOC_NR(cmd) == _IOC_NR(EVIOCGKEY(0))) |
| 758 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), | 781 | return bits_to_user(dev->key, KEY_MAX, _IOC_SIZE(cmd), |
