blob: 8d9e1693f1e210143283388d552c5ce62f7c90b9 [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
Jagger6113c432015-09-24 05:00:28 +020060static pthread_t fuzz_mainThread;
61
Robert Swieckie7294ca2017-11-11 02:46:32 +010062static void fuzz_getFileName(honggfuzz_t* hfuzz, run_t* run)
robert.swiecki3bb518c2010-10-14 00:48:24 +000063{
Robert Swieckie7294ca2017-11-11 02:46:32 +010064 snprintf(run->fileName, PATH_MAX, "%s/honggfuzz.input.%" PRIu32 ".%s.%s", hfuzz->workDir,
65 run->fuzzNo, basename(hfuzz->cmdline[0]), hfuzz->fileExtn);
robert.swiecki3bb518c2010-10-14 00:48:24 +000066}
67
Robert Swieckie7294ca2017-11-11 02:46:32 +010068static bool fuzz_prepareFileDynamically(honggfuzz_t* hfuzz, run_t* run)
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000069{
Robert Swieckie7294ca2017-11-11 02:46:32 +010070 run->origFileName = "[DYNAMIC]";
Robert Swieckia08ab1c2016-03-14 18:29:21 +010071
72 {
Robert Swieckibf8f8cc2017-11-09 00:42:50 +010073 MX_SCOPED_RWLOCK_READ(&hfuzz->dynfileq_mutex);
Robert Swiecki4b0390a2016-03-14 18:44:05 +010074
Jaggerb070b812016-03-15 05:31:30 +010075 if (hfuzz->dynfileqCnt == 0) {
Jaggere4496512016-03-16 01:55:46 +010076 LOG_F("The dynamic file corpus is empty. Apparently, the initial fuzzing of the "
77 "provided file corpus (-f) has not produced any follow-up files with positive "
78 "coverage and/or CPU counters");
Jaggerb070b812016-03-15 05:31:30 +010079 }
80
Robert Swieckie7294ca2017-11-11 02:46:32 +010081 if (run->dynfileqCurrent == NULL) {
82 run->dynfileqCurrent = TAILQ_FIRST(&hfuzz->dynfileq);
Robert Swiecki3db34292017-11-09 14:13:21 +010083 } else {
Robert Swieckie7294ca2017-11-11 02:46:32 +010084 if (run->dynfileqCurrent == TAILQ_LAST(&hfuzz->dynfileq, dyns_t)) {
85 run->dynfileqCurrent = TAILQ_FIRST(&hfuzz->dynfileq);
Robert Swiecki3db34292017-11-09 14:13:21 +010086 } else {
Robert Swieckie7294ca2017-11-11 02:46:32 +010087 run->dynfileqCurrent = TAILQ_NEXT(run->dynfileqCurrent, pointers);
Robert Swiecki3db34292017-11-09 14:13:21 +010088 }
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010089 }
90 }
91
Robert Swieckie7294ca2017-11-11 02:46:32 +010092 memcpy(run->dynamicFile, run->dynfileqCurrent->data, run->dynfileqCurrent->size);
93 run->dynamicFileSz = run->dynfileqCurrent->size;
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010094
Robert Swieckie7294ca2017-11-11 02:46:32 +010095 mangle_mangleContent(hfuzz, run);
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000096
Robert Swieckid0fa62c2017-09-28 18:11:05 +020097 if (hfuzz->persistent == false
Robert Swieckie7294ca2017-11-11 02:46:32 +010098 && files_writeBufToFile(run->fileName, run->dynamicFile, run->dynamicFileSz,
Robert Swiecki4e595fb2017-10-11 17:26:51 +020099 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC)
100 == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100101 LOG_E("Couldn't write buffer to file '%s'", run->fileName);
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +0000102 return false;
103 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000104
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000105 return true;
robert.swiecki@gmail.comd7aed312015-02-03 21:26:37 +0000106}
107
Robert Swieckie7294ca2017-11-11 02:46:32 +0100108static bool fuzz_prepareFile(honggfuzz_t* hfuzz, run_t* run, bool rewind)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000109{
Robert Swiecki92a31362017-02-24 16:21:40 +0100110 char fname[PATH_MAX];
Robert Swiecki10eeb0a2017-09-28 15:42:52 +0200111 if (input_getNext(hfuzz, fname, rewind) == false) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100112 return false;
113 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100114 run->origFileName = files_basename(fname);
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200115
Robert Swieckie7294ca2017-11-11 02:46:32 +0100116 ssize_t fileSz = files_readFileToBufMax(fname, run->dynamicFile, hfuzz->maxFileSz);
Jagger1aa94d72016-04-02 02:37:35 +0200117 if (fileSz < 0) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100118 LOG_E("Couldn't read contents of '%s'", fname);
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000119 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000120 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100121 run->dynamicFileSz = fileSz;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000122
Robert Swieckie7294ca2017-11-11 02:46:32 +0100123 mangle_mangleContent(hfuzz, run);
robert.swiecki@gmail.comc070b942015-02-25 18:29:19 +0000124
Robert Swieckid0fa62c2017-09-28 18:11:05 +0200125 if (hfuzz->persistent == false
Robert Swieckie7294ca2017-11-11 02:46:32 +0100126 && files_writeBufToFile(run->fileName, run->dynamicFile, run->dynamicFileSz,
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200127 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC)
128 == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100129 LOG_E("Couldn't write buffer to file '%s'", run->fileName);
robert.swiecki@gmail.come7680522015-02-22 22:22:37 +0000130 return false;
131 }
132
robert.swiecki3bb518c2010-10-14 00:48:24 +0000133 return true;
134}
135
Robert Swieckie7294ca2017-11-11 02:46:32 +0100136static bool fuzz_prepareFileExternally(honggfuzz_t* hfuzz, run_t* run)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000137{
Robert Swieckic1deec82017-04-27 02:42:12 +0200138 char fname[PATH_MAX];
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200139 if (input_getNext(hfuzz, fname, true /* rewind */)) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100140 run->origFileName = files_basename(fname);
141 if (files_copyFile(fname, run->fileName, NULL, false /* try_link */) == false) {
142 LOG_E("files_copyFile('%s', '%s')", fname, run->fileName);
Robert Swieckic1deec82017-04-27 02:42:12 +0200143 return false;
144 }
Robert Swiecki87ca2112017-04-27 12:03:53 +0200145 } else {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100146 run->origFileName = "[EXTERNAL]";
147 int dstfd = open(run->fileName, O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644);
Robert Swiecki87ca2112017-04-27 12:03:53 +0200148 if (dstfd == -1) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100149 PLOG_E("Couldn't create a temporary file '%s'", run->fileName);
Robert Swiecki87ca2112017-04-27 12:03:53 +0200150 return false;
151 }
152 close(dstfd);
Robert Swieckic1deec82017-04-27 02:42:12 +0200153 }
154
Robert Swieckie7294ca2017-11-11 02:46:32 +0100155 LOG_D("Created '%s' as an input file", run->fileName);
robert.swiecki3d505e22010-10-14 01:17:17 +0000156
Robert Swieckie7294ca2017-11-11 02:46:32 +0100157 const char* const argv[] = { hfuzz->externalCommand, run->fileName, NULL };
158 if (subproc_System(hfuzz, run, argv) != 0) {
Robert Swiecki54333cd2016-09-07 17:51:48 +0200159 LOG_E("Subprocess '%s' returned abnormally", hfuzz->externalCommand);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000160 return false;
161 }
Robert Swiecki54333cd2016-09-07 17:51:48 +0200162 LOG_D("Subporcess '%s' finished with success", hfuzz->externalCommand);
Jagger1d743382016-04-02 02:09:41 +0200163
Robert Swieckie7294ca2017-11-11 02:46:32 +0100164 ssize_t rsz = files_readFileToBufMax(run->fileName, run->dynamicFile, hfuzz->maxFileSz);
Jagger1aa94d72016-04-02 02:37:35 +0200165 if (rsz < 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100166 LOG_W("Couldn't read back '%s' to the buffer", run->fileName);
Jagger1d743382016-04-02 02:09:41 +0200167 return false;
168 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100169 run->dynamicFileSz = rsz;
Jagger1d743382016-04-02 02:09:41 +0200170
171 if (hfuzz->persistent) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100172 unlink(run->fileName);
Jagger1d743382016-04-02 02:09:41 +0200173 }
174
175 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000176}
177
Robert Swieckie7294ca2017-11-11 02:46:32 +0100178static bool fuzz_postProcessFile(honggfuzz_t* hfuzz, run_t* run)
Robert Swieckiee266ac2016-10-03 02:25:59 +0200179{
Robert Swieckicc88f932017-07-07 00:13:00 +0200180 if (hfuzz->persistent) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100181 if (files_writeBufToFile(run->fileName, run->dynamicFile, run->dynamicFileSz,
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200182 O_CREAT | O_TRUNC | O_WRONLY | O_CLOEXEC)
Robert Swieckid0fa62c2017-09-28 18:11:05 +0200183 == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100184 LOG_E("Couldn't write file to '%s'", run->fileName);
Robert Swieckicc88f932017-07-07 00:13:00 +0200185 return false;
186 }
Robert Swieckiee266ac2016-10-03 02:25:59 +0200187 }
188
Robert Swieckie7294ca2017-11-11 02:46:32 +0100189 const char* const argv[] = { hfuzz->postExternalCommand, run->fileName, NULL };
190 if (subproc_System(hfuzz, run, argv) != 0) {
Robert Swieckiee266ac2016-10-03 02:25:59 +0200191 LOG_E("Subprocess '%s' returned abnormally", hfuzz->postExternalCommand);
192 return false;
193 }
194 LOG_D("Subporcess '%s' finished with success", hfuzz->externalCommand);
195
Robert Swieckie7294ca2017-11-11 02:46:32 +0100196 ssize_t rsz = files_readFileToBufMax(run->fileName, run->dynamicFile, hfuzz->maxFileSz);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200197 if (rsz < 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100198 LOG_W("Couldn't read back '%s' to the buffer", run->fileName);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200199 return false;
200 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100201 run->dynamicFileSz = rsz;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200202
203 return true;
204}
205
Robert Swiecki0b566112017-10-17 17:39:07 +0200206static fuzzState_t fuzz_getState(honggfuzz_t* hfuzz) { return ATOMIC_GET(hfuzz->state); }
Robert Swieckia7841da2017-02-24 17:27:06 +0100207
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200208static void fuzz_setState(honggfuzz_t* hfuzz, fuzzState_t state)
Robert Swieckia7841da2017-02-24 17:27:06 +0100209{
Robert Swiecki3915a812017-02-25 02:07:56 +0100210 /* All threads must indicate willingness to switch to _HF_STATE_DYNAMIC_MAIN */
211 if (state == _HF_STATE_DYNAMIC_MAIN) {
212 static size_t cnt = 0;
213 ATOMIC_PRE_INC(cnt);
214 while (ATOMIC_GET(cnt) < hfuzz->threadsMax) {
Robert Swiecki1a994732017-05-31 18:32:21 +0200215 if (ATOMIC_GET(hfuzz->terminating) == true) {
216 return;
217 }
Robert Swiecki3915a812017-02-25 02:07:56 +0100218 sleep(1);
219 }
220 }
221
Robert Swieckia7841da2017-02-24 17:27:06 +0100222 static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
223 MX_SCOPED_LOCK(&state_mutex);
224
225 if (hfuzz->state == state) {
226 return;
227 }
228
229 switch (state) {
230 case _HF_STATE_DYNAMIC_PRE:
231 LOG_I("Entering phase 1/2: Dry Run");
232 break;
233 case _HF_STATE_DYNAMIC_MAIN:
234 LOG_I("Entering phase 2/2: Main");
235 break;
236 case _HF_STATE_STATIC:
237 LOG_I("Entering phase: Static");
238 break;
239 default:
240 LOG_I("Entering unknown phase: %d", state);
241 break;
242 }
243
244 ATOMIC_SET(hfuzz->state, state);
245}
246
Robert Swieckie7294ca2017-11-11 02:46:32 +0100247static bool fuzz_runVerifier(honggfuzz_t* hfuzz, run_t* crashedFuzzer)
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300248{
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300249 int crashFd = -1;
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200250 uint8_t* crashBuf = NULL;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300251 off_t crashFileSz = 0;
252
253 crashBuf = files_mapFile(crashedFuzzer->crashFileName, &crashFileSz, &crashFd, false);
254 if (crashBuf == NULL) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700255 LOG_E("Couldn't open and map '%s' in R/O mode", crashedFuzzer->crashFileName);
Robert Swieckie48811e2016-03-09 18:31:19 +0100256 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300257 }
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200258 defer
259 {
Jagger4fe18692016-04-22 23:15:07 +0200260 munmap(crashBuf, crashFileSz);
Jagger4fe18692016-04-22 23:15:07 +0200261 close(crashFd);
262 };
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300263
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700264 LOG_I("Launching verifier for %" PRIx64 " hash", crashedFuzzer->backtrace);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300265 for (int i = 0; i < _HF_VERIFIER_ITER; i++) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100266 run_t vFuzzer = {
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300267 .pid = 0,
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300268 .persistentPid = 0,
Robert Swieckia7841da2017-02-24 17:27:06 +0100269 .state = fuzz_getState(hfuzz),
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300270 .timeStartedMillis = util_timeNowMillis(),
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200271 .crashFileName = { 0 },
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300272 .pc = 0ULL,
273 .backtrace = 0ULL,
274 .access = 0ULL,
275 .exception = 0,
Robert Swieckibf8f8cc2017-11-09 00:42:50 +0100276 .dynfileqCurrent = NULL,
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300277 .dynamicFileSz = 0,
278 .dynamicFile = NULL,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200279 .sanCovCnts = {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200280 .hitBBCnt = 0ULL,
281 .totalBBCnt = 0ULL,
282 .dsoCnt = 0ULL,
283 .iDsoCnt = 0ULL,
284 .newBBCnt = 0ULL,
285 .crashesCnt = 0ULL,
286 },
287 .report = { '\0' },
Jaggerb2c1fad2016-03-17 23:37:10 +0100288 .mainWorker = false,
Jaggerfa3544a2016-08-30 02:55:55 +0200289 .fuzzNo = crashedFuzzer->fuzzNo,
Jagger93253f72016-09-01 22:40:12 +0200290 .persistentSock = -1,
Robert Swiecki013bc9c2016-12-12 17:31:06 +0100291 .tmOutSignaled = false,
Jaggerb2c1fad2016-03-17 23:37:10 +0100292
Jagger2381ef42016-03-20 23:32:05 +0100293 .linux = {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200294 .hwCnts = {
295 .cpuInstrCnt = 0ULL,
296 .cpuBranchCnt = 0ULL,
297 .bbCnt = 0ULL,
298 .newBBCnt = 0ULL,
299 .softCntPc = 0ULL,
300 .softCntEdge = 0ULL,
301 .softCntCmp = 0ULL,
302 },
303 .attachedPid = 0,
304 },
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300305 };
306
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300307 if (arch_archThreadInit(hfuzz, &vFuzzer) == false) {
308 LOG_F("Could not initialize the thread");
309 }
310
Robert Swieckieaf27322017-06-01 21:49:26 +0200311 fuzz_getFileName(hfuzz, &vFuzzer);
Robert Swiecki0b566112017-10-17 17:39:07 +0200312 if (files_writeBufToFile(
313 vFuzzer.fileName, crashBuf, crashFileSz, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC)
Robert Swieckid0fa62c2017-09-28 18:11:05 +0200314 == false) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700315 LOG_E("Couldn't write buffer to file '%s'", vFuzzer.fileName);
Robert Swieckie48811e2016-03-09 18:31:19 +0100316 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300317 }
318
Robert Swiecki940a0802016-11-02 12:42:09 +0100319 if (subproc_Run(hfuzz, &vFuzzer) == false) {
320 LOG_F("subproc_Run()");
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300321 }
Robert Swieckia8b8cb82016-08-17 18:27:08 +0200322
Anestis Bechtsoudis2b2a63b2016-12-28 15:34:40 +0200323 /* Delete intermediate files generated from verifier */
324 unlink(vFuzzer.fileName);
325
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300326 /* If stack hash doesn't match skip name tag and exit */
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300327 if (crashedFuzzer->backtrace != vFuzzer.backtrace) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700328 LOG_D("Verifier stack hash mismatch");
Robert Swieckie48811e2016-03-09 18:31:19 +0100329 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300330 }
331 }
332
333 /* Workspace is inherited, just append a extra suffix */
334 char verFile[PATH_MAX] = { 0 };
335 snprintf(verFile, sizeof(verFile), "%s.verified", crashedFuzzer->crashFileName);
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300336
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200337 /* Copy file with new suffix & remove original copy */
338 bool dstFileExists = false;
Robert Swiecki0b566112017-10-17 17:39:07 +0200339 if (files_copyFile(
340 crashedFuzzer->crashFileName, verFile, &dstFileExists, true /* try_link */)) {
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200341 LOG_I("Successfully verified, saving as (%s)", verFile);
Jaggerd34417d2016-03-16 01:26:54 +0100342 ATOMIC_POST_INC(hfuzz->verifiedCrashesCnt);
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200343 unlink(crashedFuzzer->crashFileName);
344 } else {
345 if (dstFileExists) {
346 LOG_I("It seems that '%s' already exists, skipping", verFile);
347 } else {
348 LOG_E("Couldn't copy '%s' to '%s'", crashedFuzzer->crashFileName, verFile);
Robert Swieckie48811e2016-03-09 18:31:19 +0100349 return false;
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200350 }
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300351 }
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300352
Robert Swieckie48811e2016-03-09 18:31:19 +0100353 return true;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300354}
355
Robert Swieckie7294ca2017-11-11 02:46:32 +0100356static void fuzz_addFileToFileQ(honggfuzz_t* hfuzz, run_t* run)
Robert Swieckif3534bb2016-03-14 18:55:10 +0100357{
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200358 struct dynfile_t* dynfile = (struct dynfile_t*)util_Malloc(sizeof(struct dynfile_t));
Robert Swieckie7294ca2017-11-11 02:46:32 +0100359 dynfile->size = run->dynamicFileSz;
360 dynfile->data = (uint8_t*)util_Malloc(run->dynamicFileSz);
361 memcpy(dynfile->data, run->dynamicFile, run->dynamicFileSz);
Robert Swiecki37498fd2017-03-12 21:12:54 +0100362
Robert Swieckibf8f8cc2017-11-09 00:42:50 +0100363 MX_SCOPED_RWLOCK_WRITE(&hfuzz->dynfileq_mutex);
Robert Swieckib0e261a2017-11-09 01:30:54 +0100364 TAILQ_INSERT_TAIL(&hfuzz->dynfileq, dynfile, pointers);
Robert Swieckif3534bb2016-03-14 18:55:10 +0100365 hfuzz->dynfileqCnt++;
366
Jagger3c7e7ce2016-09-25 16:05:19 +0200367 /* No need to add new coverage if we are supposed to append new coverage-inducing inputs only */
Robert Swieckie7294ca2017-11-11 02:46:32 +0100368 if (run->state == _HF_STATE_DYNAMIC_PRE && hfuzz->covDir == NULL) {
Jagger1b2d4822016-09-25 16:19:45 +0200369 LOG_D("New coverage found, but we're in the initial coverage assessment state. Skipping");
Jagger3c7e7ce2016-09-25 16:05:19 +0200370 return;
371 }
372
Robert Swieckif3534bb2016-03-14 18:55:10 +0100373 char fname[PATH_MAX];
Robert Swieckie7294ca2017-11-11 02:46:32 +0100374 uint64_t crc64f = util_CRC64(run->dynamicFile, run->dynamicFileSz);
375 uint64_t crc64r = util_CRC64Rev(run->dynamicFile, run->dynamicFileSz);
Robert Swieckifd02b692017-02-22 02:33:27 +0100376 snprintf(fname, sizeof(fname), "%s/%016" PRIx64 "%016" PRIx64 ".%08" PRIx32 ".honggfuzz.cov",
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200377 hfuzz->covDir ? hfuzz->covDir : hfuzz->inputDir, crc64f, crc64r,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100378 (uint32_t)run->dynamicFileSz);
Jagger3c7e7ce2016-09-25 16:05:19 +0200379
Robert Swiecki22f6bef2017-01-31 01:45:26 +0100380 if (access(fname, R_OK) == 0) {
381 LOG_D("File '%s' already exists in the corpus directory", fname);
382 return;
383 }
384
385 LOG_D("Adding file '%s' to the corpus directory", fname);
386
Robert Swieckie7294ca2017-11-11 02:46:32 +0100387 if (files_writeBufToFile(fname, run->dynamicFile, run->dynamicFileSz,
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200388 O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)
Jagger33cce5d2016-04-16 20:10:36 +0200389 == false) {
Robert Swieckif3534bb2016-03-14 18:55:10 +0100390 LOG_W("Couldn't write buffer to file '%s'", fname);
391 }
392}
393
Robert Swieckie7294ca2017-11-11 02:46:32 +0100394static void fuzz_perfFeedback(honggfuzz_t* hfuzz, run_t* run)
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200395{
Robert Swieckie7294ca2017-11-11 02:46:32 +0100396 if (hfuzz->skipFeedbackOnTimeout && run->tmOutSignaled) {
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100397 return;
398 }
399
Robert Swiecki0b566112017-10-17 17:39:07 +0200400 LOG_D("New file size: %zu, Perf feedback new/cur (instr,branch): %" PRIu64 "/%" PRIu64
401 "/%" PRIu64 "/%" PRIu64 ", BBcnt new/total: %" PRIu64 "/%" PRIu64,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100402 run->dynamicFileSz, run->linux.hwCnts.cpuInstrCnt, hfuzz->linux.hwCnts.cpuInstrCnt,
403 run->linux.hwCnts.cpuBranchCnt, hfuzz->linux.hwCnts.cpuBranchCnt,
404 run->linux.hwCnts.newBBCnt, hfuzz->linux.hwCnts.bbCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200405
Robert Swiecki37498fd2017-03-12 21:12:54 +0100406 MX_SCOPED_LOCK(&hfuzz->feedback_mutex);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200407
Jagger34789a72016-09-08 00:36:09 +0200408 uint64_t softCntPc = 0UL;
Robert Swieckib27c8952017-05-23 23:38:04 +0200409 uint64_t softCntEdge = 0UL;
Jagger34789a72016-09-08 00:36:09 +0200410 uint64_t softCntCmp = 0UL;
Jagger251d0192016-08-24 00:54:04 +0200411 if (hfuzz->bbFd != -1) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100412 softCntPc = ATOMIC_GET(hfuzz->feedback->pidFeedbackPc[run->fuzzNo]);
413 ATOMIC_CLEAR(hfuzz->feedback->pidFeedbackPc[run->fuzzNo]);
414 softCntEdge = ATOMIC_GET(hfuzz->feedback->pidFeedbackEdge[run->fuzzNo]);
415 ATOMIC_CLEAR(hfuzz->feedback->pidFeedbackEdge[run->fuzzNo]);
416 softCntCmp = ATOMIC_GET(hfuzz->feedback->pidFeedbackCmp[run->fuzzNo]);
417 ATOMIC_CLEAR(hfuzz->feedback->pidFeedbackCmp[run->fuzzNo]);
Jagger251d0192016-08-24 00:54:04 +0200418 }
Jaggerb01aaae2016-08-20 03:35:38 +0200419
Robert Swieckie7294ca2017-11-11 02:46:32 +0100420 int64_t diff0 = hfuzz->linux.hwCnts.cpuInstrCnt - run->linux.hwCnts.cpuInstrCnt;
421 int64_t diff1 = hfuzz->linux.hwCnts.cpuBranchCnt - run->linux.hwCnts.cpuBranchCnt;
Jagger302c2ea2016-09-07 03:54:43 +0200422
Jagger8d0002c2016-08-17 03:44:23 +0200423 /*
424 * Coverage is the primary counter, the rest is secondary, and taken into consideration only
425 * if the coverage counter has not been changed
426 */
Robert Swieckie7294ca2017-11-11 02:46:32 +0100427 if (run->linux.hwCnts.newBBCnt > 0 || softCntPc > 0 || softCntEdge > 0 || softCntCmp > 0
Robert Swieckib27c8952017-05-23 23:38:04 +0200428 || diff0 < 0 || diff1 < 0) {
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100429
430 if (diff0 < 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100431 hfuzz->linux.hwCnts.cpuInstrCnt = run->linux.hwCnts.cpuInstrCnt;
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100432 }
433 if (diff1 < 0) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100434 hfuzz->linux.hwCnts.cpuBranchCnt = run->linux.hwCnts.cpuBranchCnt;
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100435 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100436 hfuzz->linux.hwCnts.bbCnt += run->linux.hwCnts.newBBCnt;
Jagger34789a72016-09-08 00:36:09 +0200437 hfuzz->linux.hwCnts.softCntPc += softCntPc;
Robert Swieckib27c8952017-05-23 23:38:04 +0200438 hfuzz->linux.hwCnts.softCntEdge += softCntEdge;
Jagger34789a72016-09-08 00:36:09 +0200439 hfuzz->linux.hwCnts.softCntCmp += softCntCmp;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200440
Robert Swiecki0b566112017-10-17 17:39:07 +0200441 LOG_I("Size:%zu (i,b,edg,ip,hw,cmp): %" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64
442 "/%" PRIu64 "/%" PRIu64 ", Tot:%" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64
443 "/%" PRIu64 "/%" PRIu64,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100444 run->dynamicFileSz, run->linux.hwCnts.cpuInstrCnt, run->linux.hwCnts.cpuBranchCnt,
445 softCntEdge, softCntPc, run->linux.hwCnts.newBBCnt, softCntCmp,
446 hfuzz->linux.hwCnts.cpuInstrCnt, hfuzz->linux.hwCnts.cpuBranchCnt,
447 hfuzz->linux.hwCnts.softCntEdge, hfuzz->linux.hwCnts.softCntPc,
448 hfuzz->linux.hwCnts.bbCnt, hfuzz->linux.hwCnts.softCntCmp);
Jagger395df022016-08-21 01:13:25 +0200449
Robert Swieckie7294ca2017-11-11 02:46:32 +0100450 fuzz_addFileToFileQ(hfuzz, run);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200451 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200452}
453
Robert Swieckie7294ca2017-11-11 02:46:32 +0100454static void fuzz_sanCovFeedback(honggfuzz_t* hfuzz, run_t* run)
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200455{
Robert Swieckie7294ca2017-11-11 02:46:32 +0100456 if (hfuzz->skipFeedbackOnTimeout && run->tmOutSignaled) {
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100457 return;
458 }
459
Robert Swiecki0b566112017-10-17 17:39:07 +0200460 LOG_D("File size (Best/New): %zu, SanCov feedback (bb,dso): Best: [%" PRIu64 ",%" PRIu64
461 "] / New: [%" PRIu64 ",%" PRIu64 "], newBBs:%" PRIu64,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100462 run->dynamicFileSz, hfuzz->sanCovCnts.hitBBCnt, hfuzz->sanCovCnts.iDsoCnt,
463 run->sanCovCnts.hitBBCnt, run->sanCovCnts.iDsoCnt, run->sanCovCnts.newBBCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200464
Robert Swiecki37498fd2017-03-12 21:12:54 +0100465 MX_SCOPED_LOCK(&hfuzz->feedback_mutex);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200466
Robert Swieckie7294ca2017-11-11 02:46:32 +0100467 int64_t diff0 = hfuzz->linux.hwCnts.cpuInstrCnt - run->linux.hwCnts.cpuInstrCnt;
468 int64_t diff1 = hfuzz->linux.hwCnts.cpuBranchCnt - run->linux.hwCnts.cpuBranchCnt;
Jaggerd5738372016-08-17 20:12:15 +0200469
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200470 /*
471 * Keep mutated seed if:
Robert Swiecki142f9412016-03-14 19:22:01 +0100472 * a) Newly discovered (not met before) BBs
473 * b) More instrumented DSOs loaded
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100474 *
Anestis Bechtsoudisb78cf602016-01-07 13:10:50 +0200475 * TODO: (a) method can significantly assist to further improvements in interesting areas
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200476 * discovery if combined with seeds pool/queue support. If a runtime queue is maintained
477 * more interesting seeds can be saved between runs instead of instantly discarded
478 * based on current absolute elitism (only one mutated seed is promoted).
479 */
Jaggerd5738372016-08-17 20:12:15 +0200480
Robert Swieckie7294ca2017-11-11 02:46:32 +0100481 bool newCov
482 = (run->sanCovCnts.newBBCnt > 0 || hfuzz->sanCovCnts.iDsoCnt < run->sanCovCnts.iDsoCnt);
Jaggerd5738372016-08-17 20:12:15 +0200483
Robert Swieckid158aac2016-11-01 23:14:12 +0100484 if (newCov || (diff0 < 0 || diff1 < 0)) {
Robert Swiecki0b566112017-10-17 17:39:07 +0200485 LOG_I("SanCov Update: fsize:%zu, newBBs:%" PRIu64 ", (Cur,New): %" PRIu64 "/%" PRIu64
486 ",%" PRIu64 "/%" PRIu64,
Robert Swieckie7294ca2017-11-11 02:46:32 +0100487 run->dynamicFileSz, run->sanCovCnts.newBBCnt, hfuzz->sanCovCnts.hitBBCnt,
488 hfuzz->sanCovCnts.iDsoCnt, run->sanCovCnts.hitBBCnt, run->sanCovCnts.iDsoCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200489
Robert Swieckie7294ca2017-11-11 02:46:32 +0100490 hfuzz->sanCovCnts.hitBBCnt += run->sanCovCnts.newBBCnt;
491 hfuzz->sanCovCnts.dsoCnt = run->sanCovCnts.dsoCnt;
492 hfuzz->sanCovCnts.iDsoCnt = run->sanCovCnts.iDsoCnt;
493 hfuzz->sanCovCnts.crashesCnt += run->sanCovCnts.crashesCnt;
494 hfuzz->sanCovCnts.newBBCnt = run->sanCovCnts.newBBCnt;
Anestis Bechtsoudisb78cf602016-01-07 13:10:50 +0200495
Robert Swieckie7294ca2017-11-11 02:46:32 +0100496 if (hfuzz->sanCovCnts.totalBBCnt < run->sanCovCnts.totalBBCnt) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200497 /* Keep only the max value (for dlopen cases) to measure total target coverage */
Robert Swieckie7294ca2017-11-11 02:46:32 +0100498 hfuzz->sanCovCnts.totalBBCnt = run->sanCovCnts.totalBBCnt;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200499 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200500
Robert Swieckie7294ca2017-11-11 02:46:32 +0100501 hfuzz->linux.hwCnts.cpuInstrCnt = run->linux.hwCnts.cpuInstrCnt;
502 hfuzz->linux.hwCnts.cpuBranchCnt = run->linux.hwCnts.cpuBranchCnt;
Jaggerd5738372016-08-17 20:12:15 +0200503
Robert Swieckie7294ca2017-11-11 02:46:32 +0100504 fuzz_addFileToFileQ(hfuzz, run);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200505 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200506}
507
Robert Swieckie7294ca2017-11-11 02:46:32 +0100508static void fuzz_fuzzLoop(honggfuzz_t* hfuzz, run_t* run)
Jagger190f0dc2015-09-05 16:41:22 +0200509{
Robert Swieckie7294ca2017-11-11 02:46:32 +0100510 run->pid = 0;
511 run->timeStartedMillis = util_timeNowMillis();
512 run->state = fuzz_getState(hfuzz);
513 run->crashFileName[0] = '\0';
514 run->pc = 0ULL;
515 run->backtrace = 0ULL;
516 run->access = 0ULL;
517 run->exception = 0;
518 run->report[0] = '\0';
519 run->mainWorker = true;
520 run->origFileName = "DYNAMIC";
521 run->mutationsPerRun = hfuzz->mutationsPerRun;
522 run->dynamicFileSz = 0;
Robert Swieckia96d78d2016-03-14 16:50:50 +0100523
Robert Swieckie7294ca2017-11-11 02:46:32 +0100524 run->sanCovCnts.hitBBCnt = 0ULL;
525 run->sanCovCnts.totalBBCnt = 0ULL;
526 run->sanCovCnts.dsoCnt = 0ULL;
527 run->sanCovCnts.newBBCnt = 0ULL;
528 run->sanCovCnts.crashesCnt = 0ULL;
Robert Swieckia96d78d2016-03-14 16:50:50 +0100529
Robert Swieckie7294ca2017-11-11 02:46:32 +0100530 run->linux.hwCnts.cpuInstrCnt = 0ULL;
531 run->linux.hwCnts.cpuBranchCnt = 0ULL;
532 run->linux.hwCnts.bbCnt = 0ULL;
533 run->linux.hwCnts.newBBCnt = 0ULL;
Jagger190f0dc2015-09-05 16:41:22 +0200534
Robert Swieckie7294ca2017-11-11 02:46:32 +0100535 if (run->state == _HF_STATE_DYNAMIC_PRE) {
536 run->mutationsPerRun = 0U;
537 if (fuzz_prepareFile(hfuzz, run, false /* rewind */) == false) {
Robert Swieckicc88f932017-07-07 00:13:00 +0200538 fuzz_setState(hfuzz, _HF_STATE_DYNAMIC_MAIN);
Robert Swieckie7294ca2017-11-11 02:46:32 +0100539 run->state = fuzz_getState(hfuzz);
Robert Swieckiee266ac2016-10-03 02:25:59 +0200540 }
Robert Swiecki92a31362017-02-24 16:21:40 +0100541 }
Robert Swiecki1a994732017-05-31 18:32:21 +0200542
543 if (ATOMIC_GET(hfuzz->terminating) == true) {
544 return;
545 }
546
Robert Swieckie7294ca2017-11-11 02:46:32 +0100547 if (run->state == _HF_STATE_DYNAMIC_MAIN) {
Robert Swieckicc88f932017-07-07 00:13:00 +0200548 if (hfuzz->externalCommand) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100549 if (!fuzz_prepareFileExternally(hfuzz, run)) {
Robert Swieckicc88f932017-07-07 00:13:00 +0200550 LOG_F("fuzz_prepareFileExternally() failed");
551 }
Robert Swieckie7294ca2017-11-11 02:46:32 +0100552 } else if (!fuzz_prepareFileDynamically(hfuzz, run)) {
Jagger1d8e0c62016-04-02 02:22:40 +0200553 LOG_F("fuzz_prepareFileDynamically() failed");
Robert Swieckia96d78d2016-03-14 16:50:50 +0100554 }
Robert Swieckicc88f932017-07-07 00:13:00 +0200555
556 if (hfuzz->postExternalCommand) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100557 if (!fuzz_postProcessFile(hfuzz, run)) {
Robert Swieckicc88f932017-07-07 00:13:00 +0200558 LOG_F("fuzz_postProcessFile() failed");
559 }
560 }
Jagger190f0dc2015-09-05 16:41:22 +0200561 }
Robert Swieckicc88f932017-07-07 00:13:00 +0200562
Robert Swieckie7294ca2017-11-11 02:46:32 +0100563 if (run->state == _HF_STATE_STATIC) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100564 if (hfuzz->externalCommand) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100565 if (!fuzz_prepareFileExternally(hfuzz, run)) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100566 LOG_F("fuzz_prepareFileExternally() failed");
567 }
568 } else {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100569 if (!fuzz_prepareFile(hfuzz, run, true /* rewind */)) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100570 LOG_F("fuzz_prepareFile() failed");
571 }
572 }
Robert Swieckiab2b8c92017-07-07 12:55:43 +0200573
Robert Swiecki92a31362017-02-24 16:21:40 +0100574 if (hfuzz->postExternalCommand != NULL) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100575 if (!fuzz_postProcessFile(hfuzz, run)) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100576 LOG_F("fuzz_postProcessFile() failed");
577 }
Robert Swieckiee266ac2016-10-03 02:25:59 +0200578 }
579 }
580
Robert Swieckie7294ca2017-11-11 02:46:32 +0100581 if (subproc_Run(hfuzz, run) == false) {
Robert Swiecki940a0802016-11-02 12:42:09 +0100582 LOG_F("subproc_Run()");
Jagger190f0dc2015-09-05 16:41:22 +0200583 }
584
Jaggera34b3022016-04-02 02:20:40 +0200585 if (hfuzz->persistent == false) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100586 unlink(run->fileName);
Jaggera34b3022016-04-02 02:20:40 +0200587 }
Jagger190f0dc2015-09-05 16:41:22 +0200588
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100589 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100590 fuzz_perfFeedback(hfuzz, run);
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100591 }
592 if (hfuzz->useSanCov) {
Robert Swieckie7294ca2017-11-11 02:46:32 +0100593 fuzz_sanCovFeedback(hfuzz, run);
Robert Swiecki0f937af2016-03-30 18:19:16 +0200594 }
Jagger190f0dc2015-09-05 16:41:22 +0200595
Robert Swieckie7294ca2017-11-11 02:46:32 +0100596 if (hfuzz->useVerifier && (run->crashFileName[0] != 0) && run->backtrace) {
597 if (!fuzz_runVerifier(hfuzz, run)) {
598 LOG_I("Failed to verify %s", run->crashFileName);
Anestis Bechtsoudis3085f222015-09-27 18:35:26 +0300599 }
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300600 }
601
Robert Swieckie7294ca2017-11-11 02:46:32 +0100602 report_Report(hfuzz, run->report);
Jagger190f0dc2015-09-05 16:41:22 +0200603}
604
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200605static void* fuzz_threadNew(void* arg)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000606{
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200607 honggfuzz_t* hfuzz = (honggfuzz_t*)arg;
Robert Swiecki0ec98112017-02-03 02:08:14 +0100608 unsigned int fuzzNo = ATOMIC_POST_INC(hfuzz->threadsActiveCnt);
609 LOG_I("Launched new fuzzing thread, no. #%" PRId32, fuzzNo);
Anestis Bechtsoudis02b99be2015-12-27 11:53:01 +0200610
Robert Swieckie7294ca2017-11-11 02:46:32 +0100611 run_t run = {
Robert Swieckidecf14b2016-03-31 15:09:28 +0200612 .pid = 0,
613 .persistentPid = 0,
Robert Swieckibf8f8cc2017-11-09 00:42:50 +0100614 .dynfileqCurrent = NULL,
Robert Swiecki147d4672017-01-29 02:49:06 +0100615 .dynamicFile = util_Calloc(hfuzz->maxFileSz),
Jaggerfa3544a2016-08-30 02:55:55 +0200616 .fuzzNo = fuzzNo,
Jagger93253f72016-09-01 22:40:12 +0200617 .persistentSock = -1,
Robert Swiecki013bc9c2016-12-12 17:31:06 +0100618 .tmOutSignaled = false,
Robert Swiecki47f5de12017-03-28 03:25:55 +0200619 .fileName = "[UNSET]",
Robert Swiecki12800cd2016-03-31 15:38:10 +0200620
Robert Swieckib692f282016-08-25 16:21:08 +0200621 .linux.attachedPid = 0,
Robert Swieckidecf14b2016-03-31 15:09:28 +0200622 };
Robert Swieckie7294ca2017-11-11 02:46:32 +0100623 defer { free(run.dynamicFile); };
624 fuzz_getFileName(hfuzz, &run);
Robert Swieckidecf14b2016-03-31 15:09:28 +0200625
Robert Swieckie7294ca2017-11-11 02:46:32 +0100626 if (arch_archThreadInit(hfuzz, &run) == false) {
Robert Swiecki0f937af2016-03-30 18:19:16 +0200627 LOG_F("Could not initialize the thread");
628 }
629
Robert Swieckia96d78d2016-03-14 16:50:50 +0100630 for (;;) {
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200631 /* Check if dry run mode with verifier enabled */
Robert Swiecki10e93562017-11-04 00:57:47 +0100632 if (hfuzz->mutationsPerRun == 0U && hfuzz->useVerifier) {
Jaggerd34417d2016-03-16 01:26:54 +0100633 if (ATOMIC_POST_INC(hfuzz->mutationsCnt) >= hfuzz->fileCnt) {
634 ATOMIC_POST_INC(hfuzz->threadsFinished);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200635 break;
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200636 }
637 }
638 /* Check for max iterations limit if set */
Jaggerd34417d2016-03-16 01:26:54 +0100639 else if ((ATOMIC_POST_INC(hfuzz->mutationsCnt) >= hfuzz->mutationsMax)
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200640 && hfuzz->mutationsMax) {
Jaggerd34417d2016-03-16 01:26:54 +0100641 ATOMIC_POST_INC(hfuzz->threadsFinished);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200642 break;
Robert Swiecki8d01b012017-02-19 15:48:11 +0100643 }
644
Robert Swieckie7294ca2017-11-11 02:46:32 +0100645 fuzz_fuzzLoop(hfuzz, &run);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200646
647 if (ATOMIC_GET(hfuzz->terminating) == true) {
648 break;
649 }
650
651 if (hfuzz->exitUponCrash && ATOMIC_GET(hfuzz->crashesCnt) > 0) {
652 LOG_I("Seen a crash. Terminating all fuzzing threads");
653 ATOMIC_SET(hfuzz->terminating, true);
654 break;
655 }
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000656 }
Robert Swiecki069b48f2017-05-31 01:00:08 +0200657
658 LOG_I("Terminating thread no. #%" PRId32, fuzzNo);
659 ATOMIC_POST_INC(hfuzz->threadsFinished);
Robert Swieckiaa623952017-06-01 02:50:41 +0200660 pthread_kill(fuzz_mainThread, SIGALRM);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200661 return NULL;
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000662}
663
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200664static void fuzz_runThread(honggfuzz_t* hfuzz, pthread_t* thread, void* (*thread_func)(void*))
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000665{
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000666 pthread_attr_t attr;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000667
robert.swiecki@gmail.com6f5c2392015-02-16 18:13:09 +0000668 pthread_attr_init(&attr);
Robert Swiecki33fb2842017-02-19 05:39:50 +0100669 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000670 pthread_attr_setstacksize(&attr, _HF_PTHREAD_STACKSIZE);
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200671 pthread_attr_setguardsize(&attr, (size_t)sysconf(_SC_PAGESIZE));
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000672
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200673 if (pthread_create(thread, &attr, thread_func, (void*)hfuzz) < 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200674 PLOG_F("Couldn't create a new thread");
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000675 }
676
Robert Swiecki33fb2842017-02-19 05:39:50 +0100677 pthread_attr_destroy(&attr);
678
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000679 return;
680}
681
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200682void fuzz_threadsStart(honggfuzz_t* hfuzz, pthread_t* threads)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000683{
Jagger6113c432015-09-24 05:00:28 +0200684 fuzz_mainThread = pthread_self();
685
robert.swiecki@gmail.com956276a2015-04-16 16:51:52 +0000686 if (!arch_archInit(hfuzz)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200687 LOG_F("Couldn't prepare arch for fuzzing");
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000688 }
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200689 if (!sanitizers_Init(hfuzz)) {
690 LOG_F("Couldn't prepare sanitizer options");
691 }
Jagger00265602016-03-10 02:36:27 +0100692 if (!sancov_Init(hfuzz)) {
693 LOG_F("Couldn't prepare sancov options");
694 }
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000695
Robert Swieckia96d78d2016-03-14 16:50:50 +0100696 if (hfuzz->useSanCov || hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
Jaggerebe19292016-03-17 00:11:44 +0100697 fuzz_setState(hfuzz, _HF_STATE_DYNAMIC_PRE);
Robert Swieckia96d78d2016-03-14 16:50:50 +0100698 } else {
Jaggerebe19292016-03-17 00:11:44 +0100699 fuzz_setState(hfuzz, _HF_STATE_STATIC);
Robert Swieckia96d78d2016-03-14 16:50:50 +0100700 }
701
Jaggerea39a8f2015-09-05 00:57:22 +0200702 for (size_t i = 0; i < hfuzz->threadsMax; i++) {
Robert Swiecki33fb2842017-02-19 05:39:50 +0100703 fuzz_runThread(hfuzz, &threads[i], fuzz_threadNew);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000704 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000705}
Robert Swiecki33fb2842017-02-19 05:39:50 +0100706
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200707void fuzz_threadsStop(honggfuzz_t* hfuzz, pthread_t* threads)
Robert Swiecki33fb2842017-02-19 05:39:50 +0100708{
709 for (size_t i = 0; i < hfuzz->threadsMax; i++) {
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200710 void* retval;
Robert Swiecki33fb2842017-02-19 05:39:50 +0100711 if (pthread_join(threads[i], &retval) != 0) {
712 PLOG_F("Couldn't pthread_join() thread: %zu", i);
713 }
714 }
715 LOG_I("All threads done");
716}