]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.15-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 May 2024 15:36:04 +0000 (17:36 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 13 May 2024 15:36:04 +0000 (17:36 +0200)
added patches:
bluetooth-qca-add-missing-firmware-sanity-checks.patch
bluetooth-qca-fix-firmware-check-error-path.patch
bluetooth-qca-fix-nvm-configuration-parsing.patch

queue-5.15/bluetooth-qca-add-missing-firmware-sanity-checks.patch [new file with mode: 0644]
queue-5.15/bluetooth-qca-fix-firmware-check-error-path.patch [new file with mode: 0644]
queue-5.15/bluetooth-qca-fix-nvm-configuration-parsing.patch [new file with mode: 0644]
queue-5.15/series

diff --git a/queue-5.15/bluetooth-qca-add-missing-firmware-sanity-checks.patch b/queue-5.15/bluetooth-qca-add-missing-firmware-sanity-checks.patch
new file mode 100644 (file)
index 0000000..a30a80f
--- /dev/null
@@ -0,0 +1,135 @@
+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;
diff --git a/queue-5.15/bluetooth-qca-fix-firmware-check-error-path.patch b/queue-5.15/bluetooth-qca-fix-firmware-check-error-path.patch
new file mode 100644 (file)
index 0000000..ad976f8
--- /dev/null
@@ -0,0 +1,35 @@
+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;
diff --git a/queue-5.15/bluetooth-qca-fix-nvm-configuration-parsing.patch b/queue-5.15/bluetooth-qca-fix-nvm-configuration-parsing.patch
new file mode 100644 (file)
index 0000000..b3c3b04
--- /dev/null
@@ -0,0 +1,91 @@
+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;
index 01c8403b90f3b443577efed846769b2b3f059b14..8089fc2bde91a4624c430533b246d3e1537c6913 100644 (file)
@@ -169,3 +169,6 @@ drm-vmwgfx-fix-invalid-reads-in-fence-signaled-events.patch
 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