mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
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
(cherry picked from commit 778dd2ab5e)
Co-authored-by: zhiweijian <zhiweijian@espressif.com>
This commit is contained in:
@@ -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"
|
||||
@@ -318,9 +317,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)
|
||||
@@ -542,7 +544,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++;
|
||||
@@ -587,7 +589,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)
|
||||
@@ -640,7 +645,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;
|
||||
@@ -699,7 +704,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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
@@ -135,13 +135,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;
|
||||
}
|
||||
@@ -443,7 +445,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;
|
||||
|
||||
@@ -451,6 +453,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) {
|
||||
|
||||
Reference in New Issue
Block a user