fix(bt): enhanced packet length check for HCI module
This commit is contained in:
@@ -481,6 +481,10 @@ static void hci_hal_h4_hdl_rx_packet(BT_HDR *packet)
|
|||||||
packet->len--;
|
packet->len--;
|
||||||
if (type == HCI_BLE_EVENT) {
|
if (type == HCI_BLE_EVENT) {
|
||||||
#if (!CONFIG_BT_STACK_NO_LOG)
|
#if (!CONFIG_BT_STACK_NO_LOG)
|
||||||
|
if (packet->len < 1) {
|
||||||
|
osi_free(packet);
|
||||||
|
return;
|
||||||
|
}
|
||||||
uint8_t len = 0;
|
uint8_t len = 0;
|
||||||
STREAM_TO_UINT8(len, stream);
|
STREAM_TO_UINT8(len, stream);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -447,12 +447,26 @@ static bool filter_incoming_event(BT_HDR *packet)
|
|||||||
uint8_t event_code;
|
uint8_t event_code;
|
||||||
command_opcode_t opcode;
|
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_TO_UINT8(event_code, stream);
|
||||||
STREAM_SKIP_UINT8(stream); // Skip the parameter total length field
|
STREAM_SKIP_UINT8(stream); // Skip the parameter total length field
|
||||||
|
|
||||||
HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code);
|
HCI_TRACE_DEBUG("Receive packet event_code=0x%x\n", event_code);
|
||||||
|
|
||||||
if (event_code == HCI_COMMAND_COMPLETE_EVT) {
|
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_UINT8(hci_host_env.command_credits, stream);
|
||||||
STREAM_TO_UINT16(opcode, stream);
|
STREAM_TO_UINT16(opcode, stream);
|
||||||
wait_entry = get_waiting_command(opcode);
|
wait_entry = get_waiting_command(opcode);
|
||||||
@@ -481,6 +495,11 @@ static bool filter_incoming_event(BT_HDR *packet)
|
|||||||
goto intercepted;
|
goto intercepted;
|
||||||
} else if (event_code == HCI_COMMAND_STATUS_EVT) {
|
} else if (event_code == HCI_COMMAND_STATUS_EVT) {
|
||||||
uint8_t status;
|
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(status, stream);
|
||||||
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
|
STREAM_TO_UINT8(hci_host_env.command_credits, stream);
|
||||||
STREAM_TO_UINT16(opcode, stream);
|
STREAM_TO_UINT16(opcode, stream);
|
||||||
|
|||||||
@@ -27,5 +27,9 @@
|
|||||||
#define HCI_SCO_PREAMBLE_SIZE 3
|
#define HCI_SCO_PREAMBLE_SIZE 3
|
||||||
// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
|
// 1 byte for event code, 1 byte for parameter length (Volume 2, Part E, 5.4.4)
|
||||||
#define HCI_EVENT_PREAMBLE_SIZE 2
|
#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_ */
|
#endif /* _HCI_INTERNALS_H_ */
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#define START_PACKET_BOUNDARY 2
|
#define START_PACKET_BOUNDARY 2
|
||||||
#define CONTINUATION_PACKET_BOUNDARY 1
|
#define CONTINUATION_PACKET_BOUNDARY 1
|
||||||
#define L2CAP_HEADER_SIZE 4
|
#define L2CAP_HEADER_SIZE 4
|
||||||
|
#define L2CAP_LENGTH_SIZE 2
|
||||||
|
|
||||||
// TODO(zachoverflow): find good value for this
|
// TODO(zachoverflow): find good value for this
|
||||||
#define NUMBER_OF_BUCKETS 42
|
#define NUMBER_OF_BUCKETS 42
|
||||||
@@ -81,6 +82,11 @@ static void fragment_and_dispatch(BT_HDR *packet)
|
|||||||
callbacks->fragmented(packet, true);
|
callbacks->fragmented(packet, true);
|
||||||
return;
|
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 =
|
max_data_size =
|
||||||
SUB_EVENT(packet->event) == LOCAL_BR_EDR_CONTROLLER_ID ?
|
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 l2cap_length;
|
||||||
uint16_t acl_length __attribute__((unused));
|
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(handle, stream);
|
||||||
STREAM_TO_UINT16(acl_length, stream);
|
STREAM_TO_UINT16(acl_length, stream);
|
||||||
STREAM_TO_UINT16(l2cap_length, stream);
|
STREAM_TO_UINT16(l2cap_length, stream);
|
||||||
|
|||||||
Reference in New Issue
Block a user