]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
Bluetooth: btmtk: Fix short read errors in btmtk_usb_uhw_reg_read()
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 27 Jul 2026 15:57:32 +0000 (17:57 +0200)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Tue, 28 Jul 2026 20:13:48 +0000 (16:13 -0400)
If btmtk_usb_uhw_reg_read() gets a "short" read from a device, it will
accidentally treat that as a "real" read and populate the returned value
with some unknown and probably totally invalid data.

Fix this logic error up by calling usb_control_msg_recv() which
guarantees a "full" read happens, and then simplify the error checking
for when btmtk_usb_uhw_reg_read() is called.

Note, one caller of btmtk_usb_uhw_reg_read() does not check the return
value, but as we pre-initialize the return value as 0, an incorrect read
will not do anything wrong.

Cc: stable <stable@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btmtk.c

index 02a96342e964f0c45e6c5d722589abe10760959b..6f060e4433db188fb23a86262aff39c5e2f3edaf 100644 (file)
@@ -804,30 +804,24 @@ static int btmtk_usb_uhw_reg_write(struct hci_dev *hdev, u32 reg, u32 val)
 static int btmtk_usb_uhw_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
 {
        struct btmtk_data *data = hci_get_priv(hdev);
-       int pipe, err;
-       void *buf;
-
-       buf = kzalloc(4, GFP_KERNEL);
-       if (!buf)
-               return -ENOMEM;
+       u8 buf[sizeof(u32)];
+       int err;
 
-       pipe = usb_rcvctrlpipe(data->udev, 0);
-       err = usb_control_msg(data->udev, pipe, 0x01,
-                             0xDE,
-                             reg >> 16, reg & 0xffff,
-                             buf, 4, USB_CTRL_GET_TIMEOUT);
-       if (err < 0) {
+       *val = 0;
+       err = usb_control_msg_recv(data->udev, 0, 0x01,
+                                  0xDE,
+                                  reg >> 16, reg & 0xffff,
+                                  buf, sizeof(buf), USB_CTRL_GET_TIMEOUT,
+                                  GFP_KERNEL);
+       if (err) {
                bt_dev_err(hdev, "Failed to read uhw reg(%d)", err);
-               goto err_free_buf;
+               return err;
        }
 
        *val = get_unaligned_le32(buf);
        bt_dev_dbg(hdev, "reg=%x, value=0x%08x", reg, *val);
 
-err_free_buf:
-       kfree(buf);
-
-       return err;
+       return 0;
 }
 
 static int btmtk_usb_reg_read(struct hci_dev *hdev, u32 reg, u32 *val)
@@ -877,7 +871,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
 
        if (dev_id == 0x7922) {
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
-               if (err < 0)
+               if (err)
                        return err;
                val |= 0x00002020;
                err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
@@ -887,7 +881,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
-               if (err < 0)
+               if (err)
                        return err;
                val |= BIT(0);
                err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, val);
@@ -896,14 +890,14 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                msleep(100);
        } else if (dev_id == 0x7925 || dev_id == 0x6639) {
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
-               if (err < 0)
+               if (err)
                        return err;
                val |= (1 << 5);
                err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
-               if (err < 0)
+               if (err)
                        return err;
                val &= 0xFFFF00FF;
                val |= (1 << 13);
@@ -914,7 +908,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_RESET_REG_CONNV3, &val);
-               if (err < 0)
+               if (err)
                        return err;
                val |= (1 << 0);
                err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_RESET_REG_CONNV3, val);
@@ -924,13 +918,13 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
-               if (err < 0)
+               if (err)
                        return err;
                err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
-               if (err < 0)
+               if (err)
                        return err;
                msleep(100);
        } else {
@@ -940,7 +934,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_WDT_STATUS, &val);
-               if (err < 0)
+               if (err)
                        return err;
                /* Reset the bluetooth chip via USB interface. */
                err = btmtk_usb_uhw_reg_write(hdev, MTK_BT_SUBSYS_RST, 1);
@@ -950,13 +944,13 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT, &val);
-               if (err < 0)
+               if (err)
                        return err;
                err = btmtk_usb_uhw_reg_write(hdev, MTK_UDMA_INT_STA_BT1, 0x000000FF);
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_UDMA_INT_STA_BT1, &val);
-               if (err < 0)
+               if (err)
                        return err;
                /* MT7921 need to delay 20ms between toggle reset bit */
                msleep(20);
@@ -964,7 +958,7 @@ int btmtk_usb_subsys_reset(struct hci_dev *hdev, u32 dev_id)
                if (err < 0)
                        return err;
                err = btmtk_usb_uhw_reg_read(hdev, MTK_BT_SUBSYS_RST, &val);
-               if (err < 0)
+               if (err)
                        return err;
        }