aboutsummaryrefslogtreecommitdiff
path: root/fuzz
diff options
context:
space:
mode:
authorIvan Nardi <12729895+IvanNardi@users.noreply.github.com>2022-12-06 17:41:58 +0100
committerGitHub <noreply@github.com>2022-12-06 17:41:58 +0100
commitada4fe4aa8f88300cfc0dbe6ee965975274b1c40 (patch)
tree08010d2055d0159330ded8e5c15113deb0c41c3b /fuzz
parent946c3dba0f6c393c2e41b98103cec3e7308fbf2c (diff)
fuzz: add a new fuzzer testing memory allocation failures (#1818)
Try to fuzz error paths triggered by allocation errors. Fix some errors already found by this new fuzzer. Basic idea taken from: https://github.com/harfbuzz/harfbuzz/pull/2566/files `FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` is a standard define used to (not)compile specific code in fuzzing builds. See: https://llvm.org/docs/LibFuzzer.html
Diffstat (limited to 'fuzz')
-rw-r--r--fuzz/Makefile.am22
-rw-r--r--fuzz/fuzz_ndpi_reader.c33
2 files changed, 53 insertions, 2 deletions
diff --git a/fuzz/Makefile.am b/fuzz/Makefile.am
index d739fb00a..7f4f2de99 100644
--- a/fuzz/Makefile.am
+++ b/fuzz/Makefile.am
@@ -1,4 +1,4 @@
-bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_quic_get_crypto_data
+bin_PROGRAMS = fuzz_process_packet fuzz_ndpi_reader fuzz_ndpi_reader_alloc_fail fuzz_quic_get_crypto_data
fuzz_process_packet_SOURCES = fuzz_process_packet.c
fuzz_process_packet_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
@@ -26,6 +26,19 @@ 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_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)
+if HAS_FUZZLDFLAGS
+fuzz_ndpi_reader_alloc_fail_CFLAGS += $(LIB_FUZZING_ENGINE)
+fuzz_ndpi_reader_alloc_fail_LDFLAGS += $(LIB_FUZZING_ENGINE)
+endif
+# force usage of CXX for linker
+fuzz_ndpi_reader_alloc_fail_LINK=$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+ $(LIBTOOLFLAGS) --mode=link $(CXX) @NDPI_CFLAGS@ $(AM_CXXFLAGS) $(CXXFLAGS) \
+ $(fuzz_ndpi_reader_alloc_fail_LDFLAGS) @NDPI_LDFLAGS@ $(LDFLAGS) -o $@
+
fuzz_quic_get_crypto_data_SOURCES = fuzz_quic_get_crypto_data.c
fuzz_quic_get_crypto_data_CFLAGS = @NDPI_CFLAGS@ $(CXXFLAGS)
fuzz_quic_get_crypto_data_LDADD = ../src/lib/libndpi.a
@@ -46,15 +59,20 @@ testpcaps := $(wildcard ../tests/pcap/*.pcap*)
fuzz_ndpi_reader_seed_corpus.zip: $(testpcaps)
zip -r fuzz_ndpi_reader_seed_corpus.zip $(testpcaps)
+fuzz_ndpi_reader_alloc_fail_seed_corpus.zip: $(testpcaps)
+ zip -r fuzz_ndpi_reader_alloc_fail_seed_corpus.zip $(testpcaps)
+
files_corpus_fuzz_quic_get_crypto_data := $(wildcard corpus/fuzz_quic_get_crypto_data/*)
fuzz_quic_get_crypto_data_seed_corpus.zip: $(files_corpus_fuzz_quic_get_crypto_data)
zip -r fuzz_quic_get_crypto_data_seed_corpus.zip $(files_corpus_fuzz_quic_get_crypto_data)
-corpus: fuzz_quic_get_crypto_data_seed_corpus.zip
+corpus: fuzz_ndpi_reader_seed_corpus.zip fuzz_ndpi_reader_alloc_fail_seed_corpus.zip fuzz_quic_get_crypto_data_seed_corpus.zip
distdir:
find . -type d | xargs -I'{}' mkdir -p '$(distdir)/{}'
find . -type f -name '*.c' \
-o -name '*.am' \
-o -name '*.bin' | xargs -I'{}' cp '{}' '$(distdir)/{}'
+
+all: corpus
diff --git a/fuzz/fuzz_ndpi_reader.c b/fuzz/fuzz_ndpi_reader.c
index 1adba5939..76f2d7263 100644
--- a/fuzz/fuzz_ndpi_reader.c
+++ b/fuzz/fuzz_ndpi_reader.c
@@ -23,6 +23,26 @@ 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;
+
+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();
@@ -71,8 +91,17 @@ 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;
+#endif
+
fd = bufferToFile(Data, Size);
if (fd == NULL)
return 0;
@@ -92,6 +121,10 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
workflow->pcap_handle = pkts;
/* Init flow tree */
workflow->ndpi_flows_root = ndpi_calloc(workflow->prefs.num_roots, sizeof(void *));
+ if(!workflow->ndpi_flows_root) {
+ pcap_close(pkts);
+ return 0;
+ }
header = NULL;
r = pcap_next_ex(pkts, &header, &pkt);