diff --git a/drivers/bluetooth/hci_aml.c b/drivers/bluetooth/hci_aml.c index 959d9e67b669..067fbf278b44 100644 --- a/drivers/bluetooth/hci_aml.c +++ b/drivers/bluetooth/hci_aml.c @@ -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)