From 4b01d594c40b4e59414413152392963f3cf5247d Mon Sep 17 00:00:00 2001 From: David Melski Date: Thu, 28 May 2020 20:25:30 -0400 Subject: Fix read_timed when accumulating short reads The existing code appears to use 'len_read' in several places where 'total_read' was intended. The function may work if the first 1 or 2 iterations of the loop read the requested 'len' bytes. If the first two reads are "short" and a third read is done, the bytes will be placed over previously read bytes in buf and more than 'len' bytes may be read in total, though buf is never overrun. This commit changes read_timed to (1) correctly append short reads in buf (2) correctly terminate when the sum of the short reads equals the requested 'len' bytes (3) return an error when read() returns -1 or 0 The function also depends on select() decrementing the timeout structure, as it does on Linux. On other platforms, the exec_ms returned is likely incorrect. This patch does not attempt to address this issue. --- src/afl-common.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 808c9812..22342065 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -885,9 +885,9 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, timeout.tv_usec = (timeout_ms % 1000) * 1000; size_t read_total = 0; - size_t len_read = 0; + ssize_t len_read = 0; - while (len_read < len) { + while (read_total < len) { /* set exceptfds as well to return when a child exited/closed the pipe. */ int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); @@ -905,8 +905,8 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, } - len_read = read(fd, ((u8 *)buf) + len_read, len - len_read); - if (!len_read) { return 0; } + len_read = read(fd, ((u8 *)buf) + read_total, len - read_total); + if (len_read <= 0) { return 0; } read_total += len_read; } -- cgit 1.4.1 From 8316425375031cedbf7e3ea6d6b116a376f01589 Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 11:51:11 +0200 Subject: Add AFL_LLVM_WHITELIST_FNMATCH env var Only enable UNIX pattern matching on the whitelist when AFL_LLVM_WHITELIST_FNMATCH is set. The reason being that we keep backwards compatibility with old whitelists. --- llvm_mode/README.whitelist.md | 29 +++++++++++++++++++++++++++++ llvm_mode/afl-llvm-common.cc | 35 ++++++++++++++++++++++------------- src/afl-common.c | 9 +++++---- 3 files changed, 56 insertions(+), 17 deletions(-) (limited to 'src/afl-common.c') diff --git a/llvm_mode/README.whitelist.md b/llvm_mode/README.whitelist.md index 72fb5d09..6752797e 100644 --- a/llvm_mode/README.whitelist.md +++ b/llvm_mode/README.whitelist.md @@ -73,3 +73,32 @@ For old LLVM versions this feature might require to be compiled with debug information (-g), however at least from llvm version 6.0 onwards this is not required anymore (and might hurt performance and crash detection, so better not use -g). + +## 4) UNIX-style file name pattern matching +By default you need to add all the files you want to whitelist to the file +specified by AFL_LLVM_WHITELIST. By setting the env variable +AFL_LLVM_WHITELIST_FNMATCH, afl++ will allows use of wildcards and other +matching features available through `fnmatch` (we use `fnmatch` with no flags +set). Note that setting AFL_LLVM_WHITELIST_FNMATCH might +break backwards-compatibility, since it does not match on the end of the file +entry anymore, but rather matches on the full filename path. + +The behavior should be the same if you prepend `*/` to every line. + +For example, the entry: +``` +*/a*.cpp +``` + +Would now match: +``` +feature_a/a1.cpp +feature_a/a2.cpp +``` + +But +``` +a*.cpp +``` + +Would not match any of the files in the previous example. diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index e97423a0..42f2b774 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -147,20 +147,25 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { + char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); + for (std::list::iterator it = myWhitelist.begin(); it != myWhitelist.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (fnmatch((*it).c_str(), - instFilename.str().c_str(), FNM_PATHNAME) == 0) { + * specified in the list. Enable UNIX-style pattern + * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + if (instFilename.str().length() >= it->length()) { + if (enable_fnmatch && fnmatch((*it).c_str(), + instFilename.str().c_str(), 0) == 0) { + return true; + } else if (!enable_fnmatch && instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { return true; - } } @@ -183,21 +188,25 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { + char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); + for (std::list::iterator it = myWhitelist.begin(); it != myWhitelist.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), it->length(), - *it) == 0) { + * specified in the list. Enable UNIX-style pattern + * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + if (instFilename.str().length() >= it->length()) { + if (enable_fnmatch && fnmatch((*it).c_str(), + instFilename.str().c_str(), 0) == 0) { + return true; + } else if (!enable_fnmatch && instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { return true; - } } diff --git a/src/afl-common.c b/src/afl-common.c index 1bb58a60..c17f9789 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,10 +69,11 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", - "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", - "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", - "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST" , "AFL_LLVM_WHITELIST_FNMATCH", + "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", + "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", + "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", + "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally -- cgit 1.4.1 From 84df805ed3e14fb42f0c02420d6ae538a427fa2f Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 12:11:19 +0200 Subject: Do clang-format --- llvm_mode/afl-llvm-common.cc | 34 ++++++++++++++++++++++++---------- src/afl-common.c | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'src/afl-common.c') diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 42f2b774..76de1d0f 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -159,13 +159,20 @@ bool isInWhitelist(llvm::Function *F) { * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && fnmatch((*it).c_str(), - instFilename.str().c_str(), 0) == 0) { + + if (enable_fnmatch && + fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { + return true; - } else if (!enable_fnmatch && instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + + } else if (!enable_fnmatch && + + instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { + return true; + } } @@ -200,13 +207,20 @@ bool isInWhitelist(llvm::Function *F) { * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && fnmatch((*it).c_str(), - instFilename.str().c_str(), 0) == 0) { + + if (enable_fnmatch && + fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { + return true; - } else if (!enable_fnmatch && instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + + } else if (!enable_fnmatch && + + instFilename.str().compare( + instFilename.str().length() - it->length(), + it->length(), *it) == 0) { + return true; + } } diff --git a/src/afl-common.c b/src/afl-common.c index c17f9789..6675564e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,7 +69,7 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST" , "AFL_LLVM_WHITELIST_FNMATCH", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_WHITELIST_FNMATCH", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", -- cgit 1.4.1 From 8bb0232ace731c596e9e4e083a048784e35221cd Mon Sep 17 00:00:00 2001 From: Sebastian Österlund Date: Fri, 29 May 2020 15:47:34 +0200 Subject: Remove AFL_LLVM_WHITELIST_FNMATCH env variable --- llvm_mode/README.whitelist.md | 30 ++---------------------------- llvm_mode/afl-llvm-common.cc | 36 ++++++++---------------------------- src/afl-common.c | 9 ++++----- 3 files changed, 14 insertions(+), 61 deletions(-) (limited to 'src/afl-common.c') diff --git a/llvm_mode/README.whitelist.md b/llvm_mode/README.whitelist.md index 12f2e5c3..6393fae8 100644 --- a/llvm_mode/README.whitelist.md +++ b/llvm_mode/README.whitelist.md @@ -75,31 +75,5 @@ required anymore (and might hurt performance and crash detection, so better not use -g). ## 4) UNIX-style filename pattern matching -By default you need to add all the files you want to whitelist to the file -specified by AFL_LLVM_WHITELIST. By setting the env variable -AFL_LLVM_WHITELIST_FNMATCH, afl++ allows use of wildcards and other -matching features available through `fnmatch` (we use `fnmatch` with no flags -set). Note that setting AFL_LLVM_WHITELIST_FNMATCH might -break backwards-compatibility with existing whitelists, since it does not match -on the end of the file entry anymore, but rather matches on the full filename -path. - -The behavior should be the same if you prepend `*/` to every line. - -For example, the entry: -``` -*/a*.cpp -``` - -Would now match: -``` -feature_a/a1.cpp -feature_a/a2.cpp -``` - -But -``` -a*.cpp -``` - -Would not match any of the files in the previous example. +You can add UNIX-style pattern matching in the whitelist entries. See `man +fnmatch` for the syntax. We do not set any of the `fnmatch` flags. diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 76de1d0f..6c7222cd 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -147,29 +147,19 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { - char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); - for (std::list::iterator it = myWhitelist.begin(); it != myWhitelist.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we * check that the actual filename ends in the filename - * specified in the list. Enable UNIX-style pattern - * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + * specified in the list. We also allow UNIX-style pattern + * matching */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && - fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { - - return true; - - } else if (!enable_fnmatch && - - instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { return true; @@ -195,29 +185,19 @@ bool isInWhitelist(llvm::Function *F) { /* Continue only if we know where we actually are */ if (!instFilename.str().empty()) { - char *enable_fnmatch = getenv("AFL_LLVM_WHITELIST_FNMATCH"); - for (std::list::iterator it = myWhitelist.begin(); it != myWhitelist.end(); ++it) { /* We don't check for filename equality here because * filenames might actually be full paths. Instead we * check that the actual filename ends in the filename - * specified in the list. Enable UNIX-style pattern - * matching if AFL_LLVM_WHITELIST_FNMATCH is set */ + * specified in the list. We also allow UNIX-style pattern + * matching */ if (instFilename.str().length() >= it->length()) { - if (enable_fnmatch && - fnmatch((*it).c_str(), instFilename.str().c_str(), 0) == 0) { - - return true; - - } else if (!enable_fnmatch && - - instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { return true; diff --git a/src/afl-common.c b/src/afl-common.c index 6675564e..1bb58a60 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -69,11 +69,10 @@ char *afl_environment_variables[] = { "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", - "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_WHITELIST_FNMATCH", - "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", - "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", - "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", - "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", + "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", + "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", + "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", + "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally -- cgit 1.4.1 From 8726d7b0a351fcb16587acd80a4b42b521264692 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 30 May 2020 06:51:51 +0200 Subject: simplified read_timed --- src/afl-common.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 9fd4bf03..d428c9c5 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -869,53 +869,51 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } -/* Wrapper for select() and read(), reading exactly len bytes. +/* Wrapper for select() and read(), reading len bytes. + Assumes that all bytes are available on read! Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, volatile u8 *stop_soon_p) { - struct timeval timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); + struct timeval timeout; timeout.tv_sec = (timeout_ms / 1000); timeout.tv_usec = (timeout_ms % 1000) * 1000; +#if !defined(__linux__) + u64 read_start = get_cur_time_us(); +#endif - size_t read_total = 0; - ssize_t len_read = 0; - - while (read_total < len) { - - /* set exceptfds as well to return when a child exited/closed the pipe. */ - int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - - if (!sret) { - - // printf("Timeout in sret."); - return timeout_ms + 1; + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - } else if (sret < 0) { + if (!sret) { - /* Retry select for all signals other than than ctrl+c */ - if (errno == EINTR && !*stop_soon_p) { continue; } - return 0; + return timeout_ms + 1; - } + } else if (sret < 0) { - len_read = read(fd, ((u8 *)buf) + read_total, len - read_total); - if (len_read <= 0) { return 0; } - read_total += len_read; + return 0; } - s32 exec_ms = + ssize_t len_read = read(fd, ((u8 *)buf), len); + if (len_read < len) { return 0; } + +#if defined(__linux__) + u32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); - return exec_ms > 0 ? exec_ms - : 1; // at least 1 milli must have passed (0 is an error) +#else + u32 exec_ms = get_cur_time_us() - read_start; +#endif + + // ensure to report 1 ms has passed (0 is an error) + return exec_ms > 0 ? exec_ms : 1; } -- cgit 1.4.1 From 38e5c32a55086d36c8b9ee38e4b20c15517fc4b2 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 30 May 2020 11:02:34 +0200 Subject: corrected read_timed for values > 4 --- include/common.h | 3 ++ src/afl-common.c | 82 ++++++++++++++++++++++++++++++++++++---------------- src/afl-forkserver.c | 6 +++- 3 files changed, 65 insertions(+), 26 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/common.h b/include/common.h index 4aed9572..7b7bf02d 100644 --- a/include/common.h +++ b/include/common.h @@ -107,6 +107,9 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val); u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); +/* Sets a filedescriptor to non-blocking mode (for read_timed) */ +void set_nonblocking(int fd); + /* Wrapper for select() and read(), reading exactly len bytes. Returns the time passed to read. stop_soon should point to a variable indicating ctrl+c was pressed. diff --git a/src/afl-common.c b/src/afl-common.c index d428c9c5..793041b2 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -39,6 +39,7 @@ #include #include #include +#include #include #include @@ -869,51 +870,82 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } -/* Wrapper for select() and read(), reading len bytes. - Assumes that all bytes are available on read! +/* sets a FD to non-blocking mode (used for read_timed) */ +void set_nonblocking(int fd) { + + int ret = 0; + int opt = 1; + ret = ioctl(fd, FIONBIO, &opt); + if (ret == -1) { PFATAL("Could not enable non-blocking mode on fd %d", fd); } + +} + + +/* Wrapper for select() and read(), reading exactly len bytes. + Should be called on non-blocking fds. Returns the time passed to read. If the wait times out, returns timeout_ms + 1; - Returns 0 if an error occurred (fd closed, signal, ...); */ + Returns 0 if an error occurred (fd closed, signal, ...); + */ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, volatile u8 *stop_soon_p) { + struct timeval timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); - struct timeval timeout; - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; -#if !defined(__linux__) - u64 read_start = get_cur_time_us(); -#endif + size_t read_total = 0; + ssize_t len_read = 0; - /* set exceptfds as well to return when a child exited/closed the pipe. */ - int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); + #if defined(__linux__) + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; + #else + u64 time_start = get_cur_time_us(); + #endif - if (!sret) { + while (read_total < len) { - return timeout_ms + 1; + #if !defined(__linux__) + u64 time_current = get_cur_time_us(); + u64 timeout_current = timeout_ms - (time_current - time_start); + timeout.tv_sec = (timeout_current / 1000); + timeout.tv_usec = (timeout_current % 1000) * 1000; + #endif - } else if (sret < 0) { + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - return 0; + if (!sret) { - } + // printf("Timeout in sret."); + return timeout_ms + 1; + + } else if (sret < 0) { + + /* Retry select for all signals other than than ctrl+c */ + if (errno == EINTR && !*stop_soon_p) { continue; } + return 0; + + } + + len_read = read(fd, ((u8 *)buf) + read_total, len - read_total); + if (len_read <= 0) { return 0; } + read_total += len_read; - ssize_t len_read = read(fd, ((u8 *)buf), len); - if (len_read < len) { return 0; } + } -#if defined(__linux__) - u32 exec_ms = + #if defined(__linux__) + s32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); -#else - u32 exec_ms = get_cur_time_us() - read_start; -#endif + #else + u32 exec_ms = get_cur_time_us() - time_start; + #endif - // ensure to report 1 ms has passed (0 is an error) - return exec_ms > 0 ? exec_ms : 1; + return exec_ms > 0 ? exec_ms + : 1; // at least 1 milli must have passed (0 is an error) } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 137a4f99..01774cd0 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -401,6 +401,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->fsrv_ctl_fd = ctl_pipe[1]; fsrv->fsrv_st_fd = st_pipe[0]; + set_nonblocking(fsrv->fsrv_st_fd); + /* Wait for the fork server to come up, but don't wait too long. */ rlen = 0; @@ -853,7 +855,9 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, fsrv->last_run_timed_out = 0; - if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { + res = read_timed(fsrv->fsrv_st_fd, &fsrv->child_pid, 4, timeout, stop_soon_p); + + if (res < 0 || res > timeout) { if (*stop_soon_p) { return 0; } RPFATAL(res, "Unable to request new process from fork server (OOM?)"); -- cgit 1.4.1 From 8f19becb620a6fedd0f8b855b48cdeeab211c2ed Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 30 May 2020 11:05:53 +0200 Subject: code format --- src/afl-common.c | 37 ++++++++++++++++++------------------- 1 file changed, 18 insertions(+), 19 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index 793041b2..b3933b9c 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -880,7 +880,6 @@ void set_nonblocking(int fd) { } - /* Wrapper for select() and read(), reading exactly len bytes. Should be called on non-blocking fds. Returns the time passed to read. @@ -895,24 +894,24 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, FD_ZERO(&readfds); FD_SET(fd, &readfds); - size_t read_total = 0; + size_t read_total = 0; ssize_t len_read = 0; - #if defined(__linux__) - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; - #else - u64 time_start = get_cur_time_us(); - #endif +#if defined(__linux__) + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; +#else + u64 time_start = get_cur_time_us(); +#endif while (read_total < len) { - #if !defined(__linux__) - u64 time_current = get_cur_time_us(); - u64 timeout_current = timeout_ms - (time_current - time_start); - timeout.tv_sec = (timeout_current / 1000); - timeout.tv_usec = (timeout_current % 1000) * 1000; - #endif +#if !defined(__linux__) + u64 time_current = get_cur_time_us(); + u64 timeout_current = timeout_ms - (time_current - time_start); + timeout.tv_sec = (timeout_current / 1000); + timeout.tv_usec = (timeout_current % 1000) * 1000; +#endif /* set exceptfds as well to return when a child exited/closed the pipe. */ int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); @@ -936,13 +935,13 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, } - #if defined(__linux__) - s32 exec_ms = +#if defined(__linux__) + s32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); - #else - u32 exec_ms = get_cur_time_us() - time_start; - #endif +#else + u32 exec_ms = get_cur_time_us() - time_start; +#endif return exec_ms > 0 ? exec_ms : 1; // at least 1 milli must have passed (0 is an error) -- cgit 1.4.1 From b16ccb481195d338b3b4a800965ba4054d268886 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 30 May 2020 13:51:29 +0200 Subject: Revert "code format" This reverts commit 8f19becb620a6fedd0f8b855b48cdeeab211c2ed. --- src/afl-common.c | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index b3933b9c..793041b2 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -880,6 +880,7 @@ void set_nonblocking(int fd) { } + /* Wrapper for select() and read(), reading exactly len bytes. Should be called on non-blocking fds. Returns the time passed to read. @@ -894,24 +895,24 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, FD_ZERO(&readfds); FD_SET(fd, &readfds); - size_t read_total = 0; + size_t read_total = 0; ssize_t len_read = 0; -#if defined(__linux__) - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; -#else - u64 time_start = get_cur_time_us(); -#endif + #if defined(__linux__) + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; + #else + u64 time_start = get_cur_time_us(); + #endif while (read_total < len) { -#if !defined(__linux__) - u64 time_current = get_cur_time_us(); - u64 timeout_current = timeout_ms - (time_current - time_start); - timeout.tv_sec = (timeout_current / 1000); - timeout.tv_usec = (timeout_current % 1000) * 1000; -#endif + #if !defined(__linux__) + u64 time_current = get_cur_time_us(); + u64 timeout_current = timeout_ms - (time_current - time_start); + timeout.tv_sec = (timeout_current / 1000); + timeout.tv_usec = (timeout_current % 1000) * 1000; + #endif /* set exceptfds as well to return when a child exited/closed the pipe. */ int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); @@ -935,13 +936,13 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, } -#if defined(__linux__) - s32 exec_ms = + #if defined(__linux__) + s32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); -#else - u32 exec_ms = get_cur_time_us() - time_start; -#endif + #else + u32 exec_ms = get_cur_time_us() - time_start; + #endif return exec_ms > 0 ? exec_ms : 1; // at least 1 milli must have passed (0 is an error) -- cgit 1.4.1 From 95b46b427887db655b3f2b9a04dae1924e665d27 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 30 May 2020 13:53:00 +0200 Subject: reverted extendended read_timed --- include/common.h | 3 -- src/afl-common.c | 82 ++++++++++++++++------------------------------------ src/afl-forkserver.c | 3 +- 3 files changed, 26 insertions(+), 62 deletions(-) (limited to 'src/afl-common.c') diff --git a/include/common.h b/include/common.h index 7b7bf02d..4aed9572 100644 --- a/include/common.h +++ b/include/common.h @@ -107,9 +107,6 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val); u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); -/* Sets a filedescriptor to non-blocking mode (for read_timed) */ -void set_nonblocking(int fd); - /* Wrapper for select() and read(), reading exactly len bytes. Returns the time passed to read. stop_soon should point to a variable indicating ctrl+c was pressed. diff --git a/src/afl-common.c b/src/afl-common.c index 793041b2..d428c9c5 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -39,7 +39,6 @@ #include #include #include -#include #include #include @@ -870,82 +869,51 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } -/* sets a FD to non-blocking mode (used for read_timed) */ -void set_nonblocking(int fd) { - - int ret = 0; - int opt = 1; - ret = ioctl(fd, FIONBIO, &opt); - if (ret == -1) { PFATAL("Could not enable non-blocking mode on fd %d", fd); } - -} - - -/* Wrapper for select() and read(), reading exactly len bytes. - Should be called on non-blocking fds. +/* Wrapper for select() and read(), reading len bytes. + Assumes that all bytes are available on read! Returns the time passed to read. If the wait times out, returns timeout_ms + 1; - Returns 0 if an error occurred (fd closed, signal, ...); - */ + Returns 0 if an error occurred (fd closed, signal, ...); */ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, volatile u8 *stop_soon_p) { - struct timeval timeout; fd_set readfds; FD_ZERO(&readfds); FD_SET(fd, &readfds); + struct timeval timeout; - size_t read_total = 0; - ssize_t len_read = 0; - - #if defined(__linux__) - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; - #else - u64 time_start = get_cur_time_us(); - #endif - - while (read_total < len) { - - #if !defined(__linux__) - u64 time_current = get_cur_time_us(); - u64 timeout_current = timeout_ms - (time_current - time_start); - timeout.tv_sec = (timeout_current / 1000); - timeout.tv_usec = (timeout_current % 1000) * 1000; - #endif - - /* set exceptfds as well to return when a child exited/closed the pipe. */ - int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - - if (!sret) { + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; +#if !defined(__linux__) + u64 read_start = get_cur_time_us(); +#endif - // printf("Timeout in sret."); - return timeout_ms + 1; + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - } else if (sret < 0) { + if (!sret) { - /* Retry select for all signals other than than ctrl+c */ - if (errno == EINTR && !*stop_soon_p) { continue; } - return 0; + return timeout_ms + 1; - } + } else if (sret < 0) { - len_read = read(fd, ((u8 *)buf) + read_total, len - read_total); - if (len_read <= 0) { return 0; } - read_total += len_read; + return 0; } - #if defined(__linux__) - s32 exec_ms = + ssize_t len_read = read(fd, ((u8 *)buf), len); + if (len_read < len) { return 0; } + +#if defined(__linux__) + u32 exec_ms = MIN(timeout_ms, ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); - #else - u32 exec_ms = get_cur_time_us() - time_start; - #endif +#else + u32 exec_ms = get_cur_time_us() - read_start; +#endif - return exec_ms > 0 ? exec_ms - : 1; // at least 1 milli must have passed (0 is an error) + // ensure to report 1 ms has passed (0 is an error) + return exec_ms > 0 ? exec_ms : 1; } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1884ff98..137a4f99 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -401,8 +401,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->fsrv_ctl_fd = ctl_pipe[1]; fsrv->fsrv_st_fd = st_pipe[0]; - set_nonblocking(fsrv->fsrv_st_fd); - /* Wait for the fork server to come up, but don't wait too long. */ rlen = 0; @@ -857,6 +855,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { + if (*stop_soon_p) { return 0; } RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } -- cgit 1.4.1 From 24508194c2fdcc7666acafc1f60fcae06ff00a08 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 30 May 2020 14:03:52 +0200 Subject: removed read_timed --- src/afl-common.c | 49 +------------------------------------------- src/afl-forkserver.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++----- 2 files changed, 54 insertions(+), 53 deletions(-) (limited to 'src/afl-common.c') diff --git a/src/afl-common.c b/src/afl-common.c index d428c9c5..a3692756 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -869,54 +869,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } -/* Wrapper for select() and read(), reading len bytes. - Assumes that all bytes are available on read! - Returns the time passed to read. - If the wait times out, returns timeout_ms + 1; - Returns 0 if an error occurred (fd closed, signal, ...); */ -u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, - volatile u8 *stop_soon_p) { - - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(fd, &readfds); - struct timeval timeout; - - timeout.tv_sec = (timeout_ms / 1000); - timeout.tv_usec = (timeout_ms % 1000) * 1000; -#if !defined(__linux__) - u64 read_start = get_cur_time_us(); -#endif - - /* set exceptfds as well to return when a child exited/closed the pipe. */ - int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); - - if (!sret) { - - return timeout_ms + 1; - - } else if (sret < 0) { - - return 0; - - } - - ssize_t len_read = read(fd, ((u8 *)buf), len); - if (len_read < len) { return 0; } - -#if defined(__linux__) - u32 exec_ms = - MIN(timeout_ms, - ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); -#else - u32 exec_ms = get_cur_time_us() - read_start; -#endif - - // ensure to report 1 ms has passed (0 is an error) - return exec_ms > 0 ? exec_ms : 1; - -} - +/* Reads the map size from ENV */ u32 get_map_size(void) { uint32_t map_size = MAP_SIZE; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 137a4f99..880ef0a3 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -119,6 +119,54 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { } +/* Wrapper for select() and read(), reading a 32 bit var. + Returns the time passed to read. + If the wait times out, returns timeout_ms + 1; + Returns 0 if an error occurred (fd closed, signal, ...); */ +static u32 read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, + volatile u8 *stop_soon_p) { + + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + struct timeval timeout; + size_t len = 4; + + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; +#if !defined(__linux__) + u64 read_start = get_cur_time_us(); +#endif + + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); + + if (!sret) { + + return timeout_ms + 1; + + } else if (sret < 0) { + + return 0; + + } + + ssize_t len_read = read(fd, ((u8 *)buf), len); + if (len_read < len) { return 0; } + +#if defined(__linux__) + u32 exec_ms = + MIN(timeout_ms, + ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); +#else + u32 exec_ms = MIN(timeout_ms, get_cur_time_us() - read_start); +#endif + + // ensure to report 1 ms has passed (0 is an error) + return exec_ms > 0 ? exec_ms : 1; + +} + /* Internal forkserver for dumb_mode=1 and non-forkserver mode runs. It execvs for each fork, forwarding exit codes and child pids to afl. */ @@ -250,7 +298,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output) { int st_pipe[2], ctl_pipe[2]; - int status; + s32 status; s32 rlen; if (!be_quiet) { ACTF("Spinning up the fork server..."); } @@ -406,8 +454,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, rlen = 0; if (fsrv->exec_tmout) { - u32 time = read_timed(fsrv->fsrv_st_fd, &status, 4, - fsrv->exec_tmout * FORK_WAIT_MULT, stop_soon_p); + u32 time = read_s32_timed(fsrv->fsrv_st_fd, &status, + fsrv->exec_tmout * FORK_WAIT_MULT, stop_soon_p); if (!time) { @@ -862,8 +910,8 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); } - exec_ms = read_timed(fsrv->fsrv_st_fd, &fsrv->child_status, 4, timeout, - stop_soon_p); + exec_ms = read_s32_timed(fsrv->fsrv_st_fd, &fsrv->child_status, timeout, + stop_soon_p); if (exec_ms > timeout) { -- cgit 1.4.1 From 83112ed5e0da90634d73a5111892e713cc19733d Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 2 Jun 2020 14:54:24 +0200 Subject: got rid of questionable phrasing --- README.md | 6 ++-- docs/Changelog.md | 12 ++++---- docs/binaryonly_fuzzing.md | 2 +- docs/notes_for_asan.md | 6 ++-- docs/parallel_fuzzing.md | 38 ++++++++++++------------- docs/power_schedules.md | 2 +- docs/status_screen.md | 4 +-- gcc_plugin/README.md | 2 +- include/afl-fuzz.h | 10 +++---- include/sharedmem.h | 2 +- llvm_mode/README.persistent_mode.md | 2 +- llvm_mode/afl-llvm-rt.o.c | 4 +-- qemu_mode/patches/afl-qemu-tcg-runtime-inl.h | 2 +- src/afl-common.c | 4 +-- src/afl-forkserver.c | 2 +- src/afl-fuzz-bitmap.c | 8 +++--- src/afl-fuzz-init.c | 22 +++++++-------- src/afl-fuzz-one.c | 34 +++++++++++----------- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-run.c | 32 ++++++++++----------- src/afl-fuzz-stats.c | 19 +++++++------ src/afl-fuzz.c | 42 ++++++++++++++-------------- src/afl-sharedmem.c | 12 ++++---- 23 files changed, 135 insertions(+), 134 deletions(-) (limited to 'src/afl-common.c') diff --git a/README.md b/README.md index 68c387eb..76f510c8 100644 --- a/README.md +++ b/README.md @@ -381,10 +381,10 @@ The available schedules are: - rare (experimental) In parallel mode (-M/-S, several instances with the shared queue), we suggest to -run the master using the explore or fast schedule (-p explore) and the slaves -with a combination of cut-off-exponential (-p coe), exponential (-p fast), +run the main node using the explore or fast schedule (-p explore) and the secondary +nodes with a combination of cut-off-exponential (-p coe), exponential (-p fast), explore (-p explore) and mmopt (-p mmopt) schedules. If a schedule does -not perform well for a target, restart the slave with a different schedule. +not perform well for a target, restart the secondary nodes with a different schedule. In single mode, using -p fast is usually slightly more beneficial than the default explore mode. diff --git a/docs/Changelog.md b/docs/Changelog.md index f96adfa3..87e02938 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -11,11 +11,11 @@ sending a mail to . ### Version ++2.65d (dev) - afl-fuzz: - - -S slaves now only sync from the master to increase performance, - the -M master still syncs from everyone. Added checks that ensure - exactly one master is present and warn otherwise - - If no master is present at a sync one slave automatically becomes - a temporary master until a real master shows up + - -S secondary nodes now only sync from the main node to increase performance, + the -M main node still syncs from everyone. Added checks that ensure + exactly one main node is present and warn otherwise + - If no main node is present at a sync one secondary node automatically becomes + a temporary main node until a real main nodes shows up - fix/update to MOpt (thanks to arnow117) - llvm_mode: - the default instrumentation is now PCGUARD, as it is faster and provides @@ -912,7 +912,7 @@ sending a mail to . - Switched from exit() to _exit() in injected code to avoid snafus with destructors in C++ code. Spotted by sunblate. - - Made a change to avoid spuriously setting __AFL_SHM_ID when + - Made a change to avoid spuriously setting __AFL_SHM_ID when AFL_DUMB_FORKSRV is set in conjunction with -n. Spotted by Jakub Wilk. ### Version 1.94b: diff --git a/docs/binaryonly_fuzzing.md b/docs/binaryonly_fuzzing.md index f005a9b7..7c9be418 100644 --- a/docs/binaryonly_fuzzing.md +++ b/docs/binaryonly_fuzzing.md @@ -4,7 +4,7 @@ it allows for very fast and coverage guided fuzzing. However, if there is only the binary program and no source code available, - then standard `afl-fuzz -n` (dumb mode) is not effective. + then standard `afl-fuzz -n` (non-instrumented mode) is not effective. The following is a description of how these binaries can be fuzzed with afl++ diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md index 6a4806c0..2e18c15f 100644 --- a/docs/notes_for_asan.md +++ b/docs/notes_for_asan.md @@ -28,9 +28,9 @@ Note that ASAN is incompatible with -static, so be mindful of that. (You can also use AFL_USE_MSAN=1 to enable MSAN instead.) -NOTE: if you run several slaves only one should run the target compiled with -ASAN (and UBSAN, CFISAN), the others should run the target with no sanitizers -compiled in. +NOTE: if you run several secondary instances, only one should run the target +compiled with ASAN (and UBSAN, CFISAN), the others should run the target with +no sanitizers compiled in. There is also the option of generating a corpus using a non-ASAN binary, and then feeding it to an ASAN-instrumented one to check for bugs. This is faster, diff --git a/docs/parallel_fuzzing.md b/docs/parallel_fuzzing.md index c6e54218..271f8369 100644 --- a/docs/parallel_fuzzing.md +++ b/docs/parallel_fuzzing.md @@ -13,12 +13,12 @@ In fact, if you rely on just a single job on a multi-core system, you will be underutilizing the hardware. So, parallelization is usually the right way to go. -When targeting multiple unrelated binaries or using the tool in "dumb" (-n) -mode, it is perfectly fine to just start up several fully separate instances -of afl-fuzz. The picture gets more complicated when you want to have multiple -fuzzers hammering a common target: if a hard-to-hit but interesting test case -is synthesized by one fuzzer, the remaining instances will not be able to use -that input to guide their work. +When targeting multiple unrelated binaries or using the tool in +"non-instrumented" (-n) mode, it is perfectly fine to just start up several +fully separate instances of afl-fuzz. The picture gets more complicated when +you want to have multiple fuzzers hammering a common target: if a hard-to-hit +but interesting test case is synthesized by one fuzzer, the remaining instances +will not be able to use that input to guide their work. To help with this problem, afl-fuzz offers a simple way to synchronize test cases on the fly. @@ -37,7 +37,7 @@ system, simply create a new, empty output directory ("sync dir") that will be shared by all the instances of afl-fuzz; and then come up with a naming scheme for every instance - say, "fuzzer01", "fuzzer02", etc. -Run the first one ("master", -M) like this: +Run the first one ("main node", -M) like this: ``` ./afl-fuzz -i testcase_dir -o sync_dir -M fuzzer01 [...other stuff...] @@ -57,26 +57,26 @@ Each fuzzer will keep its state in a separate subdirectory, like so: Each instance will also periodically rescan the top-level sync directory for any test cases found by other fuzzers - and will incorporate them into its own fuzzing when they are deemed interesting enough. -For performance reasons only -M masters sync the queue with everyone, the --S slaves will only sync from the master. +For performance reasons only -M main node syncs the queue with everyone, the +-S secondary nodes will only sync from the main node. -The difference between the -M and -S modes is that the master instance will +The difference between the -M and -S modes is that the main instance will still perform deterministic checks; while the secondary instances will proceed straight to random tweaks. -Note that you must always have one -M master instance! +Note that you must always have one -M main instance! Note that running multiple -M instances is wasteful, although there is an experimental support for parallelizing the deterministic checks. To leverage that, you need to create -M instances like so: ``` -./afl-fuzz -i testcase_dir -o sync_dir -M masterA:1/3 [...] -./afl-fuzz -i testcase_dir -o sync_dir -M masterB:2/3 [...] -./afl-fuzz -i testcase_dir -o sync_dir -M masterC:3/3 [...] +./afl-fuzz -i testcase_dir -o sync_dir -M mainA:1/3 [...] +./afl-fuzz -i testcase_dir -o sync_dir -M mainB:2/3 [...] +./afl-fuzz -i testcase_dir -o sync_dir -M mainC:3/3 [...] ``` -...where the first value after ':' is the sequential ID of a particular master +...where the first value after ':' is the sequential ID of a particular main instance (starting at 1), and the second value is the total number of fuzzers to distribute the deterministic fuzzing across. Note that if you boot up fewer fuzzers than indicated by the second number passed to -M, you may end up with @@ -168,7 +168,7 @@ to keep in mind: This arrangement would allow test interesting cases to propagate across the fleet without having to copy every fuzzer queue to every single host. - - You do not want a "master" instance of afl-fuzz on every system; you should + - You do not want a "main" instance of afl-fuzz on every system; you should run them all with -S, and just designate a single process somewhere within the fleet to run with -M. @@ -185,10 +185,10 @@ also basic machine-readable information always written to the fuzzer_stats file in the output directory. Locally, that information can be interpreted with afl-whatsup. -In principle, you can use the status screen of the master (-M) instance to +In principle, you can use the status screen of the main (-M) instance to monitor the overall fuzzing progress and decide when to stop. In this mode, the most important signal is just that no new paths are being found -for a longer while. If you do not have a master instance, just pick any +for a longer while. If you do not have a main instance, just pick any single secondary instance to watch and go by that. You can also rely on that instance's output directory to collect the @@ -197,7 +197,7 @@ within the fleet. Secondary (-S) instances do not require any special monitoring, other than just making sure that they are up. Keep in mind that crashing inputs are *not* automatically propagated to the -master instance, so you may still want to monitor for crashes fleet-wide +main instance, so you may still want to monitor for crashes fleet-wide from within your synchronization or health checking scripts (see afl-whatsup). ## 5) Asymmetric setups diff --git a/docs/power_schedules.md b/docs/power_schedules.md index c69c64d2..067a1d91 100644 --- a/docs/power_schedules.md +++ b/docs/power_schedules.md @@ -25,7 +25,7 @@ where *α(i)* is the performance score that AFL uses to compute for the seed inp More details can be found in the paper that was accepted at the [23rd ACM Conference on Computer and Communications Security (CCS'16)](https://www.sigsac.org/ccs/CCS2016/accepted-papers/). -PS: In parallel mode (several instances with shared queue), we suggest to run the master using the exploit schedule (-p exploit) and the slaves with a combination of cut-off-exponential (-p coe), exponential (-p fast; default), and explore (-p explore) schedules. In single mode, the default settings will do. **EDIT:** In parallel mode, AFLFast seems to perform poorly because the path probability estimates are incorrect for the imported seeds. Pull requests to fix this issue by syncing the estimates accross instances are appreciated :) +PS: In parallel mode (several instances with shared queue), we suggest to run the main node using the exploit schedule (-p exploit) and the secondary nodes with a combination of cut-off-exponential (-p coe), exponential (-p fast; default), and explore (-p explore) schedules. In single mode, the default settings will do. **EDIT:** In parallel mode, AFLFast seems to perform poorly because the path probability estimates are incorrect for the imported seeds. Pull requests to fix this issue by syncing the estimates across instances are appreciated :) Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. Released under terms and conditions of Apache License, Version 2.0. diff --git a/docs/status_screen.md b/docs/status_screen.md index a66558b9..b89468ce 100644 --- a/docs/status_screen.md +++ b/docs/status_screen.md @@ -33,7 +33,7 @@ The top line shows you which mode afl-fuzz is running in (normal: "american fuzy lop", crash exploration mode: "peruvian rabbit mode") and the version of afl++. Next to the version is the banner, which, if not set with -T by hand, will -either show the binary name being fuzzed, or the -M/-S master/slave name for +either show the binary name being fuzzed, or the -M/-S main/secondary name for parallel fuzzing. Finally, the last item is the power schedule mode being run (default: explore). @@ -404,7 +404,7 @@ directory. This includes: - `var_byte_count` - how many edges are non-deterministic - `afl_banner` - banner text (e.g. the target name) - `afl_version` - the version of afl used - - `target_mode` - default, persistent, qemu, unicorn, dumb + - `target_mode` - default, persistent, qemu, unicorn, non-instrumented - `command_line` - full command line used for the fuzzing session Most of these map directly to the UI elements discussed earlier on. diff --git a/gcc_plugin/README.md b/gcc_plugin/README.md index fcc778fa..f762131e 100644 --- a/gcc_plugin/README.md +++ b/gcc_plugin/README.md @@ -71,7 +71,7 @@ reports to . ## 4) Bonus feature #1: deferred initialization AFL tries to optimize performance by executing the targeted binary just once, -stopping it just before main(), and then cloning this "master" process to get +stopping it just before main(), and then cloning this "main" process to get a steady supply of targets to fuzz. Although this approach eliminates much of the OS-, linker- and libc-level diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index bb0bbfe2..3b5cc0e2 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -408,8 +408,8 @@ typedef struct afl_state { debug, /* Debug mode */ custom_only, /* Custom mutator only mode */ python_only, /* Python-only mode */ - is_master, /* if this is a master */ - is_slave; /* if this is a slave */ + is_main_node, /* if this is the main node */ + is_secondary_node; /* if this is a secondary instance */ u32 stats_update_freq; /* Stats update frequency (execs) */ @@ -421,7 +421,7 @@ typedef struct afl_state { u8 skip_deterministic, /* Skip deterministic stages? */ use_splicing, /* Recombine input files? */ - dumb_mode, /* Run in non-instrumented mode? */ + non_instrumented_mode, /* Run in non-instrumented mode? */ score_changed, /* Scoring for favorites changed? */ resuming_fuzz, /* Resuming an older fuzzing job? */ timeout_given, /* Specific timeout given? */ @@ -503,7 +503,7 @@ typedef struct afl_state { s32 stage_cur, stage_max; /* Stage progression */ s32 splicing_with; /* Splicing with which test case? */ - u32 master_id, master_max; /* Master instance job splitting */ + u32 main_node_id, main_node_max; /* Main instance job splitting */ u32 syncing_case; /* Syncing with case #... */ @@ -916,7 +916,7 @@ u32 find_start_position(afl_state_t *); void find_timeout(afl_state_t *); double get_runnable_processes(void); void nuke_resume_dir(afl_state_t *); -int check_master_exists(afl_state_t *); +int check_main_node_exists(afl_state_t *); void setup_dirs_fds(afl_state_t *); void setup_cmdline_file(afl_state_t *, char **); void setup_stdio_file(afl_state_t *); diff --git a/include/sharedmem.h b/include/sharedmem.h index 066a9904..a77ab7c0 100644 --- a/include/sharedmem.h +++ b/include/sharedmem.h @@ -53,7 +53,7 @@ typedef struct sharedmem { } sharedmem_t; -u8 * afl_shm_init(sharedmem_t *, size_t, unsigned char dumb_mode); +u8 * afl_shm_init(sharedmem_t *, size_t, unsigned char non_instrumented_mode); void afl_shm_deinit(sharedmem_t *); #endif diff --git a/llvm_mode/README.persistent_mode.md b/llvm_mode/README.persistent_mode.md index 7aae8faa..83cc7f4d 100644 --- a/llvm_mode/README.persistent_mode.md +++ b/llvm_mode/README.persistent_mode.md @@ -55,7 +55,7 @@ The speed increase is usually x10 to x20. ## 3) deferred initialization AFL tries to optimize performance by executing the targeted binary just once, -stopping it just before main(), and then cloning this "master" process to get +stopping it just before main(), and then cloning this "main" process to get a steady supply of targets to fuzz. Although this approach eliminates much of the OS-, linker- and libc-level diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index b96ca7f4..f739691a 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -425,7 +425,7 @@ static void __afl_start_snapshots(void) { } else { - // uh this forkserver master does not understand extended option passing + // uh this forkserver does not understand extended option passing // or does not want the dictionary if (!__afl_fuzz_ptr) already_read_first = 1; @@ -627,7 +627,7 @@ static void __afl_start_forkserver(void) { } else { - // uh this forkserver master does not understand extended option passing + // uh this forkserver does not understand extended option passing // or does not want the dictionary if (!__afl_fuzz_ptr) already_read_first = 1; diff --git a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h index a0246198..400ebf24 100644 --- a/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h +++ b/qemu_mode/patches/afl-qemu-tcg-runtime-inl.h @@ -215,7 +215,7 @@ void HELPER(afl_cmplog_rtn)(CPUArchState *env) { #else - // dumb code to make it compile + // stupid code to make it compile void *ptr1 = NULL; void *ptr2 = NULL; return; diff --git a/src/afl-common.c b/src/afl-common.c index a3692756..c9b4638a 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -253,7 +253,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { "binaries that are\n" " instrumented at compile time with afl-gcc. It is also possible to " "use it as a\n" - " traditional \"dumb\" fuzzer by specifying '-n' in the command " + " traditional non-instrumented fuzzer by specifying '-n' in the command " "line.\n"); FATAL("Failed to locate 'afl-qemu-trace'."); @@ -353,7 +353,7 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { "binaries that are\n" " instrumented at compile time with afl-gcc. It is also possible to " "use it as a\n" - " traditional \"dumb\" fuzzer by specifying '-n' in the command " + " traditional non-instrumented fuzzer by specifying '-n' in the command " "line.\n", ncp); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 961748ec..6601aceb 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -167,7 +167,7 @@ static u32 read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, } -/* Internal forkserver for dumb_mode=1 and non-forkserver mode runs. +/* Internal forkserver for non_instrumented_mode=1 and non-forkserver mode runs. It execvs for each fork, forwarding exit codes and child pids to afl. */ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index ff078319..5b98be9e 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -623,14 +623,14 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { /* Timeouts are not very interesting, but we're still obliged to keep a handful of samples. We use the presence of new bits in the - hang-specific bitmap as a signal of uniqueness. In "dumb" mode, we - just keep everything. */ + hang-specific bitmap as a signal of uniqueness. In "non-instrumented" + mode, we just keep everything. */ ++afl->total_tmouts; if (afl->unique_hangs >= KEEP_UNIQUE_HANG) { return keeping; } - if (likely(!afl->dumb_mode)) { + if (likely(!afl->non_instrumented_mode)) { #ifdef WORD_SIZE_64 simplify_trace(afl, (u64 *)afl->fsrv.trace_bits); @@ -698,7 +698,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) { return keeping; } - if (likely(!afl->dumb_mode)) { + if (likely(!afl->non_instrumented_mode)) { #ifdef WORD_SIZE_64 simplify_trace(afl, (u64 *)afl->fsrv.trace_bits); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ea281b7b..05aa0cc7 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1315,10 +1315,10 @@ dir_cleanup_failed: } -/* If this is a -S slave, ensure a -M master is running, if a master is - running when another master is started then warn */ +/* If this is a -S secondary node, ensure a -M main node is running, + if a main node is running when another main is started, then warn */ -int check_master_exists(afl_state_t *afl) { +int check_main_node_exists(afl_state_t *afl) { DIR * sd; struct dirent *sd_ent; @@ -1337,7 +1337,7 @@ int check_master_exists(afl_state_t *afl) { } - fn = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name); int res = access(fn, F_OK); free(fn); if (res == 0) return 1; @@ -1392,9 +1392,9 @@ void setup_dirs_fds(afl_state_t *afl) { } - if (afl->is_master) { + if (afl->is_main_node) { - u8 *x = alloc_printf("%s/is_master", afl->out_dir); + u8 *x = alloc_printf("%s/is_main_node", afl->out_dir); int fd = open(x, O_CREAT | O_RDWR, 0644); if (fd < 0) FATAL("cannot create %s", x); free(x); @@ -1859,7 +1859,7 @@ void fix_up_sync(afl_state_t *afl) { u8 *x = afl->sync_id; - if (afl->dumb_mode) { FATAL("-S / -M and -n are mutually exclusive"); } + if (afl->non_instrumented_mode) { FATAL("-S / -M and -n are mutually exclusive"); } while (*x) { @@ -1955,7 +1955,7 @@ void setup_testcase_shmem(afl_state_t *afl) { afl->shm_fuzz = ck_alloc(sizeof(sharedmem_t)); - // we need to set the dumb mode to not overwrite the SHM_ENV_VAR + // we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR if ((afl->fsrv.shmem_fuzz = afl_shm_init(afl->shm_fuzz, MAX_FILE, 1))) { #ifdef USEMMAP @@ -2126,7 +2126,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { #endif /* ^!__APPLE__ */ - if (!afl->fsrv.qemu_mode && !afl->unicorn_mode && !afl->dumb_mode && + if (!afl->fsrv.qemu_mode && !afl->unicorn_mode && !afl->non_instrumented_mode && !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST @@ -2143,8 +2143,8 @@ void check_binary(afl_state_t *afl, u8 *fname) { " mode support. Consult the README.md for tips on how to enable " "this.\n" - " (It is also possible to use afl-fuzz as a traditional, \"dumb\" " - "fuzzer.\n" + " (It is also possible to use afl-fuzz as a traditional, " + "non-instrumented fuzzer.\n" " For that, you can use the -n option - but expect much worse " "results.)\n", doc_path); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 56f16b4c..146e30bc 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -415,7 +415,7 @@ u8 fuzz_one_original(afl_state_t *afl) { } - } else if (!afl->dumb_mode && !afl->queue_cur->favored && + } else if (!afl->non_instrumented_mode && !afl->queue_cur->favored && afl->queued_paths > 10) { @@ -512,7 +512,7 @@ u8 fuzz_one_original(afl_state_t *afl) { * TRIMMING * ************/ - if (!afl->dumb_mode && !afl->queue_cur->trim_done && !afl->disable_trim) { + if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done && !afl->disable_trim) { u8 res = trim_case(afl, afl->queue_cur, in_buf); @@ -577,10 +577,10 @@ u8 fuzz_one_original(afl_state_t *afl) { } /* Skip deterministic fuzzing if exec path checksum puts this out of scope - for this master instance. */ + for this main instance. */ - if (afl->master_max && - (afl->queue_cur->exec_cksum % afl->master_max) != afl->master_id - 1) { + if (afl->main_node_max && + (afl->queue_cur->exec_cksum % afl->main_node_max) != afl->main_node_id - 1) { goto custom_mutator_stage; @@ -650,7 +650,7 @@ u8 fuzz_one_original(afl_state_t *afl) { */ - if (!afl->dumb_mode && (afl->stage_cur & 7) == 7) { + if (!afl->non_instrumented_mode && (afl->stage_cur & 7) == 7) { u32 cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -822,10 +822,10 @@ u8 fuzz_one_original(afl_state_t *afl) { u32 cksum; - /* If in dumb mode or if the file is very short, just flag everything - without wasting time on checksums. */ + /* If in non-instrumented mode or if the file is very short, just flag + everything without wasting time on checksums. */ - if (!afl->dumb_mode && len >= EFF_MIN_LEN) { + if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) { cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -2568,7 +2568,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { } - } else if (!afl->dumb_mode && !afl->queue_cur->favored && + } else if (!afl->non_instrumented_mode && !afl->queue_cur->favored && afl->queued_paths > 10) { @@ -2660,7 +2660,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { * TRIMMING * ************/ - if (!afl->dumb_mode && !afl->queue_cur->trim_done) { + if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done) { u8 res = trim_case(afl, afl->queue_cur, in_buf); @@ -2730,10 +2730,10 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { } /* Skip deterministic fuzzing if exec path checksum puts this out of scope - for this master instance. */ + for this main instance. */ - if (afl->master_max && - (afl->queue_cur->exec_cksum % afl->master_max) != afl->master_id - 1) { + if (afl->main_node_max && + (afl->queue_cur->exec_cksum % afl->main_node_max) != afl->main_node_id - 1) { goto havoc_stage; @@ -2803,7 +2803,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { */ - if (!afl->dumb_mode && (afl->stage_cur & 7) == 7) { + if (!afl->non_instrumented_mode && (afl->stage_cur & 7) == 7) { u32 cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); @@ -2975,10 +2975,10 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u32 cksum; - /* If in dumb mode or if the file is very short, just flag everything + /* If in non-instrumented mode or if the file is very short, just flag everything without wasting time on checksums. */ - if (!afl->dumb_mode && len >= EFF_MIN_LEN) { + if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) { cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index cfeb6c5e..ea7f57e2 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -303,7 +303,7 @@ void cull_queue(afl_state_t *afl) { u32 i; u8 * temp_v = afl->map_tmp_buf; - if (afl->dumb_mode || !afl->score_changed) { return; } + if (afl->non_instrumented_mode || !afl->score_changed) { return; } afl->score_changed = 0; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 982825d8..ec5ade53 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -234,7 +234,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (afl->fsrv.support_shdmen_fuzz && !afl->fsrv.use_shdmen_fuzz) { afl_shm_deinit(afl->shm_fuzz); - free(afl->shm_fuzz); + ck_free(afl->shm_fuzz); afl->shm_fuzz = NULL; afl->fsrv.support_shdmen_fuzz = 0; afl->fsrv.shmem_fuzz = NULL; @@ -272,7 +272,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } - if (!afl->dumb_mode && !afl->stage_cur && + if (!afl->non_instrumented_mode && !afl->stage_cur && !count_bytes(afl, afl->fsrv.trace_bits)) { fault = FSRV_RUN_NOINST; @@ -337,7 +337,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, parent. This is a non-critical problem, but something to warn the user about. */ - if (!afl->dumb_mode && first_run && !fault && !new_bits) { + if (!afl->non_instrumented_mode && first_run && !fault && !new_bits) { fault = FSRV_RUN_NOBITS; @@ -412,17 +412,17 @@ void sync_fuzzers(afl_state_t *afl) { entries++; - // a slave only syncs from a master, a master syncs from everyone - if (likely(afl->is_slave)) { + // secondary nodes only syncs from main, the main node syncs from everyone + if (likely(afl->is_secondary_node)) { - sprintf(qd_path, "%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + sprintf(qd_path, "%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name); int res = access(qd_path, F_OK); - if (unlikely(afl->is_master)) { // an elected temporary master + if (unlikely(afl->is_main_node)) { // an elected temporary main node - if (likely(res == 0)) { // there is another master? downgrade. + if (likely(res == 0)) { // there is another main node? downgrade. - afl->is_master = 0; - sprintf(qd_path, "%s/is_master", afl->out_dir); + afl->is_main_node = 0; + sprintf(qd_path, "%s/is_main_node", afl->out_dir); unlink(qd_path); } @@ -561,16 +561,16 @@ void sync_fuzzers(afl_state_t *afl) { closedir(sd); - // If we are a slave and no master was found to sync then become the master - if (unlikely(synced == 0) && likely(entries) && likely(afl->is_slave)) { + // If we are a secondary and no main was found to sync then become the main + if (unlikely(synced == 0) && likely(entries) && likely(afl->is_secondary_node)) { - // there is a small race condition here that another slave runs at the same - // time. If so, the first temporary master running again will demote + // there is a small race condition here that another secondary runs at the same + // time. If so, the first temporary main node running again will demote // themselves so this is not an issue u8 path[PATH_MAX]; - afl->is_master = 1; - sprintf(path, "%s/is_master", afl->out_dir); + afl->is_main_node = 1; + sprintf(path, "%s/is_main_node", afl->out_dir); int fd = open(path, O_CREAT | O_RDWR, 0644); if (fd >= 0) { close(fd); } diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index bc75f54e..d6bb8b72 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -125,12 +125,13 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, #endif t_bytes, afl->var_byte_count, afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", - afl->dumb_mode ? " dumb " : "", afl->no_forkserver ? "no_fsrv " : "", + afl->non_instrumented_mode ? " non_instrumented " : "", + afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", afl->persistent_mode ? "persistent " : "", afl->shmem_testcase_mode ? "shmem_testcase " : "", afl->deferred_mode ? "deferred " : "", - (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->dumb_mode || + (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->non_instrumented_mode || afl->no_forkserver || afl->crash_mode || afl->persistent_mode || afl->deferred_mode) ? "" @@ -327,7 +328,7 @@ void show_stats(afl_state_t *afl) { /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ - if (!afl->dumb_mode && afl->cycles_wo_finds > 100 && + if (!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) { afl->stop_soon = 2; @@ -415,7 +416,7 @@ void show_stats(afl_state_t *afl) { " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA " overall results " bSTG bH2 bH2 bRT "\n"); - if (afl->dumb_mode) { + if (afl->non_instrumented_mode) { strcpy(tmp, cRST); @@ -461,7 +462,7 @@ void show_stats(afl_state_t *afl) { /* We want to warn people about not seeing new paths after a full cycle, except when resuming fuzzing or running in non-instrumented mode. */ - if (!afl->dumb_mode && + if (!afl->non_instrumented_mode && (afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 || afl->in_bitmap || afl->crash_mode)) { @@ -470,7 +471,7 @@ void show_stats(afl_state_t *afl) { } else { - if (afl->dumb_mode) { + if (afl->non_instrumented_mode) { SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST " (non-instrumented mode) "); @@ -526,7 +527,7 @@ void show_stats(afl_state_t *afl) { SAYF(" map density : %s%-21s" bSTG bV "\n", t_byte_ratio > 70 ? cLRD - : ((t_bytes < 200 && !afl->dumb_mode) ? cPIN : cRST), + : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST), tmp); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_paths), @@ -1021,10 +1022,10 @@ void show_init_stats(afl_state_t *afl) { } - /* In dumb mode, re-running every timing out test case with a generous time + /* In non-instrumented mode, re-running every timing out test case with a generous time limit is very expensive, so let's select a more conservative default. */ - if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout)) { + if (afl->non_instrumented_mode && !(afl->afl_env.afl_hang_tmout)) { afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 69111ea7..ee9c0c67 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -130,7 +130,7 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) { " -N - do not unlink the fuzzing input file (only for " "devices etc.!)\n" " -d - quick & dirty mode (skips deterministic steps)\n" - " -n - fuzz without instrumentation (dumb mode)\n" + " -n - fuzz without instrumentation (non-instrumented mode)\n" " -x dir - optional fuzzer dictionary (see README.md, its really " "good!)\n\n" @@ -379,17 +379,17 @@ int main(int argc, char **argv_orig, char **envp) { *c = 0; - if (sscanf(c + 1, "%u/%u", &afl->master_id, &afl->master_max) != 2 || - !afl->master_id || !afl->master_max || - afl->master_id > afl->master_max || afl->master_max > 1000000) { + if (sscanf(c + 1, "%u/%u", &afl->main_node_id, &afl->main_node_max) != 2 || + !afl->main_node_id || !afl->main_node_max || + afl->main_node_id > afl->main_node_max || afl->main_node_max > 1000000) { - FATAL("Bogus master ID passed to -M"); + FATAL("Bogus main node ID passed to -M"); } } - afl->is_master = 1; + afl->is_main_node = 1; } @@ -399,7 +399,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); } afl->sync_id = ck_strdup(optarg); - afl->is_slave = 1; + afl->is_secondary_node = 1; afl->skip_deterministic = 1; afl->use_splicing = 1; break; @@ -533,14 +533,14 @@ int main(int argc, char **argv_orig, char **envp) { case 'n': /* dumb mode */ - if (afl->dumb_mode) { FATAL("Multiple -n options not supported"); } + if (afl->non_instrumented_mode) { FATAL("Multiple -n options not supported"); } if (afl->afl_env.afl_dumb_forksrv) { - afl->dumb_mode = 2; + afl->non_instrumented_mode = 2; } else { - afl->dumb_mode = 1; + afl->non_instrumented_mode = 1; } @@ -791,10 +791,10 @@ int main(int argc, char **argv_orig, char **envp) { OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); - if (afl->sync_id && afl->is_master && afl->afl_env.afl_custom_mutator_only) { + if (afl->sync_id && afl->is_main_node && afl->afl_env.afl_custom_mutator_only) { WARNF( - "Using -M master with the AFL_CUSTOM_MUTATOR_ONLY mutator options will " + "Using -M main node with the AFL_CUSTOM_MUTATOR_ONLY mutator options will " "result in no deterministic mutations being done!"); } @@ -872,7 +872,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->dumb_mode) { + if (afl->non_instrumented_mode) { if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); } if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); } @@ -955,13 +955,13 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->dumb_mode == 2 && afl->no_forkserver) { + if (afl->non_instrumented_mode == 2 && afl->no_forkserver) { FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); } - afl->fsrv.use_fauxsrv = afl->dumb_mode == 1 || afl->no_forkserver; + afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver; if (getenv("LD_PRELOAD")) { @@ -1058,7 +1058,7 @@ int main(int argc, char **argv_orig, char **envp) { check_cpu_governor(afl); afl->fsrv.trace_bits = - afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->dumb_mode); + afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); } memset(afl->virgin_tmout, 255, afl->fsrv.map_size); @@ -1066,7 +1066,7 @@ int main(int argc, char **argv_orig, char **envp) { init_count_class16(); - if (afl->is_master && check_master_exists(afl) == 1) { + if (afl->is_main_node && check_main_node_exists(afl) == 1) { WARNF("it is wasteful to run more than one master!"); sleep(1); @@ -1075,9 +1075,9 @@ int main(int argc, char **argv_orig, char **envp) { setup_dirs_fds(afl); - if (afl->is_slave && check_master_exists(afl) == 0) { + if (afl->is_secondary_node && check_main_node_exists(afl) == 0) { - WARNF("no -M master found. You need to run one master!"); + WARNF("no -M main node found. You need to run one main instance!"); sleep(5); } @@ -1369,10 +1369,10 @@ stop_fuzzing: time_spent_working / afl->fsrv.total_execs); #endif - if (afl->is_master) { + if (afl->is_main_node) { u8 path[PATH_MAX]; - sprintf(path, "%s/is_master", afl->out_dir); + sprintf(path, "%s/is_main_node", afl->out_dir); unlink(path); } diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index f5817293..f87c75eb 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -96,7 +96,7 @@ void afl_shm_deinit(sharedmem_t *shm) { Returns a pointer to shm->map for ease of use. */ -u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { +u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char non_instrumented_mode) { shm->map_size = map_size; @@ -137,12 +137,12 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { } - /* If somebody is asking us to fuzz instrumented binaries in dumb mode, + /* If somebody is asking us to fuzz instrumented binaries in non-instrumented mode, we don't want them to detect instrumentation, since we won't be sending fork server commands. This should be replaced with better auto-detection later on, perhaps? */ - if (!dumb_mode) setenv(SHM_ENV_VAR, shm->g_shm_file_path, 1); + if (!non_instrumented_mode) setenv(SHM_ENV_VAR, shm->g_shm_file_path, 1); if (shm->map == -1 || !shm->map) PFATAL("mmap() failed"); @@ -164,12 +164,12 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { shm_str = alloc_printf("%d", shm->shm_id); - /* If somebody is asking us to fuzz instrumented binaries in dumb mode, + /* If somebody is asking us to fuzz instrumented binaries in non-instrumented mode, we don't want them to detect instrumentation, since we won't be sending fork server commands. This should be replaced with better auto-detection later on, perhaps? */ - if (!dumb_mode) { setenv(SHM_ENV_VAR, shm_str, 1); } + if (!non_instrumented_mode) { setenv(SHM_ENV_VAR, shm_str, 1); } ck_free(shm_str); @@ -177,7 +177,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { shm_str = alloc_printf("%d", shm->cmplog_shm_id); - if (!dumb_mode) { setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); } + if (!non_instrumented_mode) { setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); } ck_free(shm_str); -- cgit 1.4.1 From fc164e4709f1f1c91f9343eb116627417e7f267f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 3 Jun 2020 10:50:49 +0200 Subject: code format --- examples/aflpp_driver/aflpp_qemu_driver.c | 8 ++++--- examples/aflpp_driver/aflpp_qemu_driver_hook.c | 5 ++-- examples/qemu_persistent_hook/read_into_rdi.c | 11 +++++---- qemu_mode/patches/afl-qemu-common.h | 7 +++--- qemu_mode/patches/afl-qemu-cpu-inl.h | 33 +++++++++++++------------- src/afl-common.c | 6 +++-- src/afl-forkserver.c | 4 +++- src/afl-fuzz-init.c | 9 +++++-- src/afl-fuzz-one.c | 15 ++++++------ src/afl-fuzz-run.c | 7 +++--- src/afl-fuzz-stats.c | 11 +++++---- src/afl-fuzz.c | 19 +++++++++++---- src/afl-sharedmem.c | 19 ++++++++------- 13 files changed, 90 insertions(+), 64 deletions(-) (limited to 'src/afl-common.c') diff --git a/examples/aflpp_driver/aflpp_qemu_driver.c b/examples/aflpp_driver/aflpp_qemu_driver.c index dd272408..d8862316 100644 --- a/examples/aflpp_driver/aflpp_qemu_driver.c +++ b/examples/aflpp_driver/aflpp_qemu_driver.c @@ -6,12 +6,14 @@ int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); int main(int argc, char **argv) { - if (LLVMFuzzerInitialize) - LLVMFuzzerInitialize(&argc, &argv); + + if (LLVMFuzzerInitialize) LLVMFuzzerInitialize(&argc, &argv); // Do any other expensive one-time initialization here. uint8_t dummy_input[1] = {0}; LLVMFuzzerTestOneInput(dummy_input, 1); - + return 0; + } + diff --git a/examples/aflpp_driver/aflpp_qemu_driver_hook.c b/examples/aflpp_driver/aflpp_qemu_driver_hook.c index 17a84668..823cc42d 100644 --- a/examples/aflpp_driver/aflpp_qemu_driver_hook.c +++ b/examples/aflpp_driver/aflpp_qemu_driver_hook.c @@ -7,9 +7,9 @@ #define REGS_RSI 6 void afl_persistent_hook(uint64_t *regs, uint64_t guest_base, - uint8_t* input_buf, uint32_t input_len) { + uint8_t *input_buf, uint32_t input_len) { - memcpy(g2h(regs[REGS_RDI]), input_buf, input_len); + memcpy(g2h(regs[REGS_RDI]), input_buf, input_len); regs[REGS_RSI] = input_len; } @@ -19,3 +19,4 @@ int afl_persistent_hook_init(void) { return 1; } + diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/examples/qemu_persistent_hook/read_into_rdi.c index 29087962..180d9f00 100644 --- a/examples/qemu_persistent_hook/read_into_rdi.c +++ b/examples/qemu_persistent_hook/read_into_rdi.c @@ -36,7 +36,7 @@ enum { }; void afl_persistent_hook(uint64_t *regs, uint64_t guest_base, - uint8_t* input_buf, uint32_t input_len) { + uint8_t *input_buf, uint32_t input_len) { // In this example the register RDI is pointing to the memory location // of the target buffer, and the length of the input is in RSI. @@ -44,16 +44,17 @@ void afl_persistent_hook(uint64_t *regs, uint64_t guest_base, printf("placing input into %p\n", regs[R_EDI]); - if (input_len > 1024) - input_len = 1024; - memcpy(g2h(regs[R_EDI]), input_buf, input_len); + if (input_len > 1024) input_len = 1024; + memcpy(g2h(regs[R_EDI]), input_buf, input_len); regs[R_ESI] = input_len; } int afl_persistent_hook_init(void) { - // 1 for shared memory input (faster), 0 for normal input (you have to use read(), input_buf will be NULL) + // 1 for shared memory input (faster), 0 for normal input (you have to use + // read(), input_buf will be NULL) return 1; } + diff --git a/qemu_mode/patches/afl-qemu-common.h b/qemu_mode/patches/afl-qemu-common.h index 5812596a..f7ffa56a 100644 --- a/qemu_mode/patches/afl-qemu-common.h +++ b/qemu_mode/patches/afl-qemu-common.h @@ -63,9 +63,8 @@ #define INC_AFL_AREA(loc) afl_area_ptr[loc]++ #endif -typedef void (*afl_persistent_hook_fn)(uint64_t *regs, - uint64_t guest_base, - uint8_t* input_buf, +typedef void (*afl_persistent_hook_fn)(uint64_t *regs, uint64_t guest_base, + uint8_t *input_buf, uint32_t input_buf_len); /* Declared in afl-qemu-cpu-inl.h */ @@ -86,7 +85,7 @@ extern int persisent_retaddr_offset; extern u8 *shared_buf; extern u32 shared_buf_len; -extern u8 sharedmem_fuzzing; +extern u8 sharedmem_fuzzing; extern afl_persistent_hook_fn afl_persistent_hook_ptr; diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index dc18ea95..7836e2cf 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -85,7 +85,7 @@ int persisent_retaddr_offset; u8 *shared_buf; u32 shared_buf_len; -u8 sharedmem_fuzzing; +u8 sharedmem_fuzzing; afl_persistent_hook_fn afl_persistent_hook_ptr; @@ -163,7 +163,8 @@ static void afl_map_shm_fuzz(void) { } else { - fprintf(stderr, "[AFL] ERROR: variable for fuzzing shared memory is not set\n"); + fprintf(stderr, + "[AFL] ERROR: variable for fuzzing shared memory is not set\n"); exit(1); } @@ -282,9 +283,9 @@ void afl_setup(void) { exit(1); } - - int (*afl_persistent_hook_init_ptr)(void) = dlsym(plib, - "afl_persistent_hook_init"); + + int (*afl_persistent_hook_init_ptr)(void) = + dlsym(plib, "afl_persistent_hook_init"); if (afl_persistent_hook_init_ptr) sharedmem_fuzzing = afl_persistent_hook_init_ptr(); @@ -302,7 +303,7 @@ void afl_setup(void) { #endif } - + if (getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET")) persisent_retaddr_offset = strtoll(getenv("AFL_QEMU_PERSISTENT_RETADDR_OFFSET"), NULL, 0); @@ -318,7 +319,7 @@ void afl_setup(void) { void afl_forkserver(CPUState *cpu) { - //u32 map_size = 0; + // u32 map_size = 0; unsigned char tmp[4] = {0}; if (forkserver_installed == 1) return; @@ -331,8 +332,8 @@ void afl_forkserver(CPUState *cpu) { pid_t child_pid; int t_fd[2]; u8 child_stopped = 0; - u32 was_killed; - int status; + u32 was_killed; + int status; // with the max ID value if (MAP_SIZE <= FS_OPT_MAX_MAPSIZE) @@ -349,7 +350,7 @@ void afl_forkserver(CPUState *cpu) { afl_forksrv_pid = getpid(); int first_run = 1; - + if (sharedmem_fuzzing) { if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); @@ -358,11 +359,12 @@ void afl_forkserver(CPUState *cpu) { (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ)) afl_map_shm_fuzz(); else { - - fprintf(stderr, "[AFL] ERROR: afl-fuzz is old and does not support" - " shmem input"); + + fprintf(stderr, + "[AFL] ERROR: afl-fuzz is old and does not support" + " shmem input"); exit(1); - + } } @@ -374,7 +376,7 @@ void afl_forkserver(CPUState *cpu) { /* Whoops, parent dead? */ if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2); - + shared_buf_len = (was_killed >> 8); was_killed = (was_killed & 0xff); @@ -459,7 +461,6 @@ void afl_forkserver(CPUState *cpu) { } - /* A simplified persistent mode handler, used as explained in * llvm_mode/README.md. */ diff --git a/src/afl-common.c b/src/afl-common.c index c9b4638a..f4cba573 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -253,7 +253,8 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { "binaries that are\n" " instrumented at compile time with afl-gcc. It is also possible to " "use it as a\n" - " traditional non-instrumented fuzzer by specifying '-n' in the command " + " traditional non-instrumented fuzzer by specifying '-n' in the " + "command " "line.\n"); FATAL("Failed to locate 'afl-qemu-trace'."); @@ -353,7 +354,8 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { "binaries that are\n" " instrumented at compile time with afl-gcc. It is also possible to " "use it as a\n" - " traditional non-instrumented fuzzer by specifying '-n' in the command " + " traditional non-instrumented fuzzer by specifying '-n' in the " + "command " "line.\n", ncp); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index d32e8293..b5b55713 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -524,7 +524,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } else { - FATAL("Target requested sharedmem fuzzing, but we failed to enable it."); + FATAL( + "Target requested sharedmem fuzzing, but we failed to enable " + "it."); } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 05aa0cc7..3c3503b1 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1859,7 +1859,11 @@ void fix_up_sync(afl_state_t *afl) { u8 *x = afl->sync_id; - if (afl->non_instrumented_mode) { FATAL("-S / -M and -n are mutually exclusive"); } + if (afl->non_instrumented_mode) { + + FATAL("-S / -M and -n are mutually exclusive"); + + } while (*x) { @@ -2126,7 +2130,8 @@ void check_binary(afl_state_t *afl, u8 *fname) { #endif /* ^!__APPLE__ */ - if (!afl->fsrv.qemu_mode && !afl->unicorn_mode && !afl->non_instrumented_mode && + if (!afl->fsrv.qemu_mode && !afl->unicorn_mode && + !afl->non_instrumented_mode && !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 146e30bc..578ac584 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -512,7 +512,8 @@ u8 fuzz_one_original(afl_state_t *afl) { * TRIMMING * ************/ - if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done && !afl->disable_trim) { + if (!afl->non_instrumented_mode && !afl->queue_cur->trim_done && + !afl->disable_trim) { u8 res = trim_case(afl, afl->queue_cur, in_buf); @@ -579,8 +580,8 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Skip deterministic fuzzing if exec path checksum puts this out of scope for this main instance. */ - if (afl->main_node_max && - (afl->queue_cur->exec_cksum % afl->main_node_max) != afl->main_node_id - 1) { + if (afl->main_node_max && (afl->queue_cur->exec_cksum % afl->main_node_max) != + afl->main_node_id - 1) { goto custom_mutator_stage; @@ -2732,8 +2733,8 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { /* Skip deterministic fuzzing if exec path checksum puts this out of scope for this main instance. */ - if (afl->main_node_max && - (afl->queue_cur->exec_cksum % afl->main_node_max) != afl->main_node_id - 1) { + if (afl->main_node_max && (afl->queue_cur->exec_cksum % afl->main_node_max) != + afl->main_node_id - 1) { goto havoc_stage; @@ -2975,8 +2976,8 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u32 cksum; - /* If in non-instrumented mode or if the file is very short, just flag everything - without wasting time on checksums. */ + /* If in non-instrumented mode or if the file is very short, just flag + everything without wasting time on checksums. */ if (!afl->non_instrumented_mode && len >= EFF_MIN_LEN) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ec5ade53..5934690f 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -562,10 +562,11 @@ void sync_fuzzers(afl_state_t *afl) { closedir(sd); // If we are a secondary and no main was found to sync then become the main - if (unlikely(synced == 0) && likely(entries) && likely(afl->is_secondary_node)) { + if (unlikely(synced == 0) && likely(entries) && + likely(afl->is_secondary_node)) { - // there is a small race condition here that another secondary runs at the same - // time. If so, the first temporary main node running again will demote + // there is a small race condition here that another secondary runs at the + // same time. If so, the first temporary main node running again will demote // themselves so this is not an issue u8 path[PATH_MAX]; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index d6bb8b72..97221572 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -126,8 +126,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, t_bytes, afl->var_byte_count, afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->non_instrumented_mode ? " non_instrumented " : "", - afl->no_forkserver ? "no_fsrv " : "", - afl->crash_mode ? "crash " : "", + afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", afl->persistent_mode ? "persistent " : "", afl->shmem_testcase_mode ? "shmem_testcase " : "", afl->deferred_mode ? "deferred " : "", @@ -526,8 +525,9 @@ void show_stats(afl_state_t *afl) { t_byte_ratio); SAYF(" map density : %s%-21s" bSTG bV "\n", - t_byte_ratio > 70 ? cLRD - : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST), + t_byte_ratio > 70 + ? cLRD + : ((t_bytes < 200 && !afl->non_instrumented_mode) ? cPIN : cRST), tmp); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->cur_skipped_paths), @@ -1022,7 +1022,8 @@ void show_init_stats(afl_state_t *afl) { } - /* In non-instrumented mode, re-running every timing out test case with a generous time + /* In non-instrumented mode, re-running every timing out test case with a + generous time limit is very expensive, so let's select a more conservative default. */ if (afl->non_instrumented_mode && !(afl->afl_env.afl_hang_tmout)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index aed1e958..07e1584b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -379,9 +379,11 @@ int main(int argc, char **argv_orig, char **envp) { *c = 0; - if (sscanf(c + 1, "%u/%u", &afl->main_node_id, &afl->main_node_max) != 2 || + if (sscanf(c + 1, "%u/%u", &afl->main_node_id, &afl->main_node_max) != + 2 || !afl->main_node_id || !afl->main_node_max || - afl->main_node_id > afl->main_node_max || afl->main_node_max > 1000000) { + afl->main_node_id > afl->main_node_max || + afl->main_node_max > 1000000) { FATAL("Bogus main node ID passed to -M"); @@ -533,7 +535,12 @@ int main(int argc, char **argv_orig, char **envp) { case 'n': /* dumb mode */ - if (afl->non_instrumented_mode) { FATAL("Multiple -n options not supported"); } + if (afl->non_instrumented_mode) { + + FATAL("Multiple -n options not supported"); + + } + if (afl->afl_env.afl_dumb_forksrv) { afl->non_instrumented_mode = 2; @@ -793,10 +800,12 @@ int main(int argc, char **argv_orig, char **envp) { OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL"); OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); - if (afl->sync_id && afl->is_main_node && afl->afl_env.afl_custom_mutator_only) { + if (afl->sync_id && afl->is_main_node && + afl->afl_env.afl_custom_mutator_only) { WARNF( - "Using -M main node with the AFL_CUSTOM_MUTATOR_ONLY mutator options will " + "Using -M main node with the AFL_CUSTOM_MUTATOR_ONLY mutator options " + "will " "result in no deterministic mutations being done!"); } diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index f87c75eb..63013435 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -96,7 +96,8 @@ void afl_shm_deinit(sharedmem_t *shm) { Returns a pointer to shm->map for ease of use. */ -u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char non_instrumented_mode) { +u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, + unsigned char non_instrumented_mode) { shm->map_size = map_size; @@ -137,10 +138,10 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char non_instrument } - /* If somebody is asking us to fuzz instrumented binaries in non-instrumented mode, - we don't want them to detect instrumentation, since we won't be sending - fork server commands. This should be replaced with better auto-detection - later on, perhaps? */ + /* If somebody is asking us to fuzz instrumented binaries in non-instrumented + mode, we don't want them to detect instrumentation, since we won't be + sending fork server commands. This should be replaced with better + auto-detection later on, perhaps? */ if (!non_instrumented_mode) setenv(SHM_ENV_VAR, shm->g_shm_file_path, 1); @@ -164,10 +165,10 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char non_instrument shm_str = alloc_printf("%d", shm->shm_id); - /* If somebody is asking us to fuzz instrumented binaries in non-instrumented mode, - we don't want them to detect instrumentation, since we won't be sending - fork server commands. This should be replaced with better auto-detection - later on, perhaps? */ + /* If somebody is asking us to fuzz instrumented binaries in non-instrumented + mode, we don't want them to detect instrumentation, since we won't be + sending fork server commands. This should be replaced with better + auto-detection later on, perhaps? */ if (!non_instrumented_mode) { setenv(SHM_ENV_VAR, shm_str, 1); } -- cgit 1.4.1 From 855ee062478023983e652bed64da174d7a8dd556 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 4 Jun 2020 13:57:16 +0200 Subject: add afl-ld-lto for LTO --- docs/Changelog.md | 2 + llvm_mode/GNUmakefile | 10 +- llvm_mode/README.lto.md | 76 +++++++++- llvm_mode/afl-ld-lto.c | 358 ++++++++++++++++++++++++++++++++++++++++++++++++ src/afl-common.c | 5 +- 5 files changed, 440 insertions(+), 11 deletions(-) create mode 100644 llvm_mode/afl-ld-lto.c (limited to 'src/afl-common.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 87e02938..eaaeb529 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -22,6 +22,8 @@ sending a mail to . better coverage. The original afl instrumentation can be set via AFL_LLVM_INSTRUMENT=AFL. This is automatically done when the WHITELIST feature is used. + - some targets want a ld variant for LD that is not gcc/clang but ld, added + afl-ld-lto to solve this - lowered minimum required llvm version to 3.4 (except LLVMInsTrim, which needs 3.8.0) - WHITELIST feature now supports wildcards (thanks to sirmc) diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 5efe1e12..0e554a39 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -246,7 +246,7 @@ ifeq "$(TEST_MMAP)" "1" LDFLAGS += -Wno-deprecated-declarations endif - PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so + PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-ld-lto ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so # If prerequisites are not given, warn, do not build anything, and exit with code 0 ifeq "$(LLVMVER)" "" @@ -304,7 +304,7 @@ afl-common.o: ../src/afl-common.c $(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS) ../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps - $(CC) $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\" -Dxxx + $(CC) $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\" ln -sf afl-clang-fast ../afl-clang-fast++ ifneq "$(AFL_CLANG_FLTO)" "" ifeq "$(LLVM_LTO)" "1" @@ -330,6 +330,11 @@ ifeq "$(LLVM_LTO)" "1" $(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o endif +../afl-ld-lto: afl-ld-lto.c +ifeq "$(LLVM_LTO)" "1" + $(CC) $(CFLAGS) $< -o $@ +endif + ../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc afl-llvm-common.o ifeq "$(LLVM_LTO)" "1" $(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o @@ -392,6 +397,7 @@ install: all install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-lto-instrim.so ../afl-llvm-rt-lto*.o ../afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi + if [ -f ../afl-ld-lto ]; then set -e; install -m 755 ../afl-ld-lto $${DESTDIR}$(BIN_PATH); fi if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 48c587eb..517cb62a 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -14,9 +14,11 @@ This version requires a current llvm 11 compiled from the github master. 4. AUTODICTIONARY feature! see below -5. If any problems arise be sure to set `AR=llvm-ar RANLIB=llvm-ranlib` also - note that if that target uses _init functions or early constructors then - also set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise +5. If any problems arise be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`. + Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`. + +6. If a target uses _init functions or early constructors then additionally + set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise! ## Introduction and problem description @@ -61,7 +63,8 @@ AUTODICTIONARY: 11 strings found ## Getting llvm 11 -### Installing llvm 11 +### Installing llvm 11 from the llvm repository + Installing the llvm snapshot builds is easy and mostly painless: In the follow line change `NAME` for your Debian or Ubuntu release name @@ -80,7 +83,7 @@ apt-get install -y clang-11 clang-tools-11 libc++1-11 libc++-11-dev \ libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools ``` -### Building llvm 11 +### Building llvm 11 yourself Building llvm from github takes quite some long time and is not painless: ``` @@ -117,6 +120,9 @@ export AFL_LLVM_INSTRUMENT=CFG make ``` +NOTE: some targets also need to set the linker, try both `afl-clang-lto` and +`afl-ld-lto` for this for `LD=` for `configure`. + ## AUTODICTIONARY feature Setting `AFL_LLVM_LTO_AUTODICTIONARY` will generate a dictionary in the @@ -135,6 +141,51 @@ to be dynamic - the original afl way, which is slower). AFL_LLVM_MAP_DYNAMIC can be set so the shared memory address is dynamic (which is safer but also slower). +## Solving difficult targets + +Some targets are difficult because the configure script does unusual stuff that +is unexpected for afl. See the next chapter `Potential issues` how to solve +these. + +An example of a hard to solve target is ffmpeg. Here is how to successfully +instrument it: + +1. Get and extract the current ffmpeg and change to it's directory + +2. Running configure with --cc=clang fails and various other items will fail + when compiling, so we have to trick configure: + +``` +./configure --enable-lto --disable-shared +``` + +3. Now the configuration is done - and we edit the settings in `./ffbuild/config.mak` + (-: the original line, +: what to change it into): +``` +-CC=gcc ++CC=afl-clang-lto +-CXX=g++ ++CXX=afl-clang-lto++ +-AS=gcc ++AS=llvm-as +-LD=gcc ++LD=afl-clang-lto++ +-DEPCC=gcc ++DEPCC=afl-clang-lto +-DEPAS=gcc ++DEPAS=afl-clang-lto++ +-AR=ar ++AR=llvm-ar +-AR_CMD=ar ++AR_CMD=llvm-ar +-NM_CMD=nm -g ++NM_CMD=llvm-nm -g +-RANLIB=ranlib -D ++RANLIB=llvm-ranlib -D +``` + +4. Then type make, wait for a long time and you are done :) + ## Potential issues ### compiling libraries fails @@ -154,6 +205,16 @@ and on some target you have to to AR=/RANLIB= even for make as the configure scr Other targets ignore environment variables and need the parameters set via `./configure --cc=... --cxx= --ranlib= ...` etc. (I am looking at you ffmpeg!). + +If you see this message +``` +assembler command failed ... +``` +then try setting `llvm-as` for configure: +``` +AS=llvm-as ... +``` + ### compiling programs still fail afl-clang-lto is still work in progress. @@ -166,11 +227,12 @@ Hence if building a target with afl-clang-lto fails try to build it with llvm11 and LTO enabled (`CC=clang-11` `CXX=clang++-11` `CFLAGS=-flto=full` and `CXXFLAGS=-flto=full`). -An example that does not build with llvm 11 and LTO is ffmpeg. - If this succeeeds then there is an issue with afl-clang-lto. Please report at [https://github.com/AFLplusplus/AFLplusplus/issues/226](https://github.com/AFLplusplus/AFLplusplus/issues/226) +Even some targets where clang-11 fails can be build if the fail is just in +`./configure`, see `Solving difficult targets` above. + ### Target crashes immediately If the target is using early constructors (priority values smaller than 6) diff --git a/llvm_mode/afl-ld-lto.c b/llvm_mode/afl-ld-lto.c new file mode 100644 index 00000000..1b59bb4a --- /dev/null +++ b/llvm_mode/afl-ld-lto.c @@ -0,0 +1,358 @@ +/* + american fuzzy lop++ - wrapper for llvm 11+ lld + ----------------------------------------------- + + Written by Marc Heuse for afl++ + + Maintained by Marc Heuse , + Heiko Eißfeldt + Andrea Fioraldi + Dominik Maier + + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + The sole purpose of this wrapper is to preprocess clang LTO files when + linking with lld and performing the instrumentation on the whole program. + +*/ + +#define AFL_MAIN +#define _GNU_SOURCE + +#include "config.h" +#include "types.h" +#include "debug.h" +#include "alloc-inl.h" + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define MAX_PARAM_COUNT 4096 + +static u8 **ld_params; /* Parameters passed to the real 'ld' */ + +static u8 *afl_path = AFL_PATH; +static u8 *real_ld = AFL_REAL_LD; + +static u8 be_quiet, /* Quiet mode (no stderr output) */ + debug, /* AFL_DEBUG */ + passthrough, /* AFL_LD_PASSTHROUGH - no link+optimize*/ + just_version; /* Just show version? */ + +static u32 ld_param_cnt = 1; /* Number of params to 'ld' */ + +/* Examine and modify parameters to pass to 'ld', 'llvm-link' and 'llmv-ar'. + Note that the file name is always the last parameter passed by GCC, + so we exploit this property to keep the code "simple". */ +static void edit_params(int argc, char **argv) { + + u32 i, instrim = 0, gold_pos = 0, gold_present = 0, rt_present = 0, + rt_lto_present = 0, inst_present = 0; + char *ptr; + + ld_params = ck_alloc(4096 * sizeof(u8 *)); + + ld_params[0] = (u8 *)real_ld; + + if (!passthrough) { + + for (i = 1; i < argc; i++) { + + if (strstr(argv[i], "/afl-llvm-rt-lto.o") != NULL) rt_lto_present = 1; + if (strstr(argv[i], "/afl-llvm-rt.o") != NULL) rt_present = 1; + if (strstr(argv[i], "/afl-llvm-lto-instr") != NULL) inst_present = 1; + + } + + for (i = 1; i < argc && !gold_pos; i++) { + + if (strcmp(argv[i], "-plugin") == 0) { + + if (strncmp(argv[i], "-plugin=", strlen("-plugin=")) == 0) { + + if (strcasestr(argv[i], "LLVMgold.so") != NULL) + gold_present = gold_pos = i + 1; + + } else if (i < argc && strcasestr(argv[i + 1], "LLVMgold.so") != NULL) { + + gold_present = gold_pos = i + 2; + + } + + } + + } + + if (!gold_pos) { + + for (i = 1; i + 1 < argc && !gold_pos; i++) { + + if (argv[i][0] != '-') { + + if (argv[i - 1][0] == '-') { + + switch (argv[i - 1][1]) { + + case 'b': + break; + case 'd': + break; + case 'e': + break; + case 'F': + break; + case 'f': + break; + case 'I': + break; + case 'l': + break; + case 'L': + break; + case 'm': + break; + case 'o': + break; + case 'O': + break; + case 'p': + if (index(argv[i - 1], '=') == NULL) gold_pos = i; + break; + case 'R': + break; + case 'T': + break; + case 'u': + break; + case 'y': + break; + case 'z': + break; + case '-': { + + if (strcmp(argv[i - 1], "--oformat") == 0) break; + if (strcmp(argv[i - 1], "--output") == 0) break; + if (strncmp(argv[i - 1], "--opt-remarks-", 14) == 0) break; + gold_pos = i; + break; + + } + + default: + gold_pos = i; + + } + + } else + + gold_pos = i; + + } + + } + + } + + if (!gold_pos) gold_pos = 1; + + } + + if (getenv("AFL_LLVM_INSTRIM")) + instrim = 1; + else if ((ptr = getenv("AFL_LLVM_INSTRUMENT")) && + (strcasestr(ptr, "CFG") == 0 || strcasestr(ptr, "INSTRIM") == 0)) + instrim = 1; + + if (debug) + SAYF(cMGN "[D] " cRST + "passthrough=%s instrim=%d, gold_pos=%d, gold_present=%s " + "inst_present=%s rt_present=%s rt_lto_present=%s\n", + passthrough ? "true" : "false", instrim, gold_pos, + gold_present ? "true" : "false", inst_present ? "true" : "false", + rt_present ? "true" : "false", rt_lto_present ? "true" : "false"); + + for (i = 1; i < argc; i++) { + + if (ld_param_cnt >= MAX_PARAM_COUNT) + FATAL( + "Too many command line parameters because of unpacking .a archives, " + "this would need to be done by hand ... sorry! :-("); + + if (strcmp(argv[i], "--afl") == 0) { + + if (!be_quiet) OKF("afl++ test command line flag detected, exiting."); + exit(0); + + } + + if (i == gold_pos && !passthrough) { + + ld_params[ld_param_cnt++] = alloc_printf("-L%s/../lib", LLVM_BINDIR); + + if (!gold_present) { + + ld_params[ld_param_cnt++] = "-plugin"; + ld_params[ld_param_cnt++] = + alloc_printf("%s/../lib/LLVMgold.so", LLVM_BINDIR); + + } + + ld_params[ld_param_cnt++] = "--allow-multiple-definition"; + + if (!inst_present) { + + if (instrim) + ld_params[ld_param_cnt++] = + alloc_printf("-mllvm=-load=%s/afl-llvm-lto-instrim.so", afl_path); + else + ld_params[ld_param_cnt++] = alloc_printf( + "-mllvm=-load=%s/afl-llvm-lto-instrumentation.so", afl_path); + + } + + if (!rt_present) + ld_params[ld_param_cnt++] = alloc_printf("%s/afl-llvm-rt.o", afl_path); + if (!rt_lto_present) + ld_params[ld_param_cnt++] = + alloc_printf("%s/afl-llvm-rt-lto.o", afl_path); + + } + + ld_params[ld_param_cnt++] = argv[i]; + + } + + ld_params[ld_param_cnt] = NULL; + +} + +/* Main entry point */ + +int main(int argc, char **argv) { + + s32 pid, i, status; + u8 * ptr; + char thecwd[PATH_MAX]; + + if ((ptr = getenv("AFL_LD_CALLER")) != NULL) { + + FATAL("ld loop detected! Set AFL_REAL_LD!\n"); + + } + + if (isatty(2) && !getenv("AFL_QUIET") && !getenv("AFL_DEBUG")) { + + SAYF(cCYA "afl-ld-to" VERSION cRST + " by Marc \"vanHauser\" Heuse \n"); + + } else + + be_quiet = 1; + + if (getenv("AFL_DEBUG") != NULL) debug = 1; + if (getenv("AFL_PATH") != NULL) afl_path = getenv("AFL_PATH"); + if (getenv("AFL_LD_PASSTHROUGH") != NULL) passthrough = 1; + if (getenv("AFL_REAL_LD") != NULL) real_ld = getenv("AFL_REAL_LD"); + + if (!afl_path || !*afl_path) afl_path = "/usr/local/lib/afl"; + + setenv("AFL_LD_CALLER", "1", 1); + + if (debug) { + + (void)getcwd(thecwd, sizeof(thecwd)); + + SAYF(cMGN "[D] " cRST "cd \"%s\";", thecwd); + for (i = 0; i < argc; i++) + SAYF(" \"%s\"", argv[i]); + SAYF("\n"); + + } + + if (argc < 2) { + + SAYF( + "\n" + "This is a helper application for afl-clang-lto. It is a wrapper " + "around GNU " + "llvm's 'lld',\n" + "executed by the toolchain whenever using " + "afl-clang-lto/afl-clang-lto++.\n" + "You probably don't want to run this program directly but rather pass " + "it as LD parameter to configure scripts\n\n" + + "Environment variables:\n" + " AFL_LD_PASSTHROUGH do not link+optimize == no instrumentation\n" + " AFL_REAL_LD point to the real llvm 11 lld if necessary\n" + + "\nafl-ld-to was compiled with the fixed real 'ld' of %s and the " + "binary path of %s\n\n", + real_ld, LLVM_BINDIR); + + exit(1); + + } + + edit_params(argc, argv); // here most of the magic happens :-) + + if (debug) { + + SAYF(cMGN "[D]" cRST " cd \"%s\";", thecwd); + for (i = 0; i < ld_param_cnt; i++) + SAYF(" \"%s\"", ld_params[i]); + SAYF("\n"); + + } + + if (!(pid = fork())) { + + if (strlen(real_ld) > 1) execvp(real_ld, (char **)ld_params); + execvp("ld", (char **)ld_params); // fallback + FATAL("Oops, failed to execute 'ld' - check your PATH"); + + } + + if (pid < 0) PFATAL("fork() failed"); + + if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); + if (debug) SAYF(cMGN "[D] " cRST "linker result: %d\n", status); + + if (!just_version) { + + if (status == 0) { + + if (!be_quiet) OKF("Linker was successful"); + + } else { + + SAYF(cLRD "[-] " cRST + "Linker failed, please investigate and send a bug report. Most " + "likely an 'ld' option is incompatible with %s.\n", + AFL_CLANG_FLTO); + + } + + } + + exit(WEXITSTATUS(status)); + +} + diff --git a/src/afl-common.c b/src/afl-common.c index f4cba573..2802cda3 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -61,8 +61,9 @@ char *afl_environment_variables[] = { "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES", "AFL_IMPORT_FIRST", "AFL_INST_LIBS", "AFL_INST_RATIO", "AFL_KEEP_TRACES", "AFL_KEEP_ASSEMBLY", "AFL_LD_HARD_FAIL", "AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER", - "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", - "AFL_LLVM_CTX", "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD", + "AFL_LD_PASSTHROUGH", "AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", + "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CTX", + "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD", "AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY", "AFL_LLVM_SKIPSINGLEBLOCK", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", -- cgit 1.4.1