From 02068c6391fc5b9febac1f02de7028688c92eee2 Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 13 Dec 2016 19:12:34 -0500 Subject: For fuzzing: Expose directory_handle_command. (Nick extracted this patch from a larger patch by Teor.) --- src/or/directory.c | 4 ++-- src/or/directory.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/or/directory.c b/src/or/directory.c index 80f53c28f4..458116336b 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -14,6 +14,7 @@ #include "connection.h" #include "connection_edge.h" #include "control.h" +#define DIRECTORY_PRIVATE #include "directory.h" #include "dirserv.h" #include "dirvote.h" @@ -99,7 +100,6 @@ static void directory_send_command(dir_connection_t *conn, int purpose, int direct, const char *resource, const char *payload, size_t payload_len, time_t if_modified_since); -static int directory_handle_command(dir_connection_t *conn); static int body_is_plausible(const char *body, size_t body_len, int purpose); static char *http_get_header(const char *headers, const char *which); static void http_set_address_origin(const char *headers, connection_t *conn); @@ -3846,7 +3846,7 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers, * from the inbuf, try to process it; otherwise, leave it on the * buffer. Return a 0 on success, or -1 on error. */ -static int +STATIC int directory_handle_command(dir_connection_t *conn) { char *headers=NULL, *body=NULL; diff --git a/src/or/directory.h b/src/or/directory.h index ee0a198c52..15010d6ff7 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -148,6 +148,7 @@ int purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose, struct get_handler_args_t; STATIC int handle_get_hs_descriptor_v3(dir_connection_t *conn, const struct get_handler_args_t *args); +STATIC int directory_handle_command(dir_connection_t *conn); #endif -- cgit v1.2.3-54-g00ecf From fca91a7793f24fc5f2d043167317fd47dd58f1ed Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 13 Dec 2016 19:13:57 -0500 Subject: for fuzzing: Add a function to make a buf with given contents (Teor wrote the code, nick extracted it into a smaller patch.) --- src/or/buffers.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ src/or/buffers.h | 3 +++ 2 files changed, 51 insertions(+) diff --git a/src/or/buffers.c b/src/or/buffers.c index 8981fd283b..58ce5733eb 100644 --- a/src/or/buffers.c +++ b/src/or/buffers.c @@ -281,6 +281,7 @@ buf_pullup(buf_t *buf, size_t bytes) } #ifdef TOR_UNIT_TESTS +/* Return the data from the first chunk of buf in cp, and its length in sz. */ void buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz) { @@ -292,6 +293,53 @@ buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz) *sz = buf->head->datalen; } } + +/* Write sz bytes from cp into a newly allocated buffer buf. + * Returns NULL when passed a NULL cp or zero sz. + * Asserts on failure: only for use in unit tests. + * buf must be freed using buf_free(). */ +buf_t * +buf_new_with_data(const char *cp, size_t sz) +{ + /* Validate arguments */ + if (!cp || sz <= 0) { + return NULL; + } + + tor_assert(sz < SSIZE_T_CEILING); + + /* Allocate a buffer */ + buf_t *buf = buf_new_with_capacity(sz); + tor_assert(buf); + assert_buf_ok(buf); + tor_assert(!buf->head); + + /* Allocate a chunk that is sz bytes long */ + buf->head = chunk_new_with_alloc_size(CHUNK_ALLOC_SIZE(sz)); + buf->tail = buf->head; + tor_assert(buf->head); + assert_buf_ok(buf); + tor_assert(buf_allocation(buf) >= sz); + + /* Copy the data and size the buffers */ + tor_assert(sz <= buf_slack(buf)); + tor_assert(sz <= CHUNK_REMAINING_CAPACITY(buf->head)); + memcpy(&buf->head->mem[0], cp, sz); + buf->datalen = sz; + buf->head->datalen = sz; + buf->head->data = &buf->head->mem[0]; + assert_buf_ok(buf); + + /* Make sure everything is large enough */ + tor_assert(buf_allocation(buf) >= sz); + tor_assert(buf_allocation(buf) >= buf_datalen(buf) + buf_slack(buf)); + /* Does the buffer implementation allocate more than the requested size? + * (for example, by rounding up). If so, these checks will fail. */ + tor_assert(buf_datalen(buf) == sz); + tor_assert(buf_slack(buf) == 0); + + return buf; +} #endif /** Remove the first n bytes from buf. */ diff --git a/src/or/buffers.h b/src/or/buffers.h index 52b21d5885..08d9471fb7 100644 --- a/src/or/buffers.h +++ b/src/or/buffers.h @@ -64,7 +64,10 @@ void assert_buf_ok(buf_t *buf); #ifdef BUFFERS_PRIVATE STATIC int buf_find_string_offset(const buf_t *buf, const char *s, size_t n); STATIC void buf_pullup(buf_t *buf, size_t bytes); +#ifdef TOR_UNIT_TESTS void buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz); +buf_t *buf_new_with_data(const char *cp, size_t sz); +#endif STATIC size_t preferred_chunk_size(size_t target); #define DEBUG_CHUNK_ALLOC -- cgit v1.2.3-54-g00ecf From b96c70d668f96550401057834bb9caafb5d0e412 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 19:15:26 -0500 Subject: Fuzzing: Add an initial fuzzing tool, for descriptors. This will need some refactoring and mocking. --- Makefile.am | 1 + src/include.am | 2 +- src/test/fuzz/fuzz_descriptor.c | 26 +++++++++++++++++++++ src/test/fuzz/fuzzing.h | 7 ++++++ src/test/fuzz/fuzzing_common.c | 52 +++++++++++++++++++++++++++++++++++++++++ src/test/fuzz/include.am | 48 +++++++++++++++++++++++++++++++++++++ 6 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 src/test/fuzz/fuzz_descriptor.c create mode 100644 src/test/fuzz/fuzzing.h create mode 100644 src/test/fuzz/fuzzing_common.c create mode 100644 src/test/fuzz/include.am diff --git a/Makefile.am b/Makefile.am index b6e4e53de7..2e853d4108 100644 --- a/Makefile.am +++ b/Makefile.am @@ -9,6 +9,7 @@ noinst_LIBRARIES= EXTRA_DIST= noinst_HEADERS= bin_PROGRAMS= +EXTRA_PROGRAMS= CLEANFILES= TESTS= noinst_PROGRAMS= diff --git a/src/include.am b/src/include.am index c468af3649..d12684e187 100644 --- a/src/include.am +++ b/src/include.am @@ -6,4 +6,4 @@ include src/test/include.am include src/tools/include.am include src/win32/include.am include src/config/include.am - +include src/test/fuzz/include.am diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c new file mode 100644 index 0000000000..1364bf4291 --- /dev/null +++ b/src/test/fuzz/fuzz_descriptor.c @@ -0,0 +1,26 @@ + +#include "or.h" +#include "routerparse.h" +#include "routerlist.h" +#include "fuzzing.h" + +int +fuzz_init(void) +{ + ed25519_init(); + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + routerinfo_t *ri; + const char *str = (const char*) data; + ri = router_parse_entry_from_string((const char *)str, + str+sz, + 0, 0, 0, NULL); + if (ri) + routerinfo_free(ri); + return 0; +} + diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h new file mode 100644 index 0000000000..fbd54dafa0 --- /dev/null +++ b/src/test/fuzz/fuzzing.h @@ -0,0 +1,7 @@ +#ifndef FUZZING_H +#define FUZZING_H + +int fuzz_init(void); +int fuzz_main(const uint8_t *data, size_t sz); + +#endif /* FUZZING_H */ diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c new file mode 100644 index 0000000000..51d519b861 --- /dev/null +++ b/src/test/fuzz/fuzzing_common.c @@ -0,0 +1,52 @@ +#include "orconfig.h" +#include "torint.h" +#include "util.h" +#include "torlog.h" +#include "backtrace.h" +#include "fuzzing.h" + +extern const char tor_git_revision[]; +const char tor_git_revision[] = ""; + +#define MAX_FUZZ_SIZE (128*1024) + +#ifdef LLVM_FUZZ +int +LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { + static int initialized = 0; + if (!initialized) { + if (fuzz_init() < 0) + abort(); + } + + return fuzz_main(Data, Size); +} + +#else /* Not LLVM_FUZZ, so AFL. */ + +int +main(int argc, char **argv) +{ + size_t size; + char *input = read_file_to_str_until_eof(0, MAX_FUZZ_SIZE, &size); + + tor_threads_init(); + init_logging(1); + + if (argc > 1 && !strcmp(argv[1], "--info")) { + log_severity_list_t sev; + set_log_severity_config(LOG_INFO, LOG_ERR, &sev); + add_stream_log(&sev, "stdout", 1); + configure_backtrace_handler(NULL); + } + + tor_assert(input); + if (fuzz_init() < 0) + abort(); + fuzz_main((const uint8_t*)input, size); + tor_free(input); + return 0; +} + +#endif + diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am new file mode 100644 index 0000000000..323798f050 --- /dev/null +++ b/src/test/fuzz/include.am @@ -0,0 +1,48 @@ + +FUZZING_CPPFLAGS = \ + $(src_test_AM_CPPFLAGS) $(TEST_CPPFLAGS) +FUZZING_CFLAGS = \ + $(AM_CFLAGS) $(TEST_CFLAGS) +FUZZING_LDFLAG = \ + @TOR_LDFLAGS_zlib@ @TOR_LDFLAGS_openssl@ @TOR_LDFLAGS_libevent@ +FUZZING_LIBS = \ + src/or/libtor-testing.a \ + src/common/libor-crypto-testing.a \ + $(LIBKECCAK_TINY) \ + $(LIBDONNA) \ + src/common/libor-testing.a \ + src/common/libor-ctime-testing.a \ + src/common/libor-event-testing.a \ + src/trunnel/libor-trunnel-testing.a \ + @TOR_ZLIB_LIBS@ @TOR_LIB_MATH@ \ + @TOR_LIBEVENT_LIBS@ \ + @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ + @TOR_SYSTEMD_LIBS@ + + +noinst_HEADERS += \ + src/test/fuzz/fuzzing_boilerplate.h + +src_test_fuzz_fuzz_descriptor_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_descriptor.c +src_test_fuzz_fuzz_descriptor_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_descriptor_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_descriptor_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_descriptor_LDADD = $(FUZZING_LIBS) + +src_test_fuzz_fuzz_http_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_http.c +src_test_fuzz_fuzz_http_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_http_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_http_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_http_LDADD = $(FUZZING_LIBS) + +FUZZERS = \ + src/test/fuzz/fuzz-descriptor \ + src/test/fuzz/fuzz-http + +# The fuzzers aren't built by default right now. That should change. +EXTRA_PROGRAMS += $(FUZZERS) +fuzzers: $(FUZZERS) -- cgit v1.2.3-54-g00ecf From a967d568dcab10d6b1e03d2ffb96743e415393c0 Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 13 Dec 2016 19:16:03 -0500 Subject: Add a fuzzer for the http used in our directory protocol (Teor wrote the code, nick extracted it. It won't compile yet.) --- src/test/fuzz/fuzz_http.c | 174 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 174 insertions(+) create mode 100644 src/test/fuzz/fuzz_http.c diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c new file mode 100644 index 0000000000..abf5de8f97 --- /dev/null +++ b/src/test/fuzz/fuzz_http.c @@ -0,0 +1,174 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#include "orconfig.h" + +#define BUFFERS_PRIVATE + +#include "or.h" +#include "backtrace.h" +#include "buffers.h" +#include "config.h" +#include "connection.h" +#include "directory.h" +#include "torlog.h" + +/* Silence compiler warnings about a missing extern */ +extern const char tor_git_revision[]; +const char tor_git_revision[] = ""; + +#define MAX_FUZZ_SIZE (2*MAX_HEADERS_SIZE + MAX_DIR_UL_SIZE) + +static int mock_get_options_calls = 0; +static or_options_t *mock_options = NULL; + +static void +reset_options(or_options_t *options, int *get_options_calls) +{ + memset(options, 0, sizeof(or_options_t)); + options->TestingTorNetwork = 1; + + *get_options_calls = 0; +} + +static const or_options_t* +mock_get_options(void) +{ + ++mock_get_options_calls; + tor_assert(mock_options); + return mock_options; +} + +static void +mock_connection_write_to_buf_impl_(const char *string, size_t len, + connection_t *conn, int zlib) +{ + log_debug(LD_GENERAL, "%sResponse:\n%zu\nConnection: %p\n%s\n", + zlib ? "Compressed " : "", len, conn, string); +} + +/* Read a directory command (including HTTP headers) from stdin, parse it, and + * output what tor parsed */ +int +main(int c, char** v) +{ + /* Disable logging by default to speed up fuzzing. */ + int loglevel = LOG_ERR; + + /* Initialise logging first */ + init_logging(1); + configure_backtrace_handler(get_version()); + + for (int i = 1; i < c; ++i) { + if (!strcmp(v[i], "--warn")) { + loglevel = LOG_WARN; + } else if (!strcmp(v[i], "--notice")) { + loglevel = LOG_NOTICE; + } else if (!strcmp(v[i], "--info")) { + loglevel = LOG_INFO; + } else if (!strcmp(v[i], "--debug")) { + loglevel = LOG_DEBUG; + } + } + + { + log_severity_list_t s; + memset(&s, 0, sizeof(s)); + set_log_severity_config(loglevel, LOG_ERR, &s); + /* ALWAYS log bug warnings. */ + s.masks[LOG_WARN-LOG_ERR] |= LD_BUG; + add_stream_log(&s, "", fileno(stdout)); + } + + /* Make BUG() and nonfatal asserts crash */ + tor_set_failed_assertion_callback(abort); + + /* Set up fake variables */ + dir_connection_t dir_conn; + int rv = -1; + ssize_t data_size = -1; + char *stdin_buf = tor_malloc(MAX_FUZZ_SIZE+1); + + /* directory_handle_command checks some tor options + * just make them all 0 */ + mock_options = tor_malloc(sizeof(or_options_t)); + reset_options(mock_options, &mock_get_options_calls); + MOCK(get_options, mock_get_options); + + /* Set up the fake connection */ + memset(&dir_conn, 0, sizeof(dir_connection_t)); + dir_conn.base_.type = CONN_TYPE_DIR; + + /* Set up fake response handler */ + MOCK(connection_write_to_buf_impl_, mock_connection_write_to_buf_impl_); + +/* +afl extension - loop and reset state after parsing +likely needs to reset the allocation data structures and counts as well +#ifdef __AFL_HAVE_MANUAL_CONTROL + while (__AFL_LOOP(1000)) { +#endif +*/ + + /* Initialise the data structures */ + memset(stdin_buf, 0, MAX_FUZZ_SIZE+1); + + /* Apparently tor sets this before directory_handle_command() is called. */ + dir_conn.base_.address = tor_strdup("replace-this-address.example.com"); + +#ifdef __AFL_HAVE_MANUAL_CONTROL + /* Tell AFL to pause and fork here - ignored if not using AFL */ + __AFL_INIT(); +#endif + + /* Read the data */ + data_size = read(STDIN_FILENO, stdin_buf, MAX_FUZZ_SIZE); + tor_assert(data_size != -1); + tor_assert(data_size <= MAX_FUZZ_SIZE); + stdin_buf[data_size] = '\0'; + tor_assert(strlen(stdin_buf) >= 0); + tor_assert(strlen(stdin_buf) <= MAX_FUZZ_SIZE); + + log_debug(LD_GENERAL, "Input-Length:\n%zu\n", data_size); + log_debug(LD_GENERAL, "Input:\n%s\n", stdin_buf); + + /* Copy the stdin data into the buffer */ + tor_assert(data_size >= 0); + dir_conn.base_.inbuf = buf_new_with_data(stdin_buf, (size_t)data_size); + if (!dir_conn.base_.inbuf) { + log_debug(LD_GENERAL, "Zero-Length-Input\n"); + return 0; + } + + /* Parse the headers */ + rv = directory_handle_command(&dir_conn); + + /* TODO: check the output is correctly parsed based on the input */ + + /* Report the parsed origin address */ + if (dir_conn.base_.address) { + log_debug(LD_GENERAL, "Address:\n%s\n", dir_conn.base_.address); + } + + log_debug(LD_GENERAL, "Result:\n%d\n", rv); + + /* Reset */ + tor_free(dir_conn.base_.address); + + buf_free(dir_conn.base_.inbuf); + dir_conn.base_.inbuf = NULL; + +/* +#ifdef __AFL_HAVE_MANUAL_CONTROL + } +#endif +*/ + + /* Cleanup */ + tor_free(mock_options); + UNMOCK(get_options); + + UNMOCK(connection_write_to_buf_impl_); + + tor_free(stdin_buf); +} -- cgit v1.2.3-54-g00ecf From 60769e710f1099168f7508fe6834e458ce435ad9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 19:41:03 -0500 Subject: Port fuzz_http to use fuzzing_common. Move common logic from fuzz_http to fuzzing_common. --- src/test/fuzz/fuzz_descriptor.c | 6 ++ src/test/fuzz/fuzz_http.c | 120 ++++++++-------------------------------- src/test/fuzz/fuzzing.h | 1 + src/test/fuzz/fuzzing_common.c | 52 +++++++++++++---- src/test/fuzz/include.am | 2 +- 5 files changed, 74 insertions(+), 107 deletions(-) diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c index 1364bf4291..12297fdfc2 100644 --- a/src/test/fuzz/fuzz_descriptor.c +++ b/src/test/fuzz/fuzz_descriptor.c @@ -11,6 +11,12 @@ fuzz_init(void) return 0; } +int +fuzz_cleanup(void) +{ + return 0; +} + int fuzz_main(const uint8_t *data, size_t sz) { diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c index abf5de8f97..ea63e836f7 100644 --- a/src/test/fuzz/fuzz_http.c +++ b/src/test/fuzz/fuzz_http.c @@ -4,6 +4,7 @@ #include "orconfig.h" #define BUFFERS_PRIVATE +#define DIRECTORY_PRIVATE #include "or.h" #include "backtrace.h" @@ -13,11 +14,7 @@ #include "directory.h" #include "torlog.h" -/* Silence compiler warnings about a missing extern */ -extern const char tor_git_revision[]; -const char tor_git_revision[] = ""; - -#define MAX_FUZZ_SIZE (2*MAX_HEADERS_SIZE + MAX_DIR_UL_SIZE) +#include "fuzzing.h" static int mock_get_options_calls = 0; static or_options_t *mock_options = NULL; @@ -47,101 +44,45 @@ mock_connection_write_to_buf_impl_(const char *string, size_t len, zlib ? "Compressed " : "", len, conn, string); } -/* Read a directory command (including HTTP headers) from stdin, parse it, and - * output what tor parsed */ int -main(int c, char** v) +fuzz_init(void) { - /* Disable logging by default to speed up fuzzing. */ - int loglevel = LOG_ERR; - - /* Initialise logging first */ - init_logging(1); - configure_backtrace_handler(get_version()); - - for (int i = 1; i < c; ++i) { - if (!strcmp(v[i], "--warn")) { - loglevel = LOG_WARN; - } else if (!strcmp(v[i], "--notice")) { - loglevel = LOG_NOTICE; - } else if (!strcmp(v[i], "--info")) { - loglevel = LOG_INFO; - } else if (!strcmp(v[i], "--debug")) { - loglevel = LOG_DEBUG; - } - } - - { - log_severity_list_t s; - memset(&s, 0, sizeof(s)); - set_log_severity_config(loglevel, LOG_ERR, &s); - /* ALWAYS log bug warnings. */ - s.masks[LOG_WARN-LOG_ERR] |= LD_BUG; - add_stream_log(&s, "", fileno(stdout)); - } - - /* Make BUG() and nonfatal asserts crash */ - tor_set_failed_assertion_callback(abort); - - /* Set up fake variables */ - dir_connection_t dir_conn; - int rv = -1; - ssize_t data_size = -1; - char *stdin_buf = tor_malloc(MAX_FUZZ_SIZE+1); - - /* directory_handle_command checks some tor options - * just make them all 0 */ mock_options = tor_malloc(sizeof(or_options_t)); reset_options(mock_options, &mock_get_options_calls); MOCK(get_options, mock_get_options); - - /* Set up the fake connection */ - memset(&dir_conn, 0, sizeof(dir_connection_t)); - dir_conn.base_.type = CONN_TYPE_DIR; - /* Set up fake response handler */ MOCK(connection_write_to_buf_impl_, mock_connection_write_to_buf_impl_); + return 0; +} -/* -afl extension - loop and reset state after parsing -likely needs to reset the allocation data structures and counts as well -#ifdef __AFL_HAVE_MANUAL_CONTROL - while (__AFL_LOOP(1000)) { -#endif -*/ +int +fuzz_cleanup(void) +{ + tor_free(mock_options); + UNMOCK(get_options); + UNMOCK(connection_write_to_buf_impl_); + return 0; +} - /* Initialise the data structures */ - memset(stdin_buf, 0, MAX_FUZZ_SIZE+1); +int +fuzz_main(const uint8_t *stdin_buf, size_t data_size) +{ + dir_connection_t dir_conn; + /* Set up the fake connection */ + memset(&dir_conn, 0, sizeof(dir_connection_t)); + dir_conn.base_.type = CONN_TYPE_DIR; /* Apparently tor sets this before directory_handle_command() is called. */ dir_conn.base_.address = tor_strdup("replace-this-address.example.com"); -#ifdef __AFL_HAVE_MANUAL_CONTROL - /* Tell AFL to pause and fork here - ignored if not using AFL */ - __AFL_INIT(); -#endif - - /* Read the data */ - data_size = read(STDIN_FILENO, stdin_buf, MAX_FUZZ_SIZE); - tor_assert(data_size != -1); - tor_assert(data_size <= MAX_FUZZ_SIZE); - stdin_buf[data_size] = '\0'; - tor_assert(strlen(stdin_buf) >= 0); - tor_assert(strlen(stdin_buf) <= MAX_FUZZ_SIZE); - - log_debug(LD_GENERAL, "Input-Length:\n%zu\n", data_size); - log_debug(LD_GENERAL, "Input:\n%s\n", stdin_buf); - - /* Copy the stdin data into the buffer */ - tor_assert(data_size >= 0); - dir_conn.base_.inbuf = buf_new_with_data(stdin_buf, (size_t)data_size); + dir_conn.base_.inbuf = buf_new_with_data((char*)stdin_buf, data_size); if (!dir_conn.base_.inbuf) { log_debug(LD_GENERAL, "Zero-Length-Input\n"); return 0; } /* Parse the headers */ - rv = directory_handle_command(&dir_conn); + int rv = directory_handle_command(&dir_conn); /* TODO: check the output is correctly parsed based on the input */ @@ -152,23 +93,10 @@ likely needs to reset the allocation data structures and counts as well log_debug(LD_GENERAL, "Result:\n%d\n", rv); - /* Reset */ + /* Reset. */ tor_free(dir_conn.base_.address); - buf_free(dir_conn.base_.inbuf); dir_conn.base_.inbuf = NULL; -/* -#ifdef __AFL_HAVE_MANUAL_CONTROL - } -#endif -*/ - - /* Cleanup */ - tor_free(mock_options); - UNMOCK(get_options); - - UNMOCK(connection_write_to_buf_impl_); - - tor_free(stdin_buf); + return 0; } diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h index fbd54dafa0..794ed1461e 100644 --- a/src/test/fuzz/fuzzing.h +++ b/src/test/fuzz/fuzzing.h @@ -2,6 +2,7 @@ #define FUZZING_H int fuzz_init(void); +int fuzz_cleanup(void); int fuzz_main(const uint8_t *data, size_t sz); #endif /* FUZZING_H */ diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index 51d519b861..87affc4c04 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -1,8 +1,7 @@ #include "orconfig.h" -#include "torint.h" -#include "util.h" -#include "torlog.h" +#include "or.h" #include "backtrace.h" +#include "config.h" #include "fuzzing.h" extern const char tor_git_revision[]; @@ -28,23 +27,56 @@ int main(int argc, char **argv) { size_t size; - char *input = read_file_to_str_until_eof(0, MAX_FUZZ_SIZE, &size); tor_threads_init(); init_logging(1); - if (argc > 1 && !strcmp(argv[1], "--info")) { - log_severity_list_t sev; - set_log_severity_config(LOG_INFO, LOG_ERR, &sev); - add_stream_log(&sev, "stdout", 1); - configure_backtrace_handler(NULL); + /* Disable logging by default to speed up fuzzing. */ + int loglevel = LOG_ERR; + + /* Initialise logging first */ + init_logging(1); + configure_backtrace_handler(get_version()); + + for (int i = 1; i < argc; ++i) { + if (!strcmp(argv[i], "--warn")) { + loglevel = LOG_WARN; + } else if (!strcmp(argv[i], "--notice")) { + loglevel = LOG_NOTICE; + } else if (!strcmp(argv[i], "--info")) { + loglevel = LOG_INFO; + } else if (!strcmp(argv[i], "--debug")) { + loglevel = LOG_DEBUG; + } } - tor_assert(input); + { + log_severity_list_t s; + memset(&s, 0, sizeof(s)); + set_log_severity_config(loglevel, LOG_ERR, &s); + /* ALWAYS log bug warnings. */ + s.masks[LOG_WARN-LOG_ERR] |= LD_BUG; + add_stream_log(&s, "", fileno(stdout)); + } + + /* Make BUG() and nonfatal asserts crash */ + tor_set_failed_assertion_callback(abort); + if (fuzz_init() < 0) abort(); + +#ifdef __AFL_HAVE_MANUAL_CONTROL + /* Tell AFL to pause and fork here - ignored if not using AFL */ + __AFL_INIT(); +#endif + + char *input = read_file_to_str_until_eof(0, MAX_FUZZ_SIZE, &size); + tor_assert(input); fuzz_main((const uint8_t*)input, size); tor_free(input); + + if (fuzz_cleanup() < 0) + abort(); return 0; } diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 323798f050..7948b204c9 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -21,7 +21,7 @@ FUZZING_LIBS = \ noinst_HEADERS += \ - src/test/fuzz/fuzzing_boilerplate.h + src/test/fuzz/fuzzing.h src_test_fuzz_fuzz_descriptor_SOURCES = \ src/test/fuzz/fuzzing_common.c \ -- cgit v1.2.3-54-g00ecf From e2aeaeb76c2fd04a8b5934b7682823d77dc6f064 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 20:22:34 -0500 Subject: Make a bunch of signature/digest-checking functions mockable --- src/common/crypto.c | 15 ++++++++------- src/common/crypto.h | 10 ++++++---- src/common/crypto_ed25519.c | 22 +++++++++++----------- src/common/crypto_ed25519.h | 16 ++++++++++------ src/or/routerkeys.c | 12 ++++++------ src/or/routerkeys.h | 4 ++-- src/or/routerparse.c | 19 +++++++++++++++---- src/or/routerparse.h | 5 ++++- 8 files changed, 62 insertions(+), 41 deletions(-) diff --git a/src/common/crypto.c b/src/common/crypto.c index 062179deda..7cb3330bde 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1107,10 +1107,10 @@ crypto_pk_private_decrypt(crypto_pk_t *env, char *to, * tolen is the number of writable bytes in to, and must be * at least the length of the modulus of env. */ -int -crypto_pk_public_checksig(const crypto_pk_t *env, char *to, - size_t tolen, - const char *from, size_t fromlen) +MOCK_IMPL(int, +crypto_pk_public_checksig,(const crypto_pk_t *env, char *to, + size_t tolen, + const char *from, size_t fromlen)) { int r; tor_assert(env); @@ -1134,9 +1134,10 @@ crypto_pk_public_checksig(const crypto_pk_t *env, char *to, * in env. Return 0 if sig is a correct signature for * SHA1(data). Else return -1. */ -int -crypto_pk_public_checksig_digest(crypto_pk_t *env, const char *data, - size_t datalen, const char *sig, size_t siglen) +MOCK_IMPL(int, +crypto_pk_public_checksig_digest,(crypto_pk_t *env, const char *data, + size_t datalen, const char *sig, + size_t siglen)) { char digest[DIGEST_LEN]; char *buf; diff --git a/src/common/crypto.h b/src/common/crypto.h index bf2fa06aaa..43328f5bce 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -178,10 +178,12 @@ int crypto_pk_public_encrypt(crypto_pk_t *env, char *to, size_t tolen, int crypto_pk_private_decrypt(crypto_pk_t *env, char *to, size_t tolen, const char *from, size_t fromlen, int padding, int warnOnFailure); -int crypto_pk_public_checksig(const crypto_pk_t *env, char *to, size_t tolen, - const char *from, size_t fromlen); -int crypto_pk_public_checksig_digest(crypto_pk_t *env, const char *data, - size_t datalen, const char *sig, size_t siglen); +MOCK_DECL(int, crypto_pk_public_checksig,(const crypto_pk_t *env, + char *to, size_t tolen, + const char *from, size_t fromlen)); +MOCK_DECL(int, crypto_pk_public_checksig_digest,(crypto_pk_t *env, + const char *data, size_t datalen, + const char *sig, size_t siglen)); int crypto_pk_private_sign(const crypto_pk_t *env, char *to, size_t tolen, const char *from, size_t fromlen); int crypto_pk_private_sign_digest(crypto_pk_t *env, char *to, size_t tolen, diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c index 8977e7a325..525d25a3e0 100644 --- a/src/common/crypto_ed25519.c +++ b/src/common/crypto_ed25519.c @@ -15,6 +15,7 @@ * keys to and from the corresponding Curve25519 keys. */ +#define CRYPTO_ED25519_PRIVATE #include "orconfig.h" #ifdef HAVE_SYS_STAT_H #include @@ -34,7 +35,6 @@ #include static void pick_ed25519_impl(void); -static int ed25519_impl_spot_check(void); /** An Ed25519 implementation, as a set of function pointers. */ typedef struct { @@ -308,10 +308,10 @@ ed25519_sign_prefixed,(ed25519_signature_t *signature_out, * * Return 0 if the signature is valid; -1 if it isn't. */ -int -ed25519_checksig(const ed25519_signature_t *signature, - const uint8_t *msg, size_t len, - const ed25519_public_key_t *pubkey) +MOCK_IMPL(int, +ed25519_checksig,(const ed25519_signature_t *signature, + const uint8_t *msg, size_t len, + const ed25519_public_key_t *pubkey)) { return get_ed_impl()->open(signature->sig, msg, len, pubkey->pubkey) < 0 ? -1 : 0; @@ -354,10 +354,10 @@ ed25519_checksig_prefixed(const ed25519_signature_t *signature, * was valid. Otherwise return -N, where N is the number of invalid * signatures. */ -int -ed25519_checksig_batch(int *okay_out, - const ed25519_checkable_t *checkable, - int n_checkable) +MOCK_IMPL(int, +ed25519_checksig_batch,(int *okay_out, + const ed25519_checkable_t *checkable, + int n_checkable)) { int i, res; const ed25519_impl_t *impl = get_ed_impl(); @@ -642,8 +642,8 @@ ed25519_pubkey_copy(ed25519_public_key_t *dest, /** Check whether the given Ed25519 implementation seems to be working. * If so, return 0; otherwise return -1. */ -static int -ed25519_impl_spot_check(void) +MOCK_IMPL(STATIC int, +ed25519_impl_spot_check,(void)) { static const uint8_t alicesk[32] = { 0xc5,0xaa,0x8d,0xf4,0x3f,0x9f,0x83,0x7b, diff --git a/src/common/crypto_ed25519.h b/src/common/crypto_ed25519.h index 56782cc12e..f4a4adad68 100644 --- a/src/common/crypto_ed25519.h +++ b/src/common/crypto_ed25519.h @@ -51,9 +51,9 @@ int ed25519_keypair_generate(ed25519_keypair_t *keypair_out, int extra_strong); int ed25519_sign(ed25519_signature_t *signature_out, const uint8_t *msg, size_t len, const ed25519_keypair_t *key); -int ed25519_checksig(const ed25519_signature_t *signature, - const uint8_t *msg, size_t len, - const ed25519_public_key_t *pubkey); +MOCK_DECL(int,ed25519_checksig,(const ed25519_signature_t *signature, + const uint8_t *msg, size_t len, + const ed25519_public_key_t *pubkey)); MOCK_DECL(int, ed25519_sign_prefixed,(ed25519_signature_t *signature_out, @@ -84,9 +84,9 @@ typedef struct { size_t len; } ed25519_checkable_t; -int ed25519_checksig_batch(int *okay_out, - const ed25519_checkable_t *checkable, - int n_checkable); +MOCK_DECL(int, ed25519_checksig_batch,(int *okay_out, + const ed25519_checkable_t *checkable, + int n_checkable)); int ed25519_keypair_from_curve25519_keypair(ed25519_keypair_t *out, int *signbit_out, @@ -132,5 +132,9 @@ void crypto_ed25519_testing_force_impl(const char *name); void crypto_ed25519_testing_restore_impl(void); #endif +#ifdef CRYPTO_ED25519_PRIVATE +MOCK_DECL(STATIC int, ed25519_impl_spot_check, (void)); +#endif + #endif diff --git a/src/or/routerkeys.c b/src/or/routerkeys.c index 51802b15e5..6cc75edfa3 100644 --- a/src/or/routerkeys.c +++ b/src/or/routerkeys.c @@ -1207,12 +1207,12 @@ make_tap_onion_key_crosscert(const crypto_pk_t *onion_key, /** Check whether an RSA-TAP cross-certification is correct. Return 0 if it * is, -1 if it isn't. */ -int -check_tap_onion_key_crosscert(const uint8_t *crosscert, - int crosscert_len, - const crypto_pk_t *onion_pkey, - const ed25519_public_key_t *master_id_pkey, - const uint8_t *rsa_id_digest) +MOCK_IMPL(int, +check_tap_onion_key_crosscert,(const uint8_t *crosscert, + int crosscert_len, + const crypto_pk_t *onion_pkey, + const ed25519_public_key_t *master_id_pkey, + const uint8_t *rsa_id_digest)) { uint8_t *cc = tor_malloc(crypto_pk_keysize(onion_pkey)); int cc_len = diff --git a/src/or/routerkeys.h b/src/or/routerkeys.h index 98894cdc0b..d2027f4bbe 100644 --- a/src/or/routerkeys.h +++ b/src/or/routerkeys.h @@ -57,11 +57,11 @@ uint8_t *make_tap_onion_key_crosscert(const crypto_pk_t *onion_key, const crypto_pk_t *rsa_id_key, int *len_out); -int check_tap_onion_key_crosscert(const uint8_t *crosscert, +MOCK_DECL(int, check_tap_onion_key_crosscert,(const uint8_t *crosscert, int crosscert_len, const crypto_pk_t *onion_pkey, const ed25519_public_key_t *master_id_pkey, - const uint8_t *rsa_id_digest); + const uint8_t *rsa_id_digest)); int load_ed_keys(const or_options_t *options, time_t now); int should_make_new_ed_keys(const or_options_t *options, const time_t now); diff --git a/src/or/routerparse.c b/src/or/routerparse.c index d763a63d84..5fd2e0829c 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -863,8 +863,8 @@ dump_desc_populate_fifo_from_directory(const char *dirname) * type *type to file $DATADIR/unparseable-desc. Do not write more * than one descriptor to disk per minute. If there is already such a * file in the data directory, overwrite it. */ -STATIC void -dump_desc(const char *desc, const char *type) +MOCK_IMPL(STATIC void, +dump_desc,(const char *desc, const char *type)) { tor_assert(desc); tor_assert(type); @@ -4508,13 +4508,24 @@ router_get_hash_impl(const char *s, size_t s_len, char *digest, &start,&end)<0) return -1; + return router_compute_hash_final(digest, start, end-start, alg); +} + +/** Compute the digest of the len-byte directory object at + * start, using alg. Store the result in digest, which + * must be long enough to hold it. */ +MOCK_IMPL(STATIC int, +router_compute_hash_final,(char *digest, + const char *start, size_t len, + digest_algorithm_t alg)) +{ if (alg == DIGEST_SHA1) { - if (crypto_digest(digest, start, end-start) < 0) { + if (crypto_digest(digest, start, len) < 0) { log_warn(LD_BUG,"couldn't compute digest"); return -1; } } else { - if (crypto_digest256(digest, start, end-start, alg) < 0) { + if (crypto_digest256(digest, start, len, alg) < 0) { log_warn(LD_BUG,"couldn't compute digest"); return -1; } diff --git a/src/or/routerparse.h b/src/or/routerparse.h index 9a3fadca1f..a461d6794f 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -110,7 +110,6 @@ STATIC int routerstatus_parse_guardfraction(const char *guardfraction_str, MOCK_DECL(STATIC dumped_desc_t *, dump_desc_populate_one_file, (const char *dirname, const char *f)); STATIC void dump_desc_populate_fifo_from_directory(const char *dirname); -STATIC void dump_desc(const char *desc, const char *type); STATIC void dump_desc_fifo_cleanup(void); struct memarea_t; STATIC routerstatus_t *routerstatus_parse_entry_from_string( @@ -120,6 +119,10 @@ STATIC routerstatus_t *routerstatus_parse_entry_from_string( vote_routerstatus_t *vote_rs, int consensus_method, consensus_flavor_t flav); +MOCK_DECL(STATIC void,dump_desc,(const char *desc, const char *type)); +MOCK_DECL(STATIC int, router_compute_hash_final,(char *digest, + const char *start, size_t len, + digest_algorithm_t alg)); #endif #define ED_DESC_SIGNATURE_PREFIX "Tor router descriptor signature v1" -- cgit v1.2.3-54-g00ecf From 0666928c5c367506b0173118153bb804e46eca44 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 20:23:16 -0500 Subject: Replace signature-checking and digest-checking while fuzzing --- src/test/fuzz/fuzz_descriptor.c | 49 ++++++++++++++++++++++++-- src/test/fuzz/fuzzing.h | 2 ++ src/test/fuzz/fuzzing_common.c | 78 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 126 insertions(+), 3 deletions(-) diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c index 12297fdfc2..563787b7cc 100644 --- a/src/test/fuzz/fuzz_descriptor.c +++ b/src/test/fuzz/fuzz_descriptor.c @@ -1,12 +1,53 @@ - +#define ROUTERPARSE_PRIVATE #include "or.h" #include "routerparse.h" #include "routerlist.h" +#include "routerkeys.h" #include "fuzzing.h" +static int +mock_check_tap_onion_key_crosscert__nocheck(const uint8_t *crosscert, + int crosscert_len, + const crypto_pk_t *onion_pkey, + const ed25519_public_key_t *master_id_pkey, + const uint8_t *rsa_id_digest) +{ + tor_assert(crosscert && onion_pkey && master_id_pkey && rsa_id_digest); + /* we could look at crosscert[..] */ + (void) crosscert_len; + return 0; +} + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +static int +mock_router_produce_hash_final__nohash(char *digest, + const char *start, size_t len, + digest_algorithm_t alg) +{ + (void)start; + (void)len; + /* we could look at start[..] */ + if (alg == DIGEST_SHA1) + memset(digest, 0x01, 20); + else + memset(digest, 0x02, 32); + return 0; +} + int fuzz_init(void) { + disable_signature_checking(); + MOCK(check_tap_onion_key_crosscert, + mock_check_tap_onion_key_crosscert__nocheck); + MOCK(dump_desc, mock_dump_desc__nodump); + MOCK(router_compute_hash_final, mock_router_produce_hash_final__nohash); ed25519_init(); return 0; } @@ -25,8 +66,12 @@ fuzz_main(const uint8_t *data, size_t sz) ri = router_parse_entry_from_string((const char *)str, str+sz, 0, 0, 0, NULL); - if (ri) + if (ri) { + log_debug(LD_GENERAL, "Parsing okay"); routerinfo_free(ri); + } else { + log_debug(LD_GENERAL, "Parsing failed"); + } return 0; } diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h index 794ed1461e..a8cbb1d9e8 100644 --- a/src/test/fuzz/fuzzing.h +++ b/src/test/fuzz/fuzzing.h @@ -5,4 +5,6 @@ int fuzz_init(void); int fuzz_cleanup(void); int fuzz_main(const uint8_t *data, size_t sz); +void disable_signature_checking(void); + #endif /* FUZZING_H */ diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index 87affc4c04..e17bae3565 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -1,13 +1,88 @@ +#define CRYPTO_ED25519_PRIVATE #include "orconfig.h" #include "or.h" #include "backtrace.h" #include "config.h" #include "fuzzing.h" +#include "crypto.h" +#include "crypto_ed25519.h" extern const char tor_git_revision[]; const char tor_git_revision[] = ""; -#define MAX_FUZZ_SIZE (128*1024) +static int +mock_crypto_pk_public_checksig__nocheck(const crypto_pk_t *env, char *to, + size_t tolen, + const char *from, size_t fromlen) +{ + tor_assert(env && to && from); + (void)fromlen; + /* We could look at from[0..fromlen-1] ... */ + tor_assert(tolen >= crypto_pk_keysize(env)); + memset(to, 0x01, 20); + return 20; +} + +static int +mock_crypto_pk_public_checksig_digest__nocheck(crypto_pk_t *env, + const char *data, + size_t datalen, + const char *sig, + size_t siglen) +{ + tor_assert(env && data && sig); + (void)datalen; + (void)siglen; + /* We could look at data[..] and sig[..] */ + return 0; +} + +static int +mock_ed25519_checksig__nocheck(const ed25519_signature_t *signature, + const uint8_t *msg, size_t len, + const ed25519_public_key_t *pubkey) +{ + tor_assert(signature && msg && pubkey); + /* We could look at msg[0..len-1] ... */ + (void)len; + return 0; +} + +static int +mock_ed25519_checksig_batch__nocheck(int *okay_out, + const ed25519_checkable_t *checkable, + int n_checkable) +{ + tor_assert(checkable); + int i; + for (i = 0; i < n_checkable; ++i) { + /* We could look at messages and signatures XXX */ + tor_assert(checkable[i].pubkey); + tor_assert(checkable[i].msg); + if (okay_out) + okay_out[i] = 1; + } + return 0; +} + +static int +mock_ed25519_impl_spot_check__nocheck(void) +{ + return 0; +} + + +void +disable_signature_checking(void) +{ + MOCK(crypto_pk_public_checksig, + mock_crypto_pk_public_checksig__nocheck); + MOCK(crypto_pk_public_checksig_digest, + mock_crypto_pk_public_checksig_digest__nocheck); + MOCK(ed25519_checksig, mock_ed25519_checksig__nocheck); + MOCK(ed25519_checksig_batch, mock_ed25519_checksig_batch__nocheck); + MOCK(ed25519_impl_spot_check, mock_ed25519_impl_spot_check__nocheck); +} #ifdef LLVM_FUZZ int @@ -70,6 +145,7 @@ main(int argc, char **argv) __AFL_INIT(); #endif +#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); -- cgit v1.2.3-54-g00ecf From ca657074b9602940c3a45b9c4cfe69d5f078084c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 20:24:54 -0500 Subject: Fuzzing: initialize siphash key, don't init_logging twice. --- .gitignore | 3 +++ src/test/fuzz/fuzzing_common.c | 5 ++++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index dc6738c079..1491b11b7e 100644 --- a/.gitignore +++ b/.gitignore @@ -196,6 +196,9 @@ uptime-*.json /src/test/test-timers.exe /src/test/test_workqueue.exe +# /src/test/fuzz +/src/test/fuzz/fuzz-* + # /src/tools/ /src/tools/tor-checkkey /src/tools/tor-resolve diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index e17bae3565..f2570a1a12 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -104,7 +104,10 @@ main(int argc, char **argv) size_t size; tor_threads_init(); - init_logging(1); + { + struct sipkey sipkey = { 1337, 7331 }; + siphash_set_global_key(&sipkey); + } /* Disable logging by default to speed up fuzzing. */ int loglevel = LOG_ERR; -- cgit v1.2.3-54-g00ecf From 949e9827d643f5c84d714482963214744d37495d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 20:26:26 -0500 Subject: Add a descriptor fuzzing dictionary. --- src/test/fuzz/dict/descriptor | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/test/fuzz/dict/descriptor diff --git a/src/test/fuzz/dict/descriptor b/src/test/fuzz/dict/descriptor new file mode 100644 index 0000000000..110ee3e820 --- /dev/null +++ b/src/test/fuzz/dict/descriptor @@ -0,0 +1,41 @@ +"reject" +"accept" +"reject6" +"accept6" +"router" +"ipv6-policy" +"signing-key" +"onion-key" +"ntor-onion-key" +"router-signature" +"published" +"uptime" +"fingerprint" +"hibernating" +"platform" +"proto" +"contact" +"read-history" +"write-history" +"extra-info-digest" +"hidden-service-dir" +"identity-ed25519" +"master-key-ed25519" +"router-sig-ed25519" +"onion-key-crosscert" +"ntor-onion-key-crosscert" +"allow-single-hop-exits" +"family" +"caches-extra-info" +"or-address" +"opt" + "bandwidth" +"@purpose" +"tunnelled-dir-server" +"-----BEGIN" +"-----END" +"-----" +"ED25519 CERT" +"RSA PUBLIC KEY" +"CROSSCERT" +"SIGNATURE" -- cgit v1.2.3-54-g00ecf From f009b13029b57f9c89077a041124066f6e9ba38c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 13 Dec 2016 20:29:28 -0500 Subject: Copy fuzzing instructions by teor --- doc/HACKING/Fuzzing.md | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) create mode 100644 doc/HACKING/Fuzzing.md diff --git a/doc/HACKING/Fuzzing.md b/doc/HACKING/Fuzzing.md new file mode 100644 index 0000000000..7ba7f49026 --- /dev/null +++ b/doc/HACKING/Fuzzing.md @@ -0,0 +1,90 @@ += Fuzzing Tor + +To run the fuzzing test cases in a deterministic fashion, use: + make fuzz + +== Guided Fuzzing with AFL + +There is no HTTPS, hash, or signature for American Fuzzy Lop's source code, so +its integrity can't be verified. That said, you really shouldn't fuzz on a +machine you care about, anyway. + +To Build: + Get AFL from http://lcamtuf.coredump.cx/afl/ and unpack it + cd afl + make + cd ../tor + PATH=$PATH:../afl/ CC="../afl/afl-gcc" ./configure --enable-expensive-hardening + AFL_HARDEN=1 make clean fuzz + +To Find The ASAN Memory Limit: (64-bit only) + +On 64-bit platforms, afl needs to know how much memory ASAN uses. +Or, you can configure tor without --enable-expensive-hardening, then use + make fuzz +to run the generated test cases through an ASAN-enabled fuzz_dir. +Read afl/docs/notes_for_asan.txt for more details. + + Download recidivm from http://jwilk.net/software/recidivm + Download the signature + Check the signature + tar xvzf recidivm*.tar.gz + cd recidivm* + make + /path/to/recidivm -v src/test/fuzz_dir + Use the final "ok" figure as the input to -m when calling afl-fuzz + (Normally, recidivm would output a figure automatically, but in some cases, + the fuzzing harness will hang when the memory limit is too small.) + +To Run: + mkdir -p src/test/fuzz/fuzz_dir_testcase src/test/fuzz/fuzz_dir_findings + echo "dummy" > src/test/fuzz/fuzz_dir_testcase/minimal.case + ../afl/afl-fuzz -i src/test/fuzz/fuzz_dir_testcase -o src/test/fuzz/fuzz_dir_findings -m -- src/test/fuzz_dir + +AFL has a multi-core mode, check the documentation for details. + +macOS (OS X) requires slightly more preparation, including: +* using afl-clang (or afl-clang-fast from the llvm directory) +* disabling external crash reporting (AFL will guide you through this step) + +AFL may also benefit from using dictionary files for text-based inputs: these +can be placed in src/test/fuzz/fuzz_dir_dictionary/. + +Multiple dictionaries can be used with AFL, you should choose a combination of +dictionaries that targets the code you are fuzzing. + +== Writing Tor fuzzers + +A tor fuzzing harness should: +* read input from standard input (many fuzzing frameworks also accept file + names) +* parse that input +* produce results on standard output (this assists in diagnosing errors) + +Most fuzzing frameworks will produce many invalid inputs - a tor fuzzing +harness should rejecting invalid inputs without crashing or behaving badly. + +But the fuzzing harness should crash if tor fails an assertion, triggers a +bug, or accesses memory it shouldn't. This helps fuzzing frameworks detect +"interesting" cases. + +== Triaging Issues + +Crashes are usually interesting, particularly if using AFL_HARDEN=1 and --enable-expensive-hardening. Sometimes crashes are due to bugs in the harness code. + +Hangs might be interesting, but they might also be spurious machine slowdowns. +Check if a hang is reproducible before reporting it. Sometimes, processing +valid inputs may take a second or so, particularly with the fuzzer and +sanitizers enabled. + +To see what fuzz_dir is doing with a test case, call it like this: + src/test/fuzz_dir --debug < /path/to/test.case + +(Logging is disabled while fuzzing to increase fuzzing speed.) + +== Reporting Issues + +Please report any issues discovered using the process in Tor's security issue +policy: + +https://trac.torproject.org/projects/tor/wiki/org/meetings/2016SummerDevMeeting/Notes/SecurityIssuePolicy -- cgit v1.2.3-54-g00ecf From 584d723e04751330a677e7ce3673fc665713ea0a Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 12 Dec 2016 22:53:11 +1100 Subject: Restrict fuzzing to the directory headers --- src/or/directory.c | 12 ++++++------ src/or/directory.h | 12 ++++++++---- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/src/or/directory.c b/src/or/directory.c index 458116336b..012d440250 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -2895,9 +2895,9 @@ static const url_table_ent_t url_table[] = { * conn-\>outbuf. If the request is unrecognized, send a 404. * Return 0 if we handled this successfully, or -1 if we need to close * the connection. */ -STATIC int -directory_handle_command_get(dir_connection_t *conn, const char *headers, - const char *req_body, size_t req_body_len) +MOCK_IMPL(STATIC int, +directory_handle_command_get,(dir_connection_t *conn, const char *headers, + const char *req_body, size_t req_body_len)) { char *url, *url_mem, *header; time_t if_modified_since = 0; @@ -3705,9 +3705,9 @@ handle_post_hs_descriptor(const char *url, const char *body) * service descriptor. On finding one, process it and write a * response into conn-\>outbuf. If the request is unrecognized, send a * 400. Always return 0. */ -static int -directory_handle_command_post(dir_connection_t *conn, const char *headers, - const char *body, size_t body_len) +MOCK_IMPL(STATIC int, +directory_handle_command_post,(dir_connection_t *conn, const char *headers, + const char *body, size_t body_len)) { char *url = NULL; const or_options_t *options = get_options(); diff --git a/src/or/directory.h b/src/or/directory.h index 15010d6ff7..8be1f8e76e 100644 --- a/src/or/directory.h +++ b/src/or/directory.h @@ -158,10 +158,14 @@ STATIC int directory_handle_command(dir_connection_t *conn); STATIC int parse_http_url(const char *headers, char **url); STATIC dirinfo_type_t dir_fetch_type(int dir_purpose, int router_purpose, const char *resource); -STATIC int directory_handle_command_get(dir_connection_t *conn, - const char *headers, - const char *req_body, - size_t req_body_len); +MOCK_DECL(STATIC int, directory_handle_command_get,(dir_connection_t *conn, + const char *headers, + const char *req_body, + size_t req_body_len)); +MOCK_DECL(STATIC int, directory_handle_command_post,(dir_connection_t *conn, + const char *headers, + const char *body, + size_t body_len)); STATIC int download_status_schedule_get_delay(download_status_t *dls, const smartlist_t *schedule, int min_delay, int max_delay, -- cgit v1.2.3-54-g00ecf From 56b61d18311998210f07c3d4b4f21a497bc04d48 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Dec 2016 08:05:22 -0500 Subject: Add more tweaks from teor's http fuzzing code. Move option-manipulation code to fuzzing_common. --- src/test/fuzz/fuzz_http.c | 76 +++++++++++++++++++++++++++++------------- src/test/fuzz/fuzzing_common.c | 14 ++++++++ 2 files changed, 67 insertions(+), 23 deletions(-) diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c index ea63e836f7..15d3726763 100644 --- a/src/test/fuzz/fuzz_http.c +++ b/src/test/fuzz/fuzz_http.c @@ -16,51 +16,81 @@ #include "fuzzing.h" -static int mock_get_options_calls = 0; -static or_options_t *mock_options = NULL; - static void -reset_options(or_options_t *options, int *get_options_calls) +mock_connection_write_to_buf_impl_(const char *string, size_t len, + connection_t *conn, int zlib) { - memset(options, 0, sizeof(or_options_t)); - options->TestingTorNetwork = 1; - - *get_options_calls = 0; + log_debug(LD_GENERAL, "%sResponse:\n%zu\nConnection: %p\n%s\n", + zlib ? "Compressed " : "", len, conn, string); } -static const or_options_t* -mock_get_options(void) +static int +mock_directory_handle_command_get(dir_connection_t *conn, + const char *headers, + const char *body, + size_t body_len) { - ++mock_get_options_calls; - tor_assert(mock_options); - return mock_options; + (void)conn; + + log_debug(LD_GENERAL, "Method:\nGET\n"); + + if (headers) { + log_debug(LD_GENERAL, "Header-Length:\n%zu\n", strlen(headers)); + log_debug(LD_GENERAL, "Headers:\n%s\n", headers); + + } + + log_debug(LD_GENERAL, "Body-Length:\n%zu\n", body_len); + if (body) { + log_debug(LD_GENERAL, "Body:\n%s\n", body); + } + + /* Always tell the caller we succeeded */ + return 0; } -static void -mock_connection_write_to_buf_impl_(const char *string, size_t len, - connection_t *conn, int zlib) +static int +mock_directory_handle_command_post(dir_connection_t *conn, + const char *headers, + const char *body, + size_t body_len) { - log_debug(LD_GENERAL, "%sResponse:\n%zu\nConnection: %p\n%s\n", - zlib ? "Compressed " : "", len, conn, string); + (void)conn; + + log_debug(LD_GENERAL, "Method:\nPOST\n"); + + if (headers) { + log_debug(LD_GENERAL, "Header-Length:\n%zu\n", strlen(headers)); + log_debug(LD_GENERAL, "Headers:\n%s\n", headers); + } + + log_debug(LD_GENERAL, "Body-Length:\n%zu\n", body_len); + if (body) { + log_debug(LD_GENERAL, "Body:\n%s\n", body); + } + + /* Always tell the caller we succeeded */ + return 0; } int fuzz_init(void) { - mock_options = tor_malloc(sizeof(or_options_t)); - reset_options(mock_options, &mock_get_options_calls); - MOCK(get_options, mock_get_options); /* Set up fake response handler */ MOCK(connection_write_to_buf_impl_, mock_connection_write_to_buf_impl_); + /* Set up the fake handler functions */ + MOCK(directory_handle_command_get, mock_directory_handle_command_get); + MOCK(directory_handle_command_post, mock_directory_handle_command_post); + return 0; } int fuzz_cleanup(void) { - tor_free(mock_options); - UNMOCK(get_options); UNMOCK(connection_write_to_buf_impl_); + UNMOCK(directory_handle_command_get); + UNMOCK(directory_handle_command_post); return 0; } diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index f2570a1a12..54a792353d 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -10,6 +10,13 @@ extern const char tor_git_revision[]; const char tor_git_revision[] = ""; +static or_options_t *mock_options = NULL; +static const or_options_t * +mock_get_options(void) +{ + return mock_options; +} + static int mock_crypto_pk_public_checksig__nocheck(const crypto_pk_t *env, char *to, size_t tolen, @@ -116,6 +123,10 @@ main(int argc, char **argv) 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; @@ -156,6 +167,9 @@ main(int argc, char **argv) if (fuzz_cleanup() < 0) abort(); + + tor_free(mock_options); + UNMOCK(get_options); return 0; } -- cgit v1.2.3-54-g00ecf From 416e2f6b283801190f087445d295b391e08cc902 Mon Sep 17 00:00:00 2001 From: teor Date: Mon, 12 Dec 2016 22:55:18 +1100 Subject: Guide fuzzing by adding standard tor GET and POST testcases --- src/test/fuzz/dict/http | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/test/fuzz/dict/http diff --git a/src/test/fuzz/dict/http b/src/test/fuzz/dict/http new file mode 100644 index 0000000000..1a7b61e8d4 --- /dev/null +++ b/src/test/fuzz/dict/http @@ -0,0 +1,24 @@ +# +# AFL dictionary for the Tor Directory protocol's HTTP headers +# ------------------------------------------------------------ +# +# Extracted from directory_handle_command() in the tor source code +# +# Copyright (c) 2016, The Tor Project, Inc. +# See LICENSE for licensing information +# +# Usage: +# Select the dictionaries relevant to the part of the directory protocol you +# are fuzzing, and feed them to your fuzzer (if it supports dictionaries). + +http_header_body_delimiter = "\x0d\x0a\x0d\x0a" +http_header_header_delimiter = "\x0d\x0a" +# multi-character tokens only +#http_header_value_delimiter = " " + +content_length_header = "Content-Length:" +forwarded_for_header = "Forwarded-For:" +x_forwarded_for_header = "X-Forwarded-For:" + +get_command = "GET" +post_command = "POST" -- cgit v1.2.3-54-g00ecf From 0fb1156e9f0ee62e9b704e9e56ebae3c8d436218 Mon Sep 17 00:00:00 2001 From: teor Date: Tue, 13 Dec 2016 16:23:12 +1100 Subject: Add a script for running multiple fuzzing sessions on multiple cores --- doc/HACKING/Fuzzing.md | 1 + src/test/fuzz_multi.sh | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) create mode 100755 src/test/fuzz_multi.sh diff --git a/doc/HACKING/Fuzzing.md b/doc/HACKING/Fuzzing.md index 7ba7f49026..703f028891 100644 --- a/doc/HACKING/Fuzzing.md +++ b/doc/HACKING/Fuzzing.md @@ -42,6 +42,7 @@ To Run: ../afl/afl-fuzz -i src/test/fuzz/fuzz_dir_testcase -o src/test/fuzz/fuzz_dir_findings -m -- src/test/fuzz_dir AFL has a multi-core mode, check the documentation for details. +You might find the included fuzz-multi.sh script useful for this. macOS (OS X) requires slightly more preparation, including: * using afl-clang (or afl-clang-fast from the llvm directory) diff --git a/src/test/fuzz_multi.sh b/src/test/fuzz_multi.sh new file mode 100755 index 0000000000..b4a17ed8cb --- /dev/null +++ b/src/test/fuzz_multi.sh @@ -0,0 +1,34 @@ +MEMLIMIT_BYTES=21990500990976 + +N_CPUS=1 +if [ $# -ge 1 ]; then + N_CPUS="$1" + shift +fi + +FILTER=echo + +for i in `seq -w "$N_CPUS"`; do + if [ "$i" -eq 1 ]; then + if [ "$N_CPUS" -eq 1 ]; then + INSTANCE="" + NUMBER="" + else + INSTANCE="-M" + NUMBER="$i" + fi + else + INSTANCE="-S" + NUMBER="$i" + fi + # use whatever remains on the command-line to prefix the fuzzer command + # you have to copy and paste and run these commands yourself + "$FILTER" "$@" \ + ../afl/afl-fuzz \ + -i src/test/fuzz/fuzz_dir_testcase \ + -o src/test/fuzz/fuzz_dir_findings \ + -x src/test/fuzz/fuzz_dir_dictionary/fuzz_dir_http_header.dct \ + -m "$MEMLIMIT_BYTES" \ + "$INSTANCE" "$NUMBER" \ + -- src/test/fuzz_dir +done -- cgit v1.2.3-54-g00ecf From 44fa14c0e28ac26a551169d5621648db9bc08da9 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Dec 2016 08:12:41 -0500 Subject: Try to tweak fuzzing.md to correspond to my changes --- doc/HACKING/Fuzzing.md | 36 +++++++++++++++++++----------------- src/test/fuzz/fuzz_multi.sh | 34 ++++++++++++++++++++++++++++++++++ src/test/fuzz_multi.sh | 34 ---------------------------------- 3 files changed, 53 insertions(+), 51 deletions(-) create mode 100755 src/test/fuzz/fuzz_multi.sh delete mode 100755 src/test/fuzz_multi.sh diff --git a/doc/HACKING/Fuzzing.md b/doc/HACKING/Fuzzing.md index 703f028891..36f0fc4f5e 100644 --- a/doc/HACKING/Fuzzing.md +++ b/doc/HACKING/Fuzzing.md @@ -3,6 +3,11 @@ To run the fuzzing test cases in a deterministic fashion, use: make fuzz + [I've turned this off for now. - NM] + +To build the fuzzing harness binaries, use: + make fuzzers + == Guided Fuzzing with AFL There is no HTTPS, hash, or signature for American Fuzzy Lop's source code, so @@ -22,7 +27,7 @@ To Find The ASAN Memory Limit: (64-bit only) On 64-bit platforms, afl needs to know how much memory ASAN uses. Or, you can configure tor without --enable-expensive-hardening, then use make fuzz -to run the generated test cases through an ASAN-enabled fuzz_dir. +to run the generated test cases through an ASAN-enabled fuzz-http. Read afl/docs/notes_for_asan.txt for more details. Download recidivm from http://jwilk.net/software/recidivm @@ -36,10 +41,14 @@ Read afl/docs/notes_for_asan.txt for more details. (Normally, recidivm would output a figure automatically, but in some cases, the fuzzing harness will hang when the memory limit is too small.) +You could also just say "none" instead of the memory limit below, if you +don't care about memory limits. + + To Run: - mkdir -p src/test/fuzz/fuzz_dir_testcase src/test/fuzz/fuzz_dir_findings - echo "dummy" > src/test/fuzz/fuzz_dir_testcase/minimal.case - ../afl/afl-fuzz -i src/test/fuzz/fuzz_dir_testcase -o src/test/fuzz/fuzz_dir_findings -m -- src/test/fuzz_dir + mkdir -p src/test/fuzz/fuzz_http_findings + ../afl/afl-fuzz -i src/test/fuzz/data/http -x src/test/fuzz/dict/http -o src/test/fuzz/fuzz_http_findings -m -- src/test/fuzz_dir + AFL has a multi-core mode, check the documentation for details. You might find the included fuzz-multi.sh script useful for this. @@ -48,19 +57,12 @@ macOS (OS X) requires slightly more preparation, including: * using afl-clang (or afl-clang-fast from the llvm directory) * disabling external crash reporting (AFL will guide you through this step) -AFL may also benefit from using dictionary files for text-based inputs: these -can be placed in src/test/fuzz/fuzz_dir_dictionary/. - -Multiple dictionaries can be used with AFL, you should choose a combination of -dictionaries that targets the code you are fuzzing. - == Writing Tor fuzzers -A tor fuzzing harness should: -* read input from standard input (many fuzzing frameworks also accept file - names) -* parse that input -* produce results on standard output (this assists in diagnosing errors) +A tor fuzzing harness should have: +* a fuzz_init() function to set up any necessary global state. +* a fuzz_main() function to receive input and pass it to a parser. +* a fuzz_cleanup() function to clear global state. Most fuzzing frameworks will produce many invalid inputs - a tor fuzzing harness should rejecting invalid inputs without crashing or behaving badly. @@ -78,8 +80,8 @@ Check if a hang is reproducible before reporting it. Sometimes, processing valid inputs may take a second or so, particularly with the fuzzer and sanitizers enabled. -To see what fuzz_dir is doing with a test case, call it like this: - src/test/fuzz_dir --debug < /path/to/test.case +To see what fuzz-http is doing with a test case, call it like this: + src/test/fuzz/fuzz-http --debug < /path/to/test.case (Logging is disabled while fuzzing to increase fuzzing speed.) diff --git a/src/test/fuzz/fuzz_multi.sh b/src/test/fuzz/fuzz_multi.sh new file mode 100755 index 0000000000..b4a17ed8cb --- /dev/null +++ b/src/test/fuzz/fuzz_multi.sh @@ -0,0 +1,34 @@ +MEMLIMIT_BYTES=21990500990976 + +N_CPUS=1 +if [ $# -ge 1 ]; then + N_CPUS="$1" + shift +fi + +FILTER=echo + +for i in `seq -w "$N_CPUS"`; do + if [ "$i" -eq 1 ]; then + if [ "$N_CPUS" -eq 1 ]; then + INSTANCE="" + NUMBER="" + else + INSTANCE="-M" + NUMBER="$i" + fi + else + INSTANCE="-S" + NUMBER="$i" + fi + # use whatever remains on the command-line to prefix the fuzzer command + # you have to copy and paste and run these commands yourself + "$FILTER" "$@" \ + ../afl/afl-fuzz \ + -i src/test/fuzz/fuzz_dir_testcase \ + -o src/test/fuzz/fuzz_dir_findings \ + -x src/test/fuzz/fuzz_dir_dictionary/fuzz_dir_http_header.dct \ + -m "$MEMLIMIT_BYTES" \ + "$INSTANCE" "$NUMBER" \ + -- src/test/fuzz_dir +done diff --git a/src/test/fuzz_multi.sh b/src/test/fuzz_multi.sh deleted file mode 100755 index b4a17ed8cb..0000000000 --- a/src/test/fuzz_multi.sh +++ /dev/null @@ -1,34 +0,0 @@ -MEMLIMIT_BYTES=21990500990976 - -N_CPUS=1 -if [ $# -ge 1 ]; then - N_CPUS="$1" - shift -fi - -FILTER=echo - -for i in `seq -w "$N_CPUS"`; do - if [ "$i" -eq 1 ]; then - if [ "$N_CPUS" -eq 1 ]; then - INSTANCE="" - NUMBER="" - else - INSTANCE="-M" - NUMBER="$i" - fi - else - INSTANCE="-S" - NUMBER="$i" - fi - # use whatever remains on the command-line to prefix the fuzzer command - # you have to copy and paste and run these commands yourself - "$FILTER" "$@" \ - ../afl/afl-fuzz \ - -i src/test/fuzz/fuzz_dir_testcase \ - -o src/test/fuzz/fuzz_dir_findings \ - -x src/test/fuzz/fuzz_dir_dictionary/fuzz_dir_http_header.dct \ - -m "$MEMLIMIT_BYTES" \ - "$INSTANCE" "$NUMBER" \ - -- src/test/fuzz_dir -done -- cgit v1.2.3-54-g00ecf From 81e44c22573e86cdcca6e47a7e68b3c83d4855f1 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Dec 2016 10:05:41 -0500 Subject: Add extrainfo fuzzer --- src/test/fuzz/dict/extrainfo | 32 +++++++++++++++++++++ src/test/fuzz/fuzz_extrainfo.c | 63 ++++++++++++++++++++++++++++++++++++++++++ src/test/fuzz/include.am | 9 ++++++ 3 files changed, 104 insertions(+) create mode 100644 src/test/fuzz/dict/extrainfo create mode 100644 src/test/fuzz/fuzz_extrainfo.c diff --git a/src/test/fuzz/dict/extrainfo b/src/test/fuzz/dict/extrainfo new file mode 100644 index 0000000000..eba7a1e4ce --- /dev/null +++ b/src/test/fuzz/dict/extrainfo @@ -0,0 +1,32 @@ +"cell-circuits-per-decile" +"cell-processed-cells" +"cell-queued-cells" +"cell-stats-end" +"cell-time-in-queue" +"dirreq-stats-end" +"dirreq-v2-direct-dl" +"dirreq-v2-ips" +"dirreq-v2-reqs" +"dirreq-v2-resp" +"dirreq-v2-share" +"dirreq-v2-tunneled-dl" +"dirreq-v3-direct-dl" +"dirreq-v3-ips" +"dirreq-v3-reqs" +"dirreq-v3-resp" +"dirreq-v3-share" +"dirreq-v3-tunneled-dl" +"entry-ips" +"entry-stats-end" +"exit-kibibytes-read" +"exit-kibibytes-written" +"exit-stats-end" +"exit-streams-opened" +"extra-info" +"identity-ed25519" +"opt" +"published" +"read-history" +"router-sig-ed25519" +"router-signature" +"write-history" diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c new file mode 100644 index 0000000000..6bfc425a9a --- /dev/null +++ b/src/test/fuzz/fuzz_extrainfo.c @@ -0,0 +1,63 @@ +#define ROUTERPARSE_PRIVATE +#include "or.h" +#include "routerparse.h" +#include "routerlist.h" +#include "routerkeys.h" +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +static int +mock_router_produce_hash_final__nohash(char *digest, + const char *start, size_t len, + digest_algorithm_t alg) +{ + (void)start; + (void)len; + /* we could look at start[..] */ + if (alg == DIGEST_SHA1) + memset(digest, 0x01, 20); + else + memset(digest, 0x02, 32); + return 0; +} + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + MOCK(router_compute_hash_final, mock_router_produce_hash_final__nohash); + ed25519_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + extrainfo_t *ei; + const char *str = (const char*) data; + int again = 0; + ei = extrainfo_parse_entry_from_string((const char *)str, + str+sz, + 0, NULL, &again); + if (ei) { + log_debug(LD_GENERAL, "Parsing okay"); + extrainfo_free(ei); + } else { + log_debug(LD_GENERAL, "Parsing failed"); + } + return 0; +} + diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 7948b204c9..7f413183f7 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -39,8 +39,17 @@ 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_extrainfo_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_extrainfo.c +src_test_fuzz_fuzz_extrainfo_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_extrainfo_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_extrainfo_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_extrainfo_LDADD = $(FUZZING_LIBS) + FUZZERS = \ src/test/fuzz/fuzz-descriptor \ + src/test/fuzz/fuzz-extrainfo \ src/test/fuzz/fuzz-http # The fuzzers aren't built by default right now. That should change. -- cgit v1.2.3-54-g00ecf From 3c748559343b98f1dd37a0f49bd1e179715bf511 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Dec 2016 15:57:22 -0500 Subject: Addition to test cases: make sure fuzzer binaries allow known cases This isn't fuzzing per se, so much as replaying the highlights of past fuzzer runs. --- src/test/fuzz/include.am | 5 +++-- src/test/fuzz_static_testcases.sh | 15 +++++++++++++++ src/test/include.am | 4 +++- 3 files changed, 21 insertions(+), 3 deletions(-) create mode 100755 src/test/fuzz_static_testcases.sh diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 7f413183f7..16e5d30d50 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -52,6 +52,7 @@ FUZZERS = \ src/test/fuzz/fuzz-extrainfo \ src/test/fuzz/fuzz-http -# The fuzzers aren't built by default right now. That should change. -EXTRA_PROGRAMS += $(FUZZERS) +noinst_PROGRAMS += $(FUZZERS) fuzzers: $(FUZZERS) + + diff --git a/src/test/fuzz_static_testcases.sh b/src/test/fuzz_static_testcases.sh new file mode 100755 index 0000000000..276bc6e157 --- /dev/null +++ b/src/test/fuzz_static_testcases.sh @@ -0,0 +1,15 @@ +#!/bin/sh + +# Copyright (c) 2016, The Tor Project, Inc. +# See LICENSE for licensing information + +set -e + +for fuzzer in "${builddir:-.}"/src/test/fuzz/fuzz-* ; do + f=`basename $fuzzer` + case="${f#fuzz-}" + echo "Running tests for ${case}" + for entry in ${abs_top_srcdir:-.}/src/test/fuzz/data/${case}/*; do + "${fuzzer}" "--err" < "$entry" + done +done diff --git a/src/test/include.am b/src/test/include.am index d406d6d324..9f30443496 100644 --- a/src/test/include.am +++ b/src/test/include.am @@ -8,7 +8,9 @@ TESTS_ENVIRONMENT = \ export builddir="$(builddir)"; \ export TESTING_TOR_BINARY="$(TESTING_TOR_BINARY)"; -TESTSCRIPTS = src/test/test_zero_length_keys.sh \ +TESTSCRIPTS = \ + src/test/fuzz_static_testcases.sh \ + src/test/test_zero_length_keys.sh \ src/test/test_workqueue_cancel.sh \ src/test/test_workqueue_efd.sh \ src/test/test_workqueue_efd2.sh \ -- cgit v1.2.3-54-g00ecf From 4afb155db2d9aaafe8dd1517e9619e6bd9c95751 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Dec 2016 17:03:54 -0500 Subject: Add microdesc format fuzzer. --- src/test/fuzz/dict/microdesc | 7 +++++++ src/test/fuzz/fuzz_microdesc.c | 45 ++++++++++++++++++++++++++++++++++++++++++ src/test/fuzz/include.am | 12 ++++++++++- 3 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 src/test/fuzz/dict/microdesc create mode 100644 src/test/fuzz/fuzz_microdesc.c diff --git a/src/test/fuzz/dict/microdesc b/src/test/fuzz/dict/microdesc new file mode 100644 index 0000000000..fdd0567b65 --- /dev/null +++ b/src/test/fuzz/dict/microdesc @@ -0,0 +1,7 @@ +"onion-key" +"ntor-onion-key" +"id" +"a" +"family" +"p" +"p6" diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c new file mode 100644 index 0000000000..bb944595fe --- /dev/null +++ b/src/test/fuzz/fuzz_microdesc.c @@ -0,0 +1,45 @@ +#define ROUTERPARSE_PRIVATE +#include "or.h" +#include "routerparse.h" +#include "microdesc.h" +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + ed25519_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + const char *str = (const char*) data; + smartlist_t *result = microdescs_parse_from_string((const char *)str, + str+sz, + 0, SAVED_NOWHERE, NULL); + if (result) { + log_debug(LD_GENERAL, "Parsing okay: %d", smartlist_len(result)); + SMARTLIST_FOREACH(result, microdesc_t *, md, microdesc_free(md)); + smartlist_free(result); + } else { + log_debug(LD_GENERAL, "Parsing failed"); + } + return 0; +} + diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 16e5d30d50..bfe38089d5 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -47,12 +47,22 @@ src_test_fuzz_fuzz_extrainfo_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_extrainfo_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_extrainfo_LDADD = $(FUZZING_LIBS) +src_test_fuzz_fuzz_microdesc_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_microdesc.c +src_test_fuzz_fuzz_microdesc_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_microdesc_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_microdesc_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_microdesc_LDADD = $(FUZZING_LIBS) + FUZZERS = \ src/test/fuzz/fuzz-descriptor \ src/test/fuzz/fuzz-extrainfo \ - src/test/fuzz/fuzz-http + src/test/fuzz/fuzz-http \ + src/test/fuzz/fuzz-microdesc noinst_PROGRAMS += $(FUZZERS) fuzzers: $(FUZZERS) + -- cgit v1.2.3-54-g00ecf From 301eff0e90a727005d364ebc2e9a7ffaecd0a3ef Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 14 Dec 2016 17:11:26 -0500 Subject: fuzzing: Add copyright notices and whitespace fixes --- Makefile.am | 1 + src/test/fuzz/fuzz_descriptor.c | 2 ++ src/test/fuzz/fuzz_extrainfo.c | 2 ++ src/test/fuzz/fuzz_http.c | 2 +- src/test/fuzz/fuzz_microdesc.c | 2 ++ src/test/fuzz/fuzzing.h | 3 +++ src/test/fuzz/fuzzing_common.c | 6 ++++-- 7 files changed, 15 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 2e853d4108..5204830864 100644 --- a/Makefile.am +++ b/Makefile.am @@ -190,6 +190,7 @@ if USE_PERL $(top_srcdir)/src/common/*.[ch] \ $(top_srcdir)/src/or/*.[ch] \ $(top_srcdir)/src/test/*.[ch] \ + $(top_srcdir)/src/test/*/*.[ch] \ $(top_srcdir)/src/tools/*.[ch] endif diff --git a/src/test/fuzz/fuzz_descriptor.c b/src/test/fuzz/fuzz_descriptor.c index 563787b7cc..d19386d77f 100644 --- a/src/test/fuzz/fuzz_descriptor.c +++ b/src/test/fuzz/fuzz_descriptor.c @@ -1,3 +1,5 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ #define ROUTERPARSE_PRIVATE #include "or.h" #include "routerparse.h" diff --git a/src/test/fuzz/fuzz_extrainfo.c b/src/test/fuzz/fuzz_extrainfo.c index 6bfc425a9a..6251e606d0 100644 --- a/src/test/fuzz/fuzz_extrainfo.c +++ b/src/test/fuzz/fuzz_extrainfo.c @@ -1,3 +1,5 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ #define ROUTERPARSE_PRIVATE #include "or.h" #include "routerparse.h" diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c index 15d3726763..f069900a2c 100644 --- a/src/test/fuzz/fuzz_http.c +++ b/src/test/fuzz/fuzz_http.c @@ -37,7 +37,6 @@ mock_directory_handle_command_get(dir_connection_t *conn, if (headers) { log_debug(LD_GENERAL, "Header-Length:\n%zu\n", strlen(headers)); log_debug(LD_GENERAL, "Headers:\n%s\n", headers); - } log_debug(LD_GENERAL, "Body-Length:\n%zu\n", body_len); @@ -130,3 +129,4 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size) return 0; } + diff --git a/src/test/fuzz/fuzz_microdesc.c b/src/test/fuzz/fuzz_microdesc.c index bb944595fe..bb89546191 100644 --- a/src/test/fuzz/fuzz_microdesc.c +++ b/src/test/fuzz/fuzz_microdesc.c @@ -1,3 +1,5 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ #define ROUTERPARSE_PRIVATE #include "or.h" #include "routerparse.h" diff --git a/src/test/fuzz/fuzzing.h b/src/test/fuzz/fuzzing.h index a8cbb1d9e8..4295743458 100644 --- a/src/test/fuzz/fuzzing.h +++ b/src/test/fuzz/fuzzing.h @@ -1,3 +1,5 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ #ifndef FUZZING_H #define FUZZING_H @@ -8,3 +10,4 @@ int fuzz_main(const uint8_t *data, size_t sz); void disable_signature_checking(void); #endif /* FUZZING_H */ + diff --git a/src/test/fuzz/fuzzing_common.c b/src/test/fuzz/fuzzing_common.c index 54a792353d..57c3cf52cf 100644 --- a/src/test/fuzz/fuzzing_common.c +++ b/src/test/fuzz/fuzzing_common.c @@ -1,3 +1,5 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ #define CRYPTO_ED25519_PRIVATE #include "orconfig.h" #include "or.h" @@ -78,7 +80,6 @@ mock_ed25519_impl_spot_check__nocheck(void) return 0; } - void disable_signature_checking(void) { @@ -93,7 +94,8 @@ disable_signature_checking(void) #ifdef LLVM_FUZZ int -LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) { +LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) +{ static int initialized = 0; if (!initialized) { if (fuzz_init() < 0) -- cgit v1.2.3-54-g00ecf From 83e9918107dba1b969a226b79e1d37a852339e45 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 16 Dec 2016 10:24:36 -0500 Subject: Tools for working with directories of fuzzed stuff. --- src/test/fuzz/fixup_filenames.sh | 19 +++++++++++++++++++ src/test/fuzz/minimize.sh | 14 ++++++++++++++ 2 files changed, 33 insertions(+) create mode 100755 src/test/fuzz/fixup_filenames.sh create mode 100755 src/test/fuzz/minimize.sh diff --git a/src/test/fuzz/fixup_filenames.sh b/src/test/fuzz/fixup_filenames.sh new file mode 100755 index 0000000000..68efc1abc5 --- /dev/null +++ b/src/test/fuzz/fixup_filenames.sh @@ -0,0 +1,19 @@ +#!/bin/sh + +set -e + +if [ ! -d "$1" ] ; then + echo "I need a directory" + exit 1 +fi + +for fn in "$1"/* ; do + prev=`basename "$fn"` + post=`sha256sum "$fn" | sed -e 's/ .*//;'` + if [ "$prev" == "$post" ] ; then + echo "OK $prev" + else + echo "mv $prev $post" + mv "$fn" "$1/$post" + fi +done diff --git a/src/test/fuzz/minimize.sh b/src/test/fuzz/minimize.sh new file mode 100755 index 0000000000..87d3dda13c --- /dev/null +++ b/src/test/fuzz/minimize.sh @@ -0,0 +1,14 @@ +#!/bin/sh + +set -e + +if [ ! -d "$1" ] ; then + echo "I need a directory" + exit 1 +fi + +which=`basename "$1"` + +mkdir "$1.out" +afl-cmin -i "$1" -o "$1.out" -m none "./src/test/fuzz/fuzz-${which}" + -- cgit v1.2.3-54-g00ecf From b1567cf500044be4d6c97e4ef65345acb4aa70ff Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 19 Dec 2016 15:11:27 -0500 Subject: Three more fuzzers: consensus, hsdesc, intro points --- src/or/routerparse.c | 9 ++++- src/or/routerparse.h | 2 ++ src/test/fuzz/dict/consensus | 52 ++++++++++++++++++++++++++++ src/test/fuzz/dict/hsdescv2 | 8 +++++ src/test/fuzz/dict/iptsv2 | 6 ++++ src/test/fuzz/fuzz_consensus.c | 78 ++++++++++++++++++++++++++++++++++++++++++ src/test/fuzz/fuzz_hsdescv2.c | 52 ++++++++++++++++++++++++++++ src/test/fuzz/fuzz_iptsv2.c | 46 +++++++++++++++++++++++++ 8 files changed, 252 insertions(+), 1 deletion(-) create mode 100644 src/test/fuzz/dict/consensus create mode 100644 src/test/fuzz/dict/hsdescv2 create mode 100644 src/test/fuzz/dict/iptsv2 create mode 100644 src/test/fuzz/fuzz_consensus.c create mode 100644 src/test/fuzz/fuzz_hsdescv2.c create mode 100644 src/test/fuzz/fuzz_iptsv2.c diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 5fd2e0829c..0aa953cc52 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -1172,6 +1172,12 @@ tor_version_is_obsolete(const char *myversion, const char *versionlist) return ret; } +MOCK_IMPL(STATIC int, +signed_digest_equals, (const uint8_t *d1, const uint8_t *d2, size_t len)) +{ + return tor_memeq(d1, d2, len); +} + /** Check whether the object body of the token in tok has a good * signature for digest using key pkey. * If CST_NO_CHECK_OBJTYPE is set, do not check @@ -1214,7 +1220,8 @@ check_signature_token(const char *digest, } // log_debug(LD_DIR,"Signed %s hash starts %s", doctype, // hex_str(signed_digest,4)); - if (tor_memneq(digest, signed_digest, digest_len)) { + if (! signed_digest_equals((const uint8_t *)digest, + (const uint8_t *)signed_digest, digest_len)) { log_warn(LD_DIR, "Error reading %s: signature does not match.", doctype); tor_free(signed_digest); return -1; diff --git a/src/or/routerparse.h b/src/or/routerparse.h index a461d6794f..8eea989e31 100644 --- a/src/or/routerparse.h +++ b/src/or/routerparse.h @@ -123,6 +123,8 @@ MOCK_DECL(STATIC void,dump_desc,(const char *desc, const char *type)); MOCK_DECL(STATIC int, router_compute_hash_final,(char *digest, const char *start, size_t len, digest_algorithm_t alg)); +MOCK_DECL(STATIC int, signed_digest_equals, + (const uint8_t *d1, const uint8_t *d2, size_t len)); #endif #define ED_DESC_SIGNATURE_PREFIX "Tor router descriptor signature v1" diff --git a/src/test/fuzz/dict/consensus b/src/test/fuzz/dict/consensus new file mode 100644 index 0000000000..3fcd9ee7ff --- /dev/null +++ b/src/test/fuzz/dict/consensus @@ -0,0 +1,52 @@ +"a" +"additional-digest" +"additional-signature" +"bandwidth-weights" +"client-versions" +"consensus-digest" +"consensus-method" +"consensus-methods" +"contact" +"dir-address" +"directory-footer" +"directory-signature" +"dir-identity-key" +"dir-key-certificate-version" +"dir-key-certification" +"dir-key-crosscert" +"dir-key-expires" +"dir-key-published" +"dir-signing-key" +"dir-source" +"fingerprint" +"fresh-until" +"id" +"known-flags" +"legacy-dir-key" +"m" +"network-status-version" +"opt" +"p" +"package" +"params" +"pr" +"published" +"r" +"recommended-client-protocols" +"recommended-relay-protocols" +"required-client-protocols" +"required-relay-protocols" +"s" +"server-versions" +"shared-rand-commit" +"shared-rand-current-value" +"shared-rand-participate" +"shared-rand-previous-value" +"signing-ed25519" +"v" +"valid-after" +"valid-until" +"vote-digest" +"vote-status" +"voting-delay" +"w" diff --git a/src/test/fuzz/dict/hsdescv2 b/src/test/fuzz/dict/hsdescv2 new file mode 100644 index 0000000000..48788301dc --- /dev/null +++ b/src/test/fuzz/dict/hsdescv2 @@ -0,0 +1,8 @@ +"introduction-points" +"permanent-key" +"protocol-versions" +"publication-time" +"rendezvous-service-descriptor" +"secret-id-part" +"signature" +"version" diff --git a/src/test/fuzz/dict/iptsv2 b/src/test/fuzz/dict/iptsv2 new file mode 100644 index 0000000000..57791c5e3c --- /dev/null +++ b/src/test/fuzz/dict/iptsv2 @@ -0,0 +1,6 @@ +"introduction-point" +"ip-address" +"onion-port" +"onion-key" +"service-key" + diff --git a/src/test/fuzz/fuzz_consensus.c b/src/test/fuzz/fuzz_consensus.c new file mode 100644 index 0000000000..f5d22f69ae --- /dev/null +++ b/src/test/fuzz/fuzz_consensus.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ +#define ROUTERPARSE_PRIVATE +#include "or.h" +#include "routerparse.h" +#include "networkstatus.h" +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +static int +mock_router_produce_hash_final__nohash(char *digest, + const char *start, size_t len, + digest_algorithm_t alg) +{ + (void)start; + (void)len; + /* we could look at start[..] */ + if (alg == DIGEST_SHA1) + memset(digest, 0x01, 20); + else + memset(digest, 0x02, 32); + return 0; +} + +static int +mock_signed_digest_equals__yes(const uint8_t *d1, const uint8_t *d2, + size_t len) +{ + (void) tor_memeq(d1, d2, len); + return 1; +} + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + MOCK(router_compute_hash_final, mock_router_produce_hash_final__nohash); + MOCK(signed_digest_equals, mock_signed_digest_equals__yes); + ed25519_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + networkstatus_t *ns; + char *str = tor_memdup_nulterm(data, sz); + const char *eos = NULL; + networkstatus_type_t tp = NS_TYPE_CONSENSUS; + if (tor_memstr(data, MIN(sz, 1024), "tus vote")) + tp = NS_TYPE_VOTE; + const char *what = (tp == NS_TYPE_CONSENSUS) ? "consensus" : "vote"; + ns = networkstatus_parse_vote_from_string(str, + &eos, + tp); + if (ns) { + log_debug(LD_GENERAL, "Parsing as %s okay", what); + networkstatus_vote_free(ns); + } else { + log_debug(LD_GENERAL, "Parsing as %s failed", what); + } + tor_free(str); + return 0; +} + diff --git a/src/test/fuzz/fuzz_hsdescv2.c b/src/test/fuzz/fuzz_hsdescv2.c new file mode 100644 index 0000000000..53b7cbe2f7 --- /dev/null +++ b/src/test/fuzz/fuzz_hsdescv2.c @@ -0,0 +1,52 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ +#define ROUTERPARSE_PRIVATE +#include "or.h" +#include "routerparse.h" +#include "rendcommon.h" +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + ed25519_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + rend_service_descriptor_t *desc = NULL; + char desc_id[64]; + char *ipts = NULL; + size_t ipts_size, esize; + const char *next; + char *str = tor_memdup_nulterm(data, sz); + (void) rend_parse_v2_service_descriptor(&desc, desc_id, &ipts, &ipts_size, + &esize, &next, str, 1); + if (desc) { + log_debug(LD_GENERAL, "Parsing okay"); + rend_service_descriptor_free(desc); + } else { + log_debug(LD_GENERAL, "Parsing failed"); + } + tor_free(ipts); + tor_free(str); + return 0; +} + diff --git a/src/test/fuzz/fuzz_iptsv2.c b/src/test/fuzz/fuzz_iptsv2.c new file mode 100644 index 0000000000..341d4880bd --- /dev/null +++ b/src/test/fuzz/fuzz_iptsv2.c @@ -0,0 +1,46 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ +#define ROUTERPARSE_PRIVATE +#include "or.h" +#include "routerparse.h" +#include "rendcommon.h" +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + ed25519_init(); + return 0; +} + +int +fuzz_cleanup(void) +{ + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + rend_service_descriptor_t *desc = + tor_malloc_zero(sizeof(rend_service_descriptor_t)); + const char *str = (const char*) data; + int r = rend_parse_introduction_points(desc, str, sz); + if (r >= 0) { + log_debug(LD_GENERAL, "Parsing okay: %d", r); + } else { + log_debug(LD_GENERAL, "Parsing failed"); + } + rend_service_descriptor_free(desc); + return 0; +} + -- cgit v1.2.3-54-g00ecf From eb414a08a9272090e6b35080c2ac8b7415a83094 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 19 Dec 2016 15:17:42 -0500 Subject: Add libfuzzer support. --- .gitignore | 1 + Makefile.am | 4 ++ configure.ac | 6 ++- src/test/fuzz/fuzzing_common.c | 45 +++++++++++-------- src/test/fuzz/include.am | 99 +++++++++++++++++++++++++++++++++++++++++- 5 files changed, 135 insertions(+), 20 deletions(-) diff --git a/.gitignore b/.gitignore index 1491b11b7e..7e421d8b8e 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 5204830864..785cf34132 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 721f5cd8c3..784b3cde14 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 57c3cf52cf..e4920d3ee7 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 bfe38089d5..c716889e71 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) -- cgit v1.2.3-54-g00ecf From 024fa9d4d76d21d1a51b0a362552bcbff4159b3a Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sat, 31 Dec 2016 15:09:11 -0500 Subject: routerstatus fuzzing --- src/test/fuzz/fuzz_vrs.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++ src/test/fuzz/include.am | 23 ++++++++++++-- 2 files changed, 98 insertions(+), 3 deletions(-) create mode 100644 src/test/fuzz/fuzz_vrs.c diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c new file mode 100644 index 0000000000..1c4e5e2bfa --- /dev/null +++ b/src/test/fuzz/fuzz_vrs.c @@ -0,0 +1,78 @@ +/* Copyright (c) 2016, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ +#define ROUTERPARSE_PRIVATE +#define NETWORKSTATUS_PRIVATE +#include "or.h" +#include "routerparse.h" +#include "memarea.h" +#include "microdesc.h" +#include "networkstatus.h" +#include "fuzzing.h" + +static void +mock_dump_desc__nodump(const char *desc, const char *type) +{ + (void)desc; + (void)type; +} + +static networkstatus_t *dummy_vote = NULL; +static memarea_t *area = NULL; + +int +fuzz_init(void) +{ + disable_signature_checking(); + MOCK(dump_desc, mock_dump_desc__nodump); + ed25519_init(); + area = memarea_new(); + dummy_vote = tor_malloc_zero(sizeof(*dummy_vote)); + dummy_vote->known_flags = smartlist_new(); + smartlist_split_string(dummy_vote->known_flags, + "Authority BadExit Exit Fast Guard HSDir " + "NoEdConsensus Running Stable V2Dir Valid", + " ", 0, 0); + return 0; +} + +int +fuzz_cleanup(void) +{ + tor_free(dummy_vote); + return 0; +} + +int +fuzz_main(const uint8_t *data, size_t sz) +{ + const char *str = tor_memdup_nulterm(data, sz), *s; + routerstatus_t *rs_ns = NULL, *rs_md = NULL, *rs_vote = NULL; + vote_routerstatus_t *vrs = tor_malloc_zero(sizeof(*vrs)); + smartlist_t *tokens = smartlist_new(); + + s = str; + rs_ns = routerstatus_parse_entry_from_string(area, &s, tokens, + NULL, NULL, 26, FLAV_NS); + tor_assert(smartlist_len(tokens) == 0); + + s = str; + rs_md = routerstatus_parse_entry_from_string(area, &s, tokens, + NULL, NULL, 26, FLAV_MICRODESC); + tor_assert(smartlist_len(tokens) == 0); + + s = str; + rs_vote = routerstatus_parse_entry_from_string(area, &s, tokens, + dummy_vote, vrs, 26, FLAV_NS); + tor_assert(smartlist_len(tokens) == 0); + + log_debug(LD_GENERAL, + "ns=%p, md=%p, vote=%p", rs_ns, rs_md, rs_vote); + + routerstatus_free(rs_md); + routerstatus_free(rs_ns); + vote_routerstatus_free(vrs); + memarea_clear(area); + smartlist_free(tokens); + return 0; +} + diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index c716889e71..2bfdaf3db5 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -79,6 +79,14 @@ src_test_fuzz_fuzz_microdesc_CFLAGS = $(FUZZING_CFLAGS) src_test_fuzz_fuzz_microdesc_LDFLAGS = $(FUZZING_LDFLAG) src_test_fuzz_fuzz_microdesc_LDADD = $(FUZZING_LIBS) +src_test_fuzz_fuzz_vrs_SOURCES = \ + src/test/fuzz/fuzzing_common.c \ + src/test/fuzz/fuzz_vrs.c +src_test_fuzz_fuzz_vrs_CPPFLAGS = $(FUZZING_CPPFLAGS) +src_test_fuzz_fuzz_vrs_CFLAGS = $(FUZZING_CFLAGS) +src_test_fuzz_fuzz_vrs_LDFLAGS = $(FUZZING_LDFLAG) +src_test_fuzz_fuzz_vrs_LDADD = $(FUZZING_LIBS) + FUZZERS = \ src/test/fuzz/fuzz-consensus \ src/test/fuzz/fuzz-descriptor \ @@ -86,7 +94,9 @@ FUZZERS = \ src/test/fuzz/fuzz-http \ src/test/fuzz/fuzz-hsdescv2 \ src/test/fuzz/fuzz-iptsv2 \ - src/test/fuzz/fuzz-microdesc + src/test/fuzz/fuzz-microdesc \ + src/test/fuzz/fuzz-vrs + LIBFUZZER = /home/nickm/build/libfuzz/libFuzzer.a LIBFUZZER_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ @@ -144,6 +154,13 @@ 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) +src_test_fuzz_lf_fuzz_vrs_SOURCES = \ + $(src_test_fuzz_fuzz_vrs_SOURCES) +src_test_fuzz_lf_fuzz_vrs_CPPFLAGS = $(LIBFUZZER_CPPFLAGS) +src_test_fuzz_lf_fuzz_vrs_CFLAGS = $(LIBFUZZER_CFLAGS) +src_test_fuzz_lf_fuzz_vrs_LDFLAGS = $(LIBFUZZER_LDFLAG) +src_test_fuzz_lf_fuzz_vrs_LDADD = $(LIBFUZZER_LIBS) + LIBFUZZER_FUZZERS = \ src/test/fuzz/lf-fuzz-consensus \ src/test/fuzz/lf-fuzz-descriptor \ @@ -151,7 +168,8 @@ LIBFUZZER_FUZZERS = \ src/test/fuzz/lf-fuzz-http \ src/test/fuzz/lf-fuzz-hsdescv2 \ src/test/fuzz/lf-fuzz-iptsv2 \ - src/test/fuzz/lf-fuzz-microdesc + src/test/fuzz/lf-fuzz-microdesc \ + src/test/fuzz/lf-fuzz-vrs else LIBFUZZER_FUZZERS = @@ -160,4 +178,3 @@ endif noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) - -- cgit v1.2.3-54-g00ecf From 1b244a64e403f9b6bd452d1f2e9c961a1f91e2d7 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 10:44:55 -0500 Subject: libfuzzer tweaks per recommendations --- Makefile.am | 3 +- configure.ac | 5 +++- src/test/fuzz/include.am | 78 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 83 insertions(+), 3 deletions(-) diff --git a/Makefile.am b/Makefile.am index 785cf34132..631b44e7f5 100644 --- a/Makefile.am +++ b/Makefile.am @@ -56,7 +56,8 @@ TEST_NETWORK_FLAGS=--hs-multi-client 1 endif if LIBFUZZER_ENABLED -TEST_CFLAGS += -fsanitize-coverage=edge -fsanitize-coverage=trace-cmp +TEST_CFLAGS += -fsanitize-coverage=trace-pc-guard,trace-cmp,trace-div +# not "edge" endif TEST_NETWORK_ALL_LOG_DIR=$(top_builddir)/test_network_log diff --git a/configure.ac b/configure.ac index 784b3cde14..aff41ae60a 100644 --- a/configure.ac +++ b/configure.ac @@ -50,7 +50,9 @@ AC_ARG_ENABLE(asserts-in-tests, 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'])) + AS_HELP_STRING(--enable-libfuzzer, [build extra fuzzers based on 'libfuzzer'])) +AC_ARG_ENABLE(oss-fuzz, + AS_HELP_STRING(--enable-oss-fuzz, [build extra fuzzers based on 'oss-fuzz' environment])) 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]) @@ -60,6 +62,7 @@ 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") +AM_CONDITIONAL(OSS_FUZZ_ENABLED, test "x$enable_oss_fuzz" = "xyes") if test "$enable_static_tor" = "yes"; then enable_static_libevent="yes"; diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 2bfdaf3db5..bb92c87ff7 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -175,6 +175,82 @@ else LIBFUZZER_FUZZERS = endif -noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) +if OSS_FUZZ_ENABLED +OSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ +OSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS) +OSS_FUZZ_LDFLAG = $(FUZZING_LDFLAG) +OSS_FUZZ_LIBS = $(FUZZING_LIBS) -lFuzzingEngine -lstdc++ + +src_test_fuzz_oss_fuzz_consensus_SOURCES = \ + $(src_test_fuzz_fuzz_consensus_SOURCES) +src_test_fuzz_oss_fuzz_consensus_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_consensus_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_consensus_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_consensus_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_descriptor_SOURCES = \ + $(src_test_fuzz_fuzz_descriptor_SOURCES) +src_test_fuzz_oss_fuzz_descriptor_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_descriptor_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_descriptor_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_descriptor_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_extrainfo_SOURCES = \ + $(src_test_fuzz_fuzz_extrainfo_SOURCES) +src_test_fuzz_oss_fuzz_extrainfo_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_extrainfo_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_extrainfo_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_extrainfo_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_http_SOURCES = \ + $(src_test_fuzz_fuzz_http_SOURCES) +src_test_fuzz_oss_fuzz_http_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_http_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_http_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_http_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_hsdescv2_SOURCES = \ + $(src_test_fuzz_fuzz_hsdescv2_SOURCES) +src_test_fuzz_oss_fuzz_hsdescv2_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_hsdescv2_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_hsdescv2_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_hsdescv2_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_iptsv2_SOURCES = \ + $(src_test_fuzz_fuzz_iptsv2_SOURCES) +src_test_fuzz_oss_fuzz_iptsv2_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_iptsv2_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_iptsv2_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_iptsv2_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_microdesc_SOURCES = \ + $(src_test_fuzz_fuzz_microdesc_SOURCES) +src_test_fuzz_oss_fuzz_microdesc_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_microdesc_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_microdesc_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_microdesc_LDADD = $(OSS_FUZZ_LIBS) + +src_test_fuzz_oss_fuzz_vrs_SOURCES = \ + $(src_test_fuzz_fuzz_vrs_SOURCES) +src_test_fuzz_oss_fuzz_vrs_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_vrs_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_vrs_LDFLAGS = $(OSS_FUZZ_LDFLAG) +src_test_fuzz_oss_fuzz_vrs_LDADD = $(OSS_FUZZ_LIBS) + +OSS_FUZZ_FUZZERS = \ + src/test/fuzz/oss-fuzz-consensus \ + src/test/fuzz/oss-fuzz-descriptor \ + src/test/fuzz/oss-fuzz-extrainfo \ + src/test/fuzz/oss-fuzz-http \ + src/test/fuzz/oss-fuzz-hsdescv2 \ + src/test/fuzz/oss-fuzz-iptsv2 \ + src/test/fuzz/oss-fuzz-microdesc \ + src/test/fuzz/oss-fuzz-vrs +else +OSS_FUZZ_FUZZERS +endif + +noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) $(OSS_FUZZ_FUZZERS) +oss-fuzz-fuzzers: $(OSS_FUZZ_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) -- cgit v1.2.3-54-g00ecf From 99d4faf6d35b5923daf48605da0d9da2e7de1824 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 11:26:27 -0500 Subject: oss_fuzz also requires no PIE --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index aff41ae60a..f6438066b1 100644 --- a/configure.ac +++ b/configure.ac @@ -765,7 +765,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" && test "$enable_libfuzzer" != "yes"; then + if test "$bwin32" = "false" && test "$enable_libfuzzer" != "yes" && test "$enable_oss_fuzz" != "yes"; then TOR_CHECK_CFLAGS(-fPIE) TOR_CHECK_LDFLAGS(-pie, "$all_ldflags_for_check", "$all_libs_for_check") fi -- cgit v1.2.3-54-g00ecf From 92679d90d54d6bde28124fd56e443c02f89b4e52 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 12:25:28 -0500 Subject: Try to refactor OSS fuzzers into static libraries. --- src/test/fuzz/include.am | 87 +++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 52 deletions(-) diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index bb92c87ff7..b73139f992 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -178,79 +178,62 @@ endif if OSS_FUZZ_ENABLED OSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ OSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS) -OSS_FUZZ_LDFLAG = $(FUZZING_LDFLAG) -OSS_FUZZ_LIBS = $(FUZZING_LIBS) -lFuzzingEngine -lstdc++ -src_test_fuzz_oss_fuzz_consensus_SOURCES = \ +src_test_fuzz_oss_fuzz_consensus_a_SOURCES = \ $(src_test_fuzz_fuzz_consensus_SOURCES) -src_test_fuzz_oss_fuzz_consensus_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_consensus_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_consensus_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_consensus_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_consensus_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_consensus_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_descriptor_SOURCES = \ +src_test_fuzz_oss_fuzz_descriptor_a_SOURCES = \ $(src_test_fuzz_fuzz_descriptor_SOURCES) -src_test_fuzz_oss_fuzz_descriptor_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_descriptor_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_descriptor_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_descriptor_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_descriptor_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_descriptor_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_extrainfo_SOURCES = \ +src_test_fuzz_oss_fuzz_extrainfo_a_SOURCES = \ $(src_test_fuzz_fuzz_extrainfo_SOURCES) -src_test_fuzz_oss_fuzz_extrainfo_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_extrainfo_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_extrainfo_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_extrainfo_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_extrainfo_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_extrainfo_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_http_SOURCES = \ +src_test_fuzz_oss_fuzz_http_a_SOURCES = \ $(src_test_fuzz_fuzz_http_SOURCES) -src_test_fuzz_oss_fuzz_http_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_http_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_http_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_http_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_http_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_http_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_hsdescv2_SOURCES = \ +src_test_fuzz_oss_fuzz_hsdescv2_a_SOURCES = \ $(src_test_fuzz_fuzz_hsdescv2_SOURCES) -src_test_fuzz_oss_fuzz_hsdescv2_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_hsdescv2_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_hsdescv2_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_hsdescv2_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_hsdescv2_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_hsdescv2_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_iptsv2_SOURCES = \ +src_test_fuzz_oss_fuzz_iptsv2_a_SOURCES = \ $(src_test_fuzz_fuzz_iptsv2_SOURCES) -src_test_fuzz_oss_fuzz_iptsv2_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_iptsv2_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_iptsv2_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_iptsv2_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_iptsv2_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_iptsv2_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_microdesc_SOURCES = \ +src_test_fuzz_oss_fuzz_microdesc_a_SOURCES = \ $(src_test_fuzz_fuzz_microdesc_SOURCES) -src_test_fuzz_oss_fuzz_microdesc_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_microdesc_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_microdesc_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_microdesc_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_microdesc_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_microdesc_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_vrs_SOURCES = \ +src_test_fuzz_oss_fuzz_vrs_a_a_SOURCES = \ $(src_test_fuzz_fuzz_vrs_SOURCES) -src_test_fuzz_oss_fuzz_vrs_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_vrs_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_vrs_LDFLAGS = $(OSS_FUZZ_LDFLAG) -src_test_fuzz_oss_fuzz_vrs_LDADD = $(OSS_FUZZ_LIBS) +src_test_fuzz_oss_fuzz_vrs_a_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_vrs_a_a_CFLAGS = $(OSS_FUZZ_CFLAGS) OSS_FUZZ_FUZZERS = \ - src/test/fuzz/oss-fuzz-consensus \ - src/test/fuzz/oss-fuzz-descriptor \ - src/test/fuzz/oss-fuzz-extrainfo \ - src/test/fuzz/oss-fuzz-http \ - src/test/fuzz/oss-fuzz-hsdescv2 \ - src/test/fuzz/oss-fuzz-iptsv2 \ - src/test/fuzz/oss-fuzz-microdesc \ - src/test/fuzz/oss-fuzz-vrs + src/test/fuzz/oss-fuzz-consensus.a \ + src/test/fuzz/oss-fuzz-descriptor.a \ + src/test/fuzz/oss-fuzz-extrainfo.a \ + src/test/fuzz/oss-fuzz-http.a \ + src/test/fuzz/oss-fuzz-hsdescv2.a \ + src/test/fuzz/oss-fuzz-iptsv2.a \ + src/test/fuzz/oss-fuzz-microdesc.a \ + src/test/fuzz/oss-fuzz-vrs.a else -OSS_FUZZ_FUZZERS +OSS_FUZZ_FUZZERS = endif -noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) $(OSS_FUZZ_FUZZERS) +noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) +noinst_LIBRARIES += $(OSS_FUZZ_FUZZERS) oss-fuzz-fuzzers: $(OSS_FUZZ_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) -- cgit v1.2.3-54-g00ecf From cf71f8ad32c55c065fe05151ae357bb5b7414dcf Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 13:02:53 -0500 Subject: More oss-fuzz fixes --- src/test/fuzz/include.am | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index b73139f992..ab690e05f1 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -19,6 +19,15 @@ FUZZING_LIBS = \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ +oss-fuzz-prereqs: + src/or/libtor-testing.a \ + src/common/libor-crypto-testing.a \ + $(LIBKECCAK_TINY) \ + $(LIBDONNA) \ + src/common/libor-testing.a \ + src/common/libor-ctime-testing.a \ + src/common/libor-event-testing.a \ + src/trunnel/libor-trunnel-testing.a noinst_HEADERS += \ src/test/fuzz/fuzzing.h @@ -214,10 +223,10 @@ src_test_fuzz_oss_fuzz_microdesc_a_SOURCES = \ src_test_fuzz_oss_fuzz_microdesc_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) src_test_fuzz_oss_fuzz_microdesc_a_CFLAGS = $(OSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_vrs_a_a_SOURCES = \ +src_test_fuzz_oss_fuzz_vrs_a_SOURCES = \ $(src_test_fuzz_fuzz_vrs_SOURCES) -src_test_fuzz_oss_fuzz_vrs_a_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_vrs_a_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_oss_fuzz_vrs_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) +src_test_fuzz_oss_fuzz_vrs_a_CFLAGS = $(OSS_FUZZ_CFLAGS) OSS_FUZZ_FUZZERS = \ src/test/fuzz/oss-fuzz-consensus.a \ @@ -234,6 +243,6 @@ endif noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) noinst_LIBRARIES += $(OSS_FUZZ_FUZZERS) -oss-fuzz-fuzzers: $(OSS_FUZZ_FUZZERS) +oss-fuzz-fuzzers: oss-fuzz-prereqs $(OSS_FUZZ_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) -- cgit v1.2.3-54-g00ecf From f547352637f18f4d034027b96b26511150a94c4d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 13:15:40 -0500 Subject: differently build oss fuzzers --- src/test/fuzz/include.am | 76 ++++++++++++++++++++++++------------------------ 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index ab690e05f1..923340cd11 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -185,64 +185,64 @@ LIBFUZZER_FUZZERS = endif if OSS_FUZZ_ENABLED -OSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ -OSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS) +LIBOSS_FUZZ_CPPFLAGS = $(FUZZING_CPPFLAGS) -DLLVM_FUZZ +LIBOSS_FUZZ_CFLAGS = $(FUZZING_CFLAGS) -src_test_fuzz_oss_fuzz_consensus_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_consensus_a_SOURCES = \ $(src_test_fuzz_fuzz_consensus_SOURCES) -src_test_fuzz_oss_fuzz_consensus_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_consensus_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_consensus_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_consensus_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_descriptor_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_descriptor_a_SOURCES = \ $(src_test_fuzz_fuzz_descriptor_SOURCES) -src_test_fuzz_oss_fuzz_descriptor_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_descriptor_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_descriptor_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_descriptor_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_extrainfo_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_extrainfo_a_SOURCES = \ $(src_test_fuzz_fuzz_extrainfo_SOURCES) -src_test_fuzz_oss_fuzz_extrainfo_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_extrainfo_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_extrainfo_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_extrainfo_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_http_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_http_a_SOURCES = \ $(src_test_fuzz_fuzz_http_SOURCES) -src_test_fuzz_oss_fuzz_http_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_http_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_http_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_http_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_hsdescv2_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_hsdescv2_a_SOURCES = \ $(src_test_fuzz_fuzz_hsdescv2_SOURCES) -src_test_fuzz_oss_fuzz_hsdescv2_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_hsdescv2_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_hsdescv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_hsdescv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_iptsv2_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_iptsv2_a_SOURCES = \ $(src_test_fuzz_fuzz_iptsv2_SOURCES) -src_test_fuzz_oss_fuzz_iptsv2_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_iptsv2_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_iptsv2_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_iptsv2_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_microdesc_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_microdesc_a_SOURCES = \ $(src_test_fuzz_fuzz_microdesc_SOURCES) -src_test_fuzz_oss_fuzz_microdesc_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_microdesc_a_CFLAGS = $(OSS_FUZZ_CFLAGS) +src_test_fuzz_liboss_fuzz_microdesc_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_microdesc_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -src_test_fuzz_oss_fuzz_vrs_a_SOURCES = \ +src_test_fuzz_liboss_fuzz_vrs_a_SOURCES = \ $(src_test_fuzz_fuzz_vrs_SOURCES) -src_test_fuzz_oss_fuzz_vrs_a_CPPFLAGS = $(OSS_FUZZ_CPPFLAGS) -src_test_fuzz_oss_fuzz_vrs_a_CFLAGS = $(OSS_FUZZ_CFLAGS) - -OSS_FUZZ_FUZZERS = \ - src/test/fuzz/oss-fuzz-consensus.a \ - src/test/fuzz/oss-fuzz-descriptor.a \ - src/test/fuzz/oss-fuzz-extrainfo.a \ - src/test/fuzz/oss-fuzz-http.a \ - src/test/fuzz/oss-fuzz-hsdescv2.a \ - src/test/fuzz/oss-fuzz-iptsv2.a \ - src/test/fuzz/oss-fuzz-microdesc.a \ - src/test/fuzz/oss-fuzz-vrs.a +src_test_fuzz_liboss_fuzz_vrs_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) +src_test_fuzz_liboss_fuzz_vrs_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) + +LIBOSS_FUZZ_FUZZERS = \ + src/test/fuzz/liboss-fuzz-consensus.a \ + src/test/fuzz/liboss-fuzz-descriptor.a \ + src/test/fuzz/liboss-fuzz-extrainfo.a \ + src/test/fuzz/liboss-fuzz-http.a \ + src/test/fuzz/liboss-fuzz-hsdescv2.a \ + src/test/fuzz/liboss-fuzz-iptsv2.a \ + src/test/fuzz/liboss-fuzz-microdesc.a \ + src/test/fuzz/liboss-fuzz-vrs.a else -OSS_FUZZ_FUZZERS = +LIBOSS_FUZZ_FUZZERS = endif noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) noinst_LIBRARIES += $(OSS_FUZZ_FUZZERS) -oss-fuzz-fuzzers: oss-fuzz-prereqs $(OSS_FUZZ_FUZZERS) +oss-fuzz-fuzzers: oss-fuzz-prereqs $(SS_FUZZ_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) -- cgit v1.2.3-54-g00ecf From 1c7862bfb4007f2eafa3180f72c8267c0e628b87 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 13:58:03 -0500 Subject: missing backslash --- src/test/fuzz/include.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 923340cd11..75a83c40e6 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -19,7 +19,7 @@ FUZZING_LIBS = \ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@ @CURVE25519_LIBS@ \ @TOR_SYSTEMD_LIBS@ -oss-fuzz-prereqs: +oss-fuzz-prereqs: \ src/or/libtor-testing.a \ src/common/libor-crypto-testing.a \ $(LIBKECCAK_TINY) \ -- cgit v1.2.3-54-g00ecf From 09d01466b2d35d762f0a4916bc39a3ceb11d87bc Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 14:07:16 -0500 Subject: actually build .as for fuzzing --- src/test/fuzz/include.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index 75a83c40e6..bca0a8626a 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -228,7 +228,7 @@ src_test_fuzz_liboss_fuzz_vrs_a_SOURCES = \ src_test_fuzz_liboss_fuzz_vrs_a_CPPFLAGS = $(LIBOSS_FUZZ_CPPFLAGS) src_test_fuzz_liboss_fuzz_vrs_a_CFLAGS = $(LIBOSS_FUZZ_CFLAGS) -LIBOSS_FUZZ_FUZZERS = \ +OSS_FUZZ_FUZZERS = \ src/test/fuzz/liboss-fuzz-consensus.a \ src/test/fuzz/liboss-fuzz-descriptor.a \ src/test/fuzz/liboss-fuzz-extrainfo.a \ @@ -238,11 +238,11 @@ LIBOSS_FUZZ_FUZZERS = \ src/test/fuzz/liboss-fuzz-microdesc.a \ src/test/fuzz/liboss-fuzz-vrs.a else -LIBOSS_FUZZ_FUZZERS = +OSS_FUZZ_FUZZERS = endif noinst_PROGRAMS += $(FUZZERS) $(LIBFUZZER_FUZZERS) noinst_LIBRARIES += $(OSS_FUZZ_FUZZERS) -oss-fuzz-fuzzers: oss-fuzz-prereqs $(SS_FUZZ_FUZZERS) +oss-fuzz-fuzzers: oss-fuzz-prereqs $(OSS_FUZZ_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) -- cgit v1.2.3-54-g00ecf From a092bcdd4f619e9b08ebb09049b4dd6cbdb3ee1c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 14:25:48 -0500 Subject: Fix a memory leak found while fuzzing --- src/or/routerparse.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 0aa953cc52..8cdeb45b7f 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -3711,11 +3711,10 @@ networkstatus_parse_vote_from_string(const char *s, const char **eos_out, if (ns->type != NS_TYPE_CONSENSUS) { vote_routerstatus_t *rs = tor_malloc_zero(sizeof(vote_routerstatus_t)); if (routerstatus_parse_entry_from_string(rs_area, &s, rs_tokens, ns, - rs, 0, 0)) + rs, 0, 0)) { smartlist_add(ns->routerstatus_list, rs); - else { - tor_free(rs->version); - tor_free(rs); + } else { + vote_routerstatus_free(rs); } } else { routerstatus_t *rs; -- cgit v1.2.3-54-g00ecf From 34fd6368708daec4c6af2b93d69d5ed774ac7c47 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 9 Jan 2017 14:29:15 -0500 Subject: memory leak in fuzz_vrs --- src/test/fuzz/fuzz_vrs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c index 1c4e5e2bfa..406a4de5f3 100644 --- a/src/test/fuzz/fuzz_vrs.c +++ b/src/test/fuzz/fuzz_vrs.c @@ -45,7 +45,7 @@ fuzz_cleanup(void) int fuzz_main(const uint8_t *data, size_t sz) { - const char *str = tor_memdup_nulterm(data, sz), *s; + char *str = tor_memdup_nulterm(data, sz), *s; routerstatus_t *rs_ns = NULL, *rs_md = NULL, *rs_vote = NULL; vote_routerstatus_t *vrs = tor_malloc_zero(sizeof(*vrs)); smartlist_t *tokens = smartlist_new(); @@ -73,6 +73,7 @@ fuzz_main(const uint8_t *data, size_t sz) vote_routerstatus_free(vrs); memarea_clear(area); smartlist_free(tokens); + tor_free(str); return 0; } -- cgit v1.2.3-54-g00ecf From 143235873ba0229f83ce69c4247ba8d3c459629f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 10 Jan 2017 14:13:45 -0500 Subject: Memory leak on bogus ed key in microdesc --- src/or/routerparse.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/or/routerparse.c b/src/or/routerparse.c index 8cdeb45b7f..58b9a22438 100644 --- a/src/or/routerparse.c +++ b/src/or/routerparse.c @@ -4717,11 +4717,13 @@ microdescs_parse_from_string(const char *s, const char *eos, if (!strcmp(t->args[0], "ed25519")) { if (md->ed25519_identity_pkey) { log_warn(LD_DIR, "Extra ed25519 key in microdesc"); + smartlist_free(id_lines); goto next; } ed25519_public_key_t k; if (ed25519_public_from_base64(&k, t->args[1])<0) { log_warn(LD_DIR, "Bogus ed25519 key in microdesc"); + smartlist_free(id_lines); goto next; } md->ed25519_identity_pkey = tor_memdup(&k, sizeof(k)); -- cgit v1.2.3-54-g00ecf From 1d8e9e8c699e68cdbb33ab41ccbd65e3dab8ff6b Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 11 Jan 2017 13:24:48 -0500 Subject: Fix memory leak on zero-length input on fuzz_http.c --- src/test/fuzz/fuzz_http.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/fuzz/fuzz_http.c b/src/test/fuzz/fuzz_http.c index f069900a2c..caad0b2f02 100644 --- a/src/test/fuzz/fuzz_http.c +++ b/src/test/fuzz/fuzz_http.c @@ -107,7 +107,7 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size) dir_conn.base_.inbuf = buf_new_with_data((char*)stdin_buf, data_size); if (!dir_conn.base_.inbuf) { log_debug(LD_GENERAL, "Zero-Length-Input\n"); - return 0; + goto done; } /* Parse the headers */ @@ -122,6 +122,7 @@ fuzz_main(const uint8_t *stdin_buf, size_t data_size) log_debug(LD_GENERAL, "Result:\n%d\n", rv); + done: /* Reset. */ tor_free(dir_conn.base_.address); buf_free(dir_conn.base_.inbuf); -- cgit v1.2.3-54-g00ecf From 2202ad7ab0132ed5505067aca9020caa05c918fd Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 23 Jan 2017 14:52:51 -0500 Subject: Fix a pair of compilation errors. --- src/or/networkstatus.c | 2 +- src/or/networkstatus.h | 3 ++- src/test/fuzz/fuzz_vrs.c | 3 ++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 49ff12bd6c..508cf6c5b6 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -243,7 +243,7 @@ router_reload_consensus_networkstatus(void) } /** Free all storage held by the vote_routerstatus object rs. */ -STATIC void +void vote_routerstatus_free(vote_routerstatus_t *rs) { vote_microdesc_hash_t *h, *next; diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index edf2dc7b7a..66cd84c88e 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -132,8 +132,9 @@ document_signature_t *document_signature_dup(const document_signature_t *sig); void networkstatus_free_all(void); int networkstatus_get_weight_scale_param(networkstatus_t *ns); +void vote_routerstatus_free(vote_routerstatus_t *rs); + #ifdef NETWORKSTATUS_PRIVATE -STATIC void vote_routerstatus_free(vote_routerstatus_t *rs); #ifdef TOR_UNIT_TESTS STATIC int networkstatus_set_current_consensus_from_ns(networkstatus_t *c, const char *flavor); diff --git a/src/test/fuzz/fuzz_vrs.c b/src/test/fuzz/fuzz_vrs.c index 406a4de5f3..d2c0369f27 100644 --- a/src/test/fuzz/fuzz_vrs.c +++ b/src/test/fuzz/fuzz_vrs.c @@ -45,7 +45,8 @@ fuzz_cleanup(void) int fuzz_main(const uint8_t *data, size_t sz) { - char *str = tor_memdup_nulterm(data, sz), *s; + char *str = tor_memdup_nulterm(data, sz); + const char *s; routerstatus_t *rs_ns = NULL, *rs_md = NULL, *rs_vote = NULL; vote_routerstatus_t *vrs = tor_malloc_zero(sizeof(*vrs)); smartlist_t *tokens = smartlist_new(); -- cgit v1.2.3-54-g00ecf From d71fc474385281453eaa93522479d32af85c94ef Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 27 Jan 2017 11:16:23 -0500 Subject: Update documentation and testing integration for fuzzing --- doc/HACKING/Fuzzing.md | 63 ++++++++++++++++++++++++++++----------- src/test/fuzz/include.am | 2 ++ src/test/fuzz_static_testcases.sh | 20 ++++++++++--- 3 files changed, 63 insertions(+), 22 deletions(-) diff --git a/doc/HACKING/Fuzzing.md b/doc/HACKING/Fuzzing.md index 36f0fc4f5e..f5502b3307 100644 --- a/doc/HACKING/Fuzzing.md +++ b/doc/HACKING/Fuzzing.md @@ -1,12 +1,53 @@ = Fuzzing Tor +== The simple version (no fuzzing, only tests) + +Check out fuzzing-corpora, and set TOR_FUZZ_CORPORA to point to the place +where you checked it out. + To run the fuzzing test cases in a deterministic fashion, use: make fuzz - [I've turned this off for now. - NM] -To build the fuzzing harness binaries, use: - make fuzzers +== Different kinds of fuzzing + +Right now we support three different kinds of fuzzer. + +First, there's American Fuzzy Lop (AFL), a fuzzer that works by forking +a target binary and passing it lots of different inputs on stdin. It's the +trickiest one to set up, so I'll be describing it more below. + +Second, there's libFuzzer, a llvm-based fuzzer that you link in as a library, +and it runs a target function over and over. To use this one, you'll need to +have a reasonably recent clang and libfuzzer installed. At that point, you +just build with --enable-expensive-hardening and --enable-libfuzzer. That +will produce a set of binaries in src/test/fuzz/lf-fuzz-* . These programs +take as input a series of directories full of fuzzing examples. For more +information on libfuzzer, see http://llvm.org/docs/LibFuzzer.html + +Third, there's Google's OSS-Fuzz infrastructure, which expects to get all of +its. For more on this, see https://github.com/google/oss-fuzz and the +projects/tor subdirectory. You'll need to mess around with Docker a bit to +test this one out; it's meant to run on Google's infrastructure. + +In all cases, you'll need some starting examples to give the fuzzer when it +starts out. There's a set in the "fuzzing-corpora" git repository. Try +setting TOR_FUZZ_CORPORA to point to a checkout of that repository + +== Writing Tor fuzzers + +A tor fuzzing harness should have: +* a fuzz_init() function to set up any necessary global state. +* a fuzz_main() function to receive input and pass it to a parser. +* a fuzz_cleanup() function to clear global state. + +Most fuzzing frameworks will produce many invalid inputs - a tor fuzzing +harness should rejecting invalid inputs without crashing or behaving badly. + +But the fuzzing harness should crash if tor fails an assertion, triggers a +bug, or accesses memory it shouldn't. This helps fuzzing frameworks detect +"interesting" cases. + == Guided Fuzzing with AFL @@ -47,7 +88,7 @@ don't care about memory limits. To Run: mkdir -p src/test/fuzz/fuzz_http_findings - ../afl/afl-fuzz -i src/test/fuzz/data/http -x src/test/fuzz/dict/http -o src/test/fuzz/fuzz_http_findings -m -- src/test/fuzz_dir + ../afl/afl-fuzz -i ${TOR_FUZZ_CORPORA}/http -o src/test/fuzz/fuzz_http_findings -m -- src/test/fuzz_dir AFL has a multi-core mode, check the documentation for details. @@ -57,20 +98,6 @@ macOS (OS X) requires slightly more preparation, including: * using afl-clang (or afl-clang-fast from the llvm directory) * disabling external crash reporting (AFL will guide you through this step) -== Writing Tor fuzzers - -A tor fuzzing harness should have: -* a fuzz_init() function to set up any necessary global state. -* a fuzz_main() function to receive input and pass it to a parser. -* a fuzz_cleanup() function to clear global state. - -Most fuzzing frameworks will produce many invalid inputs - a tor fuzzing -harness should rejecting invalid inputs without crashing or behaving badly. - -But the fuzzing harness should crash if tor fails an assertion, triggers a -bug, or accesses memory it shouldn't. This helps fuzzing frameworks detect -"interesting" cases. - == Triaging Issues Crashes are usually interesting, particularly if using AFL_HARDEN=1 and --enable-expensive-hardening. Sometimes crashes are due to bugs in the harness code. diff --git a/src/test/fuzz/include.am b/src/test/fuzz/include.am index bca0a8626a..c9c1747769 100644 --- a/src/test/fuzz/include.am +++ b/src/test/fuzz/include.am @@ -246,3 +246,5 @@ noinst_LIBRARIES += $(OSS_FUZZ_FUZZERS) oss-fuzz-fuzzers: oss-fuzz-prereqs $(OSS_FUZZ_FUZZERS) fuzzers: $(FUZZERS) $(LIBFUZZER_FUZZERS) +fuzz: $(FUZZERS) + $(top_srcdir)/src/test/fuzz_static_testcases.sh diff --git a/src/test/fuzz_static_testcases.sh b/src/test/fuzz_static_testcases.sh index 276bc6e157..bfe1677573 100755 --- a/src/test/fuzz_static_testcases.sh +++ b/src/test/fuzz_static_testcases.sh @@ -5,11 +5,23 @@ set -e +if [ -z "${TOR_FUZZ_CORPORA}" ] || [ ! -d "${TOR_FUZZ_CORPORA}" ] ; then + echo "You need to set TOR_FUZZ_CORPORA to point to a checkout of " + echo "the 'fuzzing-corpora' repository." + exit 77 +fi + + + for fuzzer in "${builddir:-.}"/src/test/fuzz/fuzz-* ; do f=`basename $fuzzer` case="${f#fuzz-}" - echo "Running tests for ${case}" - for entry in ${abs_top_srcdir:-.}/src/test/fuzz/data/${case}/*; do - "${fuzzer}" "--err" < "$entry" - done + if [ -d "${TOR_FUZZ_CORPORA}/${case}" ]; then + echo "Running tests for ${case}" + for entry in "${TOR_FUZZ_CORPORA}/${case}/"*; do + "${fuzzer}" "--err" < "$entry" + done + else + echo "No tests found for ${case}" + fi done -- cgit v1.2.3-54-g00ecf