blob: 98878c15f05f6a6169440fd41117e38efc183897 [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +00003 * honggfuzz - fuzzing routines
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com8531f692015-02-17 12:25:36 +00006 * Author:
7 * Robert Swiecki <swiecki@google.com>
8 * Felix Gröbert <groebert@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000010 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000011 *
12 * Licensed under the Apache License, Version 2.0 (the "License"); you may
13 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000017 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000018 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
21 * implied. See the License for the specific language governing
22 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000023 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000024 */
robert.swiecki3bb518c2010-10-14 00:48:24 +000025
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000026#include "fuzz.h"
27
28#include <errno.h>
29#include <fcntl.h>
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +000030#include <inttypes.h>
Robert Swiecki2af83ec2017-06-05 23:54:22 +020031#include <libgen.h>
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +000032#include <pthread.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000033#include <signal.h>
34#include <stddef.h>
35#include <stdint.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
Robert Swiecki10eeb0a2017-09-28 15:42:52 +020039#include <sys/mman.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000040#include <sys/param.h>
41#include <sys/stat.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000042#include <sys/time.h>
43#include <sys/types.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000044#include <time.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000045#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000046
Robert Swieckid0fa62c2017-09-28 18:11:05 +020047#include "arch.h"
48#include "honggfuzz.h"
49#include "input.h"
Robert Swiecki10eeb0a2017-09-28 15:42:52 +020050#include "libcommon/common.h"
Robert Swiecki241a7412017-05-24 01:53:15 +020051#include "libcommon/files.h"
52#include "libcommon/log.h"
Robert Swiecki241a7412017-05-24 01:53:15 +020053#include "libcommon/util.h"
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +000054#include "mangle.h"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000055#include "report.h"
Robert Swieckiec7b8452017-06-01 13:25:56 +020056#include "sancov.h"
57#include "sanitizers.h"
Robert Swiecki2d016902017-05-24 02:12:30 +020058#include "subproc.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000059
Robert Swiecki0dde76d2017-11-16 19:25:44 +010060static time_t termTimeStamp = 0;
61
62bool fuzz_isTerminating(void) {
63 if (ATOMIC_GET(termTimeStamp) != 0) {
Robert Swiecki35978ac2017-11-16 18:00:53 +010064 return true;
65 }
66 return false;
67}
68
Robert Swiecki0dde76d2017-11-16 19:25:44 +010069void fuzz_setTerminating(void) {
70 if (ATOMIC_GET(termTimeStamp) != 0) {
Robert Swiecki35978ac2017-11-16 18:00:53 +010071 return;
72 }
Robert Swiecki0dde76d2017-11-16 19:25:44 +010073 ATOMIC_SET(termTimeStamp, time(NULL));
74}
75
76bool fuzz_shouldTerminate() {
77 if (ATOMIC_GET(termTimeStamp) == 0) {
78 return false;
79 }
80 if ((time(NULL) - ATOMIC_GET(termTimeStamp)) > 5) {
81 return true;
82 }
83 return false;
Robert Swiecki35978ac2017-11-16 18:00:53 +010084}
85
Robert Swieckid50ed422017-11-13 23:32:26 +010086static void fuzz_getFileName(run_t* run) {
Robert Swiecki97d0cee2017-12-18 00:17:50 +010087 char bname[PATH_MAX];
88 snprintf(bname, sizeof(bname), "%s", run->global->exe.cmdline[0]);
Robert Swiecki82c707c2017-11-14 16:36:23 +010089 snprintf(run->fileName, PATH_MAX, "%s/honggfuzz.input.%" PRIu32 ".%s.%s",
Robert Swiecki97d0cee2017-12-18 00:17:50 +010090 run->global->io.workDir, run->fuzzNo, basename(bname), run->global->io.fileExtn);
robert.swiecki3bb518c2010-10-14 00:48:24 +000091}
92
Robert Swieckid50ed422017-11-13 23:32:26 +010093static bool fuzz_prepareFileDynamically(run_t* run) {
Robert Swieckie7294ca2017-11-11 02:46:32 +010094 run->origFileName = "[DYNAMIC]";
Robert Swieckia08ab1c2016-03-14 18:29:21 +010095
96 {
Robert Swiecki78633d12017-11-13 23:24:55 +010097 MX_SCOPED_RWLOCK_READ(&run->global->dynfileq_mutex);
Robert Swiecki4b0390a2016-03-14 18:44:05 +010098
Robert Swiecki78633d12017-11-13 23:24:55 +010099 if (run->global->dynfileqCnt == 0) {
Robert Swieckid50ed422017-11-13 23:32:26 +0100100 LOG_F(
101 "The dynamic file corpus is empty. Apparently, the initial fuzzing of the "
102 "provided file corpus (-f) has not produced any follow-up files with positive "
103 "coverage and/or CPU counters");
Jaggerb070b812016-03-15 05:31:30 +0100104 }
105
Robert Swieckie7294ca2017-11-11 02:46:32 +0100106 if (run->dynfileqCurrent == NULL) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100107 run->dynfileqCurrent = TAILQ_FIRST(&run->global->dynfileq);
Robert Swiecki3db34292017-11-09 14:13:21 +0100108 } else {
Robert Swiecki78633d12017-11-13 23:24:55 +0100109 if (run->dynfileqCurrent == TAILQ_LAST(&run->global->dynfileq, dyns_t)) {
110 run->dynfileqCurrent = TAILQ_FIRST(&run->global->dynfileq);
Robert Swiecki3db34292017-11-09 14:13:21 +0100111 } else {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100112 run->dynfileqCurrent = TAILQ_NEXT(run->dynfileqCurrent, pointers);
Robert Swiecki3db34292017-11-09 14:13:21 +0100113 }
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100114 }
115 }
116
Robert Swieckie7294ca2017-11-11 02:46:32 +0100117 memcpy(run->dynamicFile, run->dynfileqCurrent->data, run->dynfileqCurrent->size);
118 run->dynamicFileSz = run->dynfileqCurrent->size;
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100119
Robert Swiecki78633d12017-11-13 23:24:55 +0100120 mangle_mangleContent(run);
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000121
Robert Swieckid50ed422017-11-13 23:32:26 +0100122 if (run->global->persistent == false &&
123 files_writeBufToFile(run->fileName, run->dynamicFile, run->dynamicFileSz,
124 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC) == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100125 LOG_E("Couldn't write buffer to file '%s'", run->fileName);
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +0000126 return false;
127 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000128
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000129 return true;
robert.swiecki@gmail.comd7aed312015-02-03 21:26:37 +0000130}
131
Robert Swieckid50ed422017-11-13 23:32:26 +0100132static bool fuzz_prepareFile(run_t* run, bool rewind) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100133 char fname[PATH_MAX];
Robert Swiecki78633d12017-11-13 23:24:55 +0100134 if (input_getNext(run, fname, rewind) == false) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100135 return false;
136 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100137 run->origFileName = files_basename(fname);
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200138
Robert Swiecki78633d12017-11-13 23:24:55 +0100139 ssize_t fileSz = files_readFileToBufMax(fname, run->dynamicFile, run->global->maxFileSz);
Jagger1aa94d72016-04-02 02:37:35 +0200140 if (fileSz < 0) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100141 LOG_E("Couldn't read contents of '%s'", fname);
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000142 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000143 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100144 run->dynamicFileSz = fileSz;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000145
Robert Swiecki78633d12017-11-13 23:24:55 +0100146 mangle_mangleContent(run);
robert.swiecki@gmail.comc070b942015-02-25 18:29:19 +0000147
Robert Swieckid50ed422017-11-13 23:32:26 +0100148 if (run->global->persistent == false &&
149 files_writeBufToFile(run->fileName, run->dynamicFile, run->dynamicFileSz,
150 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC) == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100151 LOG_E("Couldn't write buffer to file '%s'", run->fileName);
robert.swiecki@gmail.come7680522015-02-22 22:22:37 +0000152 return false;
153 }
154
robert.swiecki3bb518c2010-10-14 00:48:24 +0000155 return true;
156}
157
Robert Swieckid50ed422017-11-13 23:32:26 +0100158static bool fuzz_prepareFileExternally(run_t* run) {
Robert Swieckic1deec82017-04-27 02:42:12 +0200159 char fname[PATH_MAX];
Robert Swiecki78633d12017-11-13 23:24:55 +0100160 if (input_getNext(run, fname, true /* rewind */)) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100161 run->origFileName = files_basename(fname);
162 if (files_copyFile(fname, run->fileName, NULL, false /* try_link */) == false) {
163 LOG_E("files_copyFile('%s', '%s')", fname, run->fileName);
Robert Swieckic1deec82017-04-27 02:42:12 +0200164 return false;
165 }
Robert Swiecki87ca2112017-04-27 12:03:53 +0200166 } else {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100167 run->origFileName = "[EXTERNAL]";
168 int dstfd = open(run->fileName, O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644);
Robert Swiecki87ca2112017-04-27 12:03:53 +0200169 if (dstfd == -1) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100170 PLOG_E("Couldn't create a temporary file '%s'", run->fileName);
Robert Swiecki87ca2112017-04-27 12:03:53 +0200171 return false;
172 }
173 close(dstfd);
Robert Swieckic1deec82017-04-27 02:42:12 +0200174 }
175
Robert Swieckie7294ca2017-11-11 02:46:32 +0100176 LOG_D("Created '%s' as an input file", run->fileName);
robert.swiecki3d505e22010-10-14 01:17:17 +0000177
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100178 const char* const argv[] = {run->global->exe.externalCommand, run->fileName, NULL};
Robert Swiecki78633d12017-11-13 23:24:55 +0100179 if (subproc_System(run, argv) != 0) {
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100180 LOG_E("Subprocess '%s' returned abnormally", run->global->exe.externalCommand);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000181 return false;
182 }
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100183 LOG_D("Subporcess '%s' finished with success", run->global->exe.externalCommand);
Jagger1d743382016-04-02 02:09:41 +0200184
Robert Swiecki78633d12017-11-13 23:24:55 +0100185 ssize_t rsz = files_readFileToBufMax(run->fileName, run->dynamicFile, run->global->maxFileSz);
Jagger1aa94d72016-04-02 02:37:35 +0200186 if (rsz < 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100187 LOG_W("Couldn't read back '%s' to the buffer", run->fileName);
Jagger1d743382016-04-02 02:09:41 +0200188 return false;
189 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100190 run->dynamicFileSz = rsz;
Jagger1d743382016-04-02 02:09:41 +0200191
Robert Swiecki78633d12017-11-13 23:24:55 +0100192 if (run->global->persistent) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100193 unlink(run->fileName);
Jagger1d743382016-04-02 02:09:41 +0200194 }
195
196 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000197}
198
Robert Swieckid50ed422017-11-13 23:32:26 +0100199static bool fuzz_postProcessFile(run_t* run) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100200 if (run->global->persistent) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100201 if (files_writeBufToFile(run->fileName, run->dynamicFile, run->dynamicFileSz,
Robert Swieckid50ed422017-11-13 23:32:26 +0100202 O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC) == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100203 LOG_E("Couldn't write file to '%s'", run->fileName);
Robert Swieckicc88f932017-07-07 00:13:00 +0200204 return false;
205 }
Robert Swieckiee266ac2016-10-03 02:25:59 +0200206 }
207
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100208 const char* const argv[] = {run->global->exe.postExternalCommand, run->fileName, NULL};
Robert Swiecki78633d12017-11-13 23:24:55 +0100209 if (subproc_System(run, argv) != 0) {
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100210 LOG_E("Subprocess '%s' returned abnormally", run->global->exe.postExternalCommand);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200211 return false;
212 }
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100213 LOG_D("Subporcess '%s' finished with success", run->global->exe.externalCommand);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200214
Robert Swiecki78633d12017-11-13 23:24:55 +0100215 ssize_t rsz = files_readFileToBufMax(run->fileName, run->dynamicFile, run->global->maxFileSz);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200216 if (rsz < 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100217 LOG_W("Couldn't read back '%s' to the buffer", run->fileName);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200218 return false;
219 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100220 run->dynamicFileSz = rsz;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200221
222 return true;
223}
224
Robert Swiecki0b566112017-10-17 17:39:07 +0200225static fuzzState_t fuzz_getState(honggfuzz_t* hfuzz) { return ATOMIC_GET(hfuzz->state); }
Robert Swieckia7841da2017-02-24 17:27:06 +0100226
Robert Swieckid50ed422017-11-13 23:32:26 +0100227static void fuzz_setState(honggfuzz_t* hfuzz, fuzzState_t state) {
Robert Swiecki3915a812017-02-25 02:07:56 +0100228 /* All threads must indicate willingness to switch to _HF_STATE_DYNAMIC_MAIN */
229 if (state == _HF_STATE_DYNAMIC_MAIN) {
230 static size_t cnt = 0;
231 ATOMIC_PRE_INC(cnt);
Robert Swiecki66b65122017-11-11 02:55:55 +0100232 while (ATOMIC_GET(cnt) < hfuzz->threads.threadsMax) {
Robert Swiecki0dde76d2017-11-16 19:25:44 +0100233 if (fuzz_isTerminating()) {
Robert Swiecki1a994732017-05-31 18:32:21 +0200234 return;
235 }
Robert Swiecki3915a812017-02-25 02:07:56 +0100236 sleep(1);
237 }
238 }
239
Robert Swieckia7841da2017-02-24 17:27:06 +0100240 static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
241 MX_SCOPED_LOCK(&state_mutex);
242
243 if (hfuzz->state == state) {
244 return;
245 }
246
247 switch (state) {
Robert Swieckid50ed422017-11-13 23:32:26 +0100248 case _HF_STATE_DYNAMIC_PRE:
249 LOG_I("Entering phase 1/2: Dry Run");
250 break;
251 case _HF_STATE_DYNAMIC_MAIN:
252 LOG_I("Entering phase 2/2: Main");
253 break;
254 case _HF_STATE_STATIC:
255 LOG_I("Entering phase: Static");
256 break;
257 default:
258 LOG_I("Entering unknown phase: %d", state);
259 break;
Robert Swieckia7841da2017-02-24 17:27:06 +0100260 }
261
262 ATOMIC_SET(hfuzz->state, state);
263}
264
Robert Swieckid50ed422017-11-13 23:32:26 +0100265static bool fuzz_runVerifier(run_t* crashedFuzzer) {
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300266 int crashFd = -1;
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200267 uint8_t* crashBuf = NULL;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300268 off_t crashFileSz = 0;
269
270 crashBuf = files_mapFile(crashedFuzzer->crashFileName, &crashFileSz, &crashFd, false);
271 if (crashBuf == NULL) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700272 LOG_E("Couldn't open and map '%s' in R/O mode", crashedFuzzer->crashFileName);
Robert Swieckie48811e2016-03-09 18:31:19 +0100273 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300274 }
Robert Swieckid50ed422017-11-13 23:32:26 +0100275 defer {
Jagger4fe18692016-04-22 23:15:07 +0200276 munmap(crashBuf, crashFileSz);
Jagger4fe18692016-04-22 23:15:07 +0200277 close(crashFd);
278 };
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300279
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700280 LOG_I("Launching verifier for %" PRIx64 " hash", crashedFuzzer->backtrace);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300281 for (int i = 0; i < _HF_VERIFIER_ITER; i++) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100282 run_t vFuzzer = {
Robert Swieckid50ed422017-11-13 23:32:26 +0100283 .global = crashedFuzzer->global,
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300284 .pid = 0,
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300285 .persistentPid = 0,
Robert Swiecki78633d12017-11-13 23:24:55 +0100286 .state = fuzz_getState(crashedFuzzer->global),
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300287 .timeStartedMillis = util_timeNowMillis(),
Robert Swieckid50ed422017-11-13 23:32:26 +0100288 .crashFileName = {0},
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300289 .pc = 0ULL,
290 .backtrace = 0ULL,
291 .access = 0ULL,
292 .exception = 0,
Robert Swieckibf8f8cc2017-11-09 00:42:50 +0100293 .dynfileqCurrent = NULL,
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300294 .dynamicFileSz = 0,
295 .dynamicFile = NULL,
Robert Swieckid50ed422017-11-13 23:32:26 +0100296 .sanCovCnts =
297 {
298 .hitBBCnt = 0ULL,
299 .totalBBCnt = 0ULL,
300 .dsoCnt = 0ULL,
301 .iDsoCnt = 0ULL,
302 .newBBCnt = 0ULL,
303 .crashesCnt = 0ULL,
304 },
305 .report = {'\0'},
Jaggerb2c1fad2016-03-17 23:37:10 +0100306 .mainWorker = false,
Jaggerfa3544a2016-08-30 02:55:55 +0200307 .fuzzNo = crashedFuzzer->fuzzNo,
Jagger93253f72016-09-01 22:40:12 +0200308 .persistentSock = -1,
Robert Swiecki013bc9c2016-12-12 17:31:06 +0100309 .tmOutSignaled = false,
Jaggerb2c1fad2016-03-17 23:37:10 +0100310
Robert Swieckid50ed422017-11-13 23:32:26 +0100311 .linux =
312 {
313 .hwCnts =
314 {
315 .cpuInstrCnt = 0ULL,
316 .cpuBranchCnt = 0ULL,
317 .bbCnt = 0ULL,
318 .newBBCnt = 0ULL,
319 .softCntPc = 0ULL,
320 .softCntEdge = 0ULL,
321 .softCntCmp = 0ULL,
322 },
323 .attachedPid = 0,
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200324 },
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300325 };
326
Robert Swiecki78633d12017-11-13 23:24:55 +0100327 if (arch_archThreadInit(&vFuzzer) == false) {
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300328 LOG_F("Could not initialize the thread");
329 }
330
Robert Swiecki78633d12017-11-13 23:24:55 +0100331 fuzz_getFileName(&vFuzzer);
Robert Swieckid50ed422017-11-13 23:32:26 +0100332 if (files_writeBufToFile(vFuzzer.fileName, crashBuf, crashFileSz,
333 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC) == false) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700334 LOG_E("Couldn't write buffer to file '%s'", vFuzzer.fileName);
Robert Swieckie48811e2016-03-09 18:31:19 +0100335 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300336 }
337
Robert Swiecki78633d12017-11-13 23:24:55 +0100338 if (subproc_Run(&vFuzzer) == false) {
Robert Swiecki940a0802016-11-02 12:42:09 +0100339 LOG_F("subproc_Run()");
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300340 }
Robert Swieckia8b8cb82016-08-17 18:27:08 +0200341
Anestis Bechtsoudis2b2a63b2016-12-28 15:34:40 +0200342 /* Delete intermediate files generated from verifier */
343 unlink(vFuzzer.fileName);
344
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300345 /* If stack hash doesn't match skip name tag and exit */
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300346 if (crashedFuzzer->backtrace != vFuzzer.backtrace) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700347 LOG_D("Verifier stack hash mismatch");
Robert Swieckie48811e2016-03-09 18:31:19 +0100348 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300349 }
350 }
351
352 /* Workspace is inherited, just append a extra suffix */
Robert Swieckid50ed422017-11-13 23:32:26 +0100353 char verFile[PATH_MAX] = {0};
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300354 snprintf(verFile, sizeof(verFile), "%s.verified", crashedFuzzer->crashFileName);
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300355
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200356 /* Copy file with new suffix & remove original copy */
357 bool dstFileExists = false;
Robert Swiecki0b566112017-10-17 17:39:07 +0200358 if (files_copyFile(
359 crashedFuzzer->crashFileName, verFile, &dstFileExists, true /* try_link */)) {
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200360 LOG_I("Successfully verified, saving as (%s)", verFile);
Robert Swiecki2542dc02017-11-14 03:35:59 +0100361 ATOMIC_POST_INC(crashedFuzzer->global->cnts.verifiedCrashesCnt);
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200362 unlink(crashedFuzzer->crashFileName);
363 } else {
364 if (dstFileExists) {
365 LOG_I("It seems that '%s' already exists, skipping", verFile);
366 } else {
367 LOG_E("Couldn't copy '%s' to '%s'", crashedFuzzer->crashFileName, verFile);
Robert Swieckie48811e2016-03-09 18:31:19 +0100368 return false;
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200369 }
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300370 }
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300371
Robert Swieckie48811e2016-03-09 18:31:19 +0100372 return true;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300373}
374
Robert Swieckiced3eba2017-12-15 15:33:03 +0100375static bool fuzz_writeCovFile(const char* dir, const uint8_t* data, size_t len) {
376 char fname[PATH_MAX];
377
378 uint64_t crc64f = util_CRC64(data, len);
379 uint64_t crc64r = util_CRC64Rev(data, len);
380 snprintf(fname, sizeof(fname), "%s/%016" PRIx64 "%016" PRIx64 ".%08" PRIx32 ".honggfuzz.cov",
381 dir, crc64f, crc64r, (uint32_t)len);
382
383 if (access(fname, R_OK) == 0) {
384 LOG_D("File '%s' already exists in the output corpus directory '%s'", fname, dir);
385 return true;
386 }
387
388 LOG_D("Adding file '%s' to the corpus directory '%s'", fname, dir);
389
390 if (files_writeBufToFile(fname, data, len, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC) ==
391 false) {
392 LOG_W("Couldn't write buffer to file '%s'", fname);
393 return false;
394 }
395
396 return true;
397}
398
Robert Swieckid50ed422017-11-13 23:32:26 +0100399static void fuzz_addFileToFileQ(run_t* run) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200400 struct dynfile_t* dynfile = (struct dynfile_t*)util_Malloc(sizeof(struct dynfile_t));
Robert Swieckie7294ca2017-11-11 02:46:32 +0100401 dynfile->size = run->dynamicFileSz;
402 dynfile->data = (uint8_t*)util_Malloc(run->dynamicFileSz);
403 memcpy(dynfile->data, run->dynamicFile, run->dynamicFileSz);
Robert Swiecki37498fd2017-03-12 21:12:54 +0100404
Robert Swiecki78633d12017-11-13 23:24:55 +0100405 MX_SCOPED_RWLOCK_WRITE(&run->global->dynfileq_mutex);
406 TAILQ_INSERT_TAIL(&run->global->dynfileq, dynfile, pointers);
407 run->global->dynfileqCnt++;
Robert Swieckif3534bb2016-03-14 18:55:10 +0100408
Robert Swieckiced3eba2017-12-15 15:33:03 +0100409 if (!fuzz_writeCovFile(run->global->io.covDirAll, run->dynamicFile, run->dynamicFileSz)) {
410 LOG_E("Couldn't save the coverage data to '%s'", run->global->io.covDirAll);
411 }
412
413 /* No need to add files to the new coverage dir, if this is just the dry-run phase */
414 if (run->state == _HF_STATE_DYNAMIC_PRE || run->global->io.covDirNew == NULL) {
Jagger3c7e7ce2016-09-25 16:05:19 +0200415 return;
416 }
417
Robert Swieckiced3eba2017-12-15 15:33:03 +0100418 if (!fuzz_writeCovFile(run->global->io.covDirNew, run->dynamicFile, run->dynamicFileSz)) {
419 LOG_E("Couldn't save the new coverage data to '%s'", run->global->io.covDirNew);
Robert Swieckif3534bb2016-03-14 18:55:10 +0100420 }
421}
422
Robert Swieckid50ed422017-11-13 23:32:26 +0100423static void fuzz_perfFeedback(run_t* run) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100424 if (run->global->skipFeedbackOnTimeout && run->tmOutSignaled) {
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100425 return;
426 }
427
Robert Swiecki0b566112017-10-17 17:39:07 +0200428 LOG_D("New file size: %zu, Perf feedback new/cur (instr,branch): %" PRIu64 "/%" PRIu64
429 "/%" PRIu64 "/%" PRIu64 ", BBcnt new/total: %" PRIu64 "/%" PRIu64,
Robert Swiecki78633d12017-11-13 23:24:55 +0100430 run->dynamicFileSz, run->linux.hwCnts.cpuInstrCnt, run->global->linux.hwCnts.cpuInstrCnt,
431 run->linux.hwCnts.cpuBranchCnt, run->global->linux.hwCnts.cpuBranchCnt,
432 run->linux.hwCnts.newBBCnt, run->global->linux.hwCnts.bbCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200433
Robert Swiecki78633d12017-11-13 23:24:55 +0100434 MX_SCOPED_LOCK(&run->global->feedback_mutex);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200435
Jagger34789a72016-09-08 00:36:09 +0200436 uint64_t softCntPc = 0UL;
Robert Swieckib27c8952017-05-23 23:38:04 +0200437 uint64_t softCntEdge = 0UL;
Jagger34789a72016-09-08 00:36:09 +0200438 uint64_t softCntCmp = 0UL;
Robert Swiecki78633d12017-11-13 23:24:55 +0100439 if (run->global->bbFd != -1) {
440 softCntPc = ATOMIC_GET(run->global->feedback->pidFeedbackPc[run->fuzzNo]);
441 ATOMIC_CLEAR(run->global->feedback->pidFeedbackPc[run->fuzzNo]);
442 softCntEdge = ATOMIC_GET(run->global->feedback->pidFeedbackEdge[run->fuzzNo]);
443 ATOMIC_CLEAR(run->global->feedback->pidFeedbackEdge[run->fuzzNo]);
444 softCntCmp = ATOMIC_GET(run->global->feedback->pidFeedbackCmp[run->fuzzNo]);
445 ATOMIC_CLEAR(run->global->feedback->pidFeedbackCmp[run->fuzzNo]);
Jagger251d0192016-08-24 00:54:04 +0200446 }
Jaggerb01aaae2016-08-20 03:35:38 +0200447
Robert Swiecki78633d12017-11-13 23:24:55 +0100448 int64_t diff0 = run->global->linux.hwCnts.cpuInstrCnt - run->linux.hwCnts.cpuInstrCnt;
449 int64_t diff1 = run->global->linux.hwCnts.cpuBranchCnt - run->linux.hwCnts.cpuBranchCnt;
Jagger302c2ea2016-09-07 03:54:43 +0200450
Jagger8d0002c2016-08-17 03:44:23 +0200451 /*
452 * Coverage is the primary counter, the rest is secondary, and taken into consideration only
453 * if the coverage counter has not been changed
454 */
Robert Swieckid50ed422017-11-13 23:32:26 +0100455 if (run->linux.hwCnts.newBBCnt > 0 || softCntPc > 0 || softCntEdge > 0 || softCntCmp > 0 ||
456 diff0 < 0 || diff1 < 0) {
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100457 if (diff0 < 0) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100458 run->global->linux.hwCnts.cpuInstrCnt = run->linux.hwCnts.cpuInstrCnt;
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100459 }
460 if (diff1 < 0) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100461 run->global->linux.hwCnts.cpuBranchCnt = run->linux.hwCnts.cpuBranchCnt;
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100462 }
Robert Swiecki78633d12017-11-13 23:24:55 +0100463 run->global->linux.hwCnts.bbCnt += run->linux.hwCnts.newBBCnt;
464 run->global->linux.hwCnts.softCntPc += softCntPc;
465 run->global->linux.hwCnts.softCntEdge += softCntEdge;
466 run->global->linux.hwCnts.softCntCmp += softCntCmp;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200467
Robert Swieckie60f3532017-12-17 20:25:20 +0100468 LOG_I("Size:%zu (i,b,hw,edge,ip,cmp): %" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64
Robert Swiecki0b566112017-10-17 17:39:07 +0200469 "/%" PRIu64 "/%" PRIu64 ", Tot:%" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64
470 "/%" PRIu64 "/%" PRIu64,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100471 run->dynamicFileSz, run->linux.hwCnts.cpuInstrCnt, run->linux.hwCnts.cpuBranchCnt,
Robert Swieckie60f3532017-12-17 20:25:20 +0100472 run->linux.hwCnts.newBBCnt, softCntEdge, softCntPc, softCntCmp,
Robert Swiecki78633d12017-11-13 23:24:55 +0100473 run->global->linux.hwCnts.cpuInstrCnt, run->global->linux.hwCnts.cpuBranchCnt,
Robert Swieckie60f3532017-12-17 20:25:20 +0100474 run->global->linux.hwCnts.bbCnt, run->global->linux.hwCnts.softCntEdge,
475 run->global->linux.hwCnts.softCntPc, run->global->linux.hwCnts.softCntCmp);
Jagger395df022016-08-21 01:13:25 +0200476
Robert Swiecki78633d12017-11-13 23:24:55 +0100477 fuzz_addFileToFileQ(run);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200478 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200479}
480
Robert Swieckid50ed422017-11-13 23:32:26 +0100481static void fuzz_sanCovFeedback(run_t* run) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100482 if (run->global->skipFeedbackOnTimeout && run->tmOutSignaled) {
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100483 return;
484 }
485
Robert Swiecki0b566112017-10-17 17:39:07 +0200486 LOG_D("File size (Best/New): %zu, SanCov feedback (bb,dso): Best: [%" PRIu64 ",%" PRIu64
487 "] / New: [%" PRIu64 ",%" PRIu64 "], newBBs:%" PRIu64,
Robert Swiecki78633d12017-11-13 23:24:55 +0100488 run->dynamicFileSz, run->global->sanCovCnts.hitBBCnt, run->global->sanCovCnts.iDsoCnt,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100489 run->sanCovCnts.hitBBCnt, run->sanCovCnts.iDsoCnt, run->sanCovCnts.newBBCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200490
Robert Swiecki78633d12017-11-13 23:24:55 +0100491 MX_SCOPED_LOCK(&run->global->feedback_mutex);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200492
Robert Swiecki78633d12017-11-13 23:24:55 +0100493 int64_t diff0 = run->global->linux.hwCnts.cpuInstrCnt - run->linux.hwCnts.cpuInstrCnt;
494 int64_t diff1 = run->global->linux.hwCnts.cpuBranchCnt - run->linux.hwCnts.cpuBranchCnt;
Jaggerd5738372016-08-17 20:12:15 +0200495
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200496 /*
497 * Keep mutated seed if:
Robert Swiecki142f9412016-03-14 19:22:01 +0100498 * a) Newly discovered (not met before) BBs
499 * b) More instrumented DSOs loaded
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100500 *
Anestis Bechtsoudisb78cf602016-01-07 13:10:50 +0200501 * TODO: (a) method can significantly assist to further improvements in interesting areas
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200502 * discovery if combined with seeds pool/queue support. If a runtime queue is maintained
503 * more interesting seeds can be saved between runs instead of instantly discarded
504 * based on current absolute elitism (only one mutated seed is promoted).
505 */
Jaggerd5738372016-08-17 20:12:15 +0200506
Robert Swieckid50ed422017-11-13 23:32:26 +0100507 bool newCov =
508 (run->sanCovCnts.newBBCnt > 0 || run->global->sanCovCnts.iDsoCnt < run->sanCovCnts.iDsoCnt);
Jaggerd5738372016-08-17 20:12:15 +0200509
Robert Swieckid158aac2016-11-01 23:14:12 +0100510 if (newCov || (diff0 < 0 || diff1 < 0)) {
Robert Swiecki0b566112017-10-17 17:39:07 +0200511 LOG_I("SanCov Update: fsize:%zu, newBBs:%" PRIu64 ", (Cur,New): %" PRIu64 "/%" PRIu64
512 ",%" PRIu64 "/%" PRIu64,
Robert Swiecki78633d12017-11-13 23:24:55 +0100513 run->dynamicFileSz, run->sanCovCnts.newBBCnt, run->global->sanCovCnts.hitBBCnt,
514 run->global->sanCovCnts.iDsoCnt, run->sanCovCnts.hitBBCnt, run->sanCovCnts.iDsoCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200515
Robert Swiecki78633d12017-11-13 23:24:55 +0100516 run->global->sanCovCnts.hitBBCnt += run->sanCovCnts.newBBCnt;
517 run->global->sanCovCnts.dsoCnt = run->sanCovCnts.dsoCnt;
518 run->global->sanCovCnts.iDsoCnt = run->sanCovCnts.iDsoCnt;
519 run->global->sanCovCnts.crashesCnt += run->sanCovCnts.crashesCnt;
520 run->global->sanCovCnts.newBBCnt = run->sanCovCnts.newBBCnt;
Anestis Bechtsoudisb78cf602016-01-07 13:10:50 +0200521
Robert Swiecki78633d12017-11-13 23:24:55 +0100522 if (run->global->sanCovCnts.totalBBCnt < run->sanCovCnts.totalBBCnt) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200523 /* Keep only the max value (for dlopen cases) to measure total target coverage */
Robert Swiecki78633d12017-11-13 23:24:55 +0100524 run->global->sanCovCnts.totalBBCnt = run->sanCovCnts.totalBBCnt;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200525 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200526
Robert Swiecki78633d12017-11-13 23:24:55 +0100527 run->global->linux.hwCnts.cpuInstrCnt = run->linux.hwCnts.cpuInstrCnt;
528 run->global->linux.hwCnts.cpuBranchCnt = run->linux.hwCnts.cpuBranchCnt;
Jaggerd5738372016-08-17 20:12:15 +0200529
Robert Swiecki78633d12017-11-13 23:24:55 +0100530 fuzz_addFileToFileQ(run);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200531 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200532}
533
Robert Swieckid50ed422017-11-13 23:32:26 +0100534static void fuzz_fuzzLoop(run_t* run) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100535 run->pid = 0;
536 run->timeStartedMillis = util_timeNowMillis();
Robert Swiecki78633d12017-11-13 23:24:55 +0100537 run->state = fuzz_getState(run->global);
Robert Swieckie7294ca2017-11-11 02:46:32 +0100538 run->crashFileName[0] = '\0';
539 run->pc = 0ULL;
540 run->backtrace = 0ULL;
541 run->access = 0ULL;
542 run->exception = 0;
543 run->report[0] = '\0';
544 run->mainWorker = true;
545 run->origFileName = "DYNAMIC";
Robert Swiecki78633d12017-11-13 23:24:55 +0100546 run->mutationsPerRun = run->global->mutationsPerRun;
Robert Swieckie7294ca2017-11-11 02:46:32 +0100547 run->dynamicFileSz = 0;
Robert Swieckia96d78d2016-03-14 16:50:50 +0100548
Robert Swieckie7294ca2017-11-11 02:46:32 +0100549 run->sanCovCnts.hitBBCnt = 0ULL;
550 run->sanCovCnts.totalBBCnt = 0ULL;
551 run->sanCovCnts.dsoCnt = 0ULL;
552 run->sanCovCnts.newBBCnt = 0ULL;
553 run->sanCovCnts.crashesCnt = 0ULL;
Robert Swieckia96d78d2016-03-14 16:50:50 +0100554
Robert Swieckie7294ca2017-11-11 02:46:32 +0100555 run->linux.hwCnts.cpuInstrCnt = 0ULL;
556 run->linux.hwCnts.cpuBranchCnt = 0ULL;
557 run->linux.hwCnts.bbCnt = 0ULL;
558 run->linux.hwCnts.newBBCnt = 0ULL;
Jagger190f0dc2015-09-05 16:41:22 +0200559
Robert Swieckie7294ca2017-11-11 02:46:32 +0100560 if (run->state == _HF_STATE_DYNAMIC_PRE) {
561 run->mutationsPerRun = 0U;
Robert Swiecki78633d12017-11-13 23:24:55 +0100562 if (fuzz_prepareFile(run, false /* rewind */) == false) {
563 fuzz_setState(run->global, _HF_STATE_DYNAMIC_MAIN);
564 run->state = fuzz_getState(run->global);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200565 }
Robert Swiecki92a31362017-02-24 16:21:40 +0100566 }
Robert Swiecki1a994732017-05-31 18:32:21 +0200567
Robert Swiecki0dde76d2017-11-16 19:25:44 +0100568 if (fuzz_isTerminating()) {
Robert Swiecki1a994732017-05-31 18:32:21 +0200569 return;
570 }
571
Robert Swieckie7294ca2017-11-11 02:46:32 +0100572 if (run->state == _HF_STATE_DYNAMIC_MAIN) {
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100573 if (run->global->exe.externalCommand) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100574 if (!fuzz_prepareFileExternally(run)) {
Robert Swieckicc88f932017-07-07 00:13:00 +0200575 LOG_F("fuzz_prepareFileExternally() failed");
576 }
Robert Swiecki78633d12017-11-13 23:24:55 +0100577 } else if (!fuzz_prepareFileDynamically(run)) {
Jagger1d8e0c62016-04-02 02:22:40 +0200578 LOG_F("fuzz_prepareFileDynamically() failed");
Robert Swieckia96d78d2016-03-14 16:50:50 +0100579 }
Robert Swieckicc88f932017-07-07 00:13:00 +0200580
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100581 if (run->global->exe.postExternalCommand) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100582 if (!fuzz_postProcessFile(run)) {
Robert Swieckicc88f932017-07-07 00:13:00 +0200583 LOG_F("fuzz_postProcessFile() failed");
584 }
585 }
Jagger190f0dc2015-09-05 16:41:22 +0200586 }
Robert Swieckicc88f932017-07-07 00:13:00 +0200587
Robert Swieckie7294ca2017-11-11 02:46:32 +0100588 if (run->state == _HF_STATE_STATIC) {
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100589 if (run->global->exe.externalCommand) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100590 if (!fuzz_prepareFileExternally(run)) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100591 LOG_F("fuzz_prepareFileExternally() failed");
592 }
593 } else {
Robert Swiecki78633d12017-11-13 23:24:55 +0100594 if (!fuzz_prepareFile(run, true /* rewind */)) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100595 LOG_F("fuzz_prepareFile() failed");
596 }
597 }
Robert Swieckiab2b8c92017-07-07 12:55:43 +0200598
Robert Swiecki97d0cee2017-12-18 00:17:50 +0100599 if (run->global->exe.postExternalCommand != NULL) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100600 if (!fuzz_postProcessFile(run)) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100601 LOG_F("fuzz_postProcessFile() failed");
602 }
Robert Swieckiee266ac2016-10-03 02:25:59 +0200603 }
604 }
605
Robert Swiecki78633d12017-11-13 23:24:55 +0100606 if (subproc_Run(run) == false) {
Robert Swiecki940a0802016-11-02 12:42:09 +0100607 LOG_F("subproc_Run()");
Jagger190f0dc2015-09-05 16:41:22 +0200608 }
609
Robert Swiecki78633d12017-11-13 23:24:55 +0100610 if (run->global->persistent == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100611 unlink(run->fileName);
Jaggera34b3022016-04-02 02:20:40 +0200612 }
Jagger190f0dc2015-09-05 16:41:22 +0200613
Robert Swiecki78633d12017-11-13 23:24:55 +0100614 if (run->global->dynFileMethod != _HF_DYNFILE_NONE) {
615 fuzz_perfFeedback(run);
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100616 }
Robert Swiecki78633d12017-11-13 23:24:55 +0100617 if (run->global->useSanCov) {
618 fuzz_sanCovFeedback(run);
Robert Swiecki0f937af2016-03-30 18:19:16 +0200619 }
Jagger190f0dc2015-09-05 16:41:22 +0200620
Robert Swiecki78633d12017-11-13 23:24:55 +0100621 if (run->global->useVerifier && (run->crashFileName[0] != 0) && run->backtrace) {
622 if (!fuzz_runVerifier(run)) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100623 LOG_I("Failed to verify %s", run->crashFileName);
Anestis Bechtsoudis3085f222015-09-27 18:35:26 +0300624 }
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300625 }
626
Robert Swiecki78633d12017-11-13 23:24:55 +0100627 report_Report(run);
Jagger190f0dc2015-09-05 16:41:22 +0200628}
629
Robert Swieckid50ed422017-11-13 23:32:26 +0100630static void* fuzz_threadNew(void* arg) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200631 honggfuzz_t* hfuzz = (honggfuzz_t*)arg;
Robert Swiecki66b65122017-11-11 02:55:55 +0100632 unsigned int fuzzNo = ATOMIC_POST_INC(hfuzz->threads.threadsActiveCnt);
Robert Swiecki0ec98112017-02-03 02:08:14 +0100633 LOG_I("Launched new fuzzing thread, no. #%" PRId32, fuzzNo);
Anestis Bechtsoudis02b99be2015-12-27 11:53:01 +0200634
Robert Swieckie7294ca2017-11-11 02:46:32 +0100635 run_t run = {
Robert Swiecki78633d12017-11-13 23:24:55 +0100636 .global = hfuzz,
Robert Swieckidecf14b2016-03-31 15:09:28 +0200637 .pid = 0,
638 .persistentPid = 0,
Robert Swieckibf8f8cc2017-11-09 00:42:50 +0100639 .dynfileqCurrent = NULL,
Robert Swiecki147d4672017-01-29 02:49:06 +0100640 .dynamicFile = util_Calloc(hfuzz->maxFileSz),
Jaggerfa3544a2016-08-30 02:55:55 +0200641 .fuzzNo = fuzzNo,
Jagger93253f72016-09-01 22:40:12 +0200642 .persistentSock = -1,
Robert Swiecki013bc9c2016-12-12 17:31:06 +0100643 .tmOutSignaled = false,
Robert Swiecki47f5de12017-03-28 03:25:55 +0200644 .fileName = "[UNSET]",
Robert Swiecki12800cd2016-03-31 15:38:10 +0200645
Robert Swieckib692f282016-08-25 16:21:08 +0200646 .linux.attachedPid = 0,
Robert Swieckidecf14b2016-03-31 15:09:28 +0200647 };
Robert Swieckie7294ca2017-11-11 02:46:32 +0100648 defer { free(run.dynamicFile); };
Robert Swiecki78633d12017-11-13 23:24:55 +0100649 fuzz_getFileName(&run);
Robert Swieckidecf14b2016-03-31 15:09:28 +0200650
Robert Swiecki78633d12017-11-13 23:24:55 +0100651 if (arch_archThreadInit(&run) == false) {
Robert Swiecki0f937af2016-03-30 18:19:16 +0200652 LOG_F("Could not initialize the thread");
653 }
654
Robert Swieckia96d78d2016-03-14 16:50:50 +0100655 for (;;) {
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200656 /* Check if dry run mode with verifier enabled */
Robert Swiecki78633d12017-11-13 23:24:55 +0100657 if (run.global->mutationsPerRun == 0U && run.global->useVerifier) {
Robert Swiecki82c707c2017-11-14 16:36:23 +0100658 if (ATOMIC_POST_INC(run.global->cnts.mutationsCnt) >= run.global->io.fileCnt) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100659 ATOMIC_POST_INC(run.global->threads.threadsFinished);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200660 break;
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200661 }
662 }
663 /* Check for max iterations limit if set */
Robert Swiecki2542dc02017-11-14 03:35:59 +0100664 else if ((ATOMIC_POST_INC(run.global->cnts.mutationsCnt) >= run.global->mutationsMax) &&
Robert Swieckid50ed422017-11-13 23:32:26 +0100665 run.global->mutationsMax) {
Robert Swiecki78633d12017-11-13 23:24:55 +0100666 ATOMIC_POST_INC(run.global->threads.threadsFinished);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200667 break;
Robert Swiecki8d01b012017-02-19 15:48:11 +0100668 }
669
Robert Swiecki78633d12017-11-13 23:24:55 +0100670 fuzz_fuzzLoop(&run);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200671
Robert Swiecki0dde76d2017-11-16 19:25:44 +0100672 if (fuzz_isTerminating()) {
Robert Swiecki069b48f2017-05-31 01:00:08 +0200673 break;
674 }
675
Robert Swiecki2542dc02017-11-14 03:35:59 +0100676 if (run.global->exitUponCrash && ATOMIC_GET(run.global->cnts.crashesCnt) > 0) {
Robert Swiecki069b48f2017-05-31 01:00:08 +0200677 LOG_I("Seen a crash. Terminating all fuzzing threads");
Robert Swiecki0dde76d2017-11-16 19:25:44 +0100678 fuzz_setTerminating();
Robert Swiecki069b48f2017-05-31 01:00:08 +0200679 break;
680 }
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000681 }
Robert Swiecki069b48f2017-05-31 01:00:08 +0200682
683 LOG_I("Terminating thread no. #%" PRId32, fuzzNo);
Robert Swiecki78633d12017-11-13 23:24:55 +0100684 ATOMIC_POST_INC(run.global->threads.threadsFinished);
Robert Swiecki82c707c2017-11-14 16:36:23 +0100685 pthread_kill(run.global->threads.mainThread, SIGALRM);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200686 return NULL;
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000687}
688
Robert Swieckid50ed422017-11-13 23:32:26 +0100689static void fuzz_runThread(honggfuzz_t* hfuzz, pthread_t* thread, void* (*thread_func)(void*)) {
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000690 pthread_attr_t attr;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000691
robert.swiecki@gmail.com6f5c2392015-02-16 18:13:09 +0000692 pthread_attr_init(&attr);
Robert Swiecki33fb2842017-02-19 05:39:50 +0100693 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000694 pthread_attr_setstacksize(&attr, _HF_PTHREAD_STACKSIZE);
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200695 pthread_attr_setguardsize(&attr, (size_t)sysconf(_SC_PAGESIZE));
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000696
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200697 if (pthread_create(thread, &attr, thread_func, (void*)hfuzz) < 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200698 PLOG_F("Couldn't create a new thread");
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000699 }
700
Robert Swiecki33fb2842017-02-19 05:39:50 +0100701 pthread_attr_destroy(&attr);
702
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000703 return;
704}
705
Robert Swieckid50ed422017-11-13 23:32:26 +0100706void fuzz_threadsStart(honggfuzz_t* hfuzz, pthread_t* threads) {
robert.swiecki@gmail.com956276a2015-04-16 16:51:52 +0000707 if (!arch_archInit(hfuzz)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200708 LOG_F("Couldn't prepare arch for fuzzing");
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000709 }
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200710 if (!sanitizers_Init(hfuzz)) {
711 LOG_F("Couldn't prepare sanitizer options");
712 }
Jagger00265602016-03-10 02:36:27 +0100713 if (!sancov_Init(hfuzz)) {
714 LOG_F("Couldn't prepare sancov options");
715 }
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000716
Robert Swieckia96d78d2016-03-14 16:50:50 +0100717 if (hfuzz->useSanCov || hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
Jaggerebe19292016-03-17 00:11:44 +0100718 fuzz_setState(hfuzz, _HF_STATE_DYNAMIC_PRE);
Robert Swieckia96d78d2016-03-14 16:50:50 +0100719 } else {
Jaggerebe19292016-03-17 00:11:44 +0100720 fuzz_setState(hfuzz, _HF_STATE_STATIC);
Robert Swieckia96d78d2016-03-14 16:50:50 +0100721 }
722
Robert Swiecki66b65122017-11-11 02:55:55 +0100723 for (size_t i = 0; i < hfuzz->threads.threadsMax; i++) {
Robert Swiecki33fb2842017-02-19 05:39:50 +0100724 fuzz_runThread(hfuzz, &threads[i], fuzz_threadNew);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000725 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000726}
Robert Swiecki33fb2842017-02-19 05:39:50 +0100727
Robert Swieckid50ed422017-11-13 23:32:26 +0100728void fuzz_threadsStop(honggfuzz_t* hfuzz, pthread_t* threads) {
Robert Swiecki66b65122017-11-11 02:55:55 +0100729 for (size_t i = 0; i < hfuzz->threads.threadsMax; i++) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200730 void* retval;
Robert Swiecki33fb2842017-02-19 05:39:50 +0100731 if (pthread_join(threads[i], &retval) != 0) {
732 PLOG_F("Couldn't pthread_join() thread: %zu", i);
733 }
734 }
735 LOG_I("All threads done");
736}