Bluetooth: hci_aml: validate firmware segment lengths

aml_download_firmware() reads two lengths from the firmware header and
uses them to build pointers before checking that the header and segment
data are present. A truncated or inconsistent firmware image can make
the driver read past firmware->data while constructing TCI commands.

Reject images shorter than the header and ensure that the ICCM and DCCM
ranges fit within the loaded firmware before downloading either segment.

Fixes: 37bac77e46 ("Bluetooth: hci_uart: Add support for Amlogic HCI UART")
Cc: stable@vger.kernel.org
Signed-off-by: Laxman Acharya Padhya <acharyalaxman8848@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
This commit is contained in:
Laxman Acharya Padhya 2026-07-30 18:05:28 +05:45 committed by Luiz Augusto von Dentz
parent ad28b52441
commit 2bf6b9baca

View File

@ -247,7 +247,7 @@ static int aml_download_firmware(struct hci_dev *hdev, const char *fw_name)
struct hci_uart *hu = hci_get_drvdata(hdev);
struct aml_serdev *amldev = serdev_device_get_drvdata(hu->serdev);
const struct firmware *firmware = NULL;
struct aml_fw_len *fw_len = NULL;
const struct aml_fw_len *fw_len = NULL;
u8 *iccm_start = NULL, *dccm_start = NULL;
u32 iccm_len, dccm_len;
u32 value = 0;
@ -281,7 +281,21 @@ static int aml_download_firmware(struct hci_dev *hdev, const char *fw_name)
goto exit;
}
fw_len = (struct aml_fw_len *)firmware->data;
if (firmware->size < sizeof(*fw_len)) {
bt_dev_err(hdev, "Firmware is too small for its header");
ret = -EINVAL;
goto exit;
}
fw_len = (const struct aml_fw_len *)firmware->data;
if (fw_len->iccm_len < amldev->aml_dev_data->iccm_offset ||
fw_len->iccm_len > firmware->size - sizeof(*fw_len) ||
fw_len->dccm_len > firmware->size - sizeof(*fw_len) -
fw_len->iccm_len) {
bt_dev_err(hdev, "Invalid firmware segment lengths");
ret = -EINVAL;
goto exit;
}
/* Download ICCM */
iccm_start = (u8 *)(firmware->data) + sizeof(struct aml_fw_len)