Bluetooth: btusb: Fix short read errors in btusb_qca_send_vendor_req()

If btusb_qca_send_vendor_req() 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 btusb_qca_send_vendor_req() is called.

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>
This commit is contained in:
Greg Kroah-Hartman 2026-07-27 17:57:34 +02:00 committed by Luiz Augusto von Dentz
parent 0cc4b5649a
commit cac43d360c

View File

@ -3424,28 +3424,16 @@ static const char *qca_get_fw_subdirectory(const struct qca_version *ver)
static int btusb_qca_send_vendor_req(struct usb_device *udev, u8 request,
void *data, u16 size)
{
int pipe, err;
u8 *buf;
buf = kmalloc(size, GFP_KERNEL);
if (!buf)
return -ENOMEM;
int err;
/* Found some of USB hosts have IOT issues with ours so that we should
* not wait until HCI layer is ready.
*/
pipe = usb_rcvctrlpipe(udev, 0);
err = usb_control_msg(udev, pipe, request, USB_TYPE_VENDOR | USB_DIR_IN,
0, 0, buf, size, USB_CTRL_GET_TIMEOUT);
if (err < 0) {
err = usb_control_msg_recv(udev, 0, request, USB_TYPE_VENDOR | USB_DIR_IN,
0, 0, data, size, USB_CTRL_GET_TIMEOUT,
GFP_KERNEL);
if (err)
dev_err(&udev->dev, "Failed to access otp area (%d)", err);
goto done;
}
memcpy(data, buf, size);
done:
kfree(buf);
return err;
}
@ -3652,7 +3640,7 @@ static bool btusb_qca_need_patch(struct usb_device *udev)
struct qca_version ver;
if (btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
sizeof(ver)) < 0)
sizeof(ver)))
return false;
/* only low ROM versions need patches */
return !(le32_to_cpu(ver.rom_version) & ~0xffffU);
@ -3670,7 +3658,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
sizeof(ver));
if (err < 0)
if (err)
return err;
ver_rom = le32_to_cpu(ver.rom_version);
@ -3693,7 +3681,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
err = btusb_qca_send_vendor_req(udev, QCA_CHECK_STATUS, &status,
sizeof(status));
if (err < 0)
if (err)
return err;
if (!(status & QCA_PATCH_UPDATED)) {
@ -3704,7 +3692,7 @@ static int btusb_setup_qca(struct hci_dev *hdev)
err = btusb_qca_send_vendor_req(udev, QCA_GET_TARGET_VERSION, &ver,
sizeof(ver));
if (err < 0)
if (err)
return err;
btdata->qca_dump.fw_version = le32_to_cpu(ver.patch_version);