Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jikos/hid
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Oct 2017 16:08:56 +0000 (09:08 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 12 Oct 2017 16:08:56 +0000 (09:08 -0700)
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

drivers/hid/Kconfig
drivers/hid/hid-core.c
drivers/hid/hid-elecom.c
drivers/hid/hid-ids.h
drivers/hid/usbhid/hid-core.c

index 0a3117cc29e70c54b3f9b269889d9b4ccf2fb56c..374301fcbc86791e5005ba3e1b45a35c496174ad 100644 (file)
@@ -281,6 +281,7 @@ config HID_ELECOM
        Support for ELECOM devices:
          - BM084 Bluetooth Mouse
          - DEFT Trackball (Wired and wireless)
+         - HUGE Trackball (Wired and wireless)
 
 config HID_ELO
        tristate "ELO USB 4000/4500 touchscreen"
index 9bc91160819b6eaeac1b0368bdbdfe15a1328422..330ca983828ba6d11feaf5538841a6810d84f5c6 100644 (file)
@@ -2032,6 +2032,8 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
 #endif
 #if IS_ENABLED(CONFIG_HID_ELO)
        { HID_USB_DEVICE(USB_VENDOR_ID_ELO, 0x0009) },
index e2c7465df69f3ae74c2cb1979c531b02e2934089..54aeea57d2099bd8c0a1acf41b9d2f0c21c58ee6 100644 (file)
@@ -3,6 +3,7 @@
  *  Copyright (c) 2010 Richard Nauber <Richard.Nauber@gmail.com>
  *  Copyright (c) 2016 Yuxuan Shui <yshuiv7@gmail.com>
  *  Copyright (c) 2017 Diego Elio Pettenò <flameeyes@flameeyes.eu>
+ *  Copyright (c) 2017 Alex Manoussakis <amanou@gnu.org>
  */
 
 /*
@@ -32,9 +33,11 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                break;
        case USB_DEVICE_ID_ELECOM_DEFT_WIRED:
        case USB_DEVICE_ID_ELECOM_DEFT_WIRELESS:
-               /* The DEFT trackball has eight buttons, but its descriptor only
-                * reports five, disabling the three Fn buttons on the top of
-                * the mouse.
+       case USB_DEVICE_ID_ELECOM_HUGE_WIRED:
+       case USB_DEVICE_ID_ELECOM_HUGE_WIRELESS:
+               /* The DEFT/HUGE trackball has eight buttons, but its descriptor
+                * only reports five, disabling the three Fn buttons on the top
+                * of the mouse.
                 *
                 * Apply the following diff to the descriptor:
                 *
@@ -62,7 +65,7 @@ static __u8 *elecom_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                 * End Collection,                     End Collection,
                 */
                if (*rsize == 213 && rdesc[13] == 5 && rdesc[21] == 5) {
-                       hid_info(hdev, "Fixing up Elecom DEFT Fn buttons\n");
+                       hid_info(hdev, "Fixing up Elecom DEFT/HUGE Fn buttons\n");
                        rdesc[13] = 8; /* Button/Variable Report Count */
                        rdesc[21] = 8; /* Button/Variable Usage Maximum */
                        rdesc[29] = 0; /* Button/Constant Report Count */
@@ -76,6 +79,8 @@ static const struct hid_device_id elecom_devices[] = {
        { HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_BM084) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRED) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_DEFT_WIRELESS) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRED) },
+       { HID_USB_DEVICE(USB_VENDOR_ID_ELECOM, USB_DEVICE_ID_ELECOM_HUGE_WIRELESS) },
        { }
 };
 MODULE_DEVICE_TABLE(hid, elecom_devices);
index a98919199858717ecd173ba2ef04f014edcb109f..be2e005c3c516c6cb522a68a891d75e48f8f800f 100644 (file)
 #define USB_DEVICE_ID_ELECOM_BM084     0x0061
 #define USB_DEVICE_ID_ELECOM_DEFT_WIRED        0x00fe
 #define USB_DEVICE_ID_ELECOM_DEFT_WIRELESS     0x00ff
+#define USB_DEVICE_ID_ELECOM_HUGE_WIRED        0x010c
+#define USB_DEVICE_ID_ELECOM_HUGE_WIRELESS     0x010d
 
 #define USB_VENDOR_ID_DREAM_CHEEKY     0x1d34
 #define USB_DEVICE_ID_DREAM_CHEEKY_WN  0x0004
index 089bad8a9a21d6b35742df8819fabb4da5036730..045b5da9b992873ce74f5d401de34855b93a6f8e 100644 (file)
@@ -975,6 +975,8 @@ static int usbhid_parse(struct hid_device *hid)
        unsigned int rsize = 0;
        char *rdesc;
        int ret, n;
+       int num_descriptors;
+       size_t offset = offsetof(struct hid_descriptor, desc);
 
        quirks = usbhid_lookup_quirk(le16_to_cpu(dev->descriptor.idVendor),
                        le16_to_cpu(dev->descriptor.idProduct));
@@ -997,10 +999,18 @@ static int usbhid_parse(struct hid_device *hid)
                return -ENODEV;
        }
 
+       if (hdesc->bLength < sizeof(struct hid_descriptor)) {
+               dbg_hid("hid descriptor is too short\n");
+               return -EINVAL;
+       }
+
        hid->version = le16_to_cpu(hdesc->bcdHID);
        hid->country = hdesc->bCountryCode;
 
-       for (n = 0; n < hdesc->bNumDescriptors; n++)
+       num_descriptors = min_t(int, hdesc->bNumDescriptors,
+              (hdesc->bLength - offset) / sizeof(struct hid_class_descriptor));
+
+       for (n = 0; n < num_descriptors; n++)
                if (hdesc->desc[n].bDescriptorType == HID_DT_REPORT)
                        rsize = le16_to_cpu(hdesc->desc[n].wDescriptorLength);