Browse Source

Control: harden socket against malformed data and buffer overflows

- immediate close on bad size/type/payload
- recv_len guard to prevent overflow
- unknown commands now close without response
master
Evgeny 1 day ago
parent
commit
fd815150f6
  1. 33
      src/control_server.c

33
src/control_server.c

@ -528,8 +528,11 @@ static void client_read_callback(socket_t fd, void* arg) {
} }
client->recv_len += received; client->recv_len += received;
if (client->recv_len > ETCPMON_MAX_MSG_SIZE) {
/* Process messages */ DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Control recv buffer overflow");
if (server) close_client(server, client);
return;
}
if (server) { if (server) {
handle_client_data(server, client); handle_client_data(server, client);
} }
@ -601,6 +604,17 @@ static void handle_client_data(struct control_server* server, struct control_cli
while (client->recv_len >= sizeof(struct etcpmon_msg_header)) { while (client->recv_len >= sizeof(struct etcpmon_msg_header)) {
struct etcpmon_msg_header* hdr = (struct etcpmon_msg_header*)client->recv_buffer; struct etcpmon_msg_header* hdr = (struct etcpmon_msg_header*)client->recv_buffer;
if (hdr->size == 0 || hdr->size > ETCPMON_MAX_MSG_SIZE) {
DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Invalid message size from client: %u", hdr->size);
close_client(server, client);
return;
}
if (hdr->type < ETCPMON_CMD_LIST_CONN || hdr->type > ETCPMON_CMD_DISCONNECT) {
DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Invalid command type from client: 0x%02X", hdr->type);
close_client(server, client);
return;
}
/* Validate header */ /* Validate header */
if (etcpmon_validate_header(hdr) != 0) { if (etcpmon_validate_header(hdr) != 0) {
if (server->log_file) { if (server->log_file) {
@ -646,6 +660,10 @@ static void handle_client_data(struct control_server* server, struct control_cli
} }
DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Client selected connection: %016llX", DEBUG_INFO(DEBUG_CATEGORY_CONTROL, "Client selected connection: %016llX",
(unsigned long long)cmd->peer_node_id); (unsigned long long)cmd->peer_node_id);
} else {
DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Bad SELECT_CONN payload size %u", payload_size);
close_client(server, client);
return;
} }
break; break;
@ -668,14 +686,9 @@ static void handle_client_data(struct control_server* server, struct control_cli
return; return;
default: default:
if (server->log_file) { DEBUG_ERROR(DEBUG_CATEGORY_CONTROL, "Unknown command from client: 0x%02X", hdr->type);
fprintf(server->log_file, "%llu: [ERROR] Unknown command from client: 0x%02X\n", close_client(server, client);
(unsigned long long)get_timestamp_ms(), hdr->type); return;
fflush(server->log_file);
}
DEBUG_WARN(DEBUG_CATEGORY_CONTROL, "Unknown command from client: 0x%02X", hdr->type);
send_error(client, ETCPMON_ERR_INVALID_CMD, "Unknown command", req_seq);
break;
} }
/* Remove processed message from buffer */ /* Remove processed message from buffer */

Loading…
Cancel
Save