HID: check for valid USB device for many HID drivers
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 1 Dec 2021 18:35:03 +0000 (19:35 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Tue, 14 Dec 2021 10:32:34 +0000 (11:32 +0100)
commit 93020953d0fa7035fd036ad87a47ae2b7aa4ae33 upstream.

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
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
20 files changed:
drivers/hid/hid-chicony.c
drivers/hid/hid-corsair.c
drivers/hid/hid-elan.c
drivers/hid/hid-elo.c
drivers/hid/hid-holtek-kbd.c
drivers/hid/hid-holtek-mouse.c
drivers/hid/hid-lg.c
drivers/hid/hid-prodikeys.c
drivers/hid/hid-roccat-arvo.c
drivers/hid/hid-roccat-isku.c
drivers/hid/hid-roccat-kone.c
drivers/hid/hid-roccat-koneplus.c
drivers/hid/hid-roccat-konepure.c
drivers/hid/hid-roccat-kovaplus.c
drivers/hid/hid-roccat-lua.c
drivers/hid/hid-roccat-pyra.c
drivers/hid/hid-roccat-ryos.c
drivers/hid/hid-roccat-savu.c
drivers/hid/hid-samsung.c
drivers/hid/hid-uclogic-core.c

index 3f0ed6a95223499e14cf7f85608676945af5474b..e19e2b59733968d4b1efddf3f0551dd6d722c3d3 100644 (file)
@@ -58,8 +58,12 @@ static int ch_input_mapping(struct hid_device *hdev, struct hid_input *hi,
 static __u8 *ch_switch12_report_fixup(struct hid_device *hdev, __u8 *rdesc,
                unsigned int *rsize)
 {
-       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-       
+       struct usb_interface *intf;
+
+       if (!hid_is_usb(hdev))
+               return rdesc;
+
+       intf = to_usb_interface(hdev->dev.parent);
        if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
                /* Change usage maximum and logical maximum from 0x7fff to
                 * 0x2fff, so they don't exceed HID_MAX_USAGES */
index 902a60e249ed268489b22809d6c1340d638ed954..8c895c820b672772340ec17d34dc60e198eb56a5 100644 (file)
@@ -553,7 +553,12 @@ static int corsair_probe(struct hid_device *dev, const struct hid_device_id *id)
        int ret;
        unsigned long quirks = id->driver_data;
        struct corsair_drvdata *drvdata;
-       struct usb_interface *usbif = to_usb_interface(dev->dev.parent);
+       struct usb_interface *usbif;
+
+       if (!hid_is_usb(dev))
+               return -EINVAL;
+
+       usbif = to_usb_interface(dev->dev.parent);
 
        drvdata = devm_kzalloc(&dev->dev, sizeof(struct corsair_drvdata),
                               GFP_KERNEL);
index dae193749d443490390255df260fda27edc3e531..0e8f424025fea6eb1f3b3f3c25211f90faea1c47 100644 (file)
@@ -50,7 +50,7 @@ struct elan_drvdata {
 
 static int is_not_elan_touchpad(struct hid_device *hdev)
 {
-       if (hdev->bus == BUS_USB) {
+       if (hid_is_usb(hdev)) {
                struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
 
                return (intf->altsetting->desc.bInterfaceNumber !=
index 0d22713a38742b23465f0dbe216d2107c25edc52..2876cb6a7dcab0b22791f217ee1bd21e366ad756 100644 (file)
@@ -229,6 +229,9 @@ static int elo_probe(struct hid_device *hdev, const struct hid_device_id *id)
        struct elo_priv *priv;
        int ret;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (!priv)
                return -ENOMEM;
index 0a38e8e9bc783051f8bc634cff597885fdcb6161..403506b9697e75a3c2ac9042299bac8e1e2d342e 100644 (file)
@@ -140,12 +140,17 @@ static int holtek_kbd_input_event(struct input_dev *dev, unsigned int type,
 static int holtek_kbd_probe(struct hid_device *hdev,
                const struct hid_device_id *id)
 {
-       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-       int ret = hid_parse(hdev);
+       struct usb_interface *intf;
+       int ret;
+
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
 
+       ret = hid_parse(hdev);
        if (!ret)
                ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 
+       intf = to_usb_interface(hdev->dev.parent);
        if (!ret && intf->cur_altsetting->desc.bInterfaceNumber == 1) {
                struct hid_input *hidinput;
                list_for_each_entry(hidinput, &hdev->inputs, list) {
index 195b735b001d03d56f366b63b0ceb14b2d5d7552..b7172c48ef9f0898ec5b6d0596d808aa4908b26c 100644 (file)
@@ -62,6 +62,14 @@ static __u8 *holtek_mouse_report_fixup(struct hid_device *hdev, __u8 *rdesc,
        return rdesc;
 }
 
+static int holtek_mouse_probe(struct hid_device *hdev,
+                             const struct hid_device_id *id)
+{
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+       return 0;
+}
+
 static const struct hid_device_id holtek_mouse_devices[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_HOLTEK_ALT,
                        USB_DEVICE_ID_HOLTEK_ALT_MOUSE_A067) },
@@ -83,6 +91,7 @@ static struct hid_driver holtek_mouse_driver = {
        .name = "holtek_mouse",
        .id_table = holtek_mouse_devices,
        .report_fixup = holtek_mouse_report_fixup,
+       .probe = holtek_mouse_probe,
 };
 
 module_hid_driver(holtek_mouse_driver);
index 0dc7cdfc56f77470b8a8c853ebd0077b4955853c..2c7e7c089bf990f77be33ea14df06f3a242a71e2 100644 (file)
@@ -769,12 +769,18 @@ static int lg_raw_event(struct hid_device *hdev, struct hid_report *report,
 
 static int lg_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
-       struct usb_interface *iface = to_usb_interface(hdev->dev.parent);
-       __u8 iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+       struct usb_interface *iface;
+       __u8 iface_num;
        unsigned int connect_mask = HID_CONNECT_DEFAULT;
        struct lg_drv_data *drv_data;
        int ret;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
+       iface = to_usb_interface(hdev->dev.parent);
+       iface_num = iface->cur_altsetting->desc.bInterfaceNumber;
+
        /* G29 only work with the 1st interface */
        if ((hdev->product == USB_DEVICE_ID_LOGITECH_G29_WHEEL) &&
            (iface_num != 0)) {
index 2666af02d5c1a11f1a32f098eecb61ddc458cf0a..e4e9471d0f1e92d9b17a3c0f90d1b7dc0ceeb7de 100644 (file)
@@ -798,12 +798,18 @@ static int pk_raw_event(struct hid_device *hdev, struct hid_report *report,
 static int pk_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int ret;
-       struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
-       unsigned short ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+       struct usb_interface *intf;
+       unsigned short ifnum;
        unsigned long quirks = id->driver_data;
        struct pk_device *pk;
        struct pcmidi_snd *pm = NULL;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
+       intf = to_usb_interface(hdev->dev.parent);
+       ifnum = intf->cur_altsetting->desc.bInterfaceNumber;
+
        pk = kzalloc(sizeof(*pk), GFP_KERNEL);
        if (pk == NULL) {
                hid_err(hdev, "can't alloc descriptor\n");
index ffcd444ae2ba6e01d2a6aebebb7dd876b47ae6a9..4b18e1a4fc7acf2c7d80ac66d8b7bffe8137984f 100644 (file)
@@ -344,6 +344,9 @@ static int arvo_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index ce5f22519956acf91527d390d99f3ff35a424420..e95d59cd8d075dc82716fb47a4193286bd0c2b09 100644 (file)
@@ -324,6 +324,9 @@ static int isku_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 1ca64481145ee4dd5446d41d66b6bb90d249b82e..e8522eacf797342690abf1dc64169928842b03da 100644 (file)
@@ -749,6 +749,9 @@ static int kone_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 0316edf8c5bb44e4d72e5a9a6ab858b53d0eefbb..1896c69ea512f787b264ed27f82f13d813fd82ea 100644 (file)
@@ -431,6 +431,9 @@ static int koneplus_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 5248b3c7cf7859abbd62dab6fed53e88d1b37773..cf8eeb33a12571bf47c2c57118ff7935909cd865 100644 (file)
@@ -133,6 +133,9 @@ static int konepure_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 960012881570569df2d31c368b33c06f4f67ba4d..6fb9b9563769dfbcc1cfc521c1f113feb442d411 100644 (file)
@@ -501,6 +501,9 @@ static int kovaplus_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 4a88a76d5c62293b890c56093d469cf6687a7baf..d5ddf0d68346b2c147f3c888badb77c06d77f46c 100644 (file)
@@ -160,6 +160,9 @@ static int lua_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 989927defe8db84d6d1916424a9c1d50fc5c3911..4fcc8e7d276f228cb2c29f99df8e6d5db9eef119 100644 (file)
@@ -449,6 +449,9 @@ static int pyra_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 3956a6c9c5217efdb88e25c918f3598a9e5e61fb..5bf1971a2b14d83c6388d3d1e9541617ff415fa6 100644 (file)
@@ -141,6 +141,9 @@ static int ryos_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 818701f7a028178b2c565e1506a28360c1deee08..a784bb4ee6512d8b39a0ede9a653b29cf901bf5d 100644 (file)
@@ -113,6 +113,9 @@ static int savu_probe(struct hid_device *hdev,
 {
        int retval;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        retval = hid_parse(hdev);
        if (retval) {
                hid_err(hdev, "parse failed\n");
index 2e1c31156eca046417d65d76d0e8aa847719ecb3..cf5992e97094003628a4aaacbded99a9f3603a10 100644 (file)
@@ -152,6 +152,9 @@ static int samsung_probe(struct hid_device *hdev,
        int ret;
        unsigned int cmask = HID_CONNECT_DEFAULT;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        ret = hid_parse(hdev);
        if (ret) {
                hid_err(hdev, "parse failed\n");
index 8e9c9e646cb7dd45d2e84c299e8c34b0936898fd..4edb241957040209672137bc513efa3abf13d970 100644 (file)
@@ -164,6 +164,9 @@ static int uclogic_probe(struct hid_device *hdev,
        struct uclogic_drvdata *drvdata = NULL;
        bool params_initialized = false;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        /*
         * libinput requires the pad interface to be on a different node
         * than the pen, so use QUIRK_MULTI_INPUT for all tablets.