Implemented sanity checks for sample / records lengths received from the wire in libsflow logic. Closes: #848 (#849)

This commit is contained in:
Pavel Odintsov 2020-08-25 19:55:40 +01:00 committed by GitHub
parent 4e7f714d1e
commit c0286711cc
Signed by: GitHub
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 34 additions and 0 deletions

View File

@ -126,6 +126,17 @@ bool get_records(vector_tuple_t& vector_tuple,
int32_t element_type = get_int_value_by_32bit_shift(flow_record_start, 0);
int32_t element_length = get_int_value_by_32bit_shift(flow_record_start, 1);
// sFlow v5 standard does not constrain size of each sample but
// we need to apply some reasonable limits on this value to avoid possible integer overflows in boundary checks code below
// and I've decided to limit sample size by maximum UDP packet size
if (element_length > max_udp_packet_size) {
logger << log4cpp::Priority::ERROR << sflow_parser_log_prefix << "Element length " << element_length
<< " exceeds maximum allowed size: " << max_udp_packet_size;
return false;
}
uint8_t* flow_record_data_ptr = flow_record_start + sizeof(element_type) + sizeof(element_length);
uint8_t* flow_record_end = flow_record_data_ptr + element_length;
@ -178,6 +189,16 @@ bool get_all_samples(vector_sample_tuple_t& vector_sample,
int32_t enterprise_with_format = get_int_value_by_32bit_shift(sample_start, 0);
int32_t sample_length = get_int_value_by_32bit_shift(sample_start, 1);
// sFlow v5 standard does not constrain size of each sample but
// we need to apply some reasonable limits on this value to avoid possible integer overflows in boundary checks code below
// and I've decided to limit sample size by maximum UDP packet size
if (sample_length > max_udp_packet_size) {
logger << log4cpp::Priority::ERROR << sflow_parser_log_prefix << "Sample length " << sample_length
<< " exceeds maximum allowed size: " << max_udp_packet_size;
return false;
}
// Get first 20 bits as enterprise
int32_t enterprise = enterprise_with_format >> 12;
@ -238,6 +259,16 @@ bool get_all_counter_records(counter_record_sample_vector_t& counter_record_samp
int32_t enterprise_and_format = get_int_value_by_32bit_shift(record_start, 0);
uint32_t record_length = get_int_value_by_32bit_shift(record_start, 1);
// sFlow v5 standard does not constrain size of each sample but
// we need to apply some reasonable limits on this value to avoid possible integer overflows in boundary checks code below
// and I've decided to limit sample size by maximum UDP packet size
if (record_length > max_udp_packet_size) {
logger << log4cpp::Priority::ERROR << sflow_parser_log_prefix << "Record length " << record_length
<< " exceeds maximum allowed size: " << max_udp_packet_size;
return false;
}
uint8_t* current_record_end = payload_ptr + record_length;
if (current_record_end > data_block_end) {

View File

@ -12,6 +12,9 @@
#include <arpa/inet.h>
// We need it for sanity checks
const uint32_t max_udp_packet_size = 65535;
enum class sflow_sample_type_t : unsigned int {
FLOW_SAMPLE = 1,
COUNTER_SAMPLE = 2,