Unverified Commit b1a66435 authored by openeuler-ci-bot's avatar openeuler-ci-bot Committed by Gitee
Browse files

!10951 Fix CVE-2024-36880

Merge Pull Request from: @ci-robot 
 
PR sync from: Yi Yang <yiyang13@huawei.com>
https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/2NH2QCOWX6SJ22MWVNWDUCE24GOPIRKW/ 
Fix CVE-2024-36880 for OLK-5.10

Johan Hovold (2):
  Bluetooth: qca: add missing firmware sanity checks
  Bluetooth: qca: fix firmware check error path


-- 
2.25.1
 
https://gitee.com/src-openeuler/kernel/issues/I9U3C7 
 
Link:https://gitee.com/openeuler/kernel/pulls/10951

 

Reviewed-by: default avatarYang Yingliang <yangyingliang@huawei.com>
Signed-off-by: default avatarYang Yingliang <yangyingliang@huawei.com>
parents 6b96457d 55e8f460
Loading
Loading
Loading
Loading
+30 −6
Original line number Diff line number Diff line
@@ -142,8 +142,10 @@ int qca_send_pre_shutdown_cmd(struct hci_dev *hdev)
}
EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);

static void qca_tlv_check_data(struct qca_fw_config *config,
		u8 *fw_data, enum qca_btsoc_type soc_type)
static int qca_tlv_check_data(struct hci_dev *hdev,
			       struct qca_fw_config *config,
			       u8 *fw_data, size_t fw_size,
			       enum qca_btsoc_type soc_type)
{
	const u8 *data;
	u32 type_len;
@@ -167,6 +169,9 @@ static void qca_tlv_check_data(struct qca_fw_config *config,

	switch (config->type) {
	case TLV_TYPE_PATCH:
		if (fw_size < sizeof(struct tlv_type_hdr) + sizeof(struct tlv_type_patch))
			return -EINVAL;

		tlv_patch = (struct tlv_type_patch *)tlv->data;

		/* For Rome version 1.1 to 3.1, all segment commands
@@ -203,17 +208,29 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
		break;

	case TLV_TYPE_NVM:
		if (fw_size < sizeof(struct tlv_type_hdr))
			return -EINVAL;

		if (fw_size < length + (tlv->data - fw_data))
			return -EINVAL;

		idx = 0;
		data = tlv->data;
		while (idx < length) {
		while (idx < length - sizeof(struct tlv_type_nvm)) {
			tlv_nvm = (struct tlv_type_nvm *)(data + idx);

			tag_id = le16_to_cpu(tlv_nvm->tag_id);
			tag_len = le16_to_cpu(tlv_nvm->tag_len);

			if (length < idx + sizeof(struct tlv_type_nvm) + tag_len)
				return -EINVAL;

			/* Update NVM tags as needed */
			switch (tag_id) {
			case EDL_TAG_ID_HCI:
				if (tag_len < 3)
					return -EINVAL;

				/* HCI transport layer parameters
				 * enabling software inband sleep
				 * onto controller side.
@@ -229,6 +246,9 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
				break;

			case EDL_TAG_ID_DEEP_SLEEP:
				if (tag_len < 1)
					return -EINVAL;

				/* Sleep enable mask
				 * enabling deep sleep feature on controller.
				 */
@@ -237,14 +257,16 @@ static void qca_tlv_check_data(struct qca_fw_config *config,
				break;
			}

			idx += (sizeof(u16) + sizeof(u16) + 8 + tag_len);
			idx += sizeof(struct tlv_type_nvm) + tag_len;
		}
		break;

	default:
		BT_ERR("Unknown TLV type %d", config->type);
		break;
		return -EINVAL;
	}

	return 0;
}

static int qca_tlv_send_segment(struct hci_dev *hdev, int seg_size,
@@ -375,7 +397,9 @@ static int qca_download_firmware(struct hci_dev *hdev,
	memcpy(data, fw->data, size);
	release_firmware(fw);

	qca_tlv_check_data(config, data, soc_type);
	ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
	if (ret)
		goto out;

	segment = data;
	remain = size;