fix(bt): enhanced packet length check for HCI module

This commit is contained in:
Jin Cheng
2025-12-22 17:11:29 +08:00
committed by Jin Cheng
parent 41edf56707
commit 0126907574
4 changed files with 38 additions and 0 deletions
@@ -481,6 +481,10 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
packet->len--;
if (type == HCI_BLE_EVENT) {
#if (!CONFIG_BT_STACK_NO_LOG)
if (packet->len < 1) {
osi_free(packet);
return;
}
uint8_t len = 0;
STREAM_TO_UINT8(len, stream);
#endif
@@ -447,12 +447,26 @@ static bool filter_incoming_event(BT_HDR *packet)
uint8_t event_code;
command_opcode_t opcode;
if (packet == NULL) {
return true;
}
if (packet->len < HCI_EVENT_PREAMBLE_SIZE) {
HCI_TRACE_WARNING("dropping too short HCI event (len=%u)", packet->len);
osi_free(packet);
return true;
}
STREAM_TO_UINT8(event_code, stream);
STREAM_SKIP_UINT8(stream); // Skip the parameter total length field
HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code);
if (event_code == HCI_COMMAND_COMPLETE_EVT) {
if (packet->len < HCI_EVENT_PREAMBLE_SIZE + HCI_CC_EVENT_MIN_PARAM_LEN) {
HCI_TRACE_WARNING("dropping too short Command Complete (len=%u)", packet->len);
osi_free(packet);
return true;
}
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
STREAM_TO_UINT16(opcode, stream);
wait_entry = get_waiting_command(opcode);
@@ -481,6 +495,11 @@ static bool filter_incoming_event(BT_HDR *packet)
goto intercepted;
} else if (event_code == HCI_COMMAND_STATUS_EVT) {
uint8_t status;
if (packet->len < HCI_EVENT_PREAMBLE_SIZE + HCI_CS_EVENT_MIN_PARAM_LEN) {
HCI_TRACE_WARNING("dropping too short Command Status (len=%u)", packet->len);
osi_free(packet);
return true;
}
STREAM_TO_UINT8(status, stream);
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
STREAM_TO_UINT16(opcode, stream);
@@ -27,5 +27,9 @@
#define HCI_SCO_PREAMBLE_SIZE 3
// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
#define HCI_EVENT_PREAMBLE_SIZE 2
// 1 byte for Num_HCI_Command_Packets, 2 bytes for Commnad_Opcode (Volume 4, Part E, 7.7.14)
#define HCI_CC_EVENT_MIN_PARAM_LEN 3
// 1 byte for status, 1 byte for Num_HCI_Command_Packets, 2 bytes for Commnad_Opcode (Volume 4, Part E, 7.7.15)
#define HCI_CS_EVENT_MIN_PARAM_LEN 4
#endif /* _HCI_INTERNALS_H_ */
@@ -37,6 +37,7 @@
#define START_PACKET_BOUNDARY 2
#define CONTINUATION_PACKET_BOUNDARY 1
#define L2CAP_HEADER_SIZE 4
#define L2CAP_LENGTH_SIZE 2
// TODO(zachoverflow): find good value for this
#define NUMBER_OF_BUCKETS 42
@@ -81,6 +82,11 @@ static void fragment_and_dispatch(BT_HDR *packet)
callbacks->fragmented(packet, true);
return;
}
if (packet->len < HCI_ACL_PREAMBLE_SIZE) {
HCI_TRACE_ERROR("ACL packet too short for preamble (len=%u)", packet->len);
callbacks->fragmented(packet, true);
return;
}
max_data_size =
SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
@@ -143,6 +149,11 @@ static void reassemble_and_dispatch(BT_HDR *packet)
uint16_t l2cap_length;
uint16_t acl_length __attribute__((unused));
if (packet->len < HCI_ACL_PREAMBLE_SIZE + L2CAP_LENGTH_SIZE) {
HCI_TRACE_ERROR("ACL packet too short (len=%u)\n", packet->len);
osi_free(packet);
return;
}
STREAM_TO_UINT16(handle, stream);
STREAM_TO_UINT16(acl_length, stream);
STREAM_TO_UINT16(l2cap_length, stream);