diff options
author | Fabian Meumertzheim <meumertzheim@code-intelligence.com> | 2021-03-22 14:48:58 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-03-22 14:48:58 +0100 |
commit | 71ac55c6fc9d808bcc8a8e8d895f7f20141bec86 (patch) | |
tree | dfa557a023d1413799c24dbd1373d8c42c2ee8bb /third_party | |
parent | 20d72b43a58f5ffcb807245a854d7eb178c4b8b6 (diff) | |
download | jazzer-api-71ac55c6fc9d808bcc8a8e8d895f7f20141bec86.tar.gz |
Do not intercept JVM-internal C stdlib calls (#45)
* Replace uses of quick_exit and at_quick_exit
quick_exit is not supported on macOS, but can easily replaced by a call
to _Exit after running our cleanup manually.
* Run buildifier --lint=fix -r .
* Build libFuzzer from source
Building libFuzzer from source is easy and has multiple advantages:
* The clang distributed with XCode on macOS does not include libFuzzer.
* Applying a small patch to libFuzzer will allow us to replace the
--wrap linker feature, which is not supported on platforms other than
Linux.
* Replace -Wl,--wrap with a source code patch
* Pin non-native rules_python
* Print exit code on test failure
* Do not intercept JVM-internal C stdlib calls
The JVM frequently calls strcmp/memcmp/..., which fills up the table of
recent compares with entries that are either duplicates of values
already reported by the bytecode instrumentation or JDK-internal strings
that are not relevant for fuzzing.
This commit adds an ignorelist to the C stdlib interceptors that filters
out calls from known JVM libraries. If the fuzz target has not yet
loaded a native library, all such callbacks are ignored, which greatly
improves fuzzer performance for string-heavy targets. E.g.,
JsonSanitizerDenylistFuzzer takes < 1 million runs now when it used to
take over 3 million.
Diffstat (limited to 'third_party')
-rw-r--r-- | third_party/BUILD.bazel | 3 | ||||
-rw-r--r-- | third_party/jni/BUILD.bazel | 2 | ||||
-rw-r--r-- | third_party/libFuzzer-make-interceptors-configurable.patch | 109 | ||||
-rw-r--r-- | third_party/libFuzzer-pass-death-callback-to-jazzer.patch | 28 | ||||
-rw-r--r-- | third_party/libFuzzer.BUILD | 21 |
5 files changed, 163 insertions, 0 deletions
diff --git a/third_party/BUILD.bazel b/third_party/BUILD.bazel index fd65eb9b..b391ce54 100644 --- a/third_party/BUILD.bazel +++ b/third_party/BUILD.bazel @@ -2,5 +2,8 @@ exports_files([ "gflags-use-double-dash-args.patch", "jacoco-make-probe-inserter-subclassable.patch", "jacoco_internal.BUILD", + "libFuzzer-make-interceptors-configurable.patch", + "libFuzzer-pass-death-callback-to-jazzer.patch", + "libFuzzer.BUILD", "libjpeg_turbo.BUILD", ]) diff --git a/third_party/jni/BUILD.bazel b/third_party/jni/BUILD.bazel index 4d5fdd00..cda76ef0 100644 --- a/third_party/jni/BUILD.bazel +++ b/third_party/jni/BUILD.bazel @@ -1,3 +1,5 @@ +load("@rules_cc//cc:defs.bzl", "cc_import", "cc_library") + cc_library( name = "jni", visibility = ["//visibility:public"], diff --git a/third_party/libFuzzer-make-interceptors-configurable.patch b/third_party/libFuzzer-make-interceptors-configurable.patch new file mode 100644 index 00000000..9420c4aa --- /dev/null +++ b/third_party/libFuzzer-make-interceptors-configurable.patch @@ -0,0 +1,109 @@ +diff --git compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp +index b87798603fda..10e34ee86cce 100644 +--- compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp ++++ compiler-rt/lib/fuzzer/FuzzerInterceptors.cpp +@@ -147,11 +147,18 @@ DEFINE_REAL(char *, strstr, const char *, const char *) + DEFINE_REAL(char *, strcasestr, const char *, const char *) + DEFINE_REAL(void *, memmem, const void *, size_t, const void *, size_t) + ++extern "C" __attribute__((weak)) bool ++__sanitizer_weak_is_relevant_pc(void * caller_pc) { ++ return false; ++} ++ + ATTRIBUTE_INTERFACE int bcmp(const char *s1, const char *s2, size_t n) { + if (!FuzzerInited) + return internal_memcmp(s1, s2, n); + int result = REAL(bcmp)(s1, s2, n); +- __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_memcmp(caller_pc, s1, s2, n, result); + return result; + } + +@@ -159,7 +166,9 @@ ATTRIBUTE_INTERFACE int memcmp(const void *s1, const void *s2, size_t n) { + if (!FuzzerInited) + return internal_memcmp(s1, s2, n); + int result = REAL(memcmp)(s1, s2, n); +- __sanitizer_weak_hook_memcmp(GET_CALLER_PC(), s1, s2, n, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_memcmp(caller_pc, s1, s2, n, result); + return result; + } + +@@ -167,7 +176,9 @@ ATTRIBUTE_INTERFACE int strncmp(const char *s1, const char *s2, size_t n) { + if (!FuzzerInited) + return internal_strncmp(s1, s2, n); + int result = REAL(strncmp)(s1, s2, n); +- __sanitizer_weak_hook_strncmp(GET_CALLER_PC(), s1, s2, n, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_strncmp(caller_pc, s1, s2, n, result); + return result; + } + +@@ -175,21 +186,27 @@ ATTRIBUTE_INTERFACE int strcmp(const char *s1, const char *s2) { + if (!FuzzerInited) + return internal_strcmp(s1, s2); + int result = REAL(strcmp)(s1, s2); +- __sanitizer_weak_hook_strcmp(GET_CALLER_PC(), s1, s2, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_strcmp(caller_pc, s1, s2, result); + return result; + } + + ATTRIBUTE_INTERFACE int strncasecmp(const char *s1, const char *s2, size_t n) { + ensureFuzzerInited(); + int result = REAL(strncasecmp)(s1, s2, n); +- __sanitizer_weak_hook_strncasecmp(GET_CALLER_PC(), s1, s2, n, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_strncasecmp(caller_pc, s1, s2, n, result); + return result; + } + + ATTRIBUTE_INTERFACE int strcasecmp(const char *s1, const char *s2) { + ensureFuzzerInited(); + int result = REAL(strcasecmp)(s1, s2); +- __sanitizer_weak_hook_strcasecmp(GET_CALLER_PC(), s1, s2, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_strcasecmp(caller_pc, s1, s2, result); + return result; + } + +@@ -197,14 +214,18 @@ ATTRIBUTE_INTERFACE char *strstr(const char *s1, const char *s2) { + if (!FuzzerInited) + return internal_strstr(s1, s2); + char *result = REAL(strstr)(s1, s2); +- __sanitizer_weak_hook_strstr(GET_CALLER_PC(), s1, s2, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_strstr(caller_pc, s1, s2, result); + return result; + } + + ATTRIBUTE_INTERFACE char *strcasestr(const char *s1, const char *s2) { + ensureFuzzerInited(); + char *result = REAL(strcasestr)(s1, s2); +- __sanitizer_weak_hook_strcasestr(GET_CALLER_PC(), s1, s2, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_strcasestr(caller_pc, s1, s2, result); + return result; + } + +@@ -212,7 +233,9 @@ ATTRIBUTE_INTERFACE + void *memmem(const void *s1, size_t len1, const void *s2, size_t len2) { + ensureFuzzerInited(); + void *result = REAL(memmem)(s1, len1, s2, len2); +- __sanitizer_weak_hook_memmem(GET_CALLER_PC(), s1, len1, s2, len2, result); ++ void *caller_pc = GET_CALLER_PC(); ++ if (__sanitizer_weak_is_relevant_pc(caller_pc)) ++ __sanitizer_weak_hook_memmem(caller_pc, s1, len1, s2, len2, result); + return result; + } + diff --git a/third_party/libFuzzer-pass-death-callback-to-jazzer.patch b/third_party/libFuzzer-pass-death-callback-to-jazzer.patch new file mode 100644 index 00000000..3fb9fbb0 --- /dev/null +++ b/third_party/libFuzzer-pass-death-callback-to-jazzer.patch @@ -0,0 +1,28 @@ +diff --git compiler-rt/lib/fuzzer/FuzzerExtFunctions.def compiler-rt/lib/fuzzer/FuzzerExtFunctions.def +index 51edf8444e94..e31f0040268b 100644 +--- compiler-rt/lib/fuzzer/FuzzerExtFunctions.def ++++ compiler-rt/lib/fuzzer/FuzzerExtFunctions.def +@@ -42,7 +42,7 @@ EXT_FUNC(__sanitizer_symbolize_pc, void, + EXT_FUNC(__sanitizer_get_module_and_offset_for_pc, int, + (void *pc, char *module_path, + size_t module_path_len,void **pc_offset), false); +-EXT_FUNC(__sanitizer_set_death_callback, void, (void (*)(void)), true); ++EXT_FUNC(__jazzer_set_death_callback, void, (void (*)(void)), true); + EXT_FUNC(__sanitizer_set_report_fd, void, (void*), false); + EXT_FUNC(__msan_scoped_disable_interceptor_checks, void, (), false); + EXT_FUNC(__msan_scoped_enable_interceptor_checks, void, (), false); +diff --git compiler-rt/lib/fuzzer/FuzzerLoop.cpp compiler-rt/lib/fuzzer/FuzzerLoop.cpp +index 149742b4c2fe..7b361423cc32 100644 +--- compiler-rt/lib/fuzzer/FuzzerLoop.cpp ++++ compiler-rt/lib/fuzzer/FuzzerLoop.cpp +@@ -138,8 +138,8 @@ void Fuzzer::HandleMalloc(size_t Size) { + Fuzzer::Fuzzer(UserCallback CB, InputCorpus &Corpus, MutationDispatcher &MD, + FuzzingOptions Options) + : CB(CB), Corpus(Corpus), MD(MD), Options(Options) { +- if (EF->__sanitizer_set_death_callback) +- EF->__sanitizer_set_death_callback(StaticDeathCallback); ++ if (EF->__jazzer_set_death_callback) ++ EF->__jazzer_set_death_callback(StaticDeathCallback); + assert(!F); + F = this; + TPC.ResetMaps(); diff --git a/third_party/libFuzzer.BUILD b/third_party/libFuzzer.BUILD new file mode 100644 index 00000000..4bd464a4 --- /dev/null +++ b/third_party/libFuzzer.BUILD @@ -0,0 +1,21 @@ +# Based on https://github.com/llvm/llvm-project/blob/llvmorg-11.1.0/compiler-rt/lib/fuzzer/build.sh +LIB_FUZZER_PATH = "compiler-rt/lib/fuzzer" + +cc_library( + name = "libFuzzer", + srcs = glob([ + LIB_FUZZER_PATH + "/*.cpp", + ]), + hdrs = glob([ + LIB_FUZZER_PATH + "/*.h", + LIB_FUZZER_PATH + "/*.def", + ]), + copts = [ + "-g", + "-O2", + "-fno-omit-frame-pointer", + "-std=c++11", + ], + alwayslink = True, + visibility = ["//visibility:public"], +) |