fix(ble/bluedroid): Add length/pointer checks and fix error paths

- hci_hal_h4: validate packet length and pointers in hci_packet_complete,
  hdl_rx_adv_rpt, callbacks
- hci_layer: align hci_start_up error path and return; validate packet len in
  filter_incoming_event
- hci_packet_factory: ensure BT_HDR length/offset initialized in make_command_no_params
- packet_fragmenter: validate length before fragment_and_dispatch
This commit is contained in:
zhiweijian
2026-03-18 16:33:34 +08:00
parent b83647f5ea
commit 778dd2ab5e
4 changed files with 26 additions and 14 deletions
+11 -6
View File
@@ -34,7 +34,6 @@
#include "esp_bt.h"
#endif
#include "esp_bluedroid_hci.h"
#include "stack/hcimsgs.h"
#if (C2H_FLOW_CONTROL_INCLUDED == TRUE)
#include "l2c_int.h"
@@ -319,9 +318,12 @@ static void hci_packet_complete(BT_HDR *packet){
}
#endif ///C2H_FLOW_CONTROL_INCLUDED == TRUE
bool host_recv_adv_packet(uint8_t *packet)
bool host_recv_adv_packet(uint8_t *packet, uint16_t len)
{
assert(packet);
if (len < 4) {
return false;
}
if(packet[0] == DATA_TYPE_EVENT && packet[1] == HCI_BLE_EVENT) {
if(packet[3] == HCI_BLE_ADV_PKT_RPT_EVT || packet[3] == HCI_BLE_DIRECT_ADV_EVT
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
@@ -543,7 +545,7 @@ static void hci_hal_h4_hdl_rx_adv_rpt(pkt_linked_item_t *linked_pkt)
BT_HDR* packet = (BT_HDR *)linked_pkt->data;
stream = packet->data + packet->offset;
assert(host_recv_adv_packet(stream) == true);
assert(host_recv_adv_packet(stream, packet->len) == true);
STREAM_TO_UINT8(type, stream);
packet->offset++;
@@ -588,7 +590,10 @@ static void host_send_pkt_available_cb(void)
void bt_record_hci_data(uint8_t *data, uint16_t len)
{
#if (BT_HCI_LOG_INCLUDED == TRUE)
if ((data[0] == DATA_TYPE_EVENT) && (data[1] == HCI_BLE_EVENT) && ((data[3] == HCI_BLE_ADV_PKT_RPT_EVT) || (data[3] == HCI_BLE_DIRECT_ADV_EVT)
if (len < 2) {
return;
}
if ((len >= 4) && (data[0] == DATA_TYPE_EVENT) && (data[1] == HCI_BLE_EVENT) && ((data[3] == HCI_BLE_ADV_PKT_RPT_EVT) || (data[3] == HCI_BLE_DIRECT_ADV_EVT)
#if (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
|| (data[3] == HCI_BLE_ADV_DISCARD_REPORT_EVT)
#endif // (BLE_ADV_REPORT_FLOW_CONTROL == TRUE)
@@ -641,7 +646,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
}
#endif // #if (BLE_FEAT_ISO_EN == TRUE)
bool is_adv_rpt = host_recv_adv_packet(data);
bool is_adv_rpt = host_recv_adv_packet(data, len);
if (!is_adv_rpt) {
pkt_size = BT_HDR_SIZE + len;
@@ -700,7 +705,7 @@ static int host_recv_pkt_cb(uint8_t *data, uint16_t len)
hci_upstream_data_post(OSI_THREAD_MAX_TIMEOUT);
BTTRC_DUMP_BUFFER("Recv Pkt", pkt->data, len);
BTTRC_DUMP_BUFFER("Recv Pkt", data, len);
return 0;
}
+11 -7
View File
@@ -117,7 +117,7 @@ int hci_start_up(void)
hci_host_thread = osi_thread_create(HCI_HOST_TASK_NAME, HCI_HOST_TASK_STACK_SIZE, HCI_HOST_TASK_PRIO, HCI_HOST_TASK_PINNED_TO_CORE,
HCI_HOST_TASK_WORKQUEUE_NUM, workqueue_len);
if (hci_host_thread == NULL) {
return -2;
goto error;
}
osi_event_bind(hci_host_env.downstream_data_ready, hci_host_thread, HCI_DOWNSTREAM_DATA_QUEUE_IDX);
@@ -137,13 +137,15 @@ error:
void hci_shut_down(void)
{
hci_host_startup_flag = false;
/* Close HAL and cleanup before freeing thread: hal->open() and osi_event_bind()
* stored references to hci_host_thread; they must not use it after osi_thread_free(). */
if (hci_host_thread != NULL) {
hal->close();
packet_fragmenter->cleanup();
}
hci_layer_deinit_env();
packet_fragmenter->cleanup();
//low_power_manager->cleanup();
hal->close();
osi_thread_free(hci_host_thread);
hci_host_thread = NULL;
}
@@ -445,7 +447,7 @@ static bool filter_incoming_event(BT_HDR *packet)
{
pkt_linked_item_t *wait_entry = NULL;
hci_cmd_metadata_t *metadata = NULL;
uint8_t *stream = packet->data + packet->offset;
uint8_t *stream;
uint8_t event_code;
command_opcode_t opcode;
@@ -453,6 +455,8 @@ static bool filter_incoming_event(BT_HDR *packet)
return true;
}
stream = packet->data + packet->offset;
if (packet->len < HCI_EVENT_PREAMBLE_SIZE) {
HCI_TRACE_WARNING("dropping too short HCI event (len=%u)", packet->len);
osi_free(packet);
@@ -250,6 +250,8 @@ static BT_HDR *make_command_no_params(uint16_t opcode)
static BT_HDR *make_command(uint16_t opcode, size_t parameter_size, uint8_t **stream_out)
{
BT_HDR *packet = HCI_GET_CMD_BUF(parameter_size);
assert(packet != NULL);
hci_cmd_metadata_t *metadata = HCI_GET_CMD_METAMSG(packet);
metadata->opcode = opcode;
@@ -73,9 +73,10 @@ static void fragment_and_dispatch(BT_HDR *packet)
uint16_t continuation_handle;
uint16_t max_data_size, max_packet_size, remaining_length;
uint16_t event = packet->event & MSG_EVT_MASK;
uint8_t *stream = packet->data + packet->offset;
uint8_t *stream;
assert(packet != NULL);
stream = packet->data + packet->offset;
// We only fragment ACL packets
if (event != MSG_STACK_TO_HC_HCI_ACL) {