blob: f380077f2f7760f4a30162c83d6ed8ded0c715b9 [file] [log] [blame]
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +02001#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 Swiecki10eeb0a2017-09-28 15:42:52 +020013#include "libcommon/common.h"
Robert Swieckiec7b8452017-06-01 13:25:56 +020014#include "libcommon/files.h"
15#include "libcommon/log.h"
16#include "libcommon/util.h"
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020017
18/* Stringify */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020019#define XSTR(x) #x
20#define STR(x) XSTR(x)
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020021
22/*
Anestis Bechtsoudisc2722ee2017-01-29 09:40:03 +020023 * All clang sanitizers, except ASan, can be activated for target binaries
24 * with or without the matching runtime library (libcompiler_rt). If runtime
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020025 * libraries are included in target fuzzing environment, we can benefit from the
26 * various Die() callbacks and abort/exit logic manipulation. However, some
Anestis Bechtsoudisc2722ee2017-01-29 09:40:03 +020027 * setups (e.g. Android production ARM/ARM64 devices) enable sanitizers, such as
28 * UBSan, without the runtime libraries. As such, their default ftrap is activated
29 * which is for most cases a SIGABRT. For these cases end-user needs to enable
30 * SIGABRT monitoring flag, otherwise these crashes will be missed.
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020031 *
Anestis Bechtsoudisc2722ee2017-01-29 09:40:03 +020032 * Normally SIGABRT is not a wanted signal to monitor for Android, since it produces
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020033 * lots of useless crashes due to way Android process termination hacks work. As
34 * a result the sanitizer's 'abort_on_error' flag cannot be utilized since it
35 * invokes abort() internally. In order to not lose crashes a custom exitcode can
36 * be registered and monitored. Since exitcode is a global flag, it's assumed
37 * that target is compiled with only one sanitizer type enabled at a time.
38 *
Anestis Bechtsoudisc2722ee2017-01-29 09:40:03 +020039 * For cases where clang runtime library linking is not an option, SIGABRT should
40 * be monitored even for noisy targets, such as the Android OS, since no viable
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020041 * alternative exists.
Anestis Bechtsoudis523fccb2016-12-28 12:11:13 +020042 *
43 * There might be cases where ASan instrumented targets crash while generating
44 * reports for detected errors (inside __asan_report_error() proc). Under such
45 * scenarios target fails to exit or SIGABRT (AsanDie() proc) as defined in
46 * ASAN_OPTIONS flags, leaving garbage logs. An attempt is made to parse such
47 * logs for cases where enough data are written to identify potentially missed
48 * crashes. If ASan internal error results into a SIGSEGV being raised, it
49 * will get caught from ptrace API, handling the discovered ASan internal crash.
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020050 */
51
52/* 'log_path' output directory for sanitizer reports */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020053#define kSANLOGDIR "log_path="
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020054
55/* 'coverage_dir' output directory for coverage data files is set dynamically */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020056#define kSANCOVDIR "coverage_dir="
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020057
58/* Raise SIGABRT on error or continue with exitcode logic */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020059#define kABORT_ENABLED "abort_on_error=1"
60#define kABORT_DISABLED "abort_on_error=0"
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020061
62/*
63 * Common sanitizer flags
64 *
65 * symbolize: Disable symbolication since it changes logs (which are parsed) format
66 */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020067#define kSAN_COMMON "symbolize=0"
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020068
69/* --{ ASan }-- */
70/*
71 *Sanitizer specific flags (notice that if enabled 'abort_on_error' has priority
72 * over exitcode')
73 */
Robert Swieckid50ed422017-11-13 23:32:26 +010074#define kASAN_COMMON_OPTS \
75 "allow_user_segv_handler=1:" \
76 "handle_segv=0:" \
Robert Swiecki0b566112017-10-17 17:39:07 +020077 "allocator_may_return_null=1:" kSAN_COMMON ":exitcode=" STR(HF_SAN_EXIT_CODE)
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020078/* Platform specific flags */
79#if defined(__ANDROID__)
80/*
81 * start_deactivated: Enable on Android to reduce memory usage (useful when not all
82 * target's DSOs are compiled with sanitizer enabled
83 */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020084#define kASAN_OPTS kASAN_COMMON_OPTS ":start_deactivated=1"
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020085#else
Robert Swieckid0fa62c2017-09-28 18:11:05 +020086#define kASAN_OPTS kASAN_COMMON_OPTS
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020087#endif
88
89/* --{ UBSan }-- */
Robert Swieckid0fa62c2017-09-28 18:11:05 +020090#define kUBSAN_OPTS kSAN_COMMON ":exitcode=" STR(HF_SAN_EXIT_CODE)
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020091
92/* --{ MSan }-- */
Robert Swieckid50ed422017-11-13 23:32:26 +010093#define kMSAN_OPTS \
Robert Swiecki0b566112017-10-17 17:39:07 +020094 kSAN_COMMON ":exit_code=" STR(HF_SAN_EXIT_CODE) ":" \
95 "wrap_signals=0:print_stats=1"
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +020096
Robert Swieckib4e13c02017-02-10 03:59:40 +010097/* If no sanitzer support was requested, simply make it use abort() on errors */
Robert Swieckid50ed422017-11-13 23:32:26 +010098#define kSAN_REGULAR \
99 "abort_on_error=1:handle_segv=0:handle_sigbus=0:handle_abort=0:" \
100 "handle_sigill=0:handle_sigfpe=0:allocator_may_return_null=1:" \
Robert Swiecki0b566112017-10-17 17:39:07 +0200101 "symbolize=1:detect_leaks=0:disable_coredump=0:log_path=stderr"
Robert Swieckib4e13c02017-02-10 03:59:40 +0100102
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200103/*
104 * If the program ends with a signal that ASan does not handle (or can not
105 * handle at all, like SIGKILL), coverage data will be lost. This is a big
106 * problem on Android, where SIGKILL is a normal way of evicting applications
107 * from memory. With 'coverage_direct=1' coverage data is written to a
108 * memory-mapped file as soon as it collected. Non-Android targets can disable
109 * coverage direct when more coverage data collection methods are implemented.
110 */
Robert Swieckid0fa62c2017-09-28 18:11:05 +0200111#define kSAN_COV_OPTS "coverage=1:coverage_direct=1"
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200112
Robert Swieckid50ed422017-11-13 23:32:26 +0100113static bool sanitizers_Regular(void) {
Robert Swieckib7362632017-02-10 14:40:11 +0100114 if (setenv("ASAN_OPTIONS", kSAN_REGULAR, 1) == -1) {
Robert Swieckif29ec742017-02-10 14:47:36 +0100115 PLOG_E("setenv(ASAN_OPTIONS=%s", kSAN_REGULAR);
116 return false;
Robert Swieckib7362632017-02-10 14:40:11 +0100117 }
118 if (setenv("MSAN_OPTIONS", kSAN_REGULAR, 1) == -1) {
Robert Swieckif29ec742017-02-10 14:47:36 +0100119 PLOG_E("setenv(MSAN_OPTIONS=%s", kSAN_REGULAR);
120 return false;
Robert Swieckib7362632017-02-10 14:40:11 +0100121 }
122 if (setenv("UBSAN_OPTIONS", kSAN_REGULAR, 1) == -1) {
Robert Swieckif29ec742017-02-10 14:47:36 +0100123 PLOG_E("setenv(UBSAN_OPTIONS=%s", kSAN_REGULAR);
124 return false;
Robert Swieckib7362632017-02-10 14:40:11 +0100125 }
126 return true;
Robert Swieckib4e13c02017-02-10 03:59:40 +0100127}
128
Robert Swieckid50ed422017-11-13 23:32:26 +0100129bool sanitizers_Init(honggfuzz_t* hfuzz) {
Robert Swieckib4e13c02017-02-10 03:59:40 +0100130 if (hfuzz->linux.pid > 0) {
131 return true;
132 }
133
134 if (hfuzz->enableSanitizers == false) {
Robert Swieckib7362632017-02-10 14:40:11 +0100135 return sanitizers_Regular();
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200136 }
137
138 /* Set sanitizer flags once to avoid performance overhead per worker spawn */
139 size_t flagsSz = 0;
140
141 /* Larger constant combination + 2 dynamic paths */
Robert Swieckid50ed422017-11-13 23:32:26 +0100142 size_t bufSz = sizeof(kASAN_OPTS) + 1 + sizeof(kABORT_ENABLED) + 1 + sizeof(kSANLOGDIR) +
143 PATH_MAX + 1 + sizeof(kSANCOVDIR) + PATH_MAX + 1;
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200144 char* san_opts = util_Calloc(bufSz);
Robert Swiecki0b566112017-10-17 17:39:07 +0200145 defer { free(san_opts); };
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200146
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200147 char* abortFlag;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200148 if (hfuzz->monitorSIGABRT) {
149 abortFlag = kABORT_ENABLED;
150 } else {
151 abortFlag = kABORT_DISABLED;
152 }
153
Anestis Bechtsoudis523fccb2016-12-28 12:11:13 +0200154 /* Address Sanitizer (ASan) */
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200155 if (hfuzz->useSanCov) {
156 snprintf(san_opts, bufSz, "%s:%s:%s:%s%s/%s:%s%s/%s", kASAN_OPTS, abortFlag, kSAN_COV_OPTS,
Robert Swiecki82c707c2017-11-14 16:36:23 +0100157 kSANCOVDIR, hfuzz->io.workDir, _HF_SANCOV_DIR, kSANLOGDIR, hfuzz->io.workDir,
158 kLOGPREFIX);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200159 } else {
160 snprintf(san_opts, bufSz, "%s:%s:%s%s/%s", kASAN_OPTS, abortFlag, kSANLOGDIR,
Robert Swiecki82c707c2017-11-14 16:36:23 +0100161 hfuzz->io.workDir, kLOGPREFIX);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200162 }
163
164 flagsSz = strlen(san_opts) + 1;
165 hfuzz->sanOpts.asanOpts = util_Calloc(flagsSz);
166 memcpy(hfuzz->sanOpts.asanOpts, san_opts, flagsSz);
167 LOG_D("ASAN_OPTIONS=%s", hfuzz->sanOpts.asanOpts);
168
Anestis Bechtsoudis523fccb2016-12-28 12:11:13 +0200169 /* Undefined Behavior Sanitizer (UBSan) */
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200170 memset(san_opts, 0, bufSz);
171 if (hfuzz->useSanCov) {
172 snprintf(san_opts, bufSz, "%s:%s:%s:%s%s/%s:%s%s/%s", kUBSAN_OPTS, abortFlag, kSAN_COV_OPTS,
Robert Swiecki82c707c2017-11-14 16:36:23 +0100173 kSANCOVDIR, hfuzz->io.workDir, _HF_SANCOV_DIR, kSANLOGDIR, hfuzz->io.workDir,
174 kLOGPREFIX);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200175 } else {
176 snprintf(san_opts, bufSz, "%s:%s:%s%s/%s", kUBSAN_OPTS, abortFlag, kSANLOGDIR,
Robert Swiecki82c707c2017-11-14 16:36:23 +0100177 hfuzz->io.workDir, kLOGPREFIX);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200178 }
179
180 flagsSz = strlen(san_opts) + 1;
181 hfuzz->sanOpts.ubsanOpts = util_Calloc(flagsSz);
182 memcpy(hfuzz->sanOpts.ubsanOpts, san_opts, flagsSz);
183 LOG_D("UBSAN_OPTIONS=%s", hfuzz->sanOpts.ubsanOpts);
184
Anestis Bechtsoudis523fccb2016-12-28 12:11:13 +0200185 /* Memory Sanitizer (MSan) */
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200186 memset(san_opts, 0, bufSz);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200187
188 if (hfuzz->useSanCov) {
Robert Swiecki618dc2f2017-07-04 03:07:05 +0200189 snprintf(san_opts, bufSz, "%s:%s:%s:%s%s/%s:%s%s/%s", kMSAN_OPTS, abortFlag, kSAN_COV_OPTS,
Robert Swiecki82c707c2017-11-14 16:36:23 +0100190 kSANCOVDIR, hfuzz->io.workDir, _HF_SANCOV_DIR, kSANLOGDIR, hfuzz->io.workDir,
191 kLOGPREFIX);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200192 } else {
Robert Swiecki618dc2f2017-07-04 03:07:05 +0200193 snprintf(san_opts, bufSz, "%s:%s:%s%s/%s", kMSAN_OPTS, abortFlag, kSANLOGDIR,
Robert Swiecki82c707c2017-11-14 16:36:23 +0100194 hfuzz->io.workDir, kLOGPREFIX);
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200195 }
196
197 flagsSz = strlen(san_opts) + 1;
198 hfuzz->sanOpts.msanOpts = util_Calloc(flagsSz);
199 memcpy(hfuzz->sanOpts.msanOpts, san_opts, flagsSz);
200 LOG_D("MSAN_OPTIONS=%s", hfuzz->sanOpts.msanOpts);
201
202 return true;
203}
204
Robert Swieckid50ed422017-11-13 23:32:26 +0100205bool sanitizers_prepareExecve(run_t* run) {
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200206 /* Address Sanitizer (ASan) */
Robert Swiecki78633d12017-11-13 23:24:55 +0100207 if (run->global->sanOpts.asanOpts) {
208 if (setenv("ASAN_OPTIONS", run->global->sanOpts.asanOpts, 1) == -1) {
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200209 PLOG_E("setenv(ASAN_OPTIONS) failed");
210 return false;
211 }
212 }
213
214 /* Memory Sanitizer (MSan) */
Robert Swiecki78633d12017-11-13 23:24:55 +0100215 if (run->global->sanOpts.msanOpts) {
216 if (setenv("MSAN_OPTIONS", run->global->sanOpts.msanOpts, 1) == -1) {
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200217 PLOG_E("setenv(MSAN_OPTIONS) failed");
218 return false;
219 }
220 }
221
222 /* Undefined Behavior Sanitizer (UBSan) */
Robert Swiecki78633d12017-11-13 23:24:55 +0100223 if (run->global->sanOpts.ubsanOpts) {
224 if (setenv("UBSAN_OPTIONS", run->global->sanOpts.ubsanOpts, 1) == -1) {
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200225 PLOG_E("setenv(UBSAN_OPTIONS) failed");
226 return false;
227 }
228 }
229
230 return true;
231}