Fixed some moderate issues
Some checks failed
Build / macOS-14 cc (push) Has been cancelled
Build / ubuntu-latest clang (push) Has been cancelled
Build / ubuntu-latest clang-1 (push) Has been cancelled
Build / ubuntu-22.04 clang-12 (push) Has been cancelled
Build / ubuntu-latest gcc (push) Has been cancelled
Build / ubuntu-latest gcc-1 (push) Has been cancelled
Build / ubuntu-latest gcc-2 (push) Has been cancelled
Build / ubuntu-22.04 gcc-10 (push) Has been cancelled
Build / ubuntu-22.04 gcc-9 (push) Has been cancelled
Docker Build / docker (push) Has been cancelled
ArchLinux PKGBUILD / build (push) Has been cancelled
FreeBSD Build / Build and Test (push) Has been cancelled
Build OpenWrt Packages / build (armsr-armv8) (push) Has been cancelled
Build OpenWrt Packages / build (malta-be) (push) Has been cancelled
Build OpenWrt Packages / build (ramips-mt7621) (push) Has been cancelled
Build OpenWrt Packages / build (x86-64) (push) Has been cancelled
RPM Build / build (push) Has been cancelled
SonarQube Scan / Build and analyze (push) Has been cancelled

* `get_ip_address_and_netmask` checks if address and netmask is set
 * if flow analyses memory allocation fails in `alloc_detection_data`,
   all memory must be free'd to prevent memory leak
 * fix possible `get_default_pcapdev` NULL deref
 * fix broken IPv6 address compare in `ip_tuples_compare`
 * fix (unlikely) underflow in `is_error_event_threshold`
 * immediately close collector socket fd on failure in `connect_to_collector`
 * fix invalid "IPv6 packet too short" error JSON event
 * fix broken `read_uuid_from_file` and fix usage in config file
 * fix `SIGPIPE` signal which might occur on first collector connect
   (i.e. if collector not reachable at startup)
 * fix possible `gethostname` off-by-one read

Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
This commit is contained in:
Toni Uhlig 2026-09-29 10:19:38 +02:00
parent 3eea211161
commit 33e233a208
No known key found for this signature in database
GPG key ID: 22C5333D922537D2

125
nDPId.c
View file

@ -1146,6 +1146,15 @@ static void get_ip_address_and_netmask(struct ifaddrs const * const ifaddr, stru
{
enum nDPId_l3_type l3_type = (ifaddr->ifa_addr->sa_family == AF_INET ? L3_IP : L3_IP6);
if (ifaddr->ifa_addr == NULL) {
logger(1, "Expected IP address, but none found: -E and -I will not work!");
return;
}
if (ifaddr->ifa_netmask == NULL) {
logger(1, "Expected IP netmask, but none found: -E and -I will not work!");
return;
}
if (l3_type == L3_IP6) {
get_ip6_from_sockaddr((struct sockaddr_in6 *)ifaddr->ifa_netmask, &if_ip->netmask);
get_ip6_from_sockaddr((struct sockaddr_in6 *)ifaddr->ifa_addr, &if_ip->address);
@ -1846,6 +1855,11 @@ static int alloc_detection_data(struct nDPId_flow * const flow)
flow->flow_extended.flow_analysis->entropies =
(float *)ndpi_malloc(sizeof(*flow->flow_extended.flow_analysis->entropies) *
GET_CMDARG_ULL(nDPId_options.max_packets_per_flow_to_analyse));
if (flow->flow_extended.flow_analysis->directions == NULL ||
flow->flow_extended.flow_analysis->entropies == NULL)
{
goto error;
}
if (ndpi_init_bin(&flow->flow_extended.flow_analysis->payload_len_bin[FD_SRC2DST],
ndpi_bin_family8,
@ -1864,6 +1878,10 @@ static int alloc_detection_data(struct nDPId_flow * const flow)
return 0;
error:
if (GET_CMDARG_BOOL(nDPId_options.enable_data_analysis) != 0)
{
free_analysis_data(&flow->flow_extended);
}
free_detection_data(flow);
flow->info.detection_completed = 1;
return 1;
@ -1942,7 +1960,7 @@ static void free_workflow(struct nDPId_workflow ** const workflow)
static char * get_default_pcapdev(char * errbuf)
{
char * ifname;
char * ifname = NULL;
pcap_if_t * all_devices = NULL;
if (pcap_findalldevs(&all_devices, errbuf) != 0)
@ -1954,7 +1972,10 @@ static char * get_default_pcapdev(char * errbuf)
return NULL;
}
ifname = strdup(all_devices[0].name);
if (all_devices->name != NULL)
{
ifname = strdup(all_devices->name);
}
pcap_freealldevs(all_devices);
return ifname;
@ -2050,19 +2071,35 @@ static int ip_tuples_compare(struct nDPId_flow_basic const * const A, struct nDP
}
else if (A->l3_type == L3_IP6 && B->l3_type == L3_IP6)
{
if (A->src.v6.ip[0] < B->src.v6.ip[0] || A->src.v6.ip[1] < B->src.v6.ip[1])
if (A->src.v6.ip[0] < B->src.v6.ip[0])
{
return -1;
}
if (A->src.v6.ip[0] > B->src.v6.ip[0] && A->src.v6.ip[1] > B->src.v6.ip[1])
if (A->src.v6.ip[0] > B->src.v6.ip[0])
{
return 1;
}
if (A->dst.v6.ip[0] < B->dst.v6.ip[0] || A->dst.v6.ip[1] < B->dst.v6.ip[1])
if (A->src.v6.ip[1] < B->src.v6.ip[1])
{
return -1;
}
if (A->dst.v6.ip[0] > B->dst.v6.ip[0] && A->dst.v6.ip[1] > B->dst.v6.ip[1])
if (A->src.v6.ip[1] > B->src.v6.ip[1])
{
return 1;
}
if (A->dst.v6.ip[0] < B->dst.v6.ip[0])
{
return -1;
}
if (A->dst.v6.ip[0] > B->dst.v6.ip[0])
{
return 1;
}
if (A->dst.v6.ip[1] < B->dst.v6.ip[1])
{
return -1;
}
if (A->dst.v6.ip[1] > B->dst.v6.ip[1])
{
return 1;
}
@ -2148,7 +2185,8 @@ static int is_flow_update_required(struct nDPId_workflow const * const workflow,
static int is_error_event_threshold(struct nDPId_workflow * const workflow)
{
if (workflow->last_global_time - workflow->last_error_time >
if (workflow->last_global_time >= workflow->last_error_time &&
workflow->last_global_time - workflow->last_error_time >
GET_CMDARG_ULL(nDPId_options.error_event_threshold_time))
{
workflow->error_count = 0;
@ -2746,13 +2784,14 @@ static int connect_to_collector(struct nDPId_reader_thread * const reader_thread
if (reader_thread->collector_sockfd < 0 || set_fd_cloexec(reader_thread->collector_sockfd) < 0)
{
reader_thread->collector_sock_last_errno = errno;
return 1;
goto error;
}
int opt = NETWORK_BUFFER_MAX_SIZE;
if (setsockopt(reader_thread->collector_sockfd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(opt)) < 0)
{
return 1;
reader_thread->collector_sock_last_errno = errno;
goto error;
}
struct timeval sock_read;
@ -2760,7 +2799,8 @@ static int connect_to_collector(struct nDPId_reader_thread * const reader_thread
sock_read.tv_usec = 0;
if (setsockopt(reader_thread->collector_sockfd, SOL_SOCKET, SO_RCVTIMEO, &sock_read, sizeof(sock_read)) < 0)
{
return 1;
reader_thread->collector_sock_last_errno = errno;
goto error;
}
if (connect(reader_thread->collector_sockfd,
@ -2768,17 +2808,21 @@ static int connect_to_collector(struct nDPId_reader_thread * const reader_thread
nDPId_options.parsed_collector_address.size) < 0)
{
reader_thread->collector_sock_last_errno = errno;
return 1;
goto error;
}
if (set_collector_nonblock(reader_thread) != 0)
{
return 1;
goto error;
}
reader_thread->collector_sock_last_errno = 0;
return 0;
error:
close(reader_thread->collector_sockfd);
reader_thread->collector_sockfd = -1;
return 1;
}
static void send_to_collector(struct nDPId_reader_thread * const reader_thread,
@ -4675,12 +4719,12 @@ process_layer3_again:
if (distribute_single_packet(reader_thread) != 0 && is_error_event_threshold(reader_thread->workflow) == 0)
{
jsonize_error_eventf(reader_thread,
IP4_PACKET_TOO_SHORT,
IP6_PACKET_TOO_SHORT,
"%s%u %s%zu",
"size",
header->caplen,
"expected",
ip_offset + 1 + sizeof(*ip));
ip_offset + 1 + sizeof(*ip6));
jsonize_packet_event(reader_thread, header, packet, type, ip_offset, 0, 0, NULL, PACKET_EVENT_PAYLOAD);
}
return;
@ -6065,22 +6109,30 @@ static int read_uuid_from_file(char const * const path)
return 1;
}
uuid_len = fread(uuid, sizeof(uuid[0]), sizeof(uuid), fp);
if (uuid_len == 0)
if (ferror(fp) != 0)
{
logger_early(1, "Could not read UUID from file `%s': %s", path, strerror(errno));
fclose(fp);
return 1;
}
if (uuid_len >= 36)
{
uuid[36] = '\0';
}
else
{
uuid[uuid_len] = '\0';
}
fclose(fp);
if (uuid_len == 40)
{
logger_early(1, "UUID file `%s' invalid amount of characters (>= %zu) found", path, uuid_len);
return 1;
} else if (uuid_len > 36) {
if (uuid[36] != '\r' && uuid[36] != '\n')
{
logger_early(1, "Unexpected character in UUID file `%s' found: `%c'", path, uuid[36]);
return 1;
}
uuid[36] = '\0';
} else {
logger_early(1, "UUID file `%s' not an ASCII UUID, expected format 00000000-dead-c0de-0000-123456789abc", path);
return 1;
}
set_cmdarg_string(&nDPId_options.instance_uuid, uuid);
return 0;
}
@ -6194,17 +6246,7 @@ static int nDPId_parse_options(int argc, char ** argv)
set_cmdarg_string(&nDPId_options.instance_alias, optarg);
break;
case 'U':
if (strncmp(optarg, "/", 1) == 0 || strncmp(optarg, ".", 1) == 0)
{
if (read_uuid_from_file(optarg) != 0)
{
return 1;
}
}
else
{
set_cmdarg_string(&nDPId_options.instance_uuid, optarg);
}
set_cmdarg_string(&nDPId_options.instance_uuid, optarg);
break;
case 'A':
set_cmdarg_boolean(&nDPId_options.enable_data_analysis, 1);
@ -6382,13 +6424,14 @@ static int validate_options(void)
char hname[256];
errno = 0;
if (gethostname(hname, sizeof(hname)) != 0)
if (gethostname(hname, sizeof(hname) - 1) != 0)
{
logger_early(1, "Could not retrieve your hostname: %s", strerror(errno));
retval = 1;
}
else
{
hname[sizeof(hname) - 1] = '\0';
set_cmdarg_string(&nDPId_options.instance_alias, hname);
logger_early(1,
"No instance alias given, using your hostname `%s'",
@ -6401,6 +6444,15 @@ static int validate_options(void)
}
if (IS_CMDARG_SET(nDPId_options.instance_uuid) != 0)
{
if (strncmp(GET_CMDARG_STR(nDPId_options.instance_uuid), "/", 1) == 0 ||
strncmp(GET_CMDARG_STR(nDPId_options.instance_uuid), ".", 1) == 0)
{
if (read_uuid_from_file(GET_CMDARG_STR(nDPId_options.instance_uuid)) != 0)
{
return 1;
}
}
size_t uuid_errors = validate_uuid();
if (uuid_errors != 0)
{
@ -6712,6 +6764,8 @@ int main(int argc, char ** argv)
logger_early(1, "Could not initialize libnDPI global context.");
}
signal(SIGPIPE, SIG_IGN);
if (setup_reader_threads() != 0)
{
return 1;
@ -6724,7 +6778,6 @@ int main(int argc, char ** argv)
signal(SIGINT, sighandler);
signal(SIGTERM, sighandler);
signal(SIGPIPE, SIG_IGN);
while (MT_GET_AND_ADD(nDPId_main_thread_shutdown, 0) == 0 && processing_threads_error_or_eof() == 0)
{