diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | fuzz/Makefile.am | 17 | ||||
-rw-r--r-- | fuzz/fuzz_ds_address_cache.cpp | 106 | ||||
-rw-r--r-- | src/lib/ndpi_cache.c | 24 |
4 files changed, 140 insertions, 8 deletions
diff --git a/.gitignore b/.gitignore index 8ef05eb83..f94473adf 100644 --- a/.gitignore +++ b/.gitignore @@ -82,6 +82,7 @@ /fuzz/fuzz_ds_domain_classify /fuzz/fuzz_ds_kdtree /fuzz/fuzz_ds_btree +/fuzz/fuzz_ds_address_cache /fuzz/fuzz_libinjection /fuzz/fuzz_binaryfusefilter /fuzz/fuzz_tls_certificate diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am index 30ce2d969..273464d29 100644 --- a/fuzz/Makefile.am +++ b/fuzz/Makefile.am @@ -2,7 +2,7 @@ bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail #Alghoritms bin_PROGRAMS += fuzz_alg_bins fuzz_alg_hll fuzz_alg_hw_rsi_outliers_da fuzz_alg_jitter fuzz_alg_ses_des fuzz_alg_crc32_md5 fuzz_alg_bytestream fuzz_alg_shoco fuzz_alg_memmem fuzz_alg_strnstr fuzz_alg_quick_encryption #Data structures -bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tree fuzz_ds_ptree fuzz_ds_hash fuzz_ds_cmsketch fuzz_ds_bitmap64_fuse fuzz_ds_domain_classify fuzz_ds_kdtree fuzz_ds_btree +bin_PROGRAMS += fuzz_ds_patricia fuzz_ds_ahocorasick fuzz_ds_libcache fuzz_ds_tree fuzz_ds_ptree fuzz_ds_hash fuzz_ds_cmsketch fuzz_ds_bitmap64_fuse fuzz_ds_domain_classify fuzz_ds_kdtree fuzz_ds_btree fuzz_ds_address_cache #Third party bin_PROGRAMS += fuzz_libinjection fuzz_binaryfusefilter #Internal crypto @@ -444,6 +444,21 @@ fuzz_ds_btree_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \ $(fuzz_ds_btree_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@ +fuzz_ds_address_cache_SOURCES = fuzz_ds_address_cache.cpp fuzz_common_code.c +fuzz_ds_address_cache_CXXFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -DNDPI_LIB_COMPILATION +fuzz_ds_address_cache_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) -DNDPI_LIB_COMPILATION +fuzz_ds_address_cache_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS) +fuzz_ds_address_cache_LDFLAGS = $(LIBS) +if HAS_FUZZLDFLAGS +fuzz_ds_address_cache_CXXFLAGS += $(LIB_FUZZING_ENGINE) +fuzz_ds_address_cache_CFLAGS += $(LIB_FUZZING_ENGINE) +fuzz_ds_address_cache_LDFLAGS += $(LIB_FUZZING_ENGINE) +endif +# force usage of CXX for linker +fuzz_ds_address_cache_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \ + $(fuzz_ds_address_cache_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@ + fuzz_libinjection_SOURCES = fuzz_libinjection.c fuzz_libinjection_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS) fuzz_libinjection_LDADD = ../src/lib/libndpi.a $(ADDITIONAL_LIBS) diff --git a/fuzz/fuzz_ds_address_cache.cpp b/fuzz/fuzz_ds_address_cache.cpp new file mode 100644 index 000000000..4bef64fe9 --- /dev/null +++ b/fuzz/fuzz_ds_address_cache.cpp @@ -0,0 +1,106 @@ +#include "ndpi_api.h" +#include "ndpi_private.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); + u_int16_t i, num_iteration; + int is_added = 0; + struct ndpi_detection_module_struct ndpi_struct; /*Opaque; we don't really need to initialize it */ + ndpi_ip_addr_t ip_addr, ip_addr_added; + char *hostname, *hostname2; + u_int32_t epoch_now; + u_int32_t ttl; + bool rc; + char path[] = "random.dump"; + + + /* Just to have some data */ + if (fuzzed_data.remaining_bytes() < 1024) + return -1; + + /* To allow memory allocation failures */ + fuzz_set_alloc_callbacks_and_seed(size); + + + memset(&ndpi_struct, '\0', sizeof(struct ndpi_detection_module_struct)); + ndpi_struct.cfg.address_cache_size = fuzzed_data.ConsumeIntegral<u_int8_t>(); + + epoch_now = 1; + + /* Random insert */ + num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>(); + for (i = 0; i < num_iteration; i++) { + if (fuzzed_data.ConsumeBool()) { + if(fuzzed_data.remaining_bytes() > 16) { + memcpy(&ip_addr.ipv6, fuzzed_data.ConsumeBytes<u_int8_t>(16).data(), 16); + } else { + continue; + } + } else { + memset(&ip_addr, '\0', sizeof(ip_addr)); + ip_addr.ipv4 = fuzzed_data.ConsumeIntegral<u_int32_t>(); + } + hostname = strdup(fuzzed_data.ConsumeRandomLengthString(32).c_str()); + ttl = fuzzed_data.ConsumeIntegral<u_int8_t>(); + epoch_now += fuzzed_data.ConsumeIntegral<u_int8_t>(); + + rc = ndpi_cache_address(&ndpi_struct, ip_addr, hostname, epoch_now, ttl); + if (rc == true) { + if(is_added == 0 && fuzzed_data.ConsumeBool()) { + /* Keep one random node really added */ + is_added = 1; + ip_addr_added = ip_addr; + } else if(fuzzed_data.ConsumeBool()) { + /* Add also same ip with different hostname */ + hostname2 = ndpi_strdup(fuzzed_data.ConsumeRandomLengthString(32).c_str()); + ndpi_cache_address(&ndpi_struct, ip_addr, hostname2, epoch_now, ttl); + ndpi_free(hostname2); + } + } + ndpi_free(hostname); + } + + /* "Random" search */ + num_iteration = fuzzed_data.ConsumeIntegral<u_int8_t>(); + for (i = 0; i < num_iteration; i++) { + if (fuzzed_data.ConsumeBool()) { + if(fuzzed_data.remaining_bytes() > 16) { + memcpy(&ip_addr.ipv6, fuzzed_data.ConsumeBytes<u_int8_t>(16).data(), 16); + } else { + continue; + } + } else { + memset(&ip_addr, '\0', sizeof(ip_addr)); + ip_addr.ipv4 = fuzzed_data.ConsumeIntegral<u_int32_t>(); + } + + ndpi_cache_address_find(&ndpi_struct, ip_addr); + } + /* Search of an added entry */ + if(is_added) + ndpi_cache_address_find(&ndpi_struct, ip_addr_added); + + if(fuzzed_data.ConsumeBool()) { + epoch_now += fuzzed_data.ConsumeIntegral<u_int8_t>(); + ndpi_cache_address_flush_expired(&ndpi_struct, epoch_now); + } + + epoch_now += fuzzed_data.ConsumeIntegral<u_int8_t>(); + rc = ndpi_cache_address_dump(&ndpi_struct, path, epoch_now); + if(rc) { + epoch_now += fuzzed_data.ConsumeIntegral<u_int8_t>(); + ndpi_cache_address_restore(&ndpi_struct, path, epoch_now); + } + + ndpi_term_address_cache(ndpi_struct.address_cache); + + return 0; +} diff --git a/src/lib/ndpi_cache.c b/src/lib/ndpi_cache.c index 632b31487..c4e25ffea 100644 --- a/src/lib/ndpi_cache.c +++ b/src/lib/ndpi_cache.c @@ -221,7 +221,7 @@ struct ndpi_address_cache* ndpi_init_address_cache(u_int32_t max_num_entries) { ret->num_cached_addresses = 0, ret->num_entries = 0, ret->max_num_entries = max_num_entries, - ret->num_root_nodes = ndpi_min(NDPI_NUM_DEFAULT_ROOT_NODES, max_num_entries/16); + ret->num_root_nodes = ndpi_max(1, ndpi_min(NDPI_NUM_DEFAULT_ROOT_NODES, max_num_entries/16)); ret->address_cache_root = (struct ndpi_address_cache_item**)ndpi_calloc(ret->num_root_nodes, sizeof(struct ndpi_address_cache_item*)); if(ret->address_cache_root == NULL) { @@ -243,6 +243,9 @@ static void ndpi_free_addr_item(struct ndpi_address_cache_item *addr) { void ndpi_term_address_cache(struct ndpi_address_cache *cache) { u_int i; + if(!cache) + return; + for(i=0; i<cache->num_root_nodes; i++) { struct ndpi_address_cache_item *root = cache->address_cache_root[i]; @@ -323,8 +326,10 @@ struct ndpi_address_cache_item* ndpi_address_cache_find(struct ndpi_address_cach if(memcmp(&root->addr, &ip_addr, sizeof(ndpi_ip_addr_t)) == 0) { return(root); - } else + } else { + prev = root; root = root->next; + } } return(NULL); @@ -340,6 +345,9 @@ bool ndpi_address_cache_insert(struct ndpi_address_cache *cache, struct ndpi_address_cache_item *ret; u_int32_t epoch_valid_until; + if(!hostname) + return(false); + if(epoch_now == 0) epoch_now = (u_int32_t)time(NULL); ret = ndpi_address_cache_find(cache, ip_addr, epoch_now); epoch_valid_until = epoch_now + ttl; @@ -366,13 +374,13 @@ bool ndpi_address_cache_insert(struct ndpi_address_cache *cache, ret->expire_epoch = epoch_valid_until, ret->next = cache->address_cache_root[hash_id]; - /* Create linked list */ - cache->address_cache_root[hash_id] = ret; - - if((ret->hostname = strdup(hostname)) == NULL) { + if((ret->hostname = ndpi_strdup(hostname)) == NULL) { ndpi_free(ret); return(false); } + + /* Create linked list */ + cache->address_cache_root[hash_id] = ret; } else { /* Element found: update TTL of the existing element */ ret->expire_epoch = ndpi_max(ret->expire_epoch, epoch_valid_until); @@ -410,8 +418,10 @@ bool ndpi_address_cache_dump(struct ndpi_address_cache *cache, u_char *a = (u_char*)&(root->addr); u_int j, idx; - if(epoch_now && (root->expire_epoch < epoch_now)) + if(epoch_now && (root->expire_epoch < epoch_now)) { + root = root->next; continue; /* Expired epoch */ + } for(j=0, idx=0; j<sizeof(ndpi_ip_addr_t); j++, idx += 2) snprintf(&buf[idx], sizeof(buf)-idx, "%02X", a[j]); |