From 6d364dd2cb0ac31797b52e590b57bf9c10cc2302 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 5 Aug 2020 01:13:51 +0200 Subject: add sancov-like allow/denylist instrument feature --- llvm_mode/afl-clang-fast.c | 32 +++++++++++++++++++++----------- 1 file changed, 21 insertions(+), 11 deletions(-) (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index ef99e3f3..f75adf1e 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -229,7 +229,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode) { if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL || - getenv("AFL_LLVM_WHITELIST")) { + getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") || + getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; @@ -637,9 +638,13 @@ int main(int argc, char **argv, char **envp) { } - if ((getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) && + if ((getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL || + getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") || + getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) && getenv("AFL_DONT_OPTIMIZE")) - FATAL("AFL_LLVM_INSTRUMENT_FILE and AFL_DONT_OPTIMIZE cannot be combined"); + WARNF( + "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " + "for file matching, only function matching!"); if (getenv("AFL_LLVM_INSTRIM") || getenv("INSTRIM") || getenv("INSTRIM_LIB")) { @@ -787,15 +792,17 @@ int main(int argc, char **argv, char **envp) { #if LLVM_VERSION_MAJOR <= 6 instrument_mode = INSTRUMENT_AFL; #else - if (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST")) { + if (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL || + getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") || + getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST")) { instrument_mode = INSTRUMENT_AFL; WARNF( "switching to classic instrumentation because " - "AFL_LLVM_INSTRUMENT_FILE does not work with PCGUARD. Use " - "-fsanitize-coverage-allowlist=allowlist.txt if you want to use " - "PCGUARD. Requires llvm 12+. See " - "https://clang.llvm.org/docs/" + "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD. Use " + "-fsanitize-coverage-allowlist=allowlist.txt or " + "-fsanitize-coverage-blocklist=denylist.txt if you want to use " + "PCGUARD. Requires llvm 12+. See https://clang.llvm.org/docs/ " "SanitizerCoverage.html#partially-disabling-instrumentation"); } else @@ -846,11 +853,14 @@ int main(int argc, char **argv, char **envp) { "together"); if (instrument_mode == INSTRUMENT_PCGUARD && - (getenv("AFL_LLVM_INSTRUMENT_FILE") || getenv("AFL_LLVM_WHITELIST"))) + (getenv("AFL_LLVM_INSTRUMENT_FILE") != NULL || + getenv("AFL_LLVM_WHITELIST") || getenv("AFL_LLVM_ALLOWLIST") || + getenv("AFL_LLVM_DENYLIST") || getenv("AFL_LLVM_BLOCKLIST"))) FATAL( "Instrumentation type PCGUARD does not support " - "AFL_LLVM_INSTRUMENT_FILE! Use " - "-fsanitize-coverage-allowlist=allowlist.txt instead (requires llvm " + "AFL_LLVM_ALLOWLIST/DENYLIST! Use " + "-fsanitize-coverage-allowlist=allowlist.txt or " + "-fsanitize-coverage-blocklist=denylist.txt instead (requires llvm " "12+), see " "https://clang.llvm.org/docs/" "SanitizerCoverage.html#partially-disabling-instrumentation"); -- cgit 1.4.1 From 8fc727e597f26161fde7f38af8b805a39497da52 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 5 Aug 2020 10:01:58 +0200 Subject: port patch from https://github.com/google/AFL/pull/112 --- llvm_mode/afl-clang-fast.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index f75adf1e..750a6fbd 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -161,7 +161,8 @@ static void find_obj(u8 *argv0) { static void edit_params(u32 argc, char **argv, char **envp) { - u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0; + u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, + shared_linking = 0, preprocessor_only = 0; u8 have_pic = 0; u8 *name; @@ -399,6 +400,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; + + if (!strcmp(cur, "-E")) preprocessor_only = 1; + if (!strcmp(cur, "-shared")) shared_linking = 1; cc_params[cc_par_cnt++] = cur; @@ -563,6 +567,22 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "none"; } + + if (preprocessor_only || shared_linking) { + /* In the preprocessor_only case (-E), we are not actually compiling at + all but requesting the compiler to output preprocessed sources only. + We must not add the runtime in this case because the compiler will + simply output its binary content back on stdout, breaking any build + systems that rely on a separate source preprocessing step. + The shared_linking case (-shared) is more complex. This flag should + only be passed when linking a shared object. When loading such a shared + object into a binary that has also been built with AFL, two AFL runtimes + will exist side-by-side. This is only a problem in the dynamic loading + case because for static linking, the compiler can de-duplicate the + runtime. We must hence avoid attaching the runtime to shared objects. */ + cc_params[cc_par_cnt] = NULL; + return; + } #ifndef __ANDROID__ switch (bit_mode) { -- cgit 1.4.1 From bd36aac60a6d85fe83d072bf00a9ec0b2f3f135d Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 5 Aug 2020 10:27:48 +0200 Subject: remove shared_linking case --- llvm_mode/afl-clang-fast.c | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 750a6fbd..16f2c9c0 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -162,7 +162,7 @@ static void find_obj(u8 *argv0) { static void edit_params(u32 argc, char **argv, char **envp) { u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - shared_linking = 0, preprocessor_only = 0; + preprocessor_only = 0; u8 have_pic = 0; u8 *name; @@ -402,7 +402,6 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; if (!strcmp(cur, "-E")) preprocessor_only = 1; - if (!strcmp(cur, "-shared")) shared_linking = 1; cc_params[cc_par_cnt++] = cur; @@ -568,18 +567,12 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (preprocessor_only || shared_linking) { + if (preprocessor_only) { /* In the preprocessor_only case (-E), we are not actually compiling at all but requesting the compiler to output preprocessed sources only. We must not add the runtime in this case because the compiler will simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. - The shared_linking case (-shared) is more complex. This flag should - only be passed when linking a shared object. When loading such a shared - object into a binary that has also been built with AFL, two AFL runtimes - will exist side-by-side. This is only a problem in the dynamic loading - case because for static linking, the compiler can de-duplicate the - runtime. We must hence avoid attaching the runtime to shared objects. */ + systems that rely on a separate source preprocessing step. */ cc_params[cc_par_cnt] = NULL; return; } -- cgit 1.4.1 From f30ca1476c2d4d08d46fe9657ad4aa1d828eb578 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 5 Aug 2020 11:17:15 +0200 Subject: fix short write --- include/afl-fuzz.h | 4 ++-- llvm_mode/afl-clang-fast.c | 10 ++++++---- src/afl-fuzz-queue.c | 2 ++ src/afl-fuzz-run.c | 17 ++++++++++++++--- 4 files changed, 24 insertions(+), 9 deletions(-) (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 2324efa5..bb1bb314 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -986,7 +986,7 @@ uint64_t rand_next(afl_state_t *afl); static inline u32 rand_below(afl_state_t *afl, u32 limit) { - if (limit <= 1) return 0; + if (limit <= 1) return 0; /* The boundary not being necessarily a power of 2, we need to ensure the result uniformity. */ @@ -1008,7 +1008,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { expand havoc mode */ static inline u32 rand_below_datalen(afl_state_t *afl, u32 limit) { - if (limit <= 1) return 0; + if (limit <= 1) return 0; switch (rand_below(afl, 3)) { diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 16f2c9c0..3038df30 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -161,8 +161,8 @@ static void find_obj(u8 *argv0) { static void edit_params(u32 argc, char **argv, char **envp) { - u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - preprocessor_only = 0; + u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, + preprocessor_only = 0; u8 have_pic = 0; u8 *name; @@ -400,7 +400,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue; if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; - + if (!strcmp(cur, "-E")) preprocessor_only = 1; cc_params[cc_par_cnt++] = cur; @@ -566,8 +566,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "none"; } - + if (preprocessor_only) { + /* In the preprocessor_only case (-E), we are not actually compiling at all but requesting the compiler to output preprocessed sources only. We must not add the runtime in this case because the compiler will @@ -575,6 +576,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { systems that rely on a separate source preprocessing step. */ cc_params[cc_par_cnt] = NULL; return; + } #ifndef __ANDROID__ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 71874283..f35df914 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -112,8 +112,10 @@ static u8 check_if_text(struct queue_entry *q) { u8 buf[MAX_FILE]; s32 fd, len = q->len, offset = 0, ascii = 0, utf8 = 0, comp; + if (len >= MAX_FILE) len = MAX_FILE - 1; if ((fd = open(q->fname, O_RDONLY)) < 0) return 0; if ((comp = read(fd, buf, len)) != len) return 0; + buf[len] = 0; close(fd); while (offset < len) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 44d3c522..ed4a1081 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -819,16 +819,27 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } + + u32 written = 0; + while (written < q->len) { + + ssize_t result = write(fd, in_buf, q->len - written); + if (result > 0) written += result; + + } + } else { unlink(q->fname); /* ignore errors */ fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); - } + if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } - if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } + ck_write(fd, in_buf, q->len, q->fname); + + } - ck_write(fd, in_buf, q->len, q->fname); close(fd); memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size); -- cgit 1.4.1 From 19631851f6c7ecac42fb76ff70314f4e0777d3f3 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 5 Aug 2020 12:53:46 +0200 Subject: dynamic symbols export for dlopen --- dynamic_list.txt | 8 ++++++++ llvm_mode/afl-clang-fast.c | 17 ++++++++++++++--- 2 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 dynamic_list.txt (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/dynamic_list.txt b/dynamic_list.txt new file mode 100644 index 00000000..399e48ec --- /dev/null +++ b/dynamic_list.txt @@ -0,0 +1,8 @@ +{ + "__afl_area_ptr"; + "__afl_manual_init"; + "__afl_persistent_loop"; + "__afl_auto_init"; + "__afl_area_initial"; + "__afl_prev_loc"; +}; diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 16f2c9c0..10717124 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -162,7 +162,7 @@ static void find_obj(u8 *argv0) { static void edit_params(u32 argc, char **argv, char **envp) { u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - preprocessor_only = 0; + shared_linking = 0, preprocessor_only = 0; u8 have_pic = 0; u8 *name; @@ -402,6 +402,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue; if (!strcmp(cur, "-E")) preprocessor_only = 1; + if (!strcmp(cur, "-shared")) shared_linking = 1; cc_params[cc_par_cnt++] = cur; @@ -567,12 +568,18 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (preprocessor_only) { + if (preprocessor_only || shared_linking) { /* In the preprocessor_only case (-E), we are not actually compiling at all but requesting the compiler to output preprocessed sources only. We must not add the runtime in this case because the compiler will simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. */ + systems that rely on a separate source preprocessing step. + The shared_linking case (-shared) is more complex. This flag should + only be passed when linking a shared object. When loading such a shared + object into a binary that has also been built with AFL, two AFL runtimes + will exist side-by-side. This is only a problem in the dynamic loading + case because for static linking, the compiler can de-duplicate the + runtime. We must hence avoid attaching the runtime to shared objects. */ cc_params[cc_par_cnt] = NULL; return; } @@ -619,6 +626,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + if (!shared_linking) + cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); + + #endif cc_params[cc_par_cnt] = NULL; -- cgit 1.4.1 From 0281872ddf5f7b5058770eee610ea5250b82cc01 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 5 Aug 2020 13:05:30 +0200 Subject: remove shared_linking check --- llvm_mode/afl-clang-fast.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 1aa42150..e0b33475 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -568,18 +568,12 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (preprocessor_only || shared_linking) { + if (preprocessor_only) { /* In the preprocessor_only case (-E), we are not actually compiling at all but requesting the compiler to output preprocessed sources only. We must not add the runtime in this case because the compiler will simply output its binary content back on stdout, breaking any build - systems that rely on a separate source preprocessing step. - The shared_linking case (-shared) is more complex. This flag should - only be passed when linking a shared object. When loading such a shared - object into a binary that has also been built with AFL, two AFL runtimes - will exist side-by-side. This is only a problem in the dynamic loading - case because for static linking, the compiler can de-duplicate the - runtime. We must hence avoid attaching the runtime to shared objects. */ + systems that rely on a separate source preprocessing step. */ cc_params[cc_par_cnt] = NULL; return; -- cgit 1.4.1 From 1064c7114e2b4f69a6a3ef63d69900e96e7d4164 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 5 Aug 2020 13:30:43 +0200 Subject: code format --- llvm_mode/afl-clang-fast.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'llvm_mode/afl-clang-fast.c') diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index e0b33475..efaba122 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -161,8 +161,8 @@ static void find_obj(u8 *argv0) { static void edit_params(u32 argc, char **argv, char **envp) { - u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, - shared_linking = 0, preprocessor_only = 0; + u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0, + preprocessor_only = 0; u8 have_pic = 0; u8 *name; @@ -567,8 +567,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "none"; } - + if (preprocessor_only) { + /* In the preprocessor_only case (-E), we are not actually compiling at all but requesting the compiler to output preprocessed sources only. We must not add the runtime in this case because the compiler will @@ -622,8 +623,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { } if (!shared_linking) - cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); - + cc_params[cc_par_cnt++] = + alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif -- cgit 1.4.1