l2cap: verify signaling command len for CONNECTION_REQUEST, INFORMATION_REQUEST, and INFORMATION_RESPONSE

This commit is contained in:
Matthias Ringwald 2017-09-18 11:48:12 +02:00
parent ed2ed8e12c
commit 0493bf3a19

View File

@ -2412,6 +2412,7 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
// get code, signalind identifier and command len
uint8_t code = command[L2CAP_SIGNALING_COMMAND_CODE_OFFSET];
uint8_t sig_id = command[L2CAP_SIGNALING_COMMAND_SIGID_OFFSET];
uint16_t cmd_len = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_LENGTH_OFFSET);
// not for a particular channel, and not CONNECTION_REQUEST, ECHO_[REQUEST|RESPONSE], INFORMATION_RESPONSE
if (code < 1 || code == ECHO_RESPONSE || code > INFORMATION_RESPONSE){
@ -2422,31 +2423,39 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
// general commands without an assigned channel
switch(code) {
case CONNECTION_REQUEST: {
case CONNECTION_REQUEST:
if (cmd_len == 4){
uint16_t psm = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
uint16_t source_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
l2cap_handle_connection_request(handle, sig_id, psm, source_cid);
return;
} else {
l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN);
}
return;
case ECHO_REQUEST:
l2cap_register_signaling_response(handle, code, sig_id, 0, 0);
return;
case INFORMATION_REQUEST: {
case INFORMATION_REQUEST:
if (cmd_len == 2) {
uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
l2cap_register_signaling_response(handle, code, sig_id, 0, info_type);
return;
} else {
l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN);
}
return;
#ifdef ENABLE_L2CAP_ENHANCED_RETRANSMISSION_MODE
case INFORMATION_RESPONSE: {
hci_connection_t * connection = hci_connection_for_handle(handle);
if (!connection) return;
if (cmd_len >= 4) {
uint16_t info_type = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);
uint16_t result = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+2);
if (result != 0) return;
if (info_type != L2CAP_INFO_TYPE_EXTENDED_FEATURES_SUPPORTED) return;
if (cmd_len >= 6) {
connection->l2cap_state.information_state = L2CAP_INFORMATION_STATE_DONE;
connection->l2cap_state.extended_feature_mask = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET+4);
log_info("extended features mask 0x%02x", connection->l2cap_state.extended_feature_mask);
@ -2481,6 +2490,10 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
l2cap_emit_incoming_connection(channel);
}
}
return; // cmd len valid
}
}
l2cap_register_signaling_response(handle, COMMAND_REJECT, sig_id, 0, L2CAP_REJ_CMD_UNKNOWN);
return;
}
#endif
@ -2489,7 +2502,6 @@ static void l2cap_signaling_handler_dispatch(hci_con_handle_t handle, uint8_t *
break;
}
// Get potential destination CID
uint16_t dest_cid = little_endian_read_16(command, L2CAP_SIGNALING_COMMAND_DATA_OFFSET);