--- /dev/null
+From 2e4edfa1e2bd821a317e7d006517dcf2f3fac68d Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Tue, 30 Apr 2024 19:07:39 +0200
+Subject: Bluetooth: qca: add missing firmware sanity checks
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 2e4edfa1e2bd821a317e7d006517dcf2f3fac68d upstream.
+
+Add the missing sanity checks when parsing the firmware files before
+downloading them to avoid accessing and corrupting memory beyond the
+vmalloced buffer.
+
+Fixes: 83e81961ff7e ("Bluetooth: btqca: Introduce generic QCA ROME support")
+Cc: stable@vger.kernel.org # 4.10
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bluetooth/btqca.c | 38 ++++++++++++++++++++++++++++++++------
+ 1 file changed, 32 insertions(+), 6 deletions(-)
+
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -182,9 +182,10 @@ int qca_send_pre_shutdown_cmd(struct hci
+ }
+ EXPORT_SYMBOL_GPL(qca_send_pre_shutdown_cmd);
+
+-static void qca_tlv_check_data(struct hci_dev *hdev,
++static int qca_tlv_check_data(struct hci_dev *hdev,
+ struct qca_fw_config *config,
+- u8 *fw_data, enum qca_btsoc_type soc_type)
++ u8 *fw_data, size_t fw_size,
++ enum qca_btsoc_type soc_type)
+ {
+ const u8 *data;
+ u32 type_len;
+@@ -200,6 +201,9 @@ static void qca_tlv_check_data(struct hc
+
+ switch (config->type) {
+ case ELF_TYPE_PATCH:
++ if (fw_size < 7)
++ return -EINVAL;
++
+ config->dnld_mode = QCA_SKIP_EVT_VSE_CC;
+ config->dnld_type = QCA_SKIP_EVT_VSE_CC;
+
+@@ -208,6 +212,9 @@ static void qca_tlv_check_data(struct hc
+ bt_dev_dbg(hdev, "File version : 0x%x", fw_data[6]);
+ break;
+ case TLV_TYPE_PATCH:
++ if (fw_size < sizeof(struct tlv_type_hdr) + sizeof(struct tlv_type_patch))
++ return -EINVAL;
++
+ tlv = (struct tlv_type_hdr *)fw_data;
+ type_len = le32_to_cpu(tlv->type_len);
+ tlv_patch = (struct tlv_type_patch *)tlv->data;
+@@ -247,6 +254,9 @@ static void qca_tlv_check_data(struct hc
+ break;
+
+ case TLV_TYPE_NVM:
++ if (fw_size < sizeof(struct tlv_type_hdr))
++ return -EINVAL;
++
+ tlv = (struct tlv_type_hdr *)fw_data;
+
+ type_len = le32_to_cpu(tlv->type_len);
+@@ -255,17 +265,26 @@ static void qca_tlv_check_data(struct hc
+ BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
+ BT_DBG("Length\t\t : %d bytes", length);
+
++ 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.
+@@ -281,6 +300,9 @@ static void qca_tlv_check_data(struct hc
+ break;
+
+ case EDL_TAG_ID_DEEP_SLEEP:
++ if (tag_len < 1)
++ return -EINVAL;
++
+ /* Sleep enable mask
+ * enabling deep sleep feature on controller.
+ */
+@@ -289,14 +311,16 @@ static void qca_tlv_check_data(struct hc
+ 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,
+@@ -446,7 +470,9 @@ static int qca_download_firmware(struct
+ memcpy(data, fw->data, size);
+ release_firmware(fw);
+
+- qca_tlv_check_data(hdev, config, data, soc_type);
++ ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
++ if (ret)
++ return ret;
+
+ segment = data;
+ remain = size;
--- /dev/null
+From 40d442f969fb1e871da6fca73d3f8aef1f888558 Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Wed, 1 May 2024 08:37:40 +0200
+Subject: Bluetooth: qca: fix firmware check error path
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit 40d442f969fb1e871da6fca73d3f8aef1f888558 upstream.
+
+A recent commit fixed the code that parses the firmware files before
+downloading them to the controller but introduced a memory leak in case
+the sanity checks ever fail.
+
+Make sure to free the firmware buffer before returning on errors.
+
+Fixes: f905ae0be4b7 ("Bluetooth: qca: add missing firmware sanity checks")
+Cc: stable@vger.kernel.org # 4.19
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bluetooth/btqca.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -492,7 +492,7 @@ static int qca_download_firmware(struct
+
+ ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
+ if (ret)
+- return ret;
++ goto out;
+
+ segment = data;
+ remain = size;
--- /dev/null
+From a112d3c72a227f2edbb6d8094472cc6e503e52af Mon Sep 17 00:00:00 2001
+From: Johan Hovold <johan+linaro@kernel.org>
+Date: Tue, 30 Apr 2024 19:07:40 +0200
+Subject: Bluetooth: qca: fix NVM configuration parsing
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+commit a112d3c72a227f2edbb6d8094472cc6e503e52af upstream.
+
+The NVM configuration files used by WCN3988 and WCN3990/1/8 have two
+sets of configuration tags that are enclosed by a type-length header of
+type four which the current parser fails to account for.
+
+Instead the driver happily parses random data as if it were valid tags,
+something which can lead to the configuration data being corrupted if it
+ever encounters the words 0x0011 or 0x001b.
+
+As is clear from commit b63882549b2b ("Bluetooth: btqca: Fix the NVM
+baudrate tag offcet for wcn3991") the intention has always been to
+process the configuration data also for WCN3991 and WCN3998 which
+encodes the baud rate at a different offset.
+
+Fix the parser so that it can handle the WCN3xxx configuration files,
+which has an enclosing type-length header of type four and two sets of
+TLV tags enclosed by a type-length header of type two and three,
+respectively.
+
+Note that only the first set, which contains the tags the driver is
+currently looking for, will be parsed for now.
+
+With the parser fixed, the software in-band sleep bit will now be set
+for WCN3991 and WCN3998 (as it is for later controllers) and the default
+baud rate 3200000 may be updated by the driver also for WCN3xxx
+controllers.
+
+Notably the deep-sleep feature bit is already set by default in all
+configuration files in linux-firmware.
+
+Fixes: 4219d4686875 ("Bluetooth: btqca: Add wcn3990 firmware download support.")
+Cc: stable@vger.kernel.org # 4.19
+Cc: Matthias Kaehlcke <mka@chromium.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/bluetooth/btqca.c | 24 ++++++++++++++++++++++--
+ 1 file changed, 22 insertions(+), 2 deletions(-)
+
+--- a/drivers/bluetooth/btqca.c
++++ b/drivers/bluetooth/btqca.c
+@@ -195,6 +195,7 @@ static int qca_tlv_check_data(struct hci
+ struct tlv_type_patch *tlv_patch;
+ struct tlv_type_nvm *tlv_nvm;
+ uint8_t nvm_baud_rate = config->user_baud_rate;
++ u8 type;
+
+ config->dnld_mode = QCA_SKIP_EVT_NONE;
+ config->dnld_type = QCA_SKIP_EVT_NONE;
+@@ -260,11 +261,30 @@ static int qca_tlv_check_data(struct hci
+ tlv = (struct tlv_type_hdr *)fw_data;
+
+ type_len = le32_to_cpu(tlv->type_len);
+- length = (type_len >> 8) & 0x00ffffff;
++ length = type_len >> 8;
++ type = type_len & 0xff;
+
+- BT_DBG("TLV Type\t\t : 0x%x", type_len & 0x000000ff);
++ /* Some NVM files have more than one set of tags, only parse
++ * the first set when it has type 2 for now. When there is
++ * more than one set there is an enclosing header of type 4.
++ */
++ if (type == 4) {
++ if (fw_size < 2 * sizeof(struct tlv_type_hdr))
++ return -EINVAL;
++
++ tlv++;
++
++ type_len = le32_to_cpu(tlv->type_len);
++ length = type_len >> 8;
++ type = type_len & 0xff;
++ }
++
++ BT_DBG("TLV Type\t\t : 0x%x", type);
+ BT_DBG("Length\t\t : %d bytes", length);
+
++ if (type != 2)
++ break;
++
+ if (fw_size < length + (tlv->data - fw_data))
+ return -EINVAL;
+
net-fix-out-of-bounds-access-in-ops_init.patch
hwmon-pmbus-ucd9000-increase-delay-from-250-to-500us.patch
regulator-core-fix-debugfs-creation-regression.patch
+bluetooth-qca-add-missing-firmware-sanity-checks.patch
+bluetooth-qca-fix-nvm-configuration-parsing.patch
+bluetooth-qca-fix-firmware-check-error-path.patch