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)
committerPDO SCM Team <hudsoncm@motorola.com>
Tue, 14 Jun 2022 07:00:15 +0000 (02:00 -0500)
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.

Mot-CRs-fixed: (CR)
CVE-Fixed: CVE-2022-20132
Bug: 188677105

Change-Id: Ic6224ff0703c5784dc81f23de9b0c845f3af171b
Cc: Jiri Kosina <j(CR)@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>
Signed-off-by: Gajjala Chakradhar <gajjalac@motorola.com>
Reviewed-on: https://gerrit.mot.com/2276111
SME-Granted: SME Approvals Granted
SLTApproved: Slta Waiver
Tested-by: Jira Key
Reviewed-by: Xiangpo Zhao <zhaoxp3@motorola.com>
Submit-Approved: Jira Key

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 397a789a41be942a24a8673767da277869a9b670..218f0e090f638e48b587f70e5bf7e946d9ba0ce4 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 9ba5d98a118042a52dc40b895c3b2e8df67c0b39..d8cf08b6b31c65dab3ef72dd1ea3a48377a59dda 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 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 6e1a4a4fc0c109f7bf60083963d8c239a10939cf..a64f73f9811f604a0fe24017137976d2be8f2017 100644 (file)
@@ -138,12 +138,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 52026dc94d5c4b0306ce585be293cbe2cb1910d9..e752112118036b58a350d1762edd17ab415a3de9 100644 (file)
@@ -714,12 +714,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 49c4bd34b3c508259fae68e5714d17d7b0a83b70..cdc1c35bdbe58b17933518cf97d7a0fcc232faf4 100644 (file)
@@ -795,12 +795,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 329c5d1270f94331e609b01d48361e4575772bab..fb545a11214f05e6b6cce667dc1f5fa28b39a5e0 100644 (file)
@@ -347,6 +347,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 02db537f8f3eaf79e50ed9126559735d7c6e388d..c07a7ea8a6873174fda73aade07c07694eca0f53 100644 (file)
@@ -327,6 +327,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 bf4675a2739657cf735d74aeea2477ef181fe090..e102e06ad14c16ea0fab5cf19ebbb174835fa0ff 100644 (file)
@@ -743,6 +743,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 09e8fc72aa1d4a683f2e467baf3c9a5d5abe6518..b63de4c5b5dd38bac877141d04f45ba7fd3117ec 100644 (file)
@@ -434,6 +434,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 317c9c2c0a7ce9d019ece767a140a451ad249379..6256c211398a199fd29413cf285392df109528ba 100644 (file)
@@ -504,6 +504,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 ac1a7313e25964c2e9922d2b9d43a71f41c1c40b..13ae2a7d176d34acb196a960d405d3837246ac54 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 b30aa7b82bf8729def53a7a0632ad8100d57e67f..027aa9d0ec1f27b89ad289f9a0661a91e63e3600 100644 (file)
@@ -452,6 +452,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 e3e6e5c893cc05e0c934c8c9f505de9fdd06e26a..bd9363538a323838ae462603d6d0c7f4d7e96b5e 100644 (file)
@@ -791,6 +791,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