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

HID: check for valid USB device for many HID drivers

Many HID drivers assume that the HID device assigned to them is a USB
device as that was the only way HID devices used to be able to be
created in Linux. However, with the additional ways that HID devices
can be created for many different bus types, that is no longer true, so
properly check that we have a USB device associated with the HID device
before allowing a driver that makes this assumption to claim it.

Cc: Jiri Kosina <jikos@kernel.org>
Cc: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Cc: Michael Zaidman <michael.zaidman@gmail.com>
Cc: Stefan Achatz <erazor_de@users.sourceforge.net>
Cc: Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Alexandre Torgue <alexandre.torgue@foss.st.com>
Cc: linux-input@vger.kernel.org
Cc: stable@vger.kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Tested-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
[bentiss: amended for thrustmater.c hunk to apply]
Signed-off-by: Benjamin Tissoires <benjamin.tissoires@redhat.com>
Link: https://lore.kernel.org/r/20211201183503.2373082-3-gregkh@linuxfoundation.org

authored by

Greg Kroah-Hartman and committed by
Benjamin Tissoires
93020953 720ac467

+92 -9
+3
drivers/hid/hid-chicony.c
··· 114 114 { 115 115 int ret; 116 116 117 + if (!hid_is_usb(hdev)) 118 + return -EINVAL; 119 + 117 120 hdev->quirks |= HID_QUIRK_INPUT_PER_APP; 118 121 ret = hid_parse(hdev); 119 122 if (ret) {
+6 -1
drivers/hid/hid-corsair.c
··· 553 553 int ret; 554 554 unsigned long quirks = id->driver_data; 555 555 struct corsair_drvdata *drvdata; 556 - struct usb_interface *usbif = to_usb_interface(dev->dev.parent); 556 + struct usb_interface *usbif; 557 + 558 + if (!hid_is_usb(dev)) 559 + return -EINVAL; 560 + 561 + usbif = to_usb_interface(dev->dev.parent); 557 562 558 563 drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata), 559 564 GFP_KERNEL);
+1 -1
drivers/hid/hid-elan.c
··· 50 50 51 51 static int is_not_elan_touchpad(struct hid_device *hdev) 52 52 { 53 - if (hdev->bus == BUS_USB) { 53 + if (hid_is_usb(hdev)) { 54 54 struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 55 55 56 56 return (intf->altsetting->desc.bInterfaceNumber !=
+3
drivers/hid/hid-elo.c
··· 230 230 int ret; 231 231 struct usb_device *udev; 232 232 233 + if (!hid_is_usb(hdev)) 234 + return -EINVAL; 235 + 233 236 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 234 237 if (!priv) 235 238 return -ENOMEM;
+3
drivers/hid/hid-ft260.c
··· 915 915 struct ft260_get_chip_version_report version; 916 916 int ret; 917 917 918 + if (!hid_is_usb(hdev)) 919 + return -EINVAL; 920 + 918 921 dev = devm_kzalloc(&hdev->dev, sizeof(*dev), GFP_KERNEL); 919 922 if (!dev) 920 923 return -ENOMEM;
+7 -2
drivers/hid/hid-holtek-kbd.c
··· 140 140 static int holtek_kbd_probe(struct hid_device *hdev, 141 141 const struct hid_device_id *id) 142 142 { 143 - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 144 - int ret = hid_parse(hdev); 143 + struct usb_interface *intf; 144 + int ret; 145 145 146 + if (!hid_is_usb(hdev)) 147 + return -EINVAL; 148 + 149 + ret = hid_parse(hdev); 146 150 if (!ret) 147 151 ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT); 148 152 153 + intf = to_usb_interface(hdev->dev.parent); 149 154 if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) { 150 155 struct hid_input *hidinput; 151 156 list_for_each_entry(hidinput, &hdev->inputs, list) {
+9
drivers/hid/hid-holtek-mouse.c
··· 62 62 return rdesc; 63 63 } 64 64 65 + static int holtek_mouse_probe(struct hid_device *hdev, 66 + const struct hid_device_id *id) 67 + { 68 + if (!hid_is_usb(hdev)) 69 + return -EINVAL; 70 + return 0; 71 + } 72 + 65 73 static const struct hid_device_id holtek_mouse_devices[] = { 66 74 { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT, 67 75 USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) }, ··· 91 83 .name = "holtek_mouse", 92 84 .id_table = holtek_mouse_devices, 93 85 .report_fixup = holtek_mouse_report_fixup, 86 + .probe = holtek_mouse_probe, 94 87 }; 95 88 96 89 module_hid_driver(holtek_mouse_driver);
+8 -2
drivers/hid/hid-lg.c
··· 749 749 750 750 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id) 751 751 { 752 - struct usb_interface *iface = to_usb_interface(hdev->dev.parent); 753 - __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber; 752 + struct usb_interface *iface; 753 + __u8 iface_num; 754 754 unsigned int connect_mask = HID_CONNECT_DEFAULT; 755 755 struct lg_drv_data *drv_data; 756 756 int ret; 757 + 758 + if (!hid_is_usb(hdev)) 759 + return -EINVAL; 760 + 761 + iface = to_usb_interface(hdev->dev.parent); 762 + iface_num = iface->cur_altsetting->desc.bInterfaceNumber; 757 763 758 764 /* G29 only work with the 1st interface */ 759 765 if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
+8 -2
drivers/hid/hid-prodikeys.c
··· 798 798 static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id) 799 799 { 800 800 int ret; 801 - struct usb_interface *intf = to_usb_interface(hdev->dev.parent); 802 - unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 801 + struct usb_interface *intf; 802 + unsigned short ifnum; 803 803 unsigned long quirks = id->driver_data; 804 804 struct pk_device *pk; 805 805 struct pcmidi_snd *pm = NULL; 806 + 807 + if (!hid_is_usb(hdev)) 808 + return -EINVAL; 809 + 810 + intf = to_usb_interface(hdev->dev.parent); 811 + ifnum = intf->cur_altsetting->desc.bInterfaceNumber; 806 812 807 813 pk = kzalloc(sizeof(*pk), GFP_KERNEL); 808 814 if (pk == NULL) {
+3
drivers/hid/hid-roccat-arvo.c
··· 344 344 { 345 345 int retval; 346 346 347 + if (!hid_is_usb(hdev)) 348 + return -EINVAL; 349 + 347 350 retval = hid_parse(hdev); 348 351 if (retval) { 349 352 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-isku.c
··· 324 324 { 325 325 int retval; 326 326 327 + if (!hid_is_usb(hdev)) 328 + return -EINVAL; 329 + 327 330 retval = hid_parse(hdev); 328 331 if (retval) { 329 332 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-kone.c
··· 749 749 { 750 750 int retval; 751 751 752 + if (!hid_is_usb(hdev)) 753 + return -EINVAL; 754 + 752 755 retval = hid_parse(hdev); 753 756 if (retval) { 754 757 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-koneplus.c
··· 431 431 { 432 432 int retval; 433 433 434 + if (!hid_is_usb(hdev)) 435 + return -EINVAL; 436 + 434 437 retval = hid_parse(hdev); 435 438 if (retval) { 436 439 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-konepure.c
··· 133 133 { 134 134 int retval; 135 135 136 + if (!hid_is_usb(hdev)) 137 + return -EINVAL; 138 + 136 139 retval = hid_parse(hdev); 137 140 if (retval) { 138 141 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-kovaplus.c
··· 501 501 { 502 502 int retval; 503 503 504 + if (!hid_is_usb(hdev)) 505 + return -EINVAL; 506 + 504 507 retval = hid_parse(hdev); 505 508 if (retval) { 506 509 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-lua.c
··· 160 160 { 161 161 int retval; 162 162 163 + if (!hid_is_usb(hdev)) 164 + return -EINVAL; 165 + 163 166 retval = hid_parse(hdev); 164 167 if (retval) { 165 168 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-pyra.c
··· 449 449 { 450 450 int retval; 451 451 452 + if (!hid_is_usb(hdev)) 453 + return -EINVAL; 454 + 452 455 retval = hid_parse(hdev); 453 456 if (retval) { 454 457 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-ryos.c
··· 141 141 { 142 142 int retval; 143 143 144 + if (!hid_is_usb(hdev)) 145 + return -EINVAL; 146 + 144 147 retval = hid_parse(hdev); 145 148 if (retval) { 146 149 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-roccat-savu.c
··· 113 113 { 114 114 int retval; 115 115 116 + if (!hid_is_usb(hdev)) 117 + return -EINVAL; 118 + 116 119 retval = hid_parse(hdev); 117 120 if (retval) { 118 121 hid_err(hdev, "parse failed\n");
+3
drivers/hid/hid-samsung.c
··· 152 152 int ret; 153 153 unsigned int cmask = HID_CONNECT_DEFAULT; 154 154 155 + if (!hid_is_usb(hdev)) 156 + return -EINVAL; 157 + 155 158 ret = hid_parse(hdev); 156 159 if (ret) { 157 160 hid_err(hdev, "parse failed\n");
+5 -1
drivers/hid/hid-sony.c
··· 3000 3000 sc->quirks = quirks; 3001 3001 hid_set_drvdata(hdev, sc); 3002 3002 sc->hdev = hdev; 3003 - usbdev = to_usb_device(sc->hdev->dev.parent->parent); 3004 3003 3005 3004 ret = hid_parse(hdev); 3006 3005 if (ret) { ··· 3042 3043 } 3043 3044 3044 3045 if (sc->quirks & (GHL_GUITAR_PS3WIIU | GHL_GUITAR_PS4)) { 3046 + if (!hid_is_usb(hdev)) 3047 + return -EINVAL; 3048 + 3049 + usbdev = to_usb_device(sc->hdev->dev.parent->parent); 3050 + 3045 3051 sc->ghl_urb = usb_alloc_urb(0, GFP_ATOMIC); 3046 3052 if (!sc->ghl_urb) 3047 3053 return -ENOMEM;
+3
drivers/hid/hid-thrustmaster.c
··· 274 274 int ret = 0; 275 275 struct tm_wheel *tm_wheel = NULL; 276 276 277 + if (!hid_is_usb(hdev)) 278 + return -EINVAL; 279 + 277 280 ret = hid_parse(hdev); 278 281 if (ret) { 279 282 hid_err(hdev, "parse failed with error %d\n", ret);
+3
drivers/hid/hid-uclogic-core.c
··· 164 164 struct uclogic_drvdata *drvdata = NULL; 165 165 bool params_initialized = false; 166 166 167 + if (!hid_is_usb(hdev)) 168 + return -EINVAL; 169 + 167 170 /* 168 171 * libinput requires the pad interface to be on a different node 169 172 * than the pen, so use QUIRK_MULTI_INPUT for all tablets.