aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2022-12-23 19:07:13 +0100
committerGitHub <noreply@github.com>2022-12-23 19:07:13 +0100
commit560280e6f082d22e6a9de8e537b7876bacf8d072 (patch)
treea8ed2ea6c43614606cc977fc27050dd41e0c3133
parent3de76812d978060c433864c2f72de113746d70e8 (diff)
fuzz: add fuzzer testing nDPI (initial) configurations (#1830)
The goal of this fuzzer is to test init and deinit of the library, with different configurations. In details: * random memory allocation failures, even during init phase * random `ndpi_init_prefs` parameter of `ndpi_init_detection_module()` * random LRU caches sizes * random bitmask of enabled protocols * random parameters of `ndpi_set_detection_preferences()` * random initialization of opportunistic TLS * random load/don't load of configuration files This new fuzzer is a C++ file, because it uses `FuzzedDataProvider` class (see https://github.com/google/fuzzing/blob/master/docs/split-inputs.md). Note that the (existing) fuzzers need to be linked with C++ compiler anyway, so this new fuzzer doesn't add any new requirements.
-rw-r--r--.github/workflows/cifuzz.yml2
-rw-r--r--configure.ac5
-rw-r--r--fuzz/Makefile.am20
-rw-r--r--fuzz/fuzz_common_code.c30
-rw-r--r--fuzz/fuzz_common_code.h15
-rw-r--r--fuzz/fuzz_config.cpp113
-rw-r--r--fuzz/fuzz_ndpi_reader.c32
-rw-r--r--src/include/ndpi_api.h3
-rw-r--r--src/include/ndpi_define.h.in6
-rw-r--r--src/lib/ndpi_main.c84
-rw-r--r--src/lib/ndpi_utils.c13
-rw-r--r--src/lib/third_party/src/ahocorasick.c15
-rw-r--r--src/lib/third_party/src/ndpi_patricia.c32
13 files changed, 310 insertions, 60 deletions
diff --git a/.github/workflows/cifuzz.yml b/.github/workflows/cifuzz.yml
index a4b7ddbe9..62f0d417c 100644
--- a/.github/workflows/cifuzz.yml
+++ b/.github/workflows/cifuzz.yml
@@ -18,7 +18,7 @@ jobs:
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'ndpi'
- fuzz-seconds: 900
+ fuzz-seconds: 1200
dry-run: false
sanitizer: ${{ matrix.sanitizer }}
- name: Check Crash (fails when a crash is detected)
diff --git a/configure.ac b/configure.ac
index 3b3e64d4c..b55abdf61 100644
--- a/configure.ac
+++ b/configure.ac
@@ -28,7 +28,10 @@ AC_ARG_ENABLE(npcap, AS_HELP_STRING([--disable-npcap], [msys2 only: Disable link
AC_ARG_WITH(nbpf-path, AS_HELP_STRING([--with-nbpf-path], [nBPF library custom path; default: ${PWD}/../PF_RING/userland/nbpf]),[NBPF_HOME=$withval],[NBPF_HOME=${PWD}/../PF_RING/userland/nbpf])
AC_ARG_WITH(lto-and-gold-linker, AS_HELP_STRING([--with-lto-and-gold-linker], [Build with LTO and Gold linker])])
-AS_IF([test "x$enable_fuzztargets" = "xyes"], [BUILD_FUZZTARGETS=1], [BUILD_FUZZTARGETS=0])
+AS_IF([test "x$enable_fuzztargets" = "xyes"], [
+ BUILD_FUZZTARGETS=1
+ NDPI_CFLAGS="${NDPI_CFLAGS} -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION"
+], [BUILD_FUZZTARGETS=0])
AM_CONDITIONAL([BUILD_FUZZTARGETS], [test "x$enable_fuzztargets" = "xyes"])
AS_IF([test "${with_sanitizer+set}" = set -a "${with_thread_sanitizer+set}" = set],[
diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am
index 0d4f583e6..9ee8571c8 100644
--- a/fuzz/Makefile.am
+++ b/fuzz/Makefile.am
@@ -1,4 +1,4 @@
-bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail fuzz_quic_get_crypto_data
+bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail fuzz_quic_get_crypto_data fuzz_config
fuzz_process_packet_SOURCES = fuzz_process_packet.c fuzz_common_code.c
fuzz_process_packet_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
@@ -26,7 +26,7 @@ fuzz_ndpi_reader_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_ndpi_reader_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@
-fuzz_ndpi_reader_alloc_fail_SOURCES = fuzz_ndpi_reader.c ../example/reader_util.c
+fuzz_ndpi_reader_alloc_fail_SOURCES = fuzz_ndpi_reader.c fuzz_common_code.c ../example/reader_util.c
fuzz_ndpi_reader_alloc_fail_CFLAGS = -I../example/ @NDPI_CFLAGS@ $(CXXFLAGS) -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -DENABLE_MEM_ALLOC_FAILURES
fuzz_ndpi_reader_alloc_fail_LDADD = ../src/lib/libndpi.a
fuzz_ndpi_reader_alloc_fail_LDFLAGS = $(PCAP_LIB) $(ADDITIONAL_LIBS) $(LIBS)
@@ -52,6 +52,21 @@ fuzz_quic_get_crypto_data_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS)
$(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
$(fuzz_quic_get_crypto_data_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@
+fuzz_config_SOURCES = fuzz_config.cpp fuzz_common_code.c
+fuzz_config_CXXFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -DENABLE_MEM_ALLOC_FAILURES
+fuzz_config_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION -DENABLE_MEM_ALLOC_FAILURES
+fuzz_config_LDADD = ../src/lib/libndpi.a
+fuzz_config_LDFLAGS = $(ADDITIONAL_LIBS) $(LIBS)
+if HAS_FUZZLDFLAGS
+fuzz_config_CXXFLAGS += $(LIB_FUZZING_ENGINE)
+fuzz_config_CFLAGS += $(LIB_FUZZING_ENGINE)
+fuzz_config_LDFLAGS += $(LIB_FUZZING_ENGINE)
+endif
+# force usage of CXX for linker
+fuzz_config_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
+ $(fuzz_config_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@
+
# required for Google oss-fuzz
# see https://github.com/google/oss-fuzz/tree/master/projects/ndpi
testpcaps := $(wildcard ../tests/pcap/*.pcap*)
@@ -74,6 +89,7 @@ distdir:
find . -type f -name '*.c' \
-o -name '*.am' \
-o -name '*.h' \
+ -o -name '*.cpp' \
-o -name '*.bin' | xargs -I'{}' cp '{}' '$(distdir)/{}'
all: corpus
diff --git a/fuzz/fuzz_common_code.c b/fuzz/fuzz_common_code.c
index 5ad2a5899..bd5ef20a4 100644
--- a/fuzz/fuzz_common_code.c
+++ b/fuzz/fuzz_common_code.c
@@ -1,6 +1,32 @@
#include "fuzz_common_code.h"
+
+#ifdef ENABLE_MEM_ALLOC_FAILURES
+
+static int mem_alloc_state = 0;
+
+__attribute__((no_sanitize("integer")))
+static int fastrand ()
+{
+ if(!mem_alloc_state) return 1; /* No failures */
+ mem_alloc_state = (214013 * mem_alloc_state + 2531011);
+ return (mem_alloc_state >> 16) & 0x7FFF;
+}
+
+void *malloc_wrapper(size_t size) {
+ return (fastrand () % 16) ? malloc (size) : NULL;
+}
+void free_wrapper(void *freeable) {
+ free(freeable);
+}
+
+void set_mem_alloc_state(int value) {
+ mem_alloc_state = value;
+}
+
+#endif
+
void fuzz_init_detection_module(struct ndpi_detection_module_struct **ndpi_info_mod,
int enable_log)
{
@@ -8,6 +34,10 @@ void fuzz_init_detection_module(struct ndpi_detection_module_struct **ndpi_info_
NDPI_PROTOCOL_BITMASK all, debug_bitmask;
if(*ndpi_info_mod == NULL) {
+#ifdef ENABLE_MEM_ALLOC_FAILURES
+ set_ndpi_malloc(malloc_wrapper);
+ set_ndpi_free(free_wrapper);
+#endif
*ndpi_info_mod = ndpi_init_detection_module(prefs);
NDPI_BITMASK_SET_ALL(all);
ndpi_set_protocol_detection_bitmask2(*ndpi_info_mod, &all);
diff --git a/fuzz/fuzz_common_code.h b/fuzz/fuzz_common_code.h
index 5225446ad..9f26ea060 100644
--- a/fuzz/fuzz_common_code.h
+++ b/fuzz/fuzz_common_code.h
@@ -3,7 +3,22 @@
#include "ndpi_api.h"
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+#ifdef ENABLE_MEM_ALLOC_FAILURES
+void *malloc_wrapper(size_t size);
+void free_wrapper(void *freeable);
+void set_mem_alloc_state(int value);
+#endif
+
void fuzz_init_detection_module(struct ndpi_detection_module_struct **ndpi_info_mod,
int enable_log);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/fuzz/fuzz_config.cpp b/fuzz/fuzz_config.cpp
new file mode 100644
index 000000000..884e3720e
--- /dev/null
+++ b/fuzz/fuzz_config.cpp
@@ -0,0 +1,113 @@
+#include "ndpi_api.h"
+#include "fuzz_common_code.h"
+
+#include <stdint.h>
+#include <stdio.h>
+#include <assert.h>
+#include "fuzzer/FuzzedDataProvider.h"
+
+
+extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
+ FuzzedDataProvider fuzzed_data(data, size);
+ struct ndpi_detection_module_struct *ndpi_info_mod;
+ struct ndpi_flow_struct flow;
+ u_int8_t protocol_was_guessed;
+ u_int32_t i, num;
+ u_int16_t random_proto;
+ int random_value;
+ NDPI_PROTOCOL_BITMASK enabled_bitmask;
+ struct ndpi_lru_cache_stats lru_stats;
+ struct ndpi_patricia_tree_stats patricia_stats;
+ struct ndpi_automa_stats automa_stats;
+
+ if(fuzzed_data.remaining_bytes() < 4 + /* ndpi_init_detection_module() */
+ NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS +
+ 5 + /* files */
+ (NDPI_LRUCACHE_MAX * 3) + /* LRU caches */
+ 2 + 1 + 4 + /* ndpi_set_detection_preferences() */
+ 7 + /* Opportunistic tls */
+ 29 /* Min real data: ip length + udp length + 1 byte */)
+ return -1;
+
+#ifdef ENABLE_MEM_ALLOC_FAILURES
+ set_ndpi_malloc(malloc_wrapper);
+ set_ndpi_free(free_wrapper);
+ set_mem_alloc_state(size);
+#endif
+
+ ndpi_info_mod = ndpi_init_detection_module(fuzzed_data.ConsumeIntegral<u_int32_t>());
+
+ NDPI_BITMASK_RESET(enabled_bitmask);
+ for(i = 0; i < NDPI_MAX_SUPPORTED_PROTOCOLS + NDPI_MAX_NUM_CUSTOM_PROTOCOLS ; i++) {
+ if(fuzzed_data.ConsumeBool())
+ NDPI_BITMASK_ADD(enabled_bitmask, i);
+ }
+ if(ndpi_set_protocol_detection_bitmask2(ndpi_info_mod, &enabled_bitmask) == -1) {
+ ndpi_exit_detection_module(ndpi_info_mod);
+ ndpi_info_mod = NULL;
+ }
+
+ if(fuzzed_data.ConsumeBool())
+ ndpi_load_protocols_file(ndpi_info_mod, "protos.txt");
+ if(fuzzed_data.ConsumeBool())
+ ndpi_load_categories_file(ndpi_info_mod, "categories.txt", NULL);
+ if(fuzzed_data.ConsumeBool())
+ ndpi_load_risk_domain_file(ndpi_info_mod, "risky_domains.txt");
+ if(fuzzed_data.ConsumeBool())
+ ndpi_load_malicious_ja3_file(ndpi_info_mod, "ja3_fingerprints.csv");
+ if(fuzzed_data.ConsumeBool())
+ ndpi_load_malicious_sha1_file(ndpi_info_mod, "sha1_fingerprints.csv");
+
+ for(i = 0; i < NDPI_LRUCACHE_MAX; i++) {
+ ndpi_set_lru_cache_size(ndpi_info_mod, static_cast<lru_cache_type>(i),
+ fuzzed_data.ConsumeIntegralInRange(0, (1 << 24) - 1));
+ ndpi_get_lru_cache_size(ndpi_info_mod, static_cast<lru_cache_type>(i), &num);
+ }
+
+ if(fuzzed_data.ConsumeBool())
+ ndpi_set_detection_preferences(ndpi_info_mod, ndpi_pref_direction_detect_disable,
+ fuzzed_data.ConsumeBool());
+ if(fuzzed_data.ConsumeBool())
+ ndpi_set_detection_preferences(ndpi_info_mod, ndpi_pref_enable_tls_block_dissection,
+ 0 /* unused */);
+ if(fuzzed_data.ConsumeBool())
+ ndpi_set_detection_preferences(ndpi_info_mod, ndpi_pref_max_packets_to_process,
+ fuzzed_data.ConsumeIntegralInRange(0, (1 << 16)));
+
+ ndpi_set_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_SMTP, fuzzed_data.ConsumeBool());
+ ndpi_get_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_SMTP);
+ ndpi_set_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_IMAP, fuzzed_data.ConsumeBool());
+ ndpi_get_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_IMAP);
+ ndpi_set_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_POP, fuzzed_data.ConsumeBool());
+ ndpi_get_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_MAIL_POP);
+ ndpi_set_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_FTP_CONTROL, fuzzed_data.ConsumeBool());
+ ndpi_get_opportunistic_tls(ndpi_info_mod, NDPI_PROTOCOL_FTP_CONTROL);
+
+ random_proto = fuzzed_data.ConsumeIntegralInRange(0, (1 << 16) - 1);
+ random_value = fuzzed_data.ConsumeIntegralInRange(0,2); /* Only 0-1 are valid values */
+ ndpi_set_opportunistic_tls(ndpi_info_mod, random_proto, random_value);
+ ndpi_get_opportunistic_tls(ndpi_info_mod, random_proto);
+
+ ndpi_finalize_initialization(ndpi_info_mod);
+
+
+ /* Basic code to try testing this "config" */
+ memset(&flow, 0, sizeof(flow));
+ std::vector<uint8_t>pkt = fuzzed_data.ConsumeRemainingBytes<uint8_t>();
+ assert(pkt.size() >= 29); /* To be sure check on fuzzed_data.remaining_bytes() at the beginning is right */
+ ndpi_detection_process_packet(ndpi_info_mod, &flow, pkt.data(), pkt.size(), 0, NULL);
+ ndpi_detection_giveup(ndpi_info_mod, &flow, 1, &protocol_was_guessed);
+ ndpi_free_flow_data(&flow);
+
+ /* Get some final stats */
+ for(i = 0; i < NDPI_LRUCACHE_MAX; i++)
+ ndpi_get_lru_cache_stats(ndpi_info_mod, static_cast<lru_cache_type>(i), &lru_stats);
+ for(i = 0; i < NDPI_PTREE_MAX; i++)
+ ndpi_get_patricia_stats(ndpi_info_mod, static_cast<ptree_type>(i), &patricia_stats);
+ for(i = 0; i < NDPI_AUTOMA_MAX; i++)
+ ndpi_get_automa_stats(ndpi_info_mod, static_cast<automa_type>(i), &automa_stats);
+
+ ndpi_exit_detection_module(ndpi_info_mod);
+
+ return 0;
+}
diff --git a/fuzz/fuzz_ndpi_reader.c b/fuzz/fuzz_ndpi_reader.c
index dc63c7f07..ead9ce87b 100644
--- a/fuzz/fuzz_ndpi_reader.c
+++ b/fuzz/fuzz_ndpi_reader.c
@@ -1,5 +1,6 @@
#include "reader_util.h"
#include "ndpi_api.h"
+#include "fuzz_common_code.h"
#include <pcap/pcap.h>
@@ -23,27 +24,6 @@ int malloc_size_stats = 0;
int max_malloc_bins = 0;
struct ndpi_bin malloc_bins; /* unused */
-#ifdef ENABLE_MEM_ALLOC_FAILURES
-
-static int mem_alloc_state = 0;
-
-__attribute__((no_sanitize("integer")))
-static int fastrand ()
-{
- if(!mem_alloc_state) return 1; /* No failures */
- mem_alloc_state = (214013 * mem_alloc_state + 2531011);
- return (mem_alloc_state >> 16) & 0x7FFF;
-}
-
-static void *malloc_wrapper(size_t size) {
- return (fastrand () % 16) ? malloc (size) : NULL;
-}
-static void free_wrapper(void *freeable) {
- free(freeable);
-}
-
-#endif
-
FILE *bufferToFile(const uint8_t *Data, size_t Size) {
FILE *fd;
fd = tmpfile();
@@ -99,17 +79,13 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
memset(workflow->stats.protocol_flows, 0,
sizeof(workflow->stats.protocol_flows));
ndpi_finalize_initialization(workflow->ndpi_struct);
-#ifdef ENABLE_MEM_ALLOC_FAILURES
- set_ndpi_malloc(malloc_wrapper);
- set_ndpi_free(free_wrapper);
- /* Don't fail memory allocations until init phase is done */
-#endif
}
-
#ifdef ENABLE_MEM_ALLOC_FAILURES
- mem_alloc_state = Size;
+ /* Don't fail memory allocations until init phase is done */
+ set_mem_alloc_state(Size);
#endif
+
fd = bufferToFile(Data, Size);
if (fd == NULL)
return 0;
diff --git a/src/include/ndpi_api.h b/src/include/ndpi_api.h
index bd754f1e1..5214c054f 100644
--- a/src/include/ndpi_api.h
+++ b/src/include/ndpi_api.h
@@ -264,9 +264,10 @@ extern "C" {
*
* @par ndpi_struct = the detection module
* @par detection_bitmask = the protocol bitmask to set
+ * @return 0 if ok, -1 if error
*
*/
- void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct,
+ int ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_struct,
const NDPI_PROTOCOL_BITMASK * detection_bitmask);
/**
diff --git a/src/include/ndpi_define.h.in b/src/include/ndpi_define.h.in
index 31b7a1825..75f41dac2 100644
--- a/src/include/ndpi_define.h.in
+++ b/src/include/ndpi_define.h.in
@@ -218,7 +218,11 @@
# define NDPI_LOG_DBG2(...) {}
# else
# define NDPI_LOG(proto, mod, log_level, args...) { /* printf(args); */ }
-# define NDPI_LOG_ERR(mod, args...) { printf(args); }
+# ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
+# define NDPI_LOG_ERR(mod, args...) { printf(args); }
+# else
+# define NDPI_LOG_ERR(mod, args...) { /* printf(args); */ }
+# endif
# define NDPI_LOG_INFO(mod, args...) { /* printf(args); */ }
# define NDPI_LOG_DBG(mod, args...) { /* printf(args); */ }
# define NDPI_LOG_DBG2(mod, args...) { /* printf(args); */ }
diff --git a/src/lib/ndpi_main.c b/src/lib/ndpi_main.c
index c67e7b2c8..95d880dcb 100644
--- a/src/lib/ndpi_main.c
+++ b/src/lib/ndpi_main.c
@@ -491,13 +491,16 @@ void ndpi_set_proto_subprotocols(struct ndpi_detection_module_struct *ndpi_str,
ndpi_str->proto_defaults[protoId].subprotocols =
ndpi_malloc(sizeof(protoId) * ndpi_str->proto_defaults[protoId].subprotocol_count);
+ if(!ndpi_str->proto_defaults[protoId].subprotocols) {
+ ndpi_str->proto_defaults[protoId].subprotocol_count = 0;
+ return;
+ }
va_start(ap, protoId);
current_arg = va_arg(ap, int);
while (current_arg != NDPI_PROTOCOL_NO_MORE_SUBPROTOCOLS) {
- if(is_proto_enabled(ndpi_str, current_arg) &&
- ndpi_str->proto_defaults[protoId].subprotocols != NULL) {
+ if(is_proto_enabled(ndpi_str, current_arg)) {
ndpi_str->proto_defaults[protoId].subprotocols[i++] = current_arg;
}
current_arg = va_arg(ap, int);
@@ -621,6 +624,11 @@ static void addDefaultPort(struct ndpi_detection_module_struct *ndpi_str,
(void *) root,
ndpi_default_ports_tree_node_t_cmp); /* Add it to the tree */
+ if(ret == NULL) {
+ NDPI_LOG_DBG(ndpi_str, "[NDPI] %s:%d error searching for port %u\n", _func, _line, port);
+ ndpi_free(node);
+ break;
+ }
if(ret != node) {
NDPI_LOG_DBG(ndpi_str, "[NDPI] %s:%d found duplicate for port %u: overwriting it with new value\n",
_func, _line, port);
@@ -803,6 +811,8 @@ void ndpi_init_protocol_match(struct ndpi_detection_module_struct *ndpi_str,
if(ndpi_str->proto_defaults[match->protocol_id].protoName == NULL) {
ndpi_str->proto_defaults[match->protocol_id].protoName = ndpi_strdup(match->proto_name);
+ if(!ndpi_str->proto_defaults[match->protocol_id].protoName)
+ return;
ndpi_str->proto_defaults[match->protocol_id].isAppProtocol = 1;
ndpi_str->proto_defaults[match->protocol_id].protoId = match->protocol_id;
ndpi_str->proto_defaults[match->protocol_id].protoCategory = match->protocol_category;
@@ -925,6 +935,9 @@ static void init_string_based_protocols(struct ndpi_detection_module_struct *ndp
int ndpi_set_detection_preferences(struct ndpi_detection_module_struct *ndpi_str, ndpi_detection_preference pref,
int value) {
+ if(!ndpi_str)
+ return -1;
+
switch(pref) {
case ndpi_pref_direction_detect_disable:
ndpi_str->direction_detect_disable = (u_int8_t) value;
@@ -2157,6 +2170,9 @@ void ndpi_patricia_get_stats(ndpi_patricia_tree_t *tree, struct ndpi_patricia_tr
int ndpi_get_patricia_stats(struct ndpi_detection_module_struct *ndpi_struct,
ptree_type ptree_type,
struct ndpi_patricia_tree_stats *stats) {
+ if(!ndpi_struct || !stats)
+ return -1;
+
switch(ptree_type) {
case NDPI_PTREE_RISK_MASK:
ndpi_patricia_get_stats((ndpi_patricia_tree_t *)ndpi_struct->ip_risk_mask_ptree, stats);
@@ -2296,6 +2312,9 @@ u_int16_t ndpi_network_port_ptree_match(struct ndpi_detection_module_struct *ndp
ndpi_prefix_t prefix;
ndpi_patricia_node_t *node;
+ if(!ndpi_str->protocols_ptree)
+ return(NDPI_PROTOCOL_UNKNOWN);
+
if(ndpi_str->ndpi_num_custom_protocols == 0) {
/*
In case we don't have defined any custom protocol we check the ptree
@@ -2823,7 +2842,7 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
if((ndpi_str->custom_categories.ipAddresses == NULL) || (ndpi_str->custom_categories.ipAddresses_shadow == NULL)) {
NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating Patricia trees\n");
- ndpi_free(ndpi_str);
+ ndpi_exit_detection_module(ndpi_str);
return(NULL);
}
@@ -2841,7 +2860,6 @@ struct ndpi_detection_module_struct *ndpi_init_detection_module(ndpi_init_prefs
ndpi_str->opportunistic_tls_pop_enabled = 1;
ndpi_str->opportunistic_tls_ftp_enabled = 1;
-
for(i = 0; i < NUM_CUSTOM_CATEGORIES; i++)
ndpi_snprintf(ndpi_str->custom_category_labels[i], CUSTOM_CATEGORY_LABEL_LEN, "User custom category %u",
(unsigned int) (i + 1));
@@ -2899,6 +2917,9 @@ static void ndpi_add_domain_risk_exceptions(struct ndpi_detection_module_struct
void ndpi_finalize_initialization(struct ndpi_detection_module_struct *ndpi_str) {
u_int i;
+ if(!ndpi_str)
+ return;
+
ndpi_add_domain_risk_exceptions(ndpi_str);
if(ndpi_str->ookla_cache_num_entries > 0) {
@@ -3035,6 +3056,9 @@ int ndpi_get_automa_stats(struct ndpi_detection_module_struct *ndpi_struct,
automa_type automa_type,
struct ndpi_automa_stats *stats)
{
+ if(!ndpi_struct || !stats)
+ return -1;
+
switch(automa_type) {
case NDPI_AUTOMA_HOST:
ndpi_automa_get_stats(ndpi_struct->host_automa.ac_automa, stats);
@@ -3537,7 +3561,7 @@ int ndpi_add_host_risk_mask(struct ndpi_detection_module_struct *ndpi_str,
u_int len;
char *host_dup = NULL;
- if((ndpi_str->host_risk_mask_automa.ac_automa == NULL) || (host == NULL))
+ if((ndpi_str == NULL) || (ndpi_str->host_risk_mask_automa.ac_automa == NULL) || (host == NULL))
return(-2);
/* Zap heading/trailing quotes */
@@ -3928,6 +3952,8 @@ int ndpi_load_malicious_ja3_file(struct ndpi_detection_module_struct *ndpi_str,
FILE *fd;
int len, num = 0;
+ if(!ndpi_str)
+ return(-1);
if(ndpi_str->malicious_ja3_hashmap == NULL && ndpi_hash_init(&ndpi_str->malicious_ja3_hashmap) != 0)
return(-1);
@@ -3990,6 +4016,8 @@ int ndpi_load_malicious_sha1_file(struct ndpi_detection_module_struct *ndpi_str,
size_t i, len;
int num = 0;
+ if(!ndpi_str)
+ return(-1);
if(ndpi_str->malicious_sha1_hashmap == NULL && ndpi_hash_init(&ndpi_str->malicious_sha1_hashmap) != 0)
return(-1);
@@ -5119,16 +5147,19 @@ void ndpi_free_flow_data(struct ndpi_flow_struct* flow) {
if(flow->l4.udp.quic_reasm_buf_bitmap)
ndpi_free(flow->l4.udp.quic_reasm_buf_bitmap);
}
- }
- if(flow->flow_payload != NULL)
- ndpi_free(flow->flow_payload);
+ if(flow->flow_payload != NULL)
+ ndpi_free(flow->flow_payload);
+ }
}
/* ************************************************ */
-void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_str,
+int ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *ndpi_str,
const NDPI_PROTOCOL_BITMASK *dbm) {
+ if(!ndpi_str)
+ return -1;
+
NDPI_BITMASK_SET(ndpi_str->detection_bitmask, *dbm);
ndpi_init_protocol_defaults(ndpi_str);
@@ -5137,7 +5168,9 @@ void ndpi_set_protocol_detection_bitmask2(struct ndpi_detection_module_struct *n
if(ndpi_callback_init(ndpi_str)) {
NDPI_LOG_ERR(ndpi_str, "[NDPI] Error allocating callbacks\n");
+ return -1;
}
+ return 0;
}
/* ************************************************ */
@@ -5942,7 +5975,7 @@ ndpi_protocol ndpi_detection_giveup(struct ndpi_detection_module_struct *ndpi_st
*protocol_was_guessed = 0;
- if(flow == NULL)
+ if(!ndpi_str || !flow)
return(ret);
/* Init defaults */
@@ -6178,7 +6211,8 @@ int ndpi_enable_loaded_categories(struct ndpi_detection_module_struct *ndpi_str)
1 /* free patterns strings memory */);
/* Finalize */
- ac_automata_finalize((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames_shadow.ac_automa);
+ if(ndpi_str->custom_categories.hostnames_shadow.ac_automa)
+ ac_automata_finalize((AC_AUTOMATA_t *) ndpi_str->custom_categories.hostnames_shadow.ac_automa);
/* Swap */
ndpi_str->custom_categories.hostnames.ac_automa = ndpi_str->custom_categories.hostnames_shadow.ac_automa;
@@ -6410,18 +6444,23 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
struct ndpi_flow_struct *flow, const unsigned char *packet_data,
const unsigned short packetlen, const u_int64_t current_time_ms,
const struct ndpi_flow_input_info *input_info) {
- struct ndpi_packet_struct *packet = &ndpi_str->packet;
+ struct ndpi_packet_struct *packet;
NDPI_SELECTION_BITMASK_PROTOCOL_SIZE ndpi_selection_packet;
u_int32_t num_calls = 0;
- ndpi_protocol ret = { flow->detected_protocol_stack[1], flow->detected_protocol_stack[0], flow->guessed_protocol_id_by_ip, flow->category, NULL };
+ ndpi_protocol ret = { 0 };
+
+ if(!flow || !ndpi_str)
+ return(ret);
+
+ packet = &ndpi_str->packet;
NDPI_LOG_DBG(ndpi_str, "[%d/%d] START packet processing\n",
flow->detected_protocol_stack[0], flow->detected_protocol_stack[1]);
- if(flow == NULL)
- return(ret);
- else
- ret.category = flow->category;
+ ret.master_protocol = flow->detected_protocol_stack[1],
+ ret.app_protocol = flow->detected_protocol_stack[0];
+ ret.protocol_by_ip = flow->guessed_protocol_id_by_ip;
+ ret.category = flow->category;
if(flow->fail_with_unknown) {
// printf("%s(): FAIL_WITH_UNKNOWN\n", __FUNCTION__);
@@ -6437,8 +6476,6 @@ ndpi_protocol ndpi_detection_process_packet(struct ndpi_detection_module_struct
flow->num_processed_pkts++;
/* Init default */
- ret.master_protocol = flow->detected_protocol_stack[1],
- ret.app_protocol = flow->detected_protocol_stack[0];
if(flow->extra_packets_func) {
ndpi_process_extra_packet(ndpi_str, flow, packet_data, packetlen, current_time_ms, input_info);
@@ -8442,6 +8479,9 @@ int ndpi_get_lru_cache_stats(struct ndpi_detection_module_struct *ndpi_struct,
lru_cache_type cache_type,
struct ndpi_lru_cache_stats *stats)
{
+ if(!ndpi_struct || !stats)
+ return -1;
+
switch(cache_type) {
case NDPI_LRUCACHE_OOKLA:
ndpi_lru_get_stats(ndpi_struct->ookla_cache, stats);
@@ -8476,6 +8516,9 @@ int ndpi_set_lru_cache_size(struct ndpi_detection_module_struct *ndpi_struct,
lru_cache_type cache_type,
u_int32_t num_entries)
{
+ if(!ndpi_struct)
+ return -1;
+
switch(cache_type) {
case NDPI_LRUCACHE_OOKLA:
ndpi_struct->ookla_cache_num_entries = num_entries;
@@ -8510,6 +8553,9 @@ int ndpi_get_lru_cache_size(struct ndpi_detection_module_struct *ndpi_struct,
lru_cache_type cache_type,
u_int32_t *num_entries)
{
+ if(!ndpi_struct)
+ return -1;
+
switch(cache_type) {
case NDPI_LRUCACHE_OOKLA:
*num_entries = ndpi_struct->ookla_cache_num_entries;
diff --git a/src/lib/ndpi_utils.c b/src/lib/ndpi_utils.c
index c7b2ff45a..990aef9bd 100644
--- a/src/lib/ndpi_utils.c
+++ b/src/lib/ndpi_utils.c
@@ -2309,6 +2309,9 @@ static u_int64_t ndpi_host_ip_risk_ptree_match(struct ndpi_detection_module_stru
ndpi_prefix_t prefix;
ndpi_patricia_node_t *node;
+ if(!ndpi_str->protocols_ptree)
+ return((u_int64_t)-1);
+
/* Make sure all in network byte order otherwise compares wont work */
ndpi_fill_prefix_v4(&prefix, pin, 32, ((ndpi_patricia_tree_t *) ndpi_str->protocols_ptree)->maxbits);
node = ndpi_patricia_search_best(ndpi_str->ip_risk_mask_ptree, &prefix);
@@ -2642,10 +2645,16 @@ void load_common_alpns(struct ndpi_detection_module_struct *ndpi_str) {
memset(&ac_pattern, 0, sizeof(ac_pattern));
ac_pattern.astring = ndpi_strdup((char*)common_alpns[i]);
+ if(!ac_pattern.astring) {
+ NDPI_LOG_ERR(ndpi_str, "Unable to add %s [mem alloc error]\n", common_alpns[i]);
+ continue;
+ }
ac_pattern.length = strlen(common_alpns[i]);
- if(ac_automata_add(ndpi_str->common_alpns_automa.ac_automa, &ac_pattern) != ACERR_SUCCESS)
- printf("%s(): unable to add %s\n", __FUNCTION__, common_alpns[i]);
+ if(ac_automata_add(ndpi_str->common_alpns_automa.ac_automa, &ac_pattern) != ACERR_SUCCESS) {
+ ndpi_free(ac_pattern.astring);
+ NDPI_LOG_ERR(ndpi_str, "Unable to add %s\n", common_alpns[i]);
+ }
}
}
diff --git a/src/lib/third_party/src/ahocorasick.c b/src/lib/third_party/src/ahocorasick.c
index 71b414558..192735f9c 100644
--- a/src/lib/third_party/src/ahocorasick.c
+++ b/src/lib/third_party/src/ahocorasick.c
@@ -223,10 +223,15 @@ void ac_automata_enable_debug (int debug) {
AC_ERROR_t ac_automata_add (AC_AUTOMATA_t * thiz, AC_PATTERN_t * patt)
{
unsigned int i;
- AC_NODE_t * n = thiz->root;
+ AC_NODE_t * n;
AC_NODE_t * next;
AC_ALPHABET_t alpha;
+ if(!thiz || !patt || !patt->astring)
+ return ACERR_ERROR;
+
+ n = thiz->root;
+
if(!thiz->automata_open)
return ACERR_AUTOMATA_CLOSED;
@@ -556,6 +561,9 @@ static AC_ERROR_t ac_automata_release_node(AC_AUTOMATA_t * thiz,
}
void ac_automata_release (AC_AUTOMATA_t * thiz, uint8_t free_pattern) {
+ if(!thiz)
+ return;
+
ac_automata_walk(thiz,ac_automata_release_node,NULL,free_pattern ? (void *)1:NULL);
if(free_pattern <= 1) {
@@ -1013,8 +1021,11 @@ static int node_register_matchstr (AC_NODE_t * thiz, AC_PATTERN_t * str,int is_e
if (thiz->matched_patterns && node_has_matchstr(thiz, str))
return 0;
- if(!thiz->matched_patterns)
+ if(!thiz->matched_patterns) {
thiz->matched_patterns = node_resize_mp(thiz->matched_patterns);
+ if(!thiz->matched_patterns)
+ return 1;
+ }
/* Manage memory */
if (thiz->matched_patterns->num >= thiz->matched_patterns->max) {
diff --git a/src/lib/third_party/src/ndpi_patricia.c b/src/lib/third_party/src/ndpi_patricia.c
index b4cc76964..5f2aefd89 100644
--- a/src/lib/third_party/src/ndpi_patricia.c
+++ b/src/lib/third_party/src/ndpi_patricia.c
@@ -218,6 +218,8 @@ static ndpi_prefix_t * ndpi_New_Prefix2 (int family, void *dest, int bitlen, ndp
default_bitlen = sizeof(struct in6_addr) * 8;
if(prefix == NULL) {
prefix = (ndpi_prefix_t*)ndpi_calloc(1, sizeof (ndpi_prefix_t));
+ if(!prefix)
+ return (NULL);
dynamic_allocated++;
}
memcpy (&prefix->add.sin6, dest, sizeof(struct in6_addr));
@@ -232,7 +234,9 @@ static ndpi_prefix_t * ndpi_New_Prefix2 (int family, void *dest, int bitlen, ndp
//prefix4_t size incorrect on NT
prefix = ndpi_calloc(1, sizeof (ndpi_prefix_t));
#endif /* NT */
-
+ if(!prefix)
+ return (NULL);
+
dynamic_allocated++;
}
memcpy (&prefix->add.sin, dest, sizeof(struct in_addr));
@@ -298,6 +302,8 @@ ndpi_patricia_tree_t *
ndpi_patricia_new (u_int16_t maxbits)
{
ndpi_patricia_tree_t *patricia = (ndpi_patricia_tree_t*)ndpi_calloc(1, sizeof *patricia);
+ if(!patricia)
+ return (NULL);
patricia->maxbits = maxbits;
patricia->head = NULL;
@@ -536,7 +542,9 @@ ndpi_patricia_search_best2 (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefi
u_int16_t bitlen;
int cnt = 0;
- assert (patricia);
+ if(patricia == NULL)
+ return (NULL);
+
assert (prefix);
assert (prefix->bitlen <= patricia->maxbits);
@@ -653,8 +661,14 @@ ndpi_patricia_lookup (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix)
if(patricia->head == NULL) {
node = (ndpi_patricia_node_t*)ndpi_calloc(1, sizeof *node);
+ if(!node)
+ return NULL;
node->bit = prefix->bitlen;
node->prefix = ndpi_Ref_Prefix (prefix);
+ if(!node->prefix) {
+ ndpi_free(node);
+ return NULL;
+ }
node->parent = NULL;
node->l = node->r = NULL;
node->data = NULL;
@@ -757,6 +771,9 @@ ndpi_patricia_lookup (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix)
return (node);
}
node->prefix = ndpi_Ref_Prefix (prefix);
+ if(!node->prefix) {
+ return NULL;
+ }
#ifdef PATRICIA_DEBUG
fprintf (stderr, "patricia_lookup: new node #1 %s/%d (glue mod)\n",
ndpi_prefix_toa (prefix), prefix->bitlen);
@@ -769,6 +786,10 @@ ndpi_patricia_lookup (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix)
if(!new_node) return NULL;
new_node->bit = prefix->bitlen;
new_node->prefix = ndpi_Ref_Prefix (prefix);
+ if(!new_node->prefix) {
+ ndpi_free(new_node);
+ return NULL;
+ }
new_node->parent = NULL;
new_node->l = new_node->r = NULL;
new_node->data = NULL;
@@ -820,7 +841,12 @@ ndpi_patricia_lookup (ndpi_patricia_tree_t *patricia, ndpi_prefix_t *prefix)
else {
glue = (ndpi_patricia_node_t*)ndpi_calloc(1, sizeof *glue);
- if(!glue) return(NULL);
+ if(!glue) {
+ ndpi_Deref_Prefix(new_node->prefix);
+ ndpi_DeleteEntry (new_node);
+ patricia->num_active_node--;
+ return(NULL);
+ }
glue->bit = differ_bit;
glue->prefix = NULL;
glue->parent = node->parent;