Linux bluetooth development
 help / color / mirror / Atom feed
* [PATCH v12 0/7] Bluetooth: btmtk: Add MT7928 support
@ 2026-07-16  1:59 Chris Lu
  2026-07-16  1:59 ` [PATCH v12 1/7] Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path Chris Lu
                   ` (6 more replies)
  0 siblings, 7 replies; 18+ messages in thread
From: Chris Lu @ 2026-07-16  1:59 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, Paul Menzel,
	linux-bluetooth, linux-kernel, linux-mediatek, Chris Lu

This patch series adds support for MT7928 (device ID 0x7935) to the
btmtk driver, which requires a new two-stage firmware loading process
with CBMCU firmware.

The series is organized to fix existing issues first, then improve code
quality, and finally add new functionality. Patches have been reordered
in v12 to ensure dependencies are satisfied in the correct order.

Patch 1 fixes a DMA out-of-bounds access in btmtksdio_tx_packet() where
round_up() alignment causes DMA to read beyond the skb buffer, potentially
leaking kernel memory or triggering IOMMU faults. Also fixes a use-after-free
bug where sdio_hdr pointer becomes invalid after pskb_expand_head() reallocation.

Patch 2 fixes a pre-existing security issue in btmtk_setup_firmware_79xx()
by adding comprehensive firmware size validation to prevent out-of-bounds
memory access with truncated or malicious firmware files.

Patch 3 fixes a regression introduced in commit 28b7c5a6db74
("Bluetooth: btmtk: Add MT6639 (MT7927) Bluetooth support") where
SDIO devices would incorrectly pass dev_id=0 to btmtk_setup_firmware_79xx().
This prevents potential MT6639 hardware hangs and ensures correct hardware
identification in logs.

Patch 4 improves BT firmware logging to provide more useful information
for debugging: adds firmware filename before loading, displays chip ID
as HW version instead of firmware's hwver field, and uses %.16s format
specifier to prevent buffer over-read of the 16-byte datetime field.
This patch depends on Patch 3's dev_id fix to display correct hardware version.

Patch 5 fixes a pre-existing bug in btmtksdio_setup() where
btmtk_fw_get_filename() generates the correct firmware path but is
immediately overwritten by snprintf() with a generic legacy format,
causing newer chips to request incorrect filenames. This patch depends
on Patch 3's dev_id fix.

Patch 6 refactors existing firmware download code by replacing magic
numbers with a descriptive BTMTK_WMT_PKT_* enum, making the packet
sequencing logic clearer.

Patch 7 implements MT7928 firmware download flow, which requires loading
CBMCU firmware before Bluetooth firmware. The CBMCU firmware uses a
two-phase download sequence: Phase 1 downloads the section containing
global descriptor and signature data, Phase 2 downloads the remaining
firmware sections.

Tested on MT7928 hardware with successful firmware loading and
Bluetooth functionality verification.

Changes in v12:
- Swap Patch 3 and Patch 4 to fix dependency order issue:
  * Move "Pass hardware dev_id" before "Improve firmware logging"
  * Patch 4's logging improvement uses dev_id to display hardware version,
    but in v11 it would still display 0x0000 because Patch 3 (which fixes
    dev_id) came after it
  * This ensures every intermediate commit produces correct output
  Reported by AI review (Sashiko/Gemini).

Changes in v11:
- Patch 1: Fix use-after-free vulnerability in btmtksdio_tx_packet()
  After pskb_expand_head() reallocates the skb buffer, sdio_hdr pointer
  becomes invalid. Fix by reassigning sdio_hdr after reallocation.
  Reported by AI review (Sashiko/Gemini).
- Reorder patches for bisectability:
  * Move Patch 6->3 (firmware logging improvement) to prevent introducing
    buffer over-read risk in intermediate commits
  * Move Patch 3->5 and Patch 4->3 to ensure dev_id fix is applied before
    removing redundant filename override, preventing potential MT6639 hangs

Changes in v10:
- Add Patch 1 to fix DMA out-of-bounds access in btmtksdio_tx_packet()
  Discovered during v9 review - round_up() alignment can cause DMA to read
  beyond skb buffer, potentially leaking kernel memory or triggering IOMMU
  faults. Fix by expanding skb tailroom and zero-filling padding.

Changes in v9:
- Reorder patches to group SDIO fixes together (Patch 3-4)
- Patch 2 (was Patch 1 in v8): Fix firmware size validation in
  btmtk_setup_firmware_79xx()
- Patch 3 (was Patch 1, new in v9): Fix firmware filename override in
  btmtksdio_setup() where btmtk_fw_get_filename() result was incorrectly
  overwritten by snprintf()
- Patch 4 (was Patch 2 in v8): Fix SDIO device logging regression
  SDIO devices were passing hardcoded 0, causing "BT HW ver: 0x0000" log

Changes in v8:
- Split v7 Patch 1 into two separate patches:
  * Patch 1: btmtk firmware size validation
  * Patch 2: btmtksdio dev_id parameter pass-through
- Patch 3 (was v7 Patch 2): Keep BTMTK_WMT_PKT_* enum refactoring
- Patch 4 (was v7 Patch 3): Keep MT7928 support implementation

Changes in v7:
- Patch 1: Add commit 28b7c5a6db74 to Fixes tag per Luiz's feedback
- Patch 3: Keep BTMTK_WMT_PKT_* enum refactoring per Luiz's suggestion

Changes in v6:
- Patch 1: Per Luiz's feedback, add Fixes tag for commit 28b7c5a6db74
  which introduced the dev_id hardcoded 0 issue
- Patch 1: Restructure btmtk_setup_firmware_79xx() parameter comment

Changes in v5:
- Patch 1: Move btmtk_setup_firmware_79xx() dev_id documentation to
  function-level comment per Marcel's feedback

Changes in v4:
- Patch 1: Fix commit message title (remove redundant "to")
- Patch 1: Expand commit description per Marcel's suggestion
- Patch 1: Document btmtk_setup_firmware_79xx()'s dev_id parameter usage

Changes in v3:
- Patch 1: Use 'u32 dev_id' instead of 'u16 dev_id' per Marcel's feedback

Changes in v2:
- Combine MT7928 functionality into a single patch per Marcel's feedback
  (previous v1 split it into multiple patches)
- Use existing btmtk_fw_get_filename() for MT7928 firmware path
- Improve commit descriptions

Chris Lu (7):
  Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path
  Bluetooth: btmtk: Add firmware size validation in
    btmtk_setup_firmware_79xx()
  Bluetooth: btmtksdio: Pass hardware dev_id to mt79xx_setup()
  Bluetooth: btmtk: Improve BT firmware logging
  Bluetooth: btmtksdio: Remove redundant firmware filename override
  Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum
  Bluetooth: btmtk: Add MT7928 support

 drivers/bluetooth/btmtk.c     | 427 +++++++++++++++++++++++++++++++++-
 drivers/bluetooth/btmtk.h     |   9 +
 drivers/bluetooth/btmtksdio.c |  42 +++-
 3 files changed, 459 insertions(+), 19 deletions(-)

-- 
2.45.2


^ permalink raw reply	[flat|nested] 18+ messages in thread
* [PATCH v13 1/7] Bluetooth: btmtksdio: Fix SKB handling issues in TX path
@ 2026-07-16 11:23 Chris Lu
  2026-07-16 12:02 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-07-16 11:23 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, Paul Menzel,
	linux-bluetooth, linux-kernel, linux-mediatek, Chris Lu

Fix two SKB handling issues in btmtksdio_tx_packet():

1. DMA out-of-bounds read: The driver aligns transfer size to 256 bytes
   using round_up(), but does not ensure the skb buffer has sufficient
   tailroom, causing DMA to read beyond the buffer. Fix by expanding skb
   tailroom if needed and zero-filling the padding.

2. Cloned SKB corruption: The driver modifies SKB header (via skb_push)
   and tail (via skb_put_zero) without checking if the SKB is cloned.
   If the Bluetooth core passes a cloned SKB (e.g., from L2CAP
   retransmission queues), the driver corrupts the shared data buffer
   for other subsystems. Fix by calling skb_unshare() at function entry
   to ensure we have a private copy before any modifications.

Fixes: 9aebfd4a2200 ("Bluetooth: mediatek: add support for MediaTek MT7663S and MT7668S SDIO devices")
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Assisted-by: Claude:Sonnet-4.5
---
 drivers/bluetooth/btmtksdio.c | 42 ++++++++++++++++++++++++++++++-----
 1 file changed, 37 insertions(+), 5 deletions(-)

diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index 5b0fab7b89b5..8a7f2e1c4d56 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -272,9 +272,20 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
 			       struct sk_buff *skb)
 {
 	struct mtkbtsdio_hdr *sdio_hdr;
+	unsigned int padded_len, pad_len;
 	int err;

-	/* Make sure that there are enough rooms for SDIO header */
+	/* Ensure SKB is not cloned before any modification.
+	 * If cloned (e.g., L2CAP retransmission queues), create a
+	 * private copy to avoid corrupting shared data buffer.
+	 */
+	skb = skb_unshare(skb, GFP_ATOMIC);
+	if (!skb)
+		return -ENOMEM;
+
+	/* Make sure that there are enough rooms for SDIO header.
+	 * After skb_unshare(), we have exclusive ownership of the buffer.
+	 */
 	if (unlikely(skb_headroom(skb) < sizeof(*sdio_hdr))) {
 		err = pskb_expand_head(skb, sizeof(*sdio_hdr), 0,
 				       GFP_ATOMIC);
@@ -290,18 +301,39 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
 	sdio_hdr->reserved = cpu_to_le16(0);
 	sdio_hdr->bt_type = hci_skb_pkt_type(skb);

+	/* Calculate padded length for block-aligned DMA transfer.
+	 * SDIO requires transfers to be block-aligned (MTK_SDIO_BLOCK_SIZE).
+	 * Pad with zeros to prevent DMA from reading beyond skb buffer.
+	 */
+	padded_len = round_up(skb->len, MTK_SDIO_BLOCK_SIZE);
+	pad_len = padded_len - skb->len;
+
+	if (pad_len > 0) {
+		/* Ensure sufficient tailroom for padding */
+		if (unlikely(skb_tailroom(skb) < pad_len)) {
+			err = pskb_expand_head(skb, 0, pad_len, GFP_ATOMIC);
+			if (err < 0)
+				goto err_skb_pull;
+			/* Reassign sdio_hdr after buffer reallocation */
+			sdio_hdr = (void *)skb->data;
+		}
+
+		/* Zero-fill padding to prevent information disclosure */
+		skb_put_zero(skb, pad_len);
+	}
+
 	clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
-	err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
-			   round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
+	err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, padded_len);
 	if (err < 0)
-		goto err_skb_pull;
+		goto err_skb_trim;

-	bdev->hdev->stat.byte_tx += skb->len;
+	/* Record actual transmitted data (excluding padding) */
+	bdev->hdev->stat.byte_tx += le16_to_cpu(sdio_hdr->len);

 	kfree_skb(skb);

 	return 0;

+err_skb_trim:
+	if (pad_len > 0)
+		skb_trim(skb, skb->len - pad_len);
 err_skb_pull:
 	skb_pull(skb, sizeof(*sdio_hdr));
+	kfree_skb(skb);

 	return err;
 }
--
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v11 1/7] Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path
@ 2026-07-15 11:20 Chris Lu
  2026-07-15 12:19 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-07-15 11:20 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, Paul Menzel,
	linux-bluetooth, linux-kernel, linux-mediatek, Chris Lu

btmtksdio_tx_packet() aligns transfer size to 256 bytes using
round_up(), but does not ensure the skb buffer has sufficient space,
causing DMA to read beyond the buffer.

Fix by expanding skb tailroom if needed and zero-filling the padding.

Fixes: 9aebfd4a2200 ("Bluetooth: mediatek: add support for MediaTek MT7663S and MT7668S SDIO devices")
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtksdio.c | 33 +++++++++++++++++++++++++++++----
 1 file changed, 29 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index 5b0fab7b89b5..feda1ea8f256 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -272,6 +272,7 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
 			       struct sk_buff *skb)
 {
 	struct mtkbtsdio_hdr *sdio_hdr;
+	unsigned int padded_len, pad_len;
 	int err;
 
 	/* Make sure that there are enough rooms for SDIO header */
@@ -290,18 +291,42 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
 	sdio_hdr->reserved = cpu_to_le16(0);
 	sdio_hdr->bt_type = hci_skb_pkt_type(skb);
 
+	/* Calculate padded length for block-aligned DMA transfer.
+	 * SDIO requires transfers to be block-aligned (MTK_SDIO_BLOCK_SIZE).
+	 * Pad with zeros to prevent DMA from reading beyond skb buffer.
+	 */
+	padded_len = round_up(skb->len, MTK_SDIO_BLOCK_SIZE);
+	pad_len = padded_len - skb->len;
+
+	if (pad_len > 0) {
+		/* Ensure sufficient tailroom for padding */
+		if (unlikely(skb_tailroom(skb) < pad_len)) {
+			err = pskb_expand_head(skb, 0, pad_len, GFP_ATOMIC);
+			if (err < 0)
+				goto err_skb_pull;
+			/* Reassign sdio_hdr after buffer reallocation */
+			sdio_hdr = (void *)skb->data;
+		}
+
+		/* Zero-fill padding to prevent information disclosure */
+		skb_put_zero(skb, pad_len);
+	}
+
 	clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
-	err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
-			   round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
+	err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, padded_len);
 	if (err < 0)
-		goto err_skb_pull;
+		goto err_skb_trim;
 
-	bdev->hdev->stat.byte_tx += skb->len;
+	/* Record actual transmitted data (excluding padding) */
+	bdev->hdev->stat.byte_tx += le16_to_cpu(sdio_hdr->len);
 
 	kfree_skb(skb);
 
 	return 0;
 
+err_skb_trim:
+	if (pad_len > 0)
+		skb_trim(skb, skb->len - pad_len);
 err_skb_pull:
 	skb_pull(skb, sizeof(*sdio_hdr));
 
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v10 1/7] Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path
@ 2026-07-14 12:33 Chris Lu
  2026-07-14 14:48 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-07-14 12:33 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, Paul Menzel,
	linux-bluetooth, linux-kernel, linux-mediatek, Chris Lu

btmtksdio_tx_packet() aligns transfer size to 256 bytes using
round_up(), but does not ensure the skb buffer has sufficient space,
causing DMA to read beyond the buffer.

Fix by expanding skb tailroom if needed and zero-filling the padding.

Fixes: 9aebfd4a2200 ("Bluetooth: mediatek: add support for MediaTek MT7663S and MT7668S SDIO devices")
Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtksdio.c | 31 +++++++++++++++++++++++++++----
 1 file changed, 27 insertions(+), 4 deletions(-)

diff --git a/drivers/bluetooth/btmtksdio.c b/drivers/bluetooth/btmtksdio.c
index 5b0fab7b89b5..a21edefaca99 100644
--- a/drivers/bluetooth/btmtksdio.c
+++ b/drivers/bluetooth/btmtksdio.c
@@ -272,6 +272,7 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
 			       struct sk_buff *skb)
 {
 	struct mtkbtsdio_hdr *sdio_hdr;
+	unsigned int padded_len, pad_len;
 	int err;
 
 	/* Make sure that there are enough rooms for SDIO header */
@@ -290,18 +291,40 @@ static int btmtksdio_tx_packet(struct btmtksdio_dev *bdev,
 	sdio_hdr->reserved = cpu_to_le16(0);
 	sdio_hdr->bt_type = hci_skb_pkt_type(skb);
 
+	/* Calculate padded length for block-aligned DMA transfer.
+	 * SDIO requires transfers to be block-aligned (MTK_SDIO_BLOCK_SIZE).
+	 * Pad with zeros to prevent DMA from reading beyond skb buffer.
+	 */
+	padded_len = round_up(skb->len, MTK_SDIO_BLOCK_SIZE);
+	pad_len = padded_len - skb->len;
+
+	if (pad_len > 0) {
+		/* Ensure sufficient tailroom for padding */
+		if (unlikely(skb_tailroom(skb) < pad_len)) {
+			err = pskb_expand_head(skb, 0, pad_len, GFP_ATOMIC);
+			if (err < 0)
+				goto err_skb_pull;
+		}
+
+		/* Zero-fill padding to prevent information disclosure */
+		skb_put_zero(skb, pad_len);
+	}
+
 	clear_bit(BTMTKSDIO_HW_TX_READY, &bdev->tx_state);
-	err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data,
-			   round_up(skb->len, MTK_SDIO_BLOCK_SIZE));
+	err = sdio_writesb(bdev->func, MTK_REG_CTDR, skb->data, padded_len);
 	if (err < 0)
-		goto err_skb_pull;
+		goto err_skb_trim;
 
-	bdev->hdev->stat.byte_tx += skb->len;
+	/* Record actual transmitted data (excluding padding) */
+	bdev->hdev->stat.byte_tx += le16_to_cpu(sdio_hdr->len);
 
 	kfree_skb(skb);
 
 	return 0;
 
+err_skb_trim:
+	if (pad_len > 0)
+		skb_trim(skb, skb->len - pad_len);
 err_skb_pull:
 	skb_pull(skb, sizeof(*sdio_hdr));
 
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v9 1/6] Bluetooth: btmtk: Add firmware size validation in btmtk_setup_firmware_79xx()
@ 2026-07-02 10:14 Chris Lu
  2026-07-02 10:51 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-07-02 10:14 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Paul Menzel, Chris Lu

Add firmware size validation to prevent out-of-bounds access when loading
truncated or malicious firmware files.

Add three levels of validation:
1. Minimum size check for header and global descriptor
2. Section map bounds check with integer overflow protection using
   check_mul_overflow() and check_add_overflow()
3. Section data bounds check before accessing each section

This matches the validation approach used in btmtk_load_cbmcu_firmware().

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Assisted-by: Claude:Sonnet-4.5
---
 drivers/bluetooth/btmtk.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..3491060b3ae9 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -145,6 +145,7 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 	int err, dlen, i, status;
 	u8 flag, first_block, retry;
 	u32 section_num, dl_size, section_offset;
+	size_t expected_size;
 	u8 cmd[64];
 
 	err = request_firmware(&fw, fwname, &hdev->dev);
@@ -153,12 +154,40 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 		return err;
 	}
 
+	/* Validate minimum firmware size for header and global descriptor */
+	if (fw->size < MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE) {
+		bt_dev_err(hdev, "Firmware file too small: size=%zu, expected at least %u bytes",
+			   fw->size, MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE);
+		err = -EINVAL;
+		goto err_release_fw;
+	}
+
 	fw_ptr = fw->data;
 	fw_bin_ptr = fw_ptr;
 	hdr = (struct btmtk_patch_header *)fw_ptr;
 	globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
 	section_num = le32_to_cpu(globaldesc->section_num);
 
+	/* Check for potential integer overflow in size calculation */
+	if (check_mul_overflow((size_t)MTK_FW_ROM_PATCH_SEC_MAP_SIZE,
+			       (size_t)section_num, &expected_size) ||
+	    check_add_overflow(expected_size,
+			       (size_t)(MTK_FW_ROM_PATCH_HEADER_SIZE +
+					MTK_FW_ROM_PATCH_GD_SIZE),
+			       &expected_size)) {
+		bt_dev_err(hdev, "Firmware size calculation overflow (section_num=%u)",
+			   section_num);
+		err = -EINVAL;
+		goto err_release_fw;
+	}
+
+	if (fw->size < expected_size) {
+		bt_dev_err(hdev, "Firmware truncated: size=%zu, expected=%zu (section_num=%u)",
+			   fw->size, expected_size, section_num);
+		err = -EINVAL;
+		goto err_release_fw;
+	}
+
 	bt_dev_info(hdev, "HW/SW Version: 0x%04x%04x, Build Time: %s",
 		    le16_to_cpu(hdr->hwver), le16_to_cpu(hdr->swver), hdr->datetime);
 
@@ -171,6 +200,16 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 		section_offset = le32_to_cpu(sectionmap->secoffset);
 		dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
 
+		/* Validate section boundaries to prevent out-of-bounds access */
+		if (dl_size > 0 &&
+		    (section_offset > fw->size ||
+		     dl_size > fw->size - section_offset)) {
+			bt_dev_err(hdev, "Section %d out of bounds: offset=%u, size=%u, fw_size=%zu",
+				   i, section_offset, dl_size, fw->size);
+			err = -EINVAL;
+			goto err_release_fw;
+		}
+
 		/* MT6639: only download sections where dlmode byte0 == 0x01,
 		 * matching the Windows driver behavior which skips WiFi/other
 		 * sections that would cause the chip to hang.
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v8 1/5] Bluetooth: btmtk: Add firmware size validation in btmtk_setup_firmware_79xx()
@ 2026-07-02  7:28 Chris Lu
  2026-07-02  8:21 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-07-02  7:28 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Paul Menzel, Chris Lu

Add firmware size validation to prevent out-of-bounds access when loading
truncated or malicious firmware files.

Add three levels of validation:
1. Minimum size check for header and global descriptor
2. Section map bounds check with integer overflow protection using
   check_mul_overflow() and check_add_overflow()
3. Section data bounds check before accessing each section

This matches the validation approach used in btmtk_load_cbmcu_firmware().

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Assisted-by: Claude:Sonnet-4.5
---
 drivers/bluetooth/btmtk.c | 39 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 39 insertions(+)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..3491060b3ae9 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -145,6 +145,7 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 	int err, dlen, i, status;
 	u8 flag, first_block, retry;
 	u32 section_num, dl_size, section_offset;
+	size_t expected_size;
 	u8 cmd[64];
 
 	err = request_firmware(&fw, fwname, &hdev->dev);
@@ -153,12 +154,40 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 		return err;
 	}
 
+	/* Validate minimum firmware size for header and global descriptor */
+	if (fw->size < MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE) {
+		bt_dev_err(hdev, "Firmware file too small: size=%zu, expected at least %u bytes",
+			   fw->size, MTK_FW_ROM_PATCH_HEADER_SIZE + MTK_FW_ROM_PATCH_GD_SIZE);
+		err = -EINVAL;
+		goto err_release_fw;
+	}
+
 	fw_ptr = fw->data;
 	fw_bin_ptr = fw_ptr;
 	hdr = (struct btmtk_patch_header *)fw_ptr;
 	globaldesc = (struct btmtk_global_desc *)(fw_ptr + MTK_FW_ROM_PATCH_HEADER_SIZE);
 	section_num = le32_to_cpu(globaldesc->section_num);
 
+	/* Check for potential integer overflow in size calculation */
+	if (check_mul_overflow((size_t)MTK_FW_ROM_PATCH_SEC_MAP_SIZE,
+			       (size_t)section_num, &expected_size) ||
+	    check_add_overflow(expected_size,
+			       (size_t)(MTK_FW_ROM_PATCH_HEADER_SIZE +
+					MTK_FW_ROM_PATCH_GD_SIZE),
+			       &expected_size)) {
+		bt_dev_err(hdev, "Firmware size calculation overflow (section_num=%u)",
+			   section_num);
+		err = -EINVAL;
+		goto err_release_fw;
+	}
+
+	if (fw->size < expected_size) {
+		bt_dev_err(hdev, "Firmware truncated: size=%zu, expected=%zu (section_num=%u)",
+			   fw->size, expected_size, section_num);
+		err = -EINVAL;
+		goto err_release_fw;
+	}
+
 	bt_dev_info(hdev, "HW/SW Version: 0x%04x%04x, Build Time: %s",
 		    le16_to_cpu(hdr->hwver), le16_to_cpu(hdr->swver), hdr->datetime);
 
@@ -171,6 +200,16 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 		section_offset = le32_to_cpu(sectionmap->secoffset);
 		dl_size = le32_to_cpu(sectionmap->bin_info_spec.dlsize);
 
+		/* Validate section boundaries to prevent out-of-bounds access */
+		if (dl_size > 0 &&
+		    (section_offset > fw->size ||
+		     dl_size > fw->size - section_offset)) {
+			bt_dev_err(hdev, "Section %d out of bounds: offset=%u, size=%u, fw_size=%zu",
+				   i, section_offset, dl_size, fw->size);
+			err = -EINVAL;
+			goto err_release_fw;
+		}
+
 		/* MT6639: only download sections where dlmode byte0 == 0x01,
 		 * matching the Windows driver behavior which skips WiFi/other
 		 * sections that would cause the chip to hang.
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v7 1/3] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum
@ 2026-07-01 12:13 Chris Lu
  2026-07-01 14:24 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-07-01 12:13 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Paul Menzel, Chris Lu

Add BTMTK_WMT_PKT_* enum to represent WMT download packet sequence flags,
improving code readability. Replace magic numbers (1, 2, 3) in
btmtk_setup_firmware_79xx() and btmtk_setup_firmware() with descriptive
enum values:

- BTMTK_WMT_PKT_START (1): First packet of a sequence
- BTMTK_WMT_PKT_CONTINUE (2): Continuation packet
- BTMTK_WMT_PKT_END (3): Final packet of a sequence

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
Assisted-by: Claude:Sonnet-4.5
---
 drivers/bluetooth/btmtk.c | 12 ++++++------
 drivers/bluetooth/btmtk.h |  6 ++++++
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..40c2a64aa6b7 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -230,12 +230,12 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 			while (dl_size > 0) {
 				dlen = min_t(int, 250, dl_size);
 				if (first_block == 1) {
-					flag = 1;
+					flag = BTMTK_WMT_PKT_START;
 					first_block = 0;
 				} else if (dl_size - dlen <= 0) {
-					flag = 3;
+					flag = BTMTK_WMT_PKT_END;
 				} else {
-					flag = 2;
+					flag = BTMTK_WMT_PKT_CONTINUE;
 				}
 
 				wmt_params.flag = flag;
@@ -314,7 +314,7 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
 
 	fw_size -= 30;
 	fw_ptr += 30;
-	flag = 1;
+	flag = BTMTK_WMT_PKT_START;
 
 	wmt_params.op = BTMTK_WMT_PATCH_DWNLD;
 	wmt_params.status = NULL;
@@ -324,9 +324,9 @@ int btmtk_setup_firmware(struct hci_dev *hdev, const char *fwname,
 
 		/* Tell device the position in sequence */
 		if (fw_size - dlen <= 0)
-			flag = 3;
+			flag = BTMTK_WMT_PKT_END;
 		else if (fw_size < fw->size - 30)
-			flag = 2;
+			flag = BTMTK_WMT_PKT_CONTINUE;
 
 		wmt_params.flag = flag;
 		wmt_params.dlen = dlen;
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index c83c24897c95..51c18dde0a80 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -66,6 +66,12 @@ enum {
 	BTMTK_WMT_ON_PROGRESS,
 };
 
+enum {
+	BTMTK_WMT_PKT_START = 1,
+	BTMTK_WMT_PKT_CONTINUE = 2,
+	BTMTK_WMT_PKT_END = 3,
+};
+
 struct btmtk_wmt_hdr {
 	u8	dir;
 	u8	op;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v6 1/3] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum
@ 2026-06-30 12:35 Chris Lu
  2026-06-30 13:56 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-06-30 12:35 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Paul Menzel, Chris Lu

Add BTMTK_WMT_PKT_* enum to represent WMT download packet sequence flags,
improving code readability. Replace magic numbers (1, 2, 3) in
btmtk_setup_firmware_79xx() with descriptive enum values:

- BTMTK_WMT_PKT_START (1): First packet of a sequence
- BTMTK_WMT_PKT_CONTINUE (2): Continuation packet
- BTMTK_WMT_PKT_END (3): Final packet of a sequence

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
---
 drivers/bluetooth/btmtk.c | 6 +++---
 drivers/bluetooth/btmtk.h | 6 ++++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..21c08ee1cdbf 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -230,12 +230,12 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 			while (dl_size > 0) {
 				dlen = min_t(int, 250, dl_size);
 				if (first_block == 1) {
-					flag = 1;
+					flag = BTMTK_WMT_PKT_START;
 					first_block = 0;
 				} else if (dl_size - dlen <= 0) {
-					flag = 3;
+					flag = BTMTK_WMT_PKT_END;
 				} else {
-					flag = 2;
+					flag = BTMTK_WMT_PKT_CONTINUE;
 				}
 
 				wmt_params.flag = flag;
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index c83c24897c95..51c18dde0a80 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -66,6 +66,12 @@ enum {
 	BTMTK_WMT_ON_PROGRESS,
 };
 
+enum {
+	BTMTK_WMT_PKT_START = 1,
+	BTMTK_WMT_PKT_CONTINUE = 2,
+	BTMTK_WMT_PKT_END = 3,
+};
+
 struct btmtk_wmt_hdr {
 	u8	dir;
 	u8	op;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v5 1/3] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum
@ 2026-06-24  7:55 Chris Lu
  2026-06-24  9:14 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-06-24  7:55 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Chris Lu, Paul Menzel

Add BTMTK_WMT_PKT_* enum to represent WMT download packet sequence flags,
improving code readability. Replace magic numbers (1, 2, 3) in
btmtk_setup_firmware_79xx() with descriptive enum values:

- BTMTK_WMT_PKT_START (1): First packet of a sequence
- BTMTK_WMT_PKT_CONTINUE (2): Continuation packet
- BTMTK_WMT_PKT_END (3): Final packet of a sequence

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
Reviewed-by: Paul Menzel <pmenzel@molgen.mpg.de>
---
 drivers/bluetooth/btmtk.c | 6 +++---
 drivers/bluetooth/btmtk.h | 6 ++++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..21c08ee1cdbf 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -230,12 +230,12 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 			while (dl_size > 0) {
 				dlen = min_t(int, 250, dl_size);
 				if (first_block == 1) {
-					flag = 1;
+					flag = BTMTK_WMT_PKT_START;
 					first_block = 0;
 				} else if (dl_size - dlen <= 0) {
-					flag = 3;
+					flag = BTMTK_WMT_PKT_END;
 				} else {
-					flag = 2;
+					flag = BTMTK_WMT_PKT_CONTINUE;
 				}
 
 				wmt_params.flag = flag;
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index c83c24897c95..51c18dde0a80 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -66,6 +66,12 @@ enum {
 	BTMTK_WMT_ON_PROGRESS,
 };
 
+enum {
+	BTMTK_WMT_PKT_START = 1,
+	BTMTK_WMT_PKT_CONTINUE = 2,
+	BTMTK_WMT_PKT_END = 3,
+};
+
 struct btmtk_wmt_hdr {
 	u8	dir;
 	u8	op;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread
* [PATCH v4 1/2] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum
@ 2026-06-23  3:41 Chris Lu
  2026-06-23  6:23 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
  0 siblings, 1 reply; 18+ messages in thread
From: Chris Lu @ 2026-06-23  3:41 UTC (permalink / raw)
  To: Marcel Holtmann, Johan Hedberg, Luiz Von Dentz
  Cc: Sean Wang, Will Lee, SS Wu, Steve Lee, linux-bluetooth,
	linux-kernel, linux-mediatek, Chris Lu

Add BTMTK_WMT_PKT_* enum to represent WMT download packet sequence flags,
improving code readability. Replace magic numbers (1, 2, 3) in
btmtk_setup_firmware_79xx() with descriptive enum values:

- BTMTK_WMT_PKT_START (1): First packet of a sequence
- BTMTK_WMT_PKT_CONTINUE (2): Continuation packet
- BTMTK_WMT_PKT_END (3): Final packet of a sequence

Signed-off-by: Chris Lu <chris.lu@mediatek.com>
---
 drivers/bluetooth/btmtk.c | 6 +++---
 drivers/bluetooth/btmtk.h | 6 ++++++
 2 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 02a96342e964..21c08ee1cdbf 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -230,12 +230,12 @@ int btmtk_setup_firmware_79xx(struct hci_dev *hdev, const char *fwname,
 			while (dl_size > 0) {
 				dlen = min_t(int, 250, dl_size);
 				if (first_block == 1) {
-					flag = 1;
+					flag = BTMTK_WMT_PKT_START;
 					first_block = 0;
 				} else if (dl_size - dlen <= 0) {
-					flag = 3;
+					flag = BTMTK_WMT_PKT_END;
 				} else {
-					flag = 2;
+					flag = BTMTK_WMT_PKT_CONTINUE;
 				}
 
 				wmt_params.flag = flag;
diff --git a/drivers/bluetooth/btmtk.h b/drivers/bluetooth/btmtk.h
index c83c24897c95..51c18dde0a80 100644
--- a/drivers/bluetooth/btmtk.h
+++ b/drivers/bluetooth/btmtk.h
@@ -66,6 +66,12 @@ enum {
 	BTMTK_WMT_ON_PROGRESS,
 };
 
+enum {
+	BTMTK_WMT_PKT_START = 1,
+	BTMTK_WMT_PKT_CONTINUE = 2,
+	BTMTK_WMT_PKT_END = 3,
+};
+
 struct btmtk_wmt_hdr {
 	u8	dir;
 	u8	op;
-- 
2.45.2


^ permalink raw reply related	[flat|nested] 18+ messages in thread

end of thread, other threads:[~2026-07-16 12:02 UTC | newest]

Thread overview: 18+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-16  1:59 [PATCH v12 0/7] Bluetooth: btmtk: Add MT7928 support Chris Lu
2026-07-16  1:59 ` [PATCH v12 1/7] Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path Chris Lu
2026-07-16  4:01   ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-07-16  1:59 ` [PATCH v12 2/7] Bluetooth: btmtk: Add firmware size validation in btmtk_setup_firmware_79xx() Chris Lu
2026-07-16  1:59 ` [PATCH v12 3/7] Bluetooth: btmtksdio: Pass hardware dev_id to mt79xx_setup() Chris Lu
2026-07-16  1:59 ` [PATCH v12 4/7] Bluetooth: btmtk: Improve BT firmware logging Chris Lu
2026-07-16  1:59 ` [PATCH v12 5/7] Bluetooth: btmtksdio: Remove redundant firmware filename override Chris Lu
2026-07-16  1:59 ` [PATCH v12 6/7] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum Chris Lu
2026-07-16  1:59 ` [PATCH v12 7/7] Bluetooth: btmtk: Add MT7928 support Chris Lu
  -- strict thread matches above, loose matches on Subject: below --
2026-07-16 11:23 [PATCH v13 1/7] Bluetooth: btmtksdio: Fix SKB handling issues in TX path Chris Lu
2026-07-16 12:02 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-07-15 11:20 [PATCH v11 1/7] Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path Chris Lu
2026-07-15 12:19 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-07-14 12:33 [PATCH v10 1/7] Bluetooth: btmtksdio: Fix DMA out-of-bounds access in TX path Chris Lu
2026-07-14 14:48 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-07-02 10:14 [PATCH v9 1/6] Bluetooth: btmtk: Add firmware size validation in btmtk_setup_firmware_79xx() Chris Lu
2026-07-02 10:51 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-07-02  7:28 [PATCH v8 1/5] Bluetooth: btmtk: Add firmware size validation in btmtk_setup_firmware_79xx() Chris Lu
2026-07-02  8:21 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-07-01 12:13 [PATCH v7 1/3] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum Chris Lu
2026-07-01 14:24 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-06-30 12:35 [PATCH v6 1/3] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum Chris Lu
2026-06-30 13:56 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-06-24  7:55 [PATCH v5 1/3] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum Chris Lu
2026-06-24  9:14 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot
2026-06-23  3:41 [PATCH v4 1/2] Bluetooth: btmtk: Replace magic numbers with WMT packet flag enum Chris Lu
2026-06-23  6:23 ` Bluetooth: btmtk: Add MT7928 support bluez.test.bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox