Bluetooth: qca: fix info leak when fetching fw build id
authorJohan Hovold <johan+linaro@kernel.org>
Wed, 1 May 2024 12:34:52 +0000 (14:34 +0200)
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>
Fri, 3 May 2024 17:05:32 +0000 (13:05 -0400)
Add the missing sanity checks and move the 255-byte build-id buffer off
the stack to avoid leaking stack data through debugfs in case the
build-info reply is malformed.

Fixes: c0187b0bd3e9 ("Bluetooth: btqca: Add support to read FW build version for WCN3991 BTSoC")
Cc: stable@vger.kernel.org # 5.12
Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
drivers/bluetooth/btqca.c
drivers/bluetooth/btqca.h

index c6b2dd4d171623834b9c14eef8043b41054d4760..664db524b1dd496fa0ba27f65f912dcb837d183b 100644 (file)
@@ -99,7 +99,8 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
 {
        struct sk_buff *skb;
        struct edl_event_hdr *edl;
-       char cmd, build_label[QCA_FW_BUILD_VER_LEN];
+       char *build_label;
+       char cmd;
        int build_lbl_len, err = 0;
 
        bt_dev_dbg(hdev, "QCA read fw build info");
@@ -114,6 +115,11 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
                return err;
        }
 
+       if (skb->len < sizeof(*edl)) {
+               err = -EILSEQ;
+               goto out;
+       }
+
        edl = (struct edl_event_hdr *)(skb->data);
        if (!edl) {
                bt_dev_err(hdev, "QCA read fw build info with no header");
@@ -129,14 +135,25 @@ static int qca_read_fw_build_info(struct hci_dev *hdev)
                goto out;
        }
 
+       if (skb->len < sizeof(*edl) + 1) {
+               err = -EILSEQ;
+               goto out;
+       }
+
        build_lbl_len = edl->data[0];
-       if (build_lbl_len <= QCA_FW_BUILD_VER_LEN - 1) {
-               memcpy(build_label, edl->data + 1, build_lbl_len);
-               *(build_label + build_lbl_len) = '\0';
+
+       if (skb->len < sizeof(*edl) + 1 + build_lbl_len) {
+               err = -EILSEQ;
+               goto out;
        }
 
+       build_label = kstrndup(&edl->data[1], build_lbl_len, GFP_KERNEL);
+       if (!build_label)
+               goto out;
+
        hci_set_fw_info(hdev, "%s", build_label);
 
+       kfree(build_label);
 out:
        kfree_skb(skb);
        return err;
index 49ad668d0d0b5e7347def087676ed8e16b3cfa5a..215433fd76a106a21c8c70538e491eb79cb77879 100644 (file)
@@ -48,7 +48,6 @@
 #define get_soc_ver(soc_id, rom_ver)   \
        ((le32_to_cpu(soc_id) << 16) | (le16_to_cpu(rom_ver)))
 
-#define QCA_FW_BUILD_VER_LEN           255
 #define QCA_HSP_GF_SOC_ID                      0x1200
 #define QCA_HSP_GF_SOC_MASK                    0x0000ff00