diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-12 12:08:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-10-12 12:08:56 -0400 |
commit | be7484acc6fee2878dc8d1593ba81fb1e0b3d581 (patch) | |
tree | 49d15b5652190a987e7a16019d80cc89764ef430 | |
parent | 7702f47623e6c029b4ce59ce0ad39b869d5cc933 (diff) | |
parent | a0933a456ff83a3b5ffa3a1903e0b8de4a56adf5 (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
Pull HID fixes from Jiri Kosina:
- fix for potential out-of-bounds memory access (found by fuzzing,
likely requires specially crafted device to trigger) by Jaejoong Kim
- two new device IDs for elecom driver from Alex Manoussakis
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid:
HID: hid-elecom: extend to fix descriptor for HUGE trackball
HID: usbhid: fix out-of-bounds bug
-rw-r--r-- | drivers/hid/Kconfig | 1 | ||||
-rw-r--r-- | drivers/hid/hid-core.c | 2 | ||||
-rw-r--r-- | drivers/hid/hid-elecom.c | 13 | ||||
-rw-r--r-- | drivers/hid/hid-ids.h | 2 | ||||
-rw-r--r-- | drivers/hid/usbhid/hid-core.c | 12 |
5 files changed, 25 insertions, 5 deletions
diff --git a/drivers/hid/Kconfig b/drivers/hid/Kconfig index 0a3117cc29e7..374301fcbc86 100644 --- a/drivers/hid/Kconfig +++ b/drivers/hid/Kconfig | |||
@@ -281,6 +281,7 @@ config HID_ELECOM | |||
281 | Support for ELECOM devices: | 281 | Support for ELECOM devices: |
282 | - BM084 Bluetooth Mouse | 282 | - BM084 Bluetooth Mouse |
283 | - DEFT Trackball (Wired and wireless) | 283 | - DEFT Trackball (Wired and wireless) |
284 | - HUGE Trackball (Wired and wireless) | ||
284 | 285 | ||
285 | config HID_ELO | 286 | config HID_ELO |
286 | tristate "ELO USB 4000/4500 touchscreen" | 287 | tristate "ELO USB 4000/4500 touchscreen" |
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c index 9bc91160819b..330ca983828b 100644 --- a/drivers/hid/hid-core.c +++ b/drivers/hid/hid-core.c | |||
@@ -2032,6 +2032,8 @@ static const struct hid_device_id hid_have_special_driver[] = { | |||
2032 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | 2032 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
2033 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, | 2033 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, |
2034 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, | 2034 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, |
2035 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, | ||
2036 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) }, | ||
2035 | #endif | 2037 | #endif |
2036 | #if IS_ENABLED(CONFIG_HID_ELO) | 2038 | #if IS_ENABLED(CONFIG_HID_ELO) |
2037 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, | 2039 | { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) }, |
diff --git a/drivers/hid/hid-elecom.c b/drivers/hid/hid-elecom.c index e2c7465df69f..54aeea57d209 100644 --- a/drivers/hid/hid-elecom.c +++ b/drivers/hid/hid-elecom.c | |||
@@ -3,6 +3,7 @@ | |||
3 | * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> | 3 | * Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com> |
4 | * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com> | 4 | * Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com> |
5 | * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu> | 5 | * Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu> |
6 | * Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org> | ||
6 | */ | 7 | */ |
7 | 8 | ||
8 | /* | 9 | /* |
@@ -32,9 +33,11 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
32 | break; | 33 | break; |
33 | case USB_DEVICE_ID_ELECOM_DEFT_WIRED: | 34 | case USB_DEVICE_ID_ELECOM_DEFT_WIRED: |
34 | case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS: | 35 | case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS: |
35 | /* The DEFT trackball has eight buttons, but its descriptor only | 36 | case USB_DEVICE_ID_ELECOM_HUGE_WIRED: |
36 | * reports five, disabling the three Fn buttons on the top of | 37 | case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS: |
37 | * the mouse. | 38 | /* The DEFT/HUGE trackball has eight buttons, but its descriptor |
39 | * only reports five, disabling the three Fn buttons on the top | ||
40 | * of the mouse. | ||
38 | * | 41 | * |
39 | * Apply the following diff to the descriptor: | 42 | * Apply the following diff to the descriptor: |
40 | * | 43 | * |
@@ -62,7 +65,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc, | |||
62 | * End Collection, End Collection, | 65 | * End Collection, End Collection, |
63 | */ | 66 | */ |
64 | if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) { | 67 | if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) { |
65 | hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n"); | 68 | hid_info(hdev, "Fixing up Elecom DEFT/HUGE Fn buttons\n"); |
66 | rdesc[13] = 8; /* Button/Variable Report Count */ | 69 | rdesc[13] = 8; /* Button/Variable Report Count */ |
67 | rdesc[21] = 8; /* Button/Variable Usage Maximum */ | 70 | rdesc[21] = 8; /* Button/Variable Usage Maximum */ |
68 | rdesc[29] = 0; /* Button/Constant Report Count */ | 71 | rdesc[29] = 0; /* Button/Constant Report Count */ |
@@ -76,6 +79,8 @@ static const struct hid_device_id elecom_devices[] = { | |||
76 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, | 79 | { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) }, |
77 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, | 80 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) }, |
78 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, | 81 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) }, |
82 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) }, | ||
83 | { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) }, | ||
79 | { } | 84 | { } |
80 | }; | 85 | }; |
81 | MODULE_DEVICE_TABLE(hid, elecom_devices); | 86 | MODULE_DEVICE_TABLE(hid, elecom_devices); |
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index a98919199858..be2e005c3c51 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h | |||
@@ -368,6 +368,8 @@ | |||
368 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 | 368 | #define USB_DEVICE_ID_ELECOM_BM084 0x0061 |
369 | #define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe | 369 | #define USB_DEVICE_ID_ELECOM_DEFT_WIRED 0x00fe |
370 | #define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff | 370 | #define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS 0x00ff |
371 | #define USB_DEVICE_ID_ELECOM_HUGE_WIRED 0x010c | ||
372 | #define USB_DEVICE_ID_ELECOM_HUGE_WIRELESS 0x010d | ||
371 | 373 | ||
372 | #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 | 374 | #define USB_VENDOR_ID_DREAM_CHEEKY 0x1d34 |
373 | #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 | 375 | #define USB_DEVICE_ID_DREAM_CHEEKY_WN 0x0004 |
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c index 089bad8a9a21..045b5da9b992 100644 --- a/drivers/hid/usbhid/hid-core.c +++ b/drivers/hid/usbhid/hid-core.c | |||
@@ -975,6 +975,8 @@ static int usbhid_parse(struct hid_device *hid) | |||
975 | unsigned int rsize = 0; | 975 | unsigned int rsize = 0; |
976 | char *rdesc; | 976 | char *rdesc; |
977 | int ret, n; | 977 | int ret, n; |
978 | int num_descriptors; | ||
979 | size_t offset = offsetof(struct hid_descriptor, desc); | ||
978 | 980 | ||
979 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), | 981 | quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor), |
980 | le16_to_cpu(dev->descriptor.idProduct)); | 982 | le16_to_cpu(dev->descriptor.idProduct)); |
@@ -997,10 +999,18 @@ static int usbhid_parse(struct hid_device *hid) | |||
997 | return -ENODEV; | 999 | return -ENODEV; |
998 | } | 1000 | } |
999 | 1001 | ||
1002 | if (hdesc->bLength < sizeof(struct hid_descriptor)) { | ||
1003 | dbg_hid("hid descriptor is too short\n"); | ||
1004 | return -EINVAL; | ||
1005 | } | ||
1006 | |||
1000 | hid->version = le16_to_cpu(hdesc->bcdHID); | 1007 | hid->version = le16_to_cpu(hdesc->bcdHID); |
1001 | hid->country = hdesc->bCountryCode; | 1008 | hid->country = hdesc->bCountryCode; |
1002 | 1009 | ||
1003 | for (n = 0; n < hdesc->bNumDescriptors; n++) | 1010 | num_descriptors = min_t(int, hdesc->bNumDescriptors, |
1011 | (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor)); | ||
1012 | |||
1013 | for (n = 0; n < num_descriptors; n++) | ||
1004 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) | 1014 | if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT) |
1005 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); | 1015 | rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength); |
1006 | 1016 | ||