Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 1 | #include "sanitizers.h" |
| 2 | |
| 3 | #include <ctype.h> |
| 4 | #include <dirent.h> |
| 5 | #include <inttypes.h> |
| 6 | #include <stdio.h> |
| 7 | #include <stdlib.h> |
| 8 | #include <string.h> |
| 9 | #include <sys/mman.h> |
| 10 | #include <sys/stat.h> |
| 11 | #include <sys/types.h> |
| 12 | |
Robert Swiecki | 15801e8 | 2018-11-20 15:59:25 +0100 | [diff] [blame] | 13 | #include "cmdline.h" |
Robert Swiecki | 246af3e | 2018-01-05 14:56:32 +0100 | [diff] [blame] | 14 | #include "libhfcommon/common.h" |
| 15 | #include "libhfcommon/files.h" |
| 16 | #include "libhfcommon/log.h" |
| 17 | #include "libhfcommon/util.h" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 18 | |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 19 | /* |
Anestis Bechtsoudis | c2722ee | 2017-01-29 09:40:03 +0200 | [diff] [blame] | 20 | * All clang sanitizers, except ASan, can be activated for target binaries |
| 21 | * with or without the matching runtime library (libcompiler_rt). If runtime |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 22 | * libraries are included in target fuzzing environment, we can benefit from the |
| 23 | * various Die() callbacks and abort/exit logic manipulation. However, some |
Anestis Bechtsoudis | c2722ee | 2017-01-29 09:40:03 +0200 | [diff] [blame] | 24 | * setups (e.g. Android production ARM/ARM64 devices) enable sanitizers, such as |
| 25 | * UBSan, without the runtime libraries. As such, their default ftrap is activated |
| 26 | * which is for most cases a SIGABRT. For these cases end-user needs to enable |
| 27 | * SIGABRT monitoring flag, otherwise these crashes will be missed. |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 28 | * |
Anestis Bechtsoudis | c2722ee | 2017-01-29 09:40:03 +0200 | [diff] [blame] | 29 | * Normally SIGABRT is not a wanted signal to monitor for Android, since it produces |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 30 | * lots of useless crashes due to way Android process termination hacks work. As |
| 31 | * a result the sanitizer's 'abort_on_error' flag cannot be utilized since it |
| 32 | * invokes abort() internally. In order to not lose crashes a custom exitcode can |
| 33 | * be registered and monitored. Since exitcode is a global flag, it's assumed |
| 34 | * that target is compiled with only one sanitizer type enabled at a time. |
| 35 | * |
Anestis Bechtsoudis | c2722ee | 2017-01-29 09:40:03 +0200 | [diff] [blame] | 36 | * For cases where clang runtime library linking is not an option, SIGABRT should |
| 37 | * be monitored even for noisy targets, such as the Android OS, since no viable |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 38 | * alternative exists. |
Anestis Bechtsoudis | 523fccb | 2016-12-28 12:11:13 +0200 | [diff] [blame] | 39 | * |
| 40 | * There might be cases where ASan instrumented targets crash while generating |
| 41 | * reports for detected errors (inside __asan_report_error() proc). Under such |
| 42 | * scenarios target fails to exit or SIGABRT (AsanDie() proc) as defined in |
| 43 | * ASAN_OPTIONS flags, leaving garbage logs. An attempt is made to parse such |
| 44 | * logs for cases where enough data are written to identify potentially missed |
| 45 | * crashes. If ASan internal error results into a SIGSEGV being raised, it |
| 46 | * will get caught from ptrace API, handling the discovered ASan internal crash. |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 47 | */ |
| 48 | |
| 49 | /* 'log_path' output directory for sanitizer reports */ |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 50 | #define kSANLOGDIR "log_path=" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 51 | |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 52 | /* Raise SIGABRT on error or continue with exitcode logic */ |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 53 | #define kABORT_ENABLED "abort_on_error=1" |
| 54 | #define kABORT_DISABLED "abort_on_error=0" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 55 | |
| 56 | /* |
| 57 | * Common sanitizer flags |
| 58 | * |
| 59 | * symbolize: Disable symbolication since it changes logs (which are parsed) format |
| 60 | */ |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 61 | #define kSAN_COMMON "symbolize=0" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 62 | |
| 63 | /* --{ ASan }-- */ |
| 64 | /* |
| 65 | *Sanitizer specific flags (notice that if enabled 'abort_on_error' has priority |
| 66 | * over exitcode') |
| 67 | */ |
Robert Swiecki | d50ed42 | 2017-11-13 23:32:26 +0100 | [diff] [blame] | 68 | #define kASAN_COMMON_OPTS \ |
| 69 | "allow_user_segv_handler=1:" \ |
| 70 | "handle_segv=0:" \ |
Robert Swiecki | 89d444a | 2018-01-11 23:45:19 +0100 | [diff] [blame] | 71 | "allocator_may_return_null=1:" kSAN_COMMON ":exitcode=" HF_XSTR(HF_SAN_EXIT_CODE) |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 72 | /* Platform specific flags */ |
| 73 | #if defined(__ANDROID__) |
| 74 | /* |
| 75 | * start_deactivated: Enable on Android to reduce memory usage (useful when not all |
| 76 | * target's DSOs are compiled with sanitizer enabled |
| 77 | */ |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 78 | #define kASAN_OPTS kASAN_COMMON_OPTS ":start_deactivated=1" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 79 | #else |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 80 | #define kASAN_OPTS kASAN_COMMON_OPTS |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 81 | #endif |
| 82 | |
| 83 | /* --{ UBSan }-- */ |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 84 | #define kUBSAN_OPTS kSAN_COMMON ":exitcode=" STR(HF_SAN_EXIT_CODE) |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 85 | |
| 86 | /* --{ MSan }-- */ |
Robert Swiecki | 98e2337 | 2019-01-30 11:50:18 +0100 | [diff] [blame] | 87 | #define kMSAN_OPTS \ |
| 88 | kSAN_COMMON ":exit_code=" STR(HF_SAN_EXIT_CODE) ":" \ |
Robert Swiecki | 0b56611 | 2017-10-17 17:39:07 +0200 | [diff] [blame] | 89 | "wrap_signals=0:print_stats=1" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 90 | |
Robert Swiecki | b4e13c0 | 2017-02-10 03:59:40 +0100 | [diff] [blame] | 91 | /* If no sanitzer support was requested, simply make it use abort() on errors */ |
Robert Swiecki | ba3ee41 | 2018-01-04 14:10:49 +0100 | [diff] [blame] | 92 | #define kSAN_REGULAR \ |
| 93 | "abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:" \ |
| 94 | "handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:" \ |
Robert Swiecki | 0b418dd | 2018-11-19 16:08:36 +0100 | [diff] [blame] | 95 | "symbolize=1:detect_leaks=0:disable_coredump=0:" \ |
| 96 | "detect_odr_violation=0" |
Robert Swiecki | b4e13c0 | 2017-02-10 03:59:40 +0100 | [diff] [blame] | 97 | |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 98 | /* |
| 99 | * If the program ends with a signal that ASan does not handle (or can not |
| 100 | * handle at all, like SIGKILL), coverage data will be lost. This is a big |
| 101 | * problem on Android, where SIGKILL is a normal way of evicting applications |
| 102 | * from memory. With 'coverage_direct=1' coverage data is written to a |
| 103 | * memory-mapped file as soon as it collected. Non-Android targets can disable |
| 104 | * coverage direct when more coverage data collection methods are implemented. |
| 105 | */ |
Robert Swiecki | d0fa62c | 2017-09-28 18:11:05 +0200 | [diff] [blame] | 106 | #define kSAN_COV_OPTS "coverage=1:coverage_direct=1" |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 107 | |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 108 | static void sanitizers_AddFlag(honggfuzz_t* hfuzz, const char* env, char* buf, size_t buflen) { |
Robert Swiecki | a5b918a | 2018-03-07 23:59:53 +0100 | [diff] [blame] | 109 | const char* abortFlag = hfuzz->cfg.monitorSIGABRT ? kABORT_ENABLED : kABORT_DISABLED; |
Robert Swiecki | 754d169 | 2018-11-19 17:24:27 +0100 | [diff] [blame] | 110 | if (getenv(env)) { |
| 111 | LOG_W("The '%s' envar is already set. Not overriding it!", env); |
| 112 | return; |
| 113 | } |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 114 | |
Robert Swiecki | a5b918a | 2018-03-07 23:59:53 +0100 | [diff] [blame] | 115 | if (!hfuzz->sanitizer.enable) { |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 116 | snprintf(buf, buflen, "%s=%s", env, kSAN_REGULAR); |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 117 | } else { |
| 118 | snprintf(buf, buflen, "%s=%s:%s:%s%s/%s", env, kASAN_OPTS, abortFlag, kSANLOGDIR, |
| 119 | hfuzz->io.workDir, kLOGPREFIX); |
| 120 | } |
Robert Swiecki | b165bfc | 2018-01-22 16:00:07 +0100 | [diff] [blame] | 121 | /* |
| 122 | * It will make ASAN to start background thread to check RSS mem use, which |
| 123 | * will prevent the NetDrvier from using unshare(CLONE_NEWNET), which cannot |
| 124 | * be used in multi-threaded contexts |
| 125 | */ |
| 126 | if (!hfuzz->exe.netDriver && hfuzz->exe.rssLimit) { |
| 127 | util_ssnprintf(buf, buflen, ":soft_rss_limit_mb=%" PRId64, hfuzz->exe.rssLimit); |
Robert Swiecki | 5cc1f7b | 2018-01-16 20:55:43 +0100 | [diff] [blame] | 128 | } |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 129 | |
Robert Swiecki | 15801e8 | 2018-11-20 15:59:25 +0100 | [diff] [blame] | 130 | cmdlineAddEnv(hfuzz, buf); |
Robert Swiecki | cec31c9 | 2017-12-27 19:23:54 +0100 | [diff] [blame] | 131 | LOG_D("%s", env); |
Robert Swiecki | 528935c | 2017-12-27 18:51:54 +0100 | [diff] [blame] | 132 | } |
| 133 | |
Robert Swiecki | d50ed42 | 2017-11-13 23:32:26 +0100 | [diff] [blame] | 134 | bool sanitizers_Init(honggfuzz_t* hfuzz) { |
Robert Swiecki | e2a05ed | 2018-01-10 19:32:19 +0100 | [diff] [blame] | 135 | static char asanOpts[4096]; |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 136 | sanitizers_AddFlag(hfuzz, "ASAN_OPTIONS", asanOpts, sizeof(asanOpts)); |
Robert Swiecki | e2a05ed | 2018-01-10 19:32:19 +0100 | [diff] [blame] | 137 | static char ubsanOpts[4096]; |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 138 | sanitizers_AddFlag(hfuzz, "UBSAN_OPTIONS", ubsanOpts, sizeof(ubsanOpts)); |
Robert Swiecki | e2a05ed | 2018-01-10 19:32:19 +0100 | [diff] [blame] | 139 | static char msanOpts[4096]; |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 140 | sanitizers_AddFlag(hfuzz, "MSAN_OPTIONS", msanOpts, sizeof(msanOpts)); |
Robert Swiecki | e2a05ed | 2018-01-10 19:32:19 +0100 | [diff] [blame] | 141 | static char lsanOpts[4096]; |
Robert Swiecki | 97d8893 | 2018-01-10 19:29:34 +0100 | [diff] [blame] | 142 | sanitizers_AddFlag(hfuzz, "LSAN_OPTIONS", lsanOpts, sizeof(lsanOpts)); |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 143 | |
Anestis Bechtsoudis | e5f09f8 | 2016-12-27 16:06:05 +0200 | [diff] [blame] | 144 | return true; |
| 145 | } |