blob: c9283ca51d4ecc5d98a06dfe99fd2a658652176e [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 Swiecki241a7412017-05-24 01:53:15 +020026#include "libcommon/common.h"
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000027#include "fuzz.h"
28
29#include <errno.h>
30#include <fcntl.h>
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +000031#include <inttypes.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.swiecki3bb518c2010-10-14 00:48:24 +000039#include <sys/param.h>
40#include <sys/stat.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000041#include <sys/time.h>
42#include <sys/types.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000043#include <time.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000044#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000045
Robert Swiecki241a7412017-05-24 01:53:15 +020046#include "libcommon/files.h"
47#include "libcommon/log.h"
Robert Swiecki241a7412017-05-24 01:53:15 +020048#include "libcommon/util.h"
Robert Swieckie405b772017-06-01 13:29:09 +020049#include "arch.h"
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +000050#include "mangle.h"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000051#include "report.h"
Robert Swieckiec7b8452017-06-01 13:25:56 +020052#include "sancov.h"
53#include "sanitizers.h"
Robert Swiecki2d016902017-05-24 02:12:30 +020054#include "subproc.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000055
Jagger6113c432015-09-24 05:00:28 +020056static pthread_t fuzz_mainThread;
57
Robert Swieckieaf27322017-06-01 21:49:26 +020058static void fuzz_getFileName(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
robert.swiecki3bb518c2010-10-14 00:48:24 +000059{
Robert Swieckieaf27322017-06-01 21:49:26 +020060 snprintf(fuzzer->fileName, PATH_MAX, "%s/honggfuzz.input.%" PRIu32 ".%s", hfuzz->workDir,
61 fuzzer->fuzzNo, hfuzz->fileExtn);
robert.swiecki3bb518c2010-10-14 00:48:24 +000062}
63
Robert Swieckia96d78d2016-03-14 16:50:50 +010064static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000065{
Robert Swieckib10d2b62017-02-10 13:13:10 +010066 fuzzer->origFileName = "[DYNAMIC]";
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010067 struct dynfile_t *dynfile;
Robert Swieckia08ab1c2016-03-14 18:29:21 +010068
69 {
Robert Swiecki76ecd5e2016-03-16 14:57:03 +010070 MX_SCOPED_LOCK(&hfuzz->dynfileq_mutex);
Robert Swiecki4b0390a2016-03-14 18:44:05 +010071
Jaggerb070b812016-03-15 05:31:30 +010072 if (hfuzz->dynfileqCnt == 0) {
Jaggere4496512016-03-16 01:55:46 +010073 LOG_F("The dynamic file corpus is empty. Apparently, the initial fuzzing of the "
74 "provided file corpus (-f) has not produced any follow-up files with positive "
75 "coverage and/or CPU counters");
Jaggerb070b812016-03-15 05:31:30 +010076 }
77
Robert Swieckiafb16102017-03-13 22:14:31 +010078 if (hfuzz->dynfileqCurrent == NULL
79 || hfuzz->dynfileqCurrent == TAILQ_LAST(&hfuzz->dynfileq, dictq_t)) {
80 hfuzz->dynfileqCurrent = TAILQ_FIRST(&hfuzz->dynfileq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010081 }
Robert Swiecki9f5f9432017-03-09 01:48:04 +010082 dynfile = hfuzz->dynfileqCurrent;
Robert Swieckiafb16102017-03-13 22:14:31 +010083 hfuzz->dynfileqCurrent = TAILQ_NEXT(hfuzz->dynfileqCurrent, pointers);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010084 }
85
86 memcpy(fuzzer->dynamicFile, dynfile->data, dynfile->size);
Robert Swieckia08ab1c2016-03-14 18:29:21 +010087 fuzzer->dynamicFileSz = dynfile->size;
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010088
Robert Swieckia96d78d2016-03-14 16:50:50 +010089 mangle_mangleContent(hfuzz, fuzzer);
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000090
Jagger1d743382016-04-02 02:09:41 +020091 if (hfuzz->persistent == false && files_writeBufToFile
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +000092 (fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz,
Robert Swiecki69dff772017-06-04 23:11:14 +020093 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC) == false) {
Robert Swieckic8c32db2015-10-09 18:06:22 +020094 LOG_E("Couldn't write buffer to file '%s'", fuzzer->fileName);
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +000095 return false;
96 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000097
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000098 return true;
robert.swiecki@gmail.comd7aed312015-02-03 21:26:37 +000099}
100
Robert Swiecki92a31362017-02-24 16:21:40 +0100101static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, bool rewind)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000102{
Robert Swiecki92a31362017-02-24 16:21:40 +0100103 char fname[PATH_MAX];
104 if (files_getNext(hfuzz, fname, rewind) == false) {
105 return false;
106 }
107 fuzzer->origFileName = files_basename(fname);
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200108
Robert Swiecki92a31362017-02-24 16:21:40 +0100109 ssize_t fileSz = files_readFileToBufMax(fname, fuzzer->dynamicFile, hfuzz->maxFileSz);
Jagger1aa94d72016-04-02 02:37:35 +0200110 if (fileSz < 0) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100111 LOG_E("Couldn't read contents of '%s'", fname);
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000112 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000113 }
Robert Swieckia96d78d2016-03-14 16:50:50 +0100114 fuzzer->dynamicFileSz = fileSz;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000115
Robert Swieckia438a522017-03-02 14:37:54 +0100116 mangle_mangleContent(hfuzz, fuzzer);
robert.swiecki@gmail.comc070b942015-02-25 18:29:19 +0000117
Jagger1d743382016-04-02 02:09:41 +0200118 if (hfuzz->persistent == false && files_writeBufToFile
Robert Swieckia96d78d2016-03-14 16:50:50 +0100119 (fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz,
Robert Swiecki69dff772017-06-04 23:11:14 +0200120 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC) == false) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200121 LOG_E("Couldn't write buffer to file '%s'", fuzzer->fileName);
robert.swiecki@gmail.come7680522015-02-22 22:22:37 +0000122 return false;
123 }
124
robert.swiecki3bb518c2010-10-14 00:48:24 +0000125 return true;
126}
127
Jaggera34b3022016-04-02 02:20:40 +0200128static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000129{
Robert Swieckic1deec82017-04-27 02:42:12 +0200130 char fname[PATH_MAX];
131 if (files_getNext(hfuzz, fname, true /* rewind */ )) {
Robert Swiecki5aff9c62017-04-27 12:06:02 +0200132 fuzzer->origFileName = files_basename(fname);
Robert Swiecki87ca2112017-04-27 12:03:53 +0200133 if (files_copyFile(fname, fuzzer->fileName, NULL, false /* try_link */ ) == false) {
Robert Swieckic1deec82017-04-27 02:42:12 +0200134 LOG_E("files_copyFile('%s', '%s')", fname, fuzzer->fileName);
135 return false;
136 }
Robert Swiecki87ca2112017-04-27 12:03:53 +0200137 } else {
Robert Swiecki5aff9c62017-04-27 12:06:02 +0200138 fuzzer->origFileName = "[EXTERNAL]";
Robert Swiecki69dff772017-06-04 23:11:14 +0200139 int dstfd = open(fuzzer->fileName, O_CREAT | O_TRUNC | O_RDWR | O_CLOEXEC, 0644);
Robert Swiecki87ca2112017-04-27 12:03:53 +0200140 if (dstfd == -1) {
141 PLOG_E("Couldn't create a temporary file '%s'", fuzzer->fileName);
142 return false;
143 }
144 close(dstfd);
Robert Swieckic1deec82017-04-27 02:42:12 +0200145 }
146
Jaggera34b3022016-04-02 02:20:40 +0200147 LOG_D("Created '%s' as an input file", fuzzer->fileName);
robert.swiecki3d505e22010-10-14 01:17:17 +0000148
Robert Swiecki54333cd2016-09-07 17:51:48 +0200149 const char *const argv[] = { hfuzz->externalCommand, fuzzer->fileName, NULL };
Robert Swiecki810d2c92017-06-01 21:37:27 +0200150 if (subproc_System(hfuzz, fuzzer, argv) != 0) {
Robert Swiecki54333cd2016-09-07 17:51:48 +0200151 LOG_E("Subprocess '%s' returned abnormally", hfuzz->externalCommand);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000152 return false;
153 }
Robert Swiecki54333cd2016-09-07 17:51:48 +0200154 LOG_D("Subporcess '%s' finished with success", hfuzz->externalCommand);
Jagger1d743382016-04-02 02:09:41 +0200155
156 ssize_t rsz = files_readFileToBufMax(fuzzer->fileName, fuzzer->dynamicFile, hfuzz->maxFileSz);
Jagger1aa94d72016-04-02 02:37:35 +0200157 if (rsz < 0) {
Jagger1d743382016-04-02 02:09:41 +0200158 LOG_W("Couldn't read back '%s' to the buffer", fuzzer->fileName);
159 return false;
160 }
161 fuzzer->dynamicFileSz = rsz;
162
163 if (hfuzz->persistent) {
164 unlink(fuzzer->fileName);
165 }
166
167 return true;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000168}
169
Robert Swieckiee266ac2016-10-03 02:25:59 +0200170static bool fuzz_postProcessFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
171{
172 if (hfuzz->persistent == true) {
173 LOG_F("Postprocessing file in persistent mode not yet supported");
174 }
175
176 const char *const argv[] = { hfuzz->postExternalCommand, fuzzer->fileName, NULL };
Robert Swiecki810d2c92017-06-01 21:37:27 +0200177 if (subproc_System(hfuzz, fuzzer, argv) != 0) {
Robert Swieckiee266ac2016-10-03 02:25:59 +0200178 LOG_E("Subprocess '%s' returned abnormally", hfuzz->postExternalCommand);
179 return false;
180 }
181 LOG_D("Subporcess '%s' finished with success", hfuzz->externalCommand);
182
183 ssize_t rsz = files_readFileToBufMax(fuzzer->fileName, fuzzer->dynamicFile, hfuzz->maxFileSz);
184 if (rsz < 0) {
185 LOG_W("Couldn't read back '%s' to the buffer", fuzzer->fileName);
186 return false;
187 }
188 fuzzer->dynamicFileSz = rsz;
189
190 return true;
191}
192
Robert Swieckia7841da2017-02-24 17:27:06 +0100193static fuzzState_t fuzz_getState(honggfuzz_t * hfuzz)
194{
195 return ATOMIC_GET(hfuzz->state);
196}
197
198static void fuzz_setState(honggfuzz_t * hfuzz, fuzzState_t state)
199{
Robert Swiecki3915a812017-02-25 02:07:56 +0100200 /* All threads must indicate willingness to switch to _HF_STATE_DYNAMIC_MAIN */
201 if (state == _HF_STATE_DYNAMIC_MAIN) {
202 static size_t cnt = 0;
203 ATOMIC_PRE_INC(cnt);
204 while (ATOMIC_GET(cnt) < hfuzz->threadsMax) {
Robert Swiecki1a994732017-05-31 18:32:21 +0200205 if (ATOMIC_GET(hfuzz->terminating) == true) {
206 return;
207 }
Robert Swiecki3915a812017-02-25 02:07:56 +0100208 sleep(1);
209 }
210 }
211
Robert Swieckia7841da2017-02-24 17:27:06 +0100212 static pthread_mutex_t state_mutex = PTHREAD_MUTEX_INITIALIZER;
213 MX_SCOPED_LOCK(&state_mutex);
214
215 if (hfuzz->state == state) {
216 return;
217 }
218
219 switch (state) {
220 case _HF_STATE_DYNAMIC_PRE:
221 LOG_I("Entering phase 1/2: Dry Run");
222 break;
223 case _HF_STATE_DYNAMIC_MAIN:
224 LOG_I("Entering phase 2/2: Main");
225 break;
226 case _HF_STATE_STATIC:
227 LOG_I("Entering phase: Static");
228 break;
229 default:
230 LOG_I("Entering unknown phase: %d", state);
231 break;
232 }
233
234 ATOMIC_SET(hfuzz->state, state);
235}
236
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300237static bool fuzz_runVerifier(honggfuzz_t * hfuzz, fuzzer_t * crashedFuzzer)
238{
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300239 int crashFd = -1;
240 uint8_t *crashBuf = NULL;
241 off_t crashFileSz = 0;
242
243 crashBuf = files_mapFile(crashedFuzzer->crashFileName, &crashFileSz, &crashFd, false);
244 if (crashBuf == NULL) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700245 LOG_E("Couldn't open and map '%s' in R/O mode", crashedFuzzer->crashFileName);
Robert Swieckie48811e2016-03-09 18:31:19 +0100246 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300247 }
Jagger4fe18692016-04-22 23:15:07 +0200248 defer {
249 munmap(crashBuf, crashFileSz);
Jagger4fe18692016-04-22 23:15:07 +0200250 close(crashFd);
251 };
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300252
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700253 LOG_I("Launching verifier for %" PRIx64 " hash", crashedFuzzer->backtrace);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300254 for (int i = 0; i < _HF_VERIFIER_ITER; i++) {
255 fuzzer_t vFuzzer = {
256 .pid = 0,
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300257 .persistentPid = 0,
Robert Swieckia7841da2017-02-24 17:27:06 +0100258 .state = fuzz_getState(hfuzz),
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300259 .timeStartedMillis = util_timeNowMillis(),
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300260 .crashFileName = {0},
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300261 .pc = 0ULL,
262 .backtrace = 0ULL,
263 .access = 0ULL,
264 .exception = 0,
265 .dynamicFileSz = 0,
266 .dynamicFile = NULL,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200267 .sanCovCnts = {
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200268 .hitBBCnt = 0ULL,
269 .totalBBCnt = 0ULL,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200270 .dsoCnt = 0ULL,
271 .iDsoCnt = 0ULL,
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200272 .newBBCnt = 0ULL,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200273 .crashesCnt = 0ULL,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200274 },
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300275 .report = {'\0'},
Jaggerb2c1fad2016-03-17 23:37:10 +0100276 .mainWorker = false,
Jaggerfa3544a2016-08-30 02:55:55 +0200277 .fuzzNo = crashedFuzzer->fuzzNo,
Jagger93253f72016-09-01 22:40:12 +0200278 .persistentSock = -1,
Robert Swiecki013bc9c2016-12-12 17:31:06 +0100279 .tmOutSignaled = false,
Jaggerb2c1fad2016-03-17 23:37:10 +0100280
Jagger2381ef42016-03-20 23:32:05 +0100281 .linux = {
282 .hwCnts = {
283 .cpuInstrCnt = 0ULL,
284 .cpuBranchCnt = 0ULL,
Jagger2381ef42016-03-20 23:32:05 +0100285 .bbCnt = 0ULL,
286 .newBBCnt = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200287 .softCntPc = 0ULL,
Robert Swieckib27c8952017-05-23 23:38:04 +0200288 .softCntEdge = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200289 .softCntCmp = 0ULL,
Jagger2381ef42016-03-20 23:32:05 +0100290 },
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300291 .attachedPid = 0,
Jagger2381ef42016-03-20 23:32:05 +0100292 },
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300293 };
294
Anestis Bechtsoudis92b97042016-04-27 12:34:19 +0300295 if (arch_archThreadInit(hfuzz, &vFuzzer) == false) {
296 LOG_F("Could not initialize the thread");
297 }
298
Robert Swieckieaf27322017-06-01 21:49:26 +0200299 fuzz_getFileName(hfuzz, &vFuzzer);
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300300 if (files_writeBufToFile
Jagger33cce5d2016-04-16 20:10:36 +0200301 (vFuzzer.fileName, crashBuf, crashFileSz,
Robert Swiecki69dff772017-06-04 23:11:14 +0200302 O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC) == false) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700303 LOG_E("Couldn't write buffer to file '%s'", vFuzzer.fileName);
Robert Swieckie48811e2016-03-09 18:31:19 +0100304 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300305 }
306
Robert Swiecki940a0802016-11-02 12:42:09 +0100307 if (subproc_Run(hfuzz, &vFuzzer) == false) {
308 LOG_F("subproc_Run()");
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300309 }
Robert Swieckia8b8cb82016-08-17 18:27:08 +0200310
Anestis Bechtsoudis2b2a63b2016-12-28 15:34:40 +0200311 /* Delete intermediate files generated from verifier */
312 unlink(vFuzzer.fileName);
313
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300314 /* If stack hash doesn't match skip name tag and exit */
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300315 if (crashedFuzzer->backtrace != vFuzzer.backtrace) {
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700316 LOG_D("Verifier stack hash mismatch");
Robert Swieckie48811e2016-03-09 18:31:19 +0100317 return false;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300318 }
319 }
320
321 /* Workspace is inherited, just append a extra suffix */
322 char verFile[PATH_MAX] = { 0 };
323 snprintf(verFile, sizeof(verFile), "%s.verified", crashedFuzzer->crashFileName);
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300324
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200325 /* Copy file with new suffix & remove original copy */
326 bool dstFileExists = false;
Robert Swiecki87ca2112017-04-27 12:03:53 +0200327 if (files_copyFile(crashedFuzzer->crashFileName, verFile, &dstFileExists, true /* try_link */ )) {
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200328 LOG_I("Successfully verified, saving as (%s)", verFile);
Jaggerd34417d2016-03-16 01:26:54 +0100329 ATOMIC_POST_INC(hfuzz->verifiedCrashesCnt);
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200330 unlink(crashedFuzzer->crashFileName);
331 } else {
332 if (dstFileExists) {
333 LOG_I("It seems that '%s' already exists, skipping", verFile);
334 } else {
335 LOG_E("Couldn't copy '%s' to '%s'", crashedFuzzer->crashFileName, verFile);
Robert Swieckie48811e2016-03-09 18:31:19 +0100336 return false;
Anestis Bechtsoudisd86e6602015-11-07 18:34:06 +0200337 }
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300338 }
Anestis Bechtsoudisecb0a662015-09-27 18:19:46 +0300339
Robert Swieckie48811e2016-03-09 18:31:19 +0100340 return true;
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300341}
342
Robert Swiecki37498fd2017-03-12 21:12:54 +0100343static void fuzz_addFileToFileQ(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
Robert Swieckif3534bb2016-03-14 18:55:10 +0100344{
Robert Swiecki7084e652016-03-14 19:47:00 +0100345 struct dynfile_t *dynfile = (struct dynfile_t *)util_Malloc(sizeof(struct dynfile_t));
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100346 dynfile->size = fuzzer->dynamicFileSz;
347 dynfile->data = (uint8_t *) util_Malloc(fuzzer->dynamicFileSz);
348 memcpy(dynfile->data, fuzzer->dynamicFile, fuzzer->dynamicFileSz);
Robert Swiecki37498fd2017-03-12 21:12:54 +0100349
350 MX_SCOPED_LOCK(&hfuzz->dynfileq_mutex);
Robert Swiecki46c21e32017-04-28 21:15:14 +0200351 TAILQ_INSERT_HEAD(&hfuzz->dynfileq, dynfile, pointers);
Robert Swieckif3534bb2016-03-14 18:55:10 +0100352 hfuzz->dynfileqCnt++;
353
Jagger3c7e7ce2016-09-25 16:05:19 +0200354 /* No need to add new coverage if we are supposed to append new coverage-inducing inputs only */
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100355 if (fuzzer->state == _HF_STATE_DYNAMIC_PRE && hfuzz->covDir == NULL) {
Jagger1b2d4822016-09-25 16:19:45 +0200356 LOG_D("New coverage found, but we're in the initial coverage assessment state. Skipping");
Jagger3c7e7ce2016-09-25 16:05:19 +0200357 return;
358 }
359
Robert Swieckif3534bb2016-03-14 18:55:10 +0100360 char fname[PATH_MAX];
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100361 uint64_t crc64f = util_CRC64(fuzzer->dynamicFile, fuzzer->dynamicFileSz);
362 uint64_t crc64r = util_CRC64Rev(fuzzer->dynamicFile, fuzzer->dynamicFileSz);
Robert Swieckifd02b692017-02-22 02:33:27 +0100363 snprintf(fname, sizeof(fname), "%s/%016" PRIx64 "%016" PRIx64 ".%08" PRIx32 ".honggfuzz.cov",
Robert Swiecki85a91ef2017-02-24 17:42:44 +0100364 hfuzz->covDir ? hfuzz->covDir : hfuzz->inputDir, crc64f, crc64r,
365 (uint32_t) fuzzer->dynamicFileSz);
Jagger3c7e7ce2016-09-25 16:05:19 +0200366
Robert Swiecki22f6bef2017-01-31 01:45:26 +0100367 if (access(fname, R_OK) == 0) {
368 LOG_D("File '%s' already exists in the corpus directory", fname);
369 return;
370 }
371
372 LOG_D("Adding file '%s' to the corpus directory", fname);
373
Robert Swiecki85a91ef2017-02-24 17:42:44 +0100374 if (files_writeBufToFile
375 (fname, fuzzer->dynamicFile, fuzzer->dynamicFileSz,
376 O_WRONLY | O_CREAT | O_EXCL | O_TRUNC | O_CLOEXEC)
Jagger33cce5d2016-04-16 20:10:36 +0200377 == false) {
Robert Swieckif3534bb2016-03-14 18:55:10 +0100378 LOG_W("Couldn't write buffer to file '%s'", fname);
379 }
380}
381
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200382static void fuzz_perfFeedback(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
383{
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100384 if (hfuzz->skipFeedbackOnTimeout && fuzzer->tmOutSignaled) {
385 return;
386 }
387
Robert Swiecki72a86982017-02-02 03:39:24 +0100388 LOG_D("New file size: %zu, Perf feedback new/cur (instr,branch): %" PRIu64 "/%" PRIu64 "/%"
389 PRIu64 "/%" PRIu64 ", BBcnt new/total: %" PRIu64 "/%" PRIu64, fuzzer->dynamicFileSz,
390 fuzzer->linux.hwCnts.cpuInstrCnt, hfuzz->linux.hwCnts.cpuInstrCnt,
391 fuzzer->linux.hwCnts.cpuBranchCnt, hfuzz->linux.hwCnts.cpuBranchCnt,
392 fuzzer->linux.hwCnts.newBBCnt, hfuzz->linux.hwCnts.bbCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200393
Robert Swiecki37498fd2017-03-12 21:12:54 +0100394 MX_SCOPED_LOCK(&hfuzz->feedback_mutex);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200395
Jagger34789a72016-09-08 00:36:09 +0200396 uint64_t softCntPc = 0UL;
Robert Swieckib27c8952017-05-23 23:38:04 +0200397 uint64_t softCntEdge = 0UL;
Jagger34789a72016-09-08 00:36:09 +0200398 uint64_t softCntCmp = 0UL;
Jagger251d0192016-08-24 00:54:04 +0200399 if (hfuzz->bbFd != -1) {
Jagger34789a72016-09-08 00:36:09 +0200400 softCntPc = ATOMIC_GET(hfuzz->feedback->pidFeedbackPc[fuzzer->fuzzNo]);
401 ATOMIC_CLEAR(hfuzz->feedback->pidFeedbackPc[fuzzer->fuzzNo]);
Robert Swieckib27c8952017-05-23 23:38:04 +0200402 softCntEdge = ATOMIC_GET(hfuzz->feedback->pidFeedbackEdge[fuzzer->fuzzNo]);
403 ATOMIC_CLEAR(hfuzz->feedback->pidFeedbackEdge[fuzzer->fuzzNo]);
Jagger34789a72016-09-08 00:36:09 +0200404 softCntCmp = ATOMIC_GET(hfuzz->feedback->pidFeedbackCmp[fuzzer->fuzzNo]);
405 ATOMIC_CLEAR(hfuzz->feedback->pidFeedbackCmp[fuzzer->fuzzNo]);
Jagger251d0192016-08-24 00:54:04 +0200406 }
Jaggerb01aaae2016-08-20 03:35:38 +0200407
Jagger302c2ea2016-09-07 03:54:43 +0200408 int64_t diff0 = hfuzz->linux.hwCnts.cpuInstrCnt - fuzzer->linux.hwCnts.cpuInstrCnt;
409 int64_t diff1 = hfuzz->linux.hwCnts.cpuBranchCnt - fuzzer->linux.hwCnts.cpuBranchCnt;
Jagger302c2ea2016-09-07 03:54:43 +0200410
Jagger8d0002c2016-08-17 03:44:23 +0200411 /*
412 * Coverage is the primary counter, the rest is secondary, and taken into consideration only
413 * if the coverage counter has not been changed
414 */
Robert Swieckib27c8952017-05-23 23:38:04 +0200415 if (fuzzer->linux.hwCnts.newBBCnt > 0 || softCntPc > 0 || softCntEdge > 0 || softCntCmp > 0
416 || diff0 < 0 || diff1 < 0) {
Robert Swiecki92ec8d22016-11-21 01:10:18 +0100417
418 if (diff0 < 0) {
419 hfuzz->linux.hwCnts.cpuInstrCnt = fuzzer->linux.hwCnts.cpuInstrCnt;
420 }
421 if (diff1 < 0) {
422 hfuzz->linux.hwCnts.cpuBranchCnt = fuzzer->linux.hwCnts.cpuBranchCnt;
423 }
Jagger247c3b42016-03-21 23:24:05 +0100424 hfuzz->linux.hwCnts.bbCnt += fuzzer->linux.hwCnts.newBBCnt;
Jagger34789a72016-09-08 00:36:09 +0200425 hfuzz->linux.hwCnts.softCntPc += softCntPc;
Robert Swieckib27c8952017-05-23 23:38:04 +0200426 hfuzz->linux.hwCnts.softCntEdge += softCntEdge;
Jagger34789a72016-09-08 00:36:09 +0200427 hfuzz->linux.hwCnts.softCntCmp += softCntCmp;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200428
Robert Swieckic296e782017-05-24 00:48:04 +0200429 if (hfuzz->useScreen) {
Robert Swiecki54525f22017-06-01 23:59:39 +0200430 LOG_I("NEW, size:%zu (i,b,edgs,ips,hw,cmp): %" PRIu64 "/%"
Robert Swieckic296e782017-05-24 00:48:04 +0200431 PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64, fuzzer->dynamicFileSz,
432 fuzzer->linux.hwCnts.cpuInstrCnt, fuzzer->linux.hwCnts.cpuBranchCnt, softCntEdge,
433 softCntPc, fuzzer->linux.hwCnts.newBBCnt, softCntCmp);
434 } else {
Robert Swiecki54525f22017-06-01 23:59:39 +0200435 LOG_I("NEW, size:%zu (i,b,edgs,ips,hw,cmp): %" PRIu64 "/%"
Robert Swieckic296e782017-05-24 00:48:04 +0200436 PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64 ", Tot:%" PRIu64
437 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64 "/%" PRIu64,
438 fuzzer->dynamicFileSz, fuzzer->linux.hwCnts.cpuInstrCnt,
439 fuzzer->linux.hwCnts.cpuBranchCnt, softCntEdge, softCntPc,
440 fuzzer->linux.hwCnts.newBBCnt, softCntCmp, hfuzz->linux.hwCnts.cpuInstrCnt,
441 hfuzz->linux.hwCnts.cpuBranchCnt, hfuzz->linux.hwCnts.softCntEdge,
442 hfuzz->linux.hwCnts.softCntPc, hfuzz->linux.hwCnts.bbCnt,
443 hfuzz->linux.hwCnts.softCntCmp);
444 }
Jagger395df022016-08-21 01:13:25 +0200445
Robert Swiecki37498fd2017-03-12 21:12:54 +0100446 fuzz_addFileToFileQ(hfuzz, fuzzer);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200447 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200448}
449
450static void fuzz_sanCovFeedback(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
451{
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100452 if (hfuzz->skipFeedbackOnTimeout && fuzzer->tmOutSignaled) {
453 return;
454 }
455
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200456 LOG_D
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100457 ("File size (Best/New): %zu, SanCov feedback (bb,dso): Best: [%" PRIu64
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200458 ",%" PRIu64 "] / New: [%" PRIu64 ",%" PRIu64 "], newBBs:%" PRIu64,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100459 fuzzer->dynamicFileSz, hfuzz->sanCovCnts.hitBBCnt,
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200460 hfuzz->sanCovCnts.iDsoCnt, fuzzer->sanCovCnts.hitBBCnt, fuzzer->sanCovCnts.iDsoCnt,
461 fuzzer->sanCovCnts.newBBCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200462
Robert Swiecki37498fd2017-03-12 21:12:54 +0100463 MX_SCOPED_LOCK(&hfuzz->feedback_mutex);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200464
Jaggerd5738372016-08-17 20:12:15 +0200465 int64_t diff0 = hfuzz->linux.hwCnts.cpuInstrCnt - fuzzer->linux.hwCnts.cpuInstrCnt;
466 int64_t diff1 = hfuzz->linux.hwCnts.cpuBranchCnt - fuzzer->linux.hwCnts.cpuBranchCnt;
Jaggerd5738372016-08-17 20:12:15 +0200467
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200468 /*
469 * Keep mutated seed if:
Robert Swiecki142f9412016-03-14 19:22:01 +0100470 * a) Newly discovered (not met before) BBs
471 * b) More instrumented DSOs loaded
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100472 *
Anestis Bechtsoudisb78cf602016-01-07 13:10:50 +0200473 * TODO: (a) method can significantly assist to further improvements in interesting areas
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200474 * discovery if combined with seeds pool/queue support. If a runtime queue is maintained
475 * more interesting seeds can be saved between runs instead of instantly discarded
476 * based on current absolute elitism (only one mutated seed is promoted).
477 */
Jaggerd5738372016-08-17 20:12:15 +0200478
479 bool newCov = (fuzzer->sanCovCnts.newBBCnt > 0
480 || hfuzz->sanCovCnts.iDsoCnt < fuzzer->sanCovCnts.iDsoCnt);
481
Robert Swieckid158aac2016-11-01 23:14:12 +0100482 if (newCov || (diff0 < 0 || diff1 < 0)) {
Robert Swiecki19d80f62017-02-19 20:00:58 +0100483 LOG_I("SanCov Update: fsize:%zu, newBBs:%" PRIu64
484 ", (Cur,New): %" PRIu64 "/%" PRIu64 ",%" PRIu64 "/%" PRIu64,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100485 fuzzer->dynamicFileSz, fuzzer->sanCovCnts.newBBCnt,
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200486 hfuzz->sanCovCnts.hitBBCnt, hfuzz->sanCovCnts.iDsoCnt, fuzzer->sanCovCnts.hitBBCnt,
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200487 fuzzer->sanCovCnts.iDsoCnt);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200488
Robert Swiecki142f9412016-03-14 19:22:01 +0100489 hfuzz->sanCovCnts.hitBBCnt += fuzzer->sanCovCnts.newBBCnt;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200490 hfuzz->sanCovCnts.dsoCnt = fuzzer->sanCovCnts.dsoCnt;
491 hfuzz->sanCovCnts.iDsoCnt = fuzzer->sanCovCnts.iDsoCnt;
492 hfuzz->sanCovCnts.crashesCnt += fuzzer->sanCovCnts.crashesCnt;
Robert Swiecki142f9412016-03-14 19:22:01 +0100493 hfuzz->sanCovCnts.newBBCnt = fuzzer->sanCovCnts.newBBCnt;
Anestis Bechtsoudisb78cf602016-01-07 13:10:50 +0200494
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200495 if (hfuzz->sanCovCnts.totalBBCnt < fuzzer->sanCovCnts.totalBBCnt) {
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200496 /* Keep only the max value (for dlopen cases) to measure total target coverage */
Anestis Bechtsoudis56e360f2016-01-11 14:29:17 +0200497 hfuzz->sanCovCnts.totalBBCnt = fuzzer->sanCovCnts.totalBBCnt;
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200498 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200499
Jaggerd5738372016-08-17 20:12:15 +0200500 hfuzz->linux.hwCnts.cpuInstrCnt = fuzzer->linux.hwCnts.cpuInstrCnt;
501 hfuzz->linux.hwCnts.cpuBranchCnt = fuzzer->linux.hwCnts.cpuBranchCnt;
Jaggerd5738372016-08-17 20:12:15 +0200502
Robert Swiecki37498fd2017-03-12 21:12:54 +0100503 fuzz_addFileToFileQ(hfuzz, fuzzer);
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200504 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200505}
506
Robert Swieckidecf14b2016-03-31 15:09:28 +0200507static void fuzz_fuzzLoop(honggfuzz_t * hfuzz, fuzzer_t * fuzzer)
Jagger190f0dc2015-09-05 16:41:22 +0200508{
Robert Swieckidecf14b2016-03-31 15:09:28 +0200509 fuzzer->pid = 0;
510 fuzzer->timeStartedMillis = util_timeNowMillis();
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100511 fuzzer->state = fuzz_getState(hfuzz);
Robert Swieckidecf14b2016-03-31 15:09:28 +0200512 fuzzer->crashFileName[0] = '\0';
513 fuzzer->pc = 0ULL;
514 fuzzer->backtrace = 0ULL;
515 fuzzer->access = 0ULL;
516 fuzzer->exception = 0;
517 fuzzer->report[0] = '\0';
518 fuzzer->mainWorker = true;
519 fuzzer->origFileName = "DYNAMIC";
520 fuzzer->flipRate = hfuzz->origFlipRate;
521 fuzzer->dynamicFileSz = 0;
Robert Swieckia96d78d2016-03-14 16:50:50 +0100522
Robert Swieckidecf14b2016-03-31 15:09:28 +0200523 fuzzer->sanCovCnts.hitBBCnt = 0ULL;
524 fuzzer->sanCovCnts.totalBBCnt = 0ULL;
525 fuzzer->sanCovCnts.dsoCnt = 0ULL;
526 fuzzer->sanCovCnts.newBBCnt = 0ULL;
527 fuzzer->sanCovCnts.crashesCnt = 0ULL;
Robert Swieckia96d78d2016-03-14 16:50:50 +0100528
Robert Swieckidecf14b2016-03-31 15:09:28 +0200529 fuzzer->linux.hwCnts.cpuInstrCnt = 0ULL;
530 fuzzer->linux.hwCnts.cpuBranchCnt = 0ULL;
Robert Swieckidecf14b2016-03-31 15:09:28 +0200531 fuzzer->linux.hwCnts.bbCnt = 0ULL;
532 fuzzer->linux.hwCnts.newBBCnt = 0ULL;
Jagger190f0dc2015-09-05 16:41:22 +0200533
Robert Swiecki80057e02017-01-26 21:19:28 +0100534 if (hfuzz->persistent == false) {
Robert Swieckieaf27322017-06-01 21:49:26 +0200535 fuzz_getFileName(hfuzz, fuzzer);
Robert Swiecki80057e02017-01-26 21:19:28 +0100536 }
Jagger190f0dc2015-09-05 16:41:22 +0200537
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100538 if (fuzzer->state == _HF_STATE_DYNAMIC_PRE) {
Robert Swieckiee266ac2016-10-03 02:25:59 +0200539 fuzzer->flipRate = 0.0f;
Robert Swiecki53c90af2017-04-24 22:32:50 +0200540 if (hfuzz->externalCommand) {
541 if (!fuzz_prepareFileExternally(hfuzz, fuzzer)) {
542 LOG_F("fuzz_prepareFileExternally() failed");
543 }
544 } else {
545 if (fuzz_prepareFile(hfuzz, fuzzer, false /* rewind */ ) == false) {
546 fuzz_setState(hfuzz, _HF_STATE_DYNAMIC_MAIN);
547 fuzzer->state = fuzz_getState(hfuzz);
548 }
Robert Swieckiee266ac2016-10-03 02:25:59 +0200549 }
Robert Swiecki92a31362017-02-24 16:21:40 +0100550 }
Robert Swiecki1a994732017-05-31 18:32:21 +0200551
552 if (ATOMIC_GET(hfuzz->terminating) == true) {
553 return;
554 }
555
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100556 if (fuzzer->state == _HF_STATE_DYNAMIC_MAIN) {
Robert Swieckidecf14b2016-03-31 15:09:28 +0200557 if (!fuzz_prepareFileDynamically(hfuzz, fuzzer)) {
Jagger1d8e0c62016-04-02 02:22:40 +0200558 LOG_F("fuzz_prepareFileDynamically() failed");
Robert Swieckia96d78d2016-03-14 16:50:50 +0100559 }
Jagger190f0dc2015-09-05 16:41:22 +0200560 }
Robert Swieckie6a4ff32017-02-24 17:07:05 +0100561 if (fuzzer->state == _HF_STATE_STATIC) {
Robert Swiecki92a31362017-02-24 16:21:40 +0100562 if (hfuzz->externalCommand) {
563 if (!fuzz_prepareFileExternally(hfuzz, fuzzer)) {
564 LOG_F("fuzz_prepareFileExternally() failed");
565 }
566 } else {
567 if (!fuzz_prepareFile(hfuzz, fuzzer, true /* rewind */ )) {
568 LOG_F("fuzz_prepareFile() failed");
569 }
570 }
Jagger190f0dc2015-09-05 16:41:22 +0200571
Robert Swiecki92a31362017-02-24 16:21:40 +0100572 if (hfuzz->postExternalCommand != NULL) {
573 if (!fuzz_postProcessFile(hfuzz, fuzzer)) {
574 LOG_F("fuzz_postProcessFile() failed");
575 }
Robert Swieckiee266ac2016-10-03 02:25:59 +0200576 }
577 }
578
Robert Swiecki940a0802016-11-02 12:42:09 +0100579 if (subproc_Run(hfuzz, fuzzer) == false) {
580 LOG_F("subproc_Run()");
Jagger190f0dc2015-09-05 16:41:22 +0200581 }
582
Jaggera34b3022016-04-02 02:20:40 +0200583 if (hfuzz->persistent == false) {
584 unlink(fuzzer->fileName);
585 }
Jagger190f0dc2015-09-05 16:41:22 +0200586
Robert Swiecki53ec9e42017-02-15 20:34:27 +0100587 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
588 fuzz_perfFeedback(hfuzz, fuzzer);
589 }
590 if (hfuzz->useSanCov) {
591 fuzz_sanCovFeedback(hfuzz, fuzzer);
Robert Swiecki0f937af2016-03-30 18:19:16 +0200592 }
Jagger190f0dc2015-09-05 16:41:22 +0200593
Robert Swieckidecf14b2016-03-31 15:09:28 +0200594 if (hfuzz->useVerifier && (fuzzer->crashFileName[0] != 0) && fuzzer->backtrace) {
595 if (!fuzz_runVerifier(hfuzz, fuzzer)) {
596 LOG_I("Failed to verify %s", fuzzer->crashFileName);
Anestis Bechtsoudis3085f222015-09-27 18:35:26 +0300597 }
Anestis Bechtsoudis5c86ebc2015-09-27 18:06:43 +0300598 }
599
Robert Swiecki216fef62016-10-20 18:32:58 +0200600 report_Report(hfuzz, fuzzer->report);
Jagger190f0dc2015-09-05 16:41:22 +0200601}
602
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000603static void *fuzz_threadNew(void *arg)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000604{
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000605 honggfuzz_t *hfuzz = (honggfuzz_t *) arg;
Robert Swiecki0ec98112017-02-03 02:08:14 +0100606 unsigned int fuzzNo = ATOMIC_POST_INC(hfuzz->threadsActiveCnt);
607 LOG_I("Launched new fuzzing thread, no. #%" PRId32, fuzzNo);
Anestis Bechtsoudis02b99be2015-12-27 11:53:01 +0200608
Robert Swieckidecf14b2016-03-31 15:09:28 +0200609 fuzzer_t fuzzer = {
610 .pid = 0,
611 .persistentPid = 0,
Robert Swiecki147d4672017-01-29 02:49:06 +0100612 .dynamicFile = util_Calloc(hfuzz->maxFileSz),
Jaggerfa3544a2016-08-30 02:55:55 +0200613 .fuzzNo = fuzzNo,
Jagger93253f72016-09-01 22:40:12 +0200614 .persistentSock = -1,
Robert Swiecki013bc9c2016-12-12 17:31:06 +0100615 .tmOutSignaled = false,
Robert Swiecki47f5de12017-03-28 03:25:55 +0200616 .fileName = "[UNSET]",
Robert Swiecki12800cd2016-03-31 15:38:10 +0200617
Robert Swieckib692f282016-08-25 16:21:08 +0200618 .linux.attachedPid = 0,
Robert Swieckidecf14b2016-03-31 15:09:28 +0200619 };
Jagger4fe18692016-04-22 23:15:07 +0200620 defer {
621 free(fuzzer.dynamicFile);
622 };
Robert Swieckidecf14b2016-03-31 15:09:28 +0200623
624 if (arch_archThreadInit(hfuzz, &fuzzer) == false) {
Robert Swiecki0f937af2016-03-30 18:19:16 +0200625 LOG_F("Could not initialize the thread");
626 }
627
Robert Swieckia96d78d2016-03-14 16:50:50 +0100628 for (;;) {
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200629 /* Check if dry run mode with verifier enabled */
Robert Swieckia96d78d2016-03-14 16:50:50 +0100630 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Jaggerd34417d2016-03-16 01:26:54 +0100631 if (ATOMIC_POST_INC(hfuzz->mutationsCnt) >= hfuzz->fileCnt) {
632 ATOMIC_POST_INC(hfuzz->threadsFinished);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200633 break;
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200634 }
635 }
636 /* Check for max iterations limit if set */
Jaggerd34417d2016-03-16 01:26:54 +0100637 else if ((ATOMIC_POST_INC(hfuzz->mutationsCnt) >= hfuzz->mutationsMax)
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200638 && hfuzz->mutationsMax) {
Jaggerd34417d2016-03-16 01:26:54 +0100639 ATOMIC_POST_INC(hfuzz->threadsFinished);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200640 break;
Robert Swiecki8d01b012017-02-19 15:48:11 +0100641 }
642
Robert Swieckidecf14b2016-03-31 15:09:28 +0200643 fuzz_fuzzLoop(hfuzz, &fuzzer);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200644
645 if (ATOMIC_GET(hfuzz->terminating) == true) {
646 break;
647 }
648
649 if (hfuzz->exitUponCrash && ATOMIC_GET(hfuzz->crashesCnt) > 0) {
650 LOG_I("Seen a crash. Terminating all fuzzing threads");
651 ATOMIC_SET(hfuzz->terminating, true);
652 break;
653 }
654
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000655 }
Robert Swiecki069b48f2017-05-31 01:00:08 +0200656
657 LOG_I("Terminating thread no. #%" PRId32, fuzzNo);
658 ATOMIC_POST_INC(hfuzz->threadsFinished);
Robert Swieckiaa623952017-06-01 02:50:41 +0200659 pthread_kill(fuzz_mainThread, SIGALRM);
Robert Swiecki069b48f2017-05-31 01:00:08 +0200660 return NULL;
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000661}
662
Robert Swiecki33fb2842017-02-19 05:39:50 +0100663static void fuzz_runThread(honggfuzz_t * hfuzz, pthread_t * thread, void *(*thread_func) (void *))
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000664{
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000665 pthread_attr_t attr;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000666
robert.swiecki@gmail.com6f5c2392015-02-16 18:13:09 +0000667 pthread_attr_init(&attr);
Robert Swiecki33fb2842017-02-19 05:39:50 +0100668 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000669 pthread_attr_setstacksize(&attr, _HF_PTHREAD_STACKSIZE);
robert.swiecki@gmail.com011981f2015-02-17 19:06:44 +0000670 pthread_attr_setguardsize(&attr, (size_t) sysconf(_SC_PAGESIZE));
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000671
Robert Swiecki33fb2842017-02-19 05:39:50 +0100672 if (pthread_create(thread, &attr, thread_func, (void *)hfuzz) < 0) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200673 PLOG_F("Couldn't create a new thread");
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000674 }
675
Robert Swiecki33fb2842017-02-19 05:39:50 +0100676 pthread_attr_destroy(&attr);
677
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000678 return;
679}
680
Robert Swiecki33fb2842017-02-19 05:39:50 +0100681void fuzz_threadsStart(honggfuzz_t * hfuzz, pthread_t * threads)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000682{
Jagger6113c432015-09-24 05:00:28 +0200683 fuzz_mainThread = pthread_self();
684
robert.swiecki@gmail.com956276a2015-04-16 16:51:52 +0000685 if (!arch_archInit(hfuzz)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200686 LOG_F("Couldn't prepare arch for fuzzing");
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000687 }
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200688 if (!sanitizers_Init(hfuzz)) {
689 LOG_F("Couldn't prepare sanitizer options");
690 }
Jagger00265602016-03-10 02:36:27 +0100691 if (!sancov_Init(hfuzz)) {
692 LOG_F("Couldn't prepare sancov options");
693 }
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000694
Robert Swieckia96d78d2016-03-14 16:50:50 +0100695 if (hfuzz->useSanCov || hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
Jaggerebe19292016-03-17 00:11:44 +0100696 fuzz_setState(hfuzz, _HF_STATE_DYNAMIC_PRE);
Robert Swieckia96d78d2016-03-14 16:50:50 +0100697 } else {
Jaggerebe19292016-03-17 00:11:44 +0100698 fuzz_setState(hfuzz, _HF_STATE_STATIC);
Robert Swieckia96d78d2016-03-14 16:50:50 +0100699 }
700
Jaggerea39a8f2015-09-05 00:57:22 +0200701 for (size_t i = 0; i < hfuzz->threadsMax; i++) {
Robert Swiecki33fb2842017-02-19 05:39:50 +0100702 fuzz_runThread(hfuzz, &threads[i], fuzz_threadNew);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000703 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000704}
Robert Swiecki33fb2842017-02-19 05:39:50 +0100705
706void fuzz_threadsStop(honggfuzz_t * hfuzz, pthread_t * threads)
707{
708 for (size_t i = 0; i < hfuzz->threadsMax; i++) {
709 void *retval;
710 if (pthread_join(threads[i], &retval) != 0) {
711 PLOG_F("Couldn't pthread_join() thread: %zu", i);
712 }
713 }
714 LOG_I("All threads done");
715}