]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
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 09:03:48 +0000 (10:03 +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>
19 files changed:
drivers/hid/hid-chicony.c
drivers/hid/hid-corsair.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.c

index f04ed9aabc3f9fea0baf5b074acd83b6d07527c6..f11948ddf642e72c934167aa9e25571cb1ef7b7c 100644 (file)
@@ -61,8 +61,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 88be56321610acedd60b88c9f51176437f16a197..0f429034f205349ec2b6b3821a7a7db7913842d1 100644 (file)
@@ -551,7 +551,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 5eea6fe0d7bd8181082599a4ed0f05eda3268d5c..c3ecac13e62035a0ff761da030494e4d20d7e00f 100644 (file)
@@ -230,6 +230,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 ab9da597106fa5f49d4a12c07cbfff76ad33088d..2f8eb663974445f88d18e56e3d07a61b9a5385bb 100644 (file)
@@ -143,12 +143,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 78b3a0c767751534c16167846cfb3571641ce6af..27c08ddab0e1a4c098ff2d7bb55855212a46d997 100644 (file)
@@ -65,6 +65,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) },
@@ -86,6 +94,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 0fd9fc135f3d9ae39f6847461c982547931fa04e..c77e2303ba3e6d98dedb48696fa8103818eab994 100644 (file)
@@ -659,12 +659,18 @@ static int lg_event(struct hid_device *hdev, struct hid_field *field,
 
 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 cba15edd47c2a428de43cb1a67e122fd9ba11ecc..e708152d3ea039592f56a6f8a2ef0da51e1ee5da 100644 (file)
@@ -803,12 +803,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 1948208fe0380ad2b091038d369d6502de5d2a11..58ab1d878a949399f2c89bcf4b1169745dc9f266 100644 (file)
@@ -349,6 +349,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 bc62ed91e451cb51b70542cf39808aa0b58e68c6..529dcc51a2beb7736c09f4742bc9f8e56226285a 100644 (file)
@@ -329,6 +329,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 6c2b821c8d8b5eb081f84b62534684de4547f1a0..227504764c2f8d39ddeb2b10160e7cb05fb44842 100644 (file)
@@ -756,6 +756,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 5e99fcdc71b9cf0631cb7adcc8b61a22c36ae728..3403cc528f4e9fd54b3dffef3f432a0dc1831785 100644 (file)
@@ -438,6 +438,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 07de2f9014c67f914209a5dfc08185892955bd79..ef9508822e5f0b788efefa430c1d0c64e450e252 100644 (file)
@@ -136,6 +136,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 1073c0d1fae596d306b92abd0b7ebb76f5af9cbd..549b15ef79b946c547a52238d9d55d4c304f8765 100644 (file)
@@ -508,6 +508,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 65e2e76bf2fe559cc5392d9848bde77fd6047ef1..6a8dc17cddf206985dc5e0a6596ab4d5cb4b4455 100644 (file)
@@ -163,6 +163,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 47d7e74231e5a3245461eb5f34a3acecc5bd67d1..4fed4b899da25e7ba66a0e8a9767feb3cadaad32 100644 (file)
@@ -457,6 +457,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 47cc8f30ff6d4fa4784dd96f7b31d2de8ecb9944..fda4a396a12e82a1e795f1c1c488f182723f51e9 100644 (file)
@@ -144,6 +144,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 6dbf6e04dce75c82dd32109d46b330d5a60cd043..0230fb54f08a5c44757712b2dcfd497eddd0554d 100644 (file)
@@ -116,6 +116,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 7cbb067d4a9e399f62b57b54830d384956037cbc..89bb2260367f3ce3c77bf73873b9b0bcc6ef111c 100644 (file)
@@ -157,6 +157,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 85ac43517e3ffc3232461f54d43054cd36a39a29..4cf0aaad56198b327250b9c515002d16c113e5e1 100644 (file)
@@ -795,6 +795,9 @@ static int uclogic_tablet_enable(struct hid_device *hdev)
        __u8 *p;
        s32 v;
 
+       if (!hid_is_usb(hdev))
+               return -EINVAL;
+
        /*
         * Read string descriptor containing tablet parameters. The specific
         * string descriptor and data were discovered by sniffing the Windows