diff --git a/.gitignore b/.gitignore index 1491b11b7..7e421d8b8 100644 --- a/.gitignore +++ b/.gitignore @@ -198,6 +198,7 @@ uptime-*.json # /src/test/fuzz /src/test/fuzz/fuzz-* +/src/test/fuzz/lf-fuzz-* # /src/tools/ /src/tools/tor-checkkey diff --git a/Makefile.am b/Makefile.am index 520483086..785cf3413 100644 --- a/Makefile.am +++ b/Makefile.am @@ -55,6 +55,10 @@ TEST_CPPFLAGS=-DTOR_UNIT_TESTS TEST_NETWORK_FLAGS=--hs-multi-client 1 endif +if LIBFUZZER_ENABLED +TEST_CFLAGS += -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp +endif + TEST_NETWORK_ALL_LOG_DIR=$(top_builddir)/test_network_log TEST_NETWORK_ALL_DRIVER_FLAGS=--color-tests yes diff --git a/configure.ac b/configure.ac index 721f5cd8c..784b3cde1 100644 --- a/configure.ac +++ b/configure.ac @@ -49,6 +49,8 @@ AC_ARG_ENABLE(asserts-in-tests, AS_HELP_STRING(--disable-asserts-in-tests, [disable tor_assert() calls in the unit tests, for branch coverage])) AC_ARG_ENABLE(system-torrc, AS_HELP_STRING(--disable-system-torrc, [don't look for a system-wide torrc file])) +AC_ARG_ENABLE(libfuzzer, + AS_HELP_STRING(--libfuzzer, [build extra fuzzers based on 'libfuzzer'])) if test "x$enable_coverage" != "xyes" -a "x$enable_asserts_in_tests" = "xno" ; then AC_MSG_ERROR([Can't disable assertions outside of coverage build]) @@ -57,6 +59,7 @@ fi AM_CONDITIONAL(UNITTESTS_ENABLED, test "x$enable_unittests" != "xno") AM_CONDITIONAL(COVERAGE_ENABLED, test "x$enable_coverage" = "xyes") AM_CONDITIONAL(DISABLE_ASSERTS_IN_UNIT_TESTS, test "x$enable_asserts_in_tests" = "xno") +AM_CONDITIONAL(LIBFUZZER_ENABLED, test "x$enable_libfuzzer" = "xyes") if test "$enable_static_tor" = "yes"; then enable_static_libevent="yes"; @@ -735,6 +738,7 @@ CFLAGS_FWRAPV= CFLAGS_ASAN= CFLAGS_UBSAN= + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([], [ #if !defined(__clang__) #error @@ -758,7 +762,7 @@ m4_ifdef([AS_VAR_IF],[ AS_VAR_POPDEF([can_compile]) TOR_CHECK_CFLAGS(-Wstack-protector) TOR_CHECK_CFLAGS(--param ssp-buffer-size=1) - if test "$bwin32" = "false"; then + if test "$bwin32" = "false" && test "$enable_libfuzzer" != "yes"; then TOR_CHECK_CFLAGS(-fPIE) TOR_CHECK_LDFLAGS(-pie, "$all_ldflags_for_check", "$all_libs_for_check") fi diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index 57c3cf52c..e4920d3ee 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -92,14 +92,38 @@ disable_signature_checking(void) MOCK(ed25519_impl_spot_check, mock_ed25519_impl_spot_check__nocheck); } +static void +global_init(void) +{ + tor_threads_init(); + { + struct sipkey sipkey = { 1337, 7331 }; + siphash_set_global_key(&sipkey); + } + + /* Initialise logging first */ + init_logging(1); + configure_backtrace_handler(get_version()); + + /* set up the options. */ + mock_options = tor_malloc(sizeof(or_options_t)); + MOCK(get_options, mock_get_options); + + /* Make BUG() and nonfatal asserts crash */ + tor_set_failed_assertion_callback(abort); +} + #ifdef LLVM_FUZZ +int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { static int initialized = 0; if (!initialized) { + global_init(); if (fuzz_init() < 0) abort(); + initialized = 1; } return fuzz_main(Data, Size); @@ -112,23 +136,11 @@ main(int argc, char **argv) { size_t size; - tor_threads_init(); - { - struct sipkey sipkey = { 1337, 7331 }; - siphash_set_global_key(&sipkey); - } + global_init(); /* Disable logging by default to speed up fuzzing. */ int loglevel = LOG_ERR; - /* Initialise logging first */ - init_logging(1); - configure_backtrace_handler(get_version()); - - /* set up the options. */ - mock_options = tor_malloc(sizeof(or_options_t)); - MOCK(get_options, mock_get_options); - for (int i = 1; i < argc; ++i) { if (!strcmp(argv[i], "--warn")) { loglevel = LOG_WARN; @@ -150,9 +162,6 @@ main(int argc, char **argv) add_stream_log(&s, "", fileno(stdout)); } - /* Make BUG() and nonfatal asserts crash */ - tor_set_failed_assertion_callback(abort); - if (fuzz_init() < 0) abort(); @@ -164,8 +173,10 @@ main(int argc, char **argv) #define MAX_FUZZ_SIZE (128*1024) char *input = read_file_to_str_until_eof(0, MAX_FUZZ_SIZE, &size); tor_assert(input); - fuzz_main((const uint8_t*)input, size); + char *raw = tor_memdup(input, size); /* Because input is nul-terminated */ tor_free(input); + fuzz_main((const uint8_t*)raw, size); + tor_free(raw); if (fuzz_cleanup() < 0) abort(); diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index bfe38089d..c716889e7 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -23,6 +23,14 @@ FUZZING_LIBS = \ noinst_HEADERS += \ src/test/fuzz/fuzzing.h +src_test_fuzz_fuzz_consensus_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_consensus.c +src_test_fuzz_fuzz_consensus_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_consensus_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_consensus_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_consensus_LDADD = $(FUZZING_LIBS) + src_test_fuzz_fuzz_descriptor_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_descriptor.c @@ -39,6 +47,22 @@ src_test_fuzz_fuzz_http_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_http_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_http_LDADD = $(FUZZING_LIBS) +src_test_fuzz_fuzz_hsdescv2_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_hsdescv2.c +src_test_fuzz_fuzz_hsdescv2_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_hsdescv2_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_hsdescv2_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_hsdescv2_LDADD = $(FUZZING_LIBS) + +src_test_fuzz_fuzz_iptsv2_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_iptsv2.c +src_test_fuzz_fuzz_iptsv2_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_iptsv2_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_iptsv2_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_iptsv2_LDADD = $(FUZZING_LIBS) + src_test_fuzz_fuzz_extrainfo_SOURCES = \ src/test/fuzz/fuzzing_common.c \ src/test/fuzz/fuzz_extrainfo.c @@ -56,13 +80,84 @@ src_test_fuzz_fuzz_microdesc_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_microdesc_LDADD = $(FUZZING_LIBS) FUZZERS = \ + src/test/fuzz/fuzz-consensus \ src/test/fuzz/fuzz-descriptor \ src/test/fuzz/fuzz-extrainfo \ src/test/fuzz/fuzz-http \ + src/test/fuzz/fuzz-hsdescv2 \ + src/test/fuzz/fuzz-iptsv2 \ src/test/fuzz/fuzz-microdesc -noinst_PROGRAMS += $(FUZZERS) -fuzzers: $(FUZZERS) - +LIBFUZZER = /home/nickm/build/libfuzz/libFuzzer.a +LIBFUZZER_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ +LIBFUZZER_CFLAGS = $(FUZZING_CFLAGS) +LIBFUZZER_LDFLAG = $(FUZZING_LDFLAG) +LIBFUZZER_LIBS = $(FUZZING_LIBS) $(LIBFUZZER) -lstdc++ + +if LIBFUZZER_ENABLED +src_test_fuzz_lf_fuzz_consensus_SOURCES = \ + $(src_test_fuzz_fuzz_consensus_SOURCES) +src_test_fuzz_lf_fuzz_consensus_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_consensus_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_consensus_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_consensus_LDADD = $(LIBFUZZER_LIBS) + +src_test_fuzz_lf_fuzz_descriptor_SOURCES = \ + $(src_test_fuzz_fuzz_descriptor_SOURCES) +src_test_fuzz_lf_fuzz_descriptor_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_descriptor_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_descriptor_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_descriptor_LDADD = $(LIBFUZZER_LIBS) + +src_test_fuzz_lf_fuzz_extrainfo_SOURCES = \ + $(src_test_fuzz_fuzz_extrainfo_SOURCES) +src_test_fuzz_lf_fuzz_extrainfo_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_extrainfo_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_extrainfo_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_extrainfo_LDADD = $(LIBFUZZER_LIBS) + +src_test_fuzz_lf_fuzz_http_SOURCES = \ + $(src_test_fuzz_fuzz_http_SOURCES) +src_test_fuzz_lf_fuzz_http_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_http_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_http_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_http_LDADD = $(LIBFUZZER_LIBS) + +src_test_fuzz_lf_fuzz_hsdescv2_SOURCES = \ + $(src_test_fuzz_fuzz_hsdescv2_SOURCES) +src_test_fuzz_lf_fuzz_hsdescv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_hsdescv2_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_hsdescv2_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_hsdescv2_LDADD = $(LIBFUZZER_LIBS) + +src_test_fuzz_lf_fuzz_iptsv2_SOURCES = \ + $(src_test_fuzz_fuzz_iptsv2_SOURCES) +src_test_fuzz_lf_fuzz_iptsv2_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_iptsv2_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_iptsv2_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_iptsv2_LDADD = $(LIBFUZZER_LIBS) + +src_test_fuzz_lf_fuzz_microdesc_SOURCES = \ + $(src_test_fuzz_fuzz_microdesc_SOURCES) +src_test_fuzz_lf_fuzz_microdesc_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_microdesc_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_microdesc_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_microdesc_LDADD = $(LIBFUZZER_LIBS) + +LIBFUZZER_FUZZERS = \ + src/test/fuzz/lf-fuzz-consensus \ + src/test/fuzz/lf-fuzz-descriptor \ + src/test/fuzz/lf-fuzz-extrainfo \ + src/test/fuzz/lf-fuzz-http \ + src/test/fuzz/lf-fuzz-hsdescv2 \ + src/test/fuzz/lf-fuzz-iptsv2 \ + src/test/fuzz/lf-fuzz-microdesc + +else +LIBFUZZER_FUZZERS = +endif + +noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) +fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS)