From 2cf13e5c6dc3cb41f73a6f313bfbbf150e07cfd2 Mon Sep 17 00:00:00 2001 From: Zhang Hai Peng Date: Tue, 30 Dec 2025 11:53:41 +0800 Subject: [PATCH] fix(ble/bluedroid): Fix multiple out-of-bounds read vulnerabilities in GATT PDU handlers (cherry picked from commit 643d9c2387f9fc677025e66faf714667a7e75f85) Co-authored-by: zhanghaipeng --- .../bt/host/bluedroid/stack/gatt/gatt_cl.c | 8 +++++- .../bt/host/bluedroid/stack/gatt/gatt_sr.c | 25 +++++++++++++++---- 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c index 1cc9aefb47..1bdbfaec08 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_cl.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_cl.c @@ -554,7 +554,13 @@ void gatt_process_error_rsp(tGATT_TCB *p_tcb, tGATT_CLCB *p_clcb, UINT8 op_code, tGATT_VALUE *p_attr = (tGATT_VALUE *)p_clcb->p_attr_buf; UNUSED(op_code); - UNUSED(len); + + /* Fix: Validate minimum length (opcode:1 + handle:2 + reason:1 = 4 bytes) */ + if (len < 4) { + GATT_TRACE_ERROR("invalid error rsp len: %d", len); + gatt_end_operation(p_clcb, GATT_INVALID_PDU, NULL); + return; + } GATT_TRACE_DEBUG("%s", __func__); STREAM_TO_UINT8(opcode, p); diff --git a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c index 585a4c921a..2a7e9fb35c 100644 --- a/components/bt/host/bluedroid/stack/gatt/gatt_sr.c +++ b/components/bt/host/bluedroid/stack/gatt/gatt_sr.c @@ -479,7 +479,13 @@ void gatt_process_exec_write_req (tGATT_TCB *p_tcb, UINT8 op_code, UINT16 len, U BOOLEAN is_need_dequeue_sr_cmd = FALSE; tGATT_PREPARE_WRITE_RECORD *prepare_record = NULL; tGATT_PREPARE_WRITE_QUEUE_DATA * queue_data = NULL; - UNUSED(len); + + /* Fix: Validate minimum length (flags: 1 byte) */ + if (len < 1) { + GATT_TRACE_ERROR("invalid exec write req len: %d", len); + gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, 0, FALSE); + return; + } #if GATT_CONFORMANCE_TESTING == TRUE if (gatt_cb.enable_err_rsp && gatt_cb.req_op_code == op_code) { @@ -1234,10 +1240,13 @@ void gatts_process_write_req (tGATT_TCB *p_tcb, UINT8 i_rcb, UINT16 handle, switch (op_code) { case GATT_SIGN_CMD_WRITE: - if (op_code == GATT_SIGN_CMD_WRITE) { - GATT_TRACE_DEBUG("Write CMD with data signing" ); - len -= GATT_AUTH_SIGN_LEN; + /* Fix: Validate length before subtraction to prevent underflow */ + if (len < GATT_AUTH_SIGN_LEN) { + GATT_TRACE_ERROR("signed write len too short: %d", len); + return; /* GATT_SIGN_CMD_WRITE has no response */ } + GATT_TRACE_DEBUG("Write CMD with data signing" ); + len -= GATT_AUTH_SIGN_LEN; /* fall through */ case GATT_CMD_WRITE: case GATT_REQ_WRITE: @@ -1473,7 +1482,13 @@ static void gatts_process_read_req(tGATT_TCB *p_tcb, tGATT_SR_REG *p_rcb, UINT8 UINT8 sec_flag, key_size, *p; UINT16 offset = 0, value_len = 0; - UNUSED (len); + /* Fix: Validate length for GATT_REQ_READ_BLOB (needs offset: 2 bytes) */ + if (op_code == GATT_REQ_READ_BLOB && len < 2) { + GATT_TRACE_ERROR("invalid read blob req len: %d", len); + gatt_send_error_rsp(p_tcb, GATT_INVALID_PDU, op_code, handle, FALSE); + return; + } + if ((p_msg = (BT_HDR *)osi_calloc(buf_len)) == NULL) { GATT_TRACE_ERROR("gatts_process_find_info failed. no resources.\n");