* [PATCH v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1()
@ 2026-07-20 19:13 Doruk Tan Ozturk
2026-07-20 19:58 ` Luiz Augusto von Dentz
2026-07-20 20:27 ` [v2] " bluez.test.bot
0 siblings, 2 replies; 3+ messages in thread
From: Doruk Tan Ozturk @ 2026-07-20 19:13 UTC (permalink / raw)
To: Luiz Augusto von Dentz, Marcel Holtmann, Amitkumar Karwar,
Neeraj Kale
Cc: Paul Menzel, linux-bluetooth, linux-kernel, stable,
Doruk Tan Ozturk
Commit 25c286d75821 ("Bluetooth: btnxpuart: Fix out-of-bounds firmware
read in nxp_recv_fw_req_v3()") bounded the v3 firmware download offset but
left an unbounded read in the v1 handler.
nxp_recv_fw_req_v1() advances a device-driven download offset
(fw_dnld_v1_offset) by fw_v1_sent_bytes on every request, and that
bookkeeping runs even when the payload write is skipped, so the offset can
walk past nxpdev->fw->size. When the controller then requests a header
(len == HDR_LEN), the driver reads the 16-byte bootloader header at
nxp_get_data_len(nxpdev->fw->data + nxpdev->fw_dnld_v1_offset)
with no bound on the offset, reading past the end of the firmware image.
A malicious or malfunctioning NXP UART controller can drive this to read
out-of-bounds kernel memory during firmware download.
Bound the offset before the header read, and convert the payload write
guard to the overflow-safe form used by the v3 path (fw_dnld_v1_offset is
u32, so fw_dnld_v1_offset + len can wrap). Log the offset, expected length
and firmware size at the reject site to aid debugging of a real device.
This was found by 0sec automated security-research tooling
(https://0sec.ai).
Fixes: 689ca16e5232 ("Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets")
Cc: stable@vger.kernel.org
Reviewed-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
Assisted-by: 0sec:claude-opus-4-8
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
---
v2: log offset/expected_len/fw size at the reject site (requested by
Neeraj Kale and Paul Menzel). No functional change to the bound
itself vs v1.
v1: https://lore.kernel.org/linux-bluetooth/20260705115650.81724-1-doruk@0sec.ai/
drivers/bluetooth/btnxpuart.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 0bb300eef157..6d62d07a542b 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1041,11 +1041,19 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
* and we need to re-send the previous header again.
*/
if (len == nxpdev->fw_v1_expected_len) {
- if (len == HDR_LEN)
+ if (len == HDR_LEN) {
+ if (nxpdev->fw_dnld_v1_offset >= nxpdev->fw->size ||
+ nxpdev->fw->size - nxpdev->fw_dnld_v1_offset < HDR_LEN) {
+ bt_dev_err(hdev, "FW request out of bounds: offset %u, expected_len %u, fw size %zu",
+ nxpdev->fw_dnld_v1_offset, len,
+ nxpdev->fw->size);
+ goto free_skb;
+ }
nxpdev->fw_v1_expected_len = nxp_get_data_len(nxpdev->fw->data +
nxpdev->fw_dnld_v1_offset);
- else
+ } else {
nxpdev->fw_v1_expected_len = HDR_LEN;
+ }
} else if (len == HDR_LEN) {
/* FW download out of sync. Send previous chunk again */
nxpdev->fw_dnld_v1_offset -= nxpdev->fw_v1_sent_bytes;
@@ -1053,7 +1061,8 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
}
}
- if (nxpdev->fw_dnld_v1_offset + len <= nxpdev->fw->size)
+ if (nxpdev->fw_dnld_v1_offset < nxpdev->fw->size &&
+ len <= nxpdev->fw->size - nxpdev->fw_dnld_v1_offset)
serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
nxpdev->fw_dnld_v1_offset, len);
nxpdev->fw_v1_sent_bytes = len;
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1()
2026-07-20 19:13 [PATCH v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1() Doruk Tan Ozturk
@ 2026-07-20 19:58 ` Luiz Augusto von Dentz
2026-07-20 20:27 ` [v2] " bluez.test.bot
1 sibling, 0 replies; 3+ messages in thread
From: Luiz Augusto von Dentz @ 2026-07-20 19:58 UTC (permalink / raw)
To: Doruk Tan Ozturk
Cc: Marcel Holtmann, Amitkumar Karwar, Neeraj Kale, Paul Menzel,
linux-bluetooth, linux-kernel, stable
Hi Doruk,
On Mon, Jul 20, 2026 at 3:13 PM Doruk Tan Ozturk <doruk@0sec.ai> wrote:
>
> Commit 25c286d75821 ("Bluetooth: btnxpuart: Fix out-of-bounds firmware
> read in nxp_recv_fw_req_v3()") bounded the v3 firmware download offset but
> left an unbounded read in the v1 handler.
>
> nxp_recv_fw_req_v1() advances a device-driven download offset
> (fw_dnld_v1_offset) by fw_v1_sent_bytes on every request, and that
> bookkeeping runs even when the payload write is skipped, so the offset can
> walk past nxpdev->fw->size. When the controller then requests a header
> (len == HDR_LEN), the driver reads the 16-byte bootloader header at
>
> nxp_get_data_len(nxpdev->fw->data + nxpdev->fw_dnld_v1_offset)
>
> with no bound on the offset, reading past the end of the firmware image.
> A malicious or malfunctioning NXP UART controller can drive this to read
> out-of-bounds kernel memory during firmware download.
>
> Bound the offset before the header read, and convert the payload write
> guard to the overflow-safe form used by the v3 path (fw_dnld_v1_offset is
> u32, so fw_dnld_v1_offset + len can wrap). Log the offset, expected length
> and firmware size at the reject site to aid debugging of a real device.
>
> This was found by 0sec automated security-research tooling
> (https://0sec.ai).
>
> Fixes: 689ca16e5232 ("Bluetooth: NXP: Add protocol support for NXP Bluetooth chipsets")
> Cc: stable@vger.kernel.org
> Reviewed-by: Neeraj Sanjay Kale <neeraj.sanjaykale@nxp.com>
> Assisted-by: 0sec:claude-opus-4-8
> Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
> ---
> v2: log offset/expected_len/fw size at the reject site (requested by
> Neeraj Kale and Paul Menzel). No functional change to the bound
> itself vs v1.
>
> v1: https://lore.kernel.org/linux-bluetooth/20260705115650.81724-1-doruk@0sec.ai/
> drivers/bluetooth/btnxpuart.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
> index 0bb300eef157..6d62d07a542b 100644
> --- a/drivers/bluetooth/btnxpuart.c
> +++ b/drivers/bluetooth/btnxpuart.c
> @@ -1041,11 +1041,19 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
> * and we need to re-send the previous header again.
> */
> if (len == nxpdev->fw_v1_expected_len) {
> - if (len == HDR_LEN)
> + if (len == HDR_LEN) {
> + if (nxpdev->fw_dnld_v1_offset >= nxpdev->fw->size ||
> + nxpdev->fw->size - nxpdev->fw_dnld_v1_offset < HDR_LEN) {
> + bt_dev_err(hdev, "FW request out of bounds: offset %u, expected_len %u, fw size %zu",
We still have the 80 columns limit in Bluetooth.
> + nxpdev->fw_dnld_v1_offset, len,
> + nxpdev->fw->size);
> + goto free_skb;
> + }
> nxpdev->fw_v1_expected_len = nxp_get_data_len(nxpdev->fw->data +
> nxpdev->fw_dnld_v1_offset);
> - else
> + } else {
> nxpdev->fw_v1_expected_len = HDR_LEN;
> + }
> } else if (len == HDR_LEN) {
> /* FW download out of sync. Send previous chunk again */
> nxpdev->fw_dnld_v1_offset -= nxpdev->fw_v1_sent_bytes;
> @@ -1053,7 +1061,8 @@ static int nxp_recv_fw_req_v1(struct hci_dev *hdev, struct sk_buff *skb)
> }
> }
>
> - if (nxpdev->fw_dnld_v1_offset + len <= nxpdev->fw->size)
> + if (nxpdev->fw_dnld_v1_offset < nxpdev->fw->size &&
> + len <= nxpdev->fw->size - nxpdev->fw_dnld_v1_offset)
> serdev_device_write_buf(nxpdev->serdev, nxpdev->fw->data +
> nxpdev->fw_dnld_v1_offset, len);
> nxpdev->fw_v1_sent_bytes = len;
> --
> 2.43.0
>
--
Luiz Augusto von Dentz
^ permalink raw reply [flat|nested] 3+ messages in thread
* RE: [v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1()
2026-07-20 19:13 [PATCH v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1() Doruk Tan Ozturk
2026-07-20 19:58 ` Luiz Augusto von Dentz
@ 2026-07-20 20:27 ` bluez.test.bot
1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-07-20 20:27 UTC (permalink / raw)
To: linux-bluetooth, doruk
[-- Attachment #1: Type: text/plain, Size: 1468 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1131114
---Test result---
Test Summary:
CheckPatch PASS 0.65 seconds
VerifyFixes PASS 0.10 seconds
VerifySignedoff PASS 0.14 seconds
GitLint FAIL 0.26 seconds
SubjectPrefix PASS 0.09 seconds
BuildKernel PASS 24.54 seconds
CheckAllWarning PASS 27.46 seconds
CheckSparse PASS 26.13 seconds
BuildKernel32 PASS 24.39 seconds
CheckKernelLLVM SKIP 0.00 seconds
TestRunnerSetup PASS 451.97 seconds
IncrementalBuild PASS 24.16 seconds
Details
##############################
Test: GitLint - FAIL
Desc: Run gitlint
Output:
[v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1()
1: T1 Title exceeds max length (82>80): "[v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1()"
##############################
Test: CheckKernelLLVM - SKIP
Desc: Build kernel with LLVM + context analysis
Output:
Clang not found
https://github.com/bluez/bluetooth-next/pull/466
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-20 20:27 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 19:13 [PATCH v2] Bluetooth: btnxpuart: Fix out-of-bounds firmware read in nxp_recv_fw_req_v1() Doruk Tan Ozturk
2026-07-20 19:58 ` Luiz Augusto von Dentz
2026-07-20 20:27 ` [v2] " 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