From 42c0e54a4b6639c3fcfbb98bd52afc536f0f5146 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Thu, 27 Nov 2025 20:10:07 +0800 Subject: [PATCH] fix(ble/bluedroid): Fix potential CVE-2020-0022 in reassemble_and_dispatch - Reference: https://nvd.nist.gov/vuln/detail/CVE-2020-0022 (cherry picked from commit 1f7fd91b5a3b6a753bc0d93df1f3f0cb9fb8a21a) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/hci/packet_fragmenter.c | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/components/bt/host/bluedroid/hci/packet_fragmenter.c b/components/bt/host/bluedroid/hci/packet_fragmenter.c index bfb9843eb39..ccc220fbf1e 100644 --- a/components/bt/host/bluedroid/hci/packet_fragmenter.c +++ b/components/bt/host/bluedroid/hci/packet_fragmenter.c @@ -161,6 +161,13 @@ static void reassemble_and_dispatch(BT_HDR *packet) osi_free(partial_packet); } + /* Check for integer overflow in length calculation */ + if (l2cap_length > (UINT16_MAX - L2CAP_HEADER_SIZE - HCI_ACL_PREAMBLE_SIZE)) { + HCI_TRACE_ERROR("L2CAP length too large: %u", l2cap_length); + osi_free(packet); + return; + } + uint16_t full_length = l2cap_length + L2CAP_HEADER_SIZE + HCI_ACL_PREAMBLE_SIZE; if (full_length <= packet->len) { if (full_length < packet->len) { @@ -200,6 +207,20 @@ static void reassemble_and_dispatch(BT_HDR *packet) packet->offset += HCI_ACL_PREAMBLE_SIZE; // skip ACL preamble packet->len -= HCI_ACL_PREAMBLE_SIZE; + + // CVE-2020-0022 (BlueFrag) Fix: Prevent integer underflow + if (partial_packet->offset > partial_packet->len) { + HCI_TRACE_ERROR("%s offset exceeds expected length. Dropping packet.\n", __func__); + osi_free(packet); + return; + } + + if (packet->len > UINT16_MAX - partial_packet->offset) { + HCI_TRACE_ERROR("%s: packet->len too large, would overflow. Dropping packet.\n", __func__); + osi_free(packet); + return; + } + uint16_t projected_offset = partial_packet->offset + packet->len; if (projected_offset > partial_packet->len) { // len stores the expected length HCI_TRACE_ERROR("%s got packet which would exceed expected length of %d. Truncating.\n", __func__, partial_packet->len);