blob: e3bc19296e0151929ba068cef56206f0a877e6a9 [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 "common.h"
27#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/mman.h>
40#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>
44#include <sys/wait.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000045#include <time.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000046#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000047
robert.swiecki3bb518c2010-10-14 00:48:24 +000048#include "arch.h"
Jagger0764ad72015-09-06 01:11:08 +020049#include "display.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000050#include "files.h"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000051#include "log.h"
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +000052#include "mangle.h"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000053#include "report.h"
54#include "util.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000055
Anestis Bechtsoudisb2887c42015-08-08 08:07:08 +030056#if defined(__ANDROID__) && !defined(__NR_fork)
Anestis Bechtsoudiscfc39fb2015-08-06 10:31:36 +030057#include <sys/syscall.h>
58
59pid_t honggfuzz_aarch64_fork(void)
60{
Jaggerd628a702015-08-23 12:59:37 +020061 return syscall(__NR_clone, SIGCHLD, 0, 0, 0);
Anestis Bechtsoudiscfc39fb2015-08-06 10:31:36 +030062}
Jaggerd628a702015-08-23 12:59:37 +020063
64#define fork honggfuzz_aarch64_fork
Anestis Bechtsoudiscfc39fb2015-08-06 10:31:36 +030065#endif
Anestis Bechtsoudiscfc39fb2015-08-06 10:31:36 +030066
robert.swiecki@gmail.comcf4e8d02015-04-23 15:53:39 +000067static int fuzz_sigReceived = 0;
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +000068
robert.swiecki@gmail.com77294502015-04-23 15:41:15 +000069static void fuzz_sigHandler(int sig, siginfo_t * si, void *v)
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +000070{
robert.swiecki@gmail.comcf4e8d02015-04-23 15:53:39 +000071 fuzz_sigReceived = sig;
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +000072 return;
robert.swiecki@gmail.com77294502015-04-23 15:41:15 +000073 if (si == NULL) {
74 return;
75 }
76 if (v == NULL) {
77 return;
78 }
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +000079}
80
robert.swiecki3bb518c2010-10-14 00:48:24 +000081static void fuzz_getFileName(honggfuzz_t * hfuzz, char *fileName)
82{
robert.swieckiba512632011-01-28 11:57:26 +000083 struct timeval tv;
84 gettimeofday(&tv, NULL);
85
Anestis Bechtsoudisd9680532015-09-06 17:37:05 +030086 snprintf(fileName, PATH_MAX, "%s/.honggfuzz.%d.%lu.%llx.%s", hfuzz->workDir, (int)getpid(),
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +000087 (unsigned long int)tv.tv_sec, (unsigned long long int)util_rndGet(0, 1ULL << 62),
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +000088 hfuzz->fileExtn);
robert.swiecki3bb518c2010-10-14 00:48:24 +000089
90 return;
91}
92
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +000093static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index)
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000094{
Jagger421aca82015-09-05 14:09:47 +020095 MX_LOCK(&hfuzz->dynamicFile_mutex);
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +000096
robert.swiecki@gmail.com7aad7172015-03-03 04:34:15 +000097 if (hfuzz->inputFile && hfuzz->branchBestCnt[0] == 0 && hfuzz->branchBestCnt[1] == 0
robert.swiecki7185c262015-03-20 17:21:28 +000098 && hfuzz->branchBestCnt[2] == 0 && hfuzz->branchBestCnt[3] == 0) {
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +000099 size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], hfuzz->dynamicFileBest,
100 hfuzz->maxFileSz);
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000101 if (fileSz == 0) {
Jagger421aca82015-09-05 14:09:47 +0200102 MX_UNLOCK(&hfuzz->dynamicFile_mutex);
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000103 LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]);
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +0000104 return false;
105 }
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000106 hfuzz->dynamicFileBestSz = fileSz;
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +0000107 }
108
robert.swiecki@gmail.com060a9dd2015-02-28 06:37:27 +0000109 if (hfuzz->dynamicFileBestSz > hfuzz->maxFileSz) {
110 LOGMSG(l_FATAL, "Current BEST file Sz > maxFileSz (%zu > %zu)", hfuzz->dynamicFileBestSz,
111 hfuzz->maxFileSz);
112 }
113
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000114 fuzzer->dynamicFileSz = hfuzz->dynamicFileBestSz;
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +0000115 memcpy(fuzzer->dynamicFile, hfuzz->dynamicFileBest, hfuzz->dynamicFileBestSz);
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000116
Jagger421aca82015-09-05 14:09:47 +0200117 MX_UNLOCK(&hfuzz->dynamicFile_mutex);
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +0000118
robert.swiecki@gmail.com141c4522015-02-19 15:49:23 +0000119 /* The first pass should be on an empty/initial file */
robert.swiecki2a953692015-03-16 19:33:37 +0000120 if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0
121 || hfuzz->branchBestCnt[3] > 0) {
robert.swiecki@gmail.comace40862015-03-08 07:09:56 +0000122 mangle_Resize(hfuzz, fuzzer->dynamicFile, &fuzzer->dynamicFileSz);
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +0000123 mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz);
robert.swiecki@gmail.com141c4522015-02-19 15:49:23 +0000124 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000125
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000126 if (files_writeBufToFile
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000127 (fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz,
128 O_WRONLY | O_CREAT | O_EXCL | O_TRUNC) == false) {
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000129 LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName);
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +0000130 return false;
131 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000132
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000133 return true;
robert.swiecki@gmail.comd7aed312015-02-03 21:26:37 +0000134}
135
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000136static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000137{
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000138 size_t fileSz =
139 files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz);
140 if (fileSz == 0UL) {
141 LOGMSG(l_ERROR, "Couldn't read contents of '%s'", hfuzz->files[rnd_index]);
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000142 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000143 }
144
robert.swiecki@gmail.comace40862015-03-08 07:09:56 +0000145 mangle_Resize(hfuzz, fuzzer->dynamicFile, &fileSz);
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000146 mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fileSz);
robert.swiecki@gmail.comc070b942015-02-25 18:29:19 +0000147
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000148 if (files_writeBufToFile
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000149 (fuzzer->fileName, fuzzer->dynamicFile, fileSz, O_WRONLY | O_CREAT | O_EXCL) == false) {
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000150 LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName);
robert.swiecki@gmail.come7680522015-02-22 22:22:37 +0000151 return false;
152 }
153
robert.swiecki3bb518c2010-10-14 00:48:24 +0000154 return true;
155}
156
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000157static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000158{
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000159 int dstfd = open(fuzzer->fileName, O_CREAT | O_EXCL | O_RDWR, 0644);
robert.swiecki3d505e22010-10-14 01:17:17 +0000160 if (dstfd == -1) {
Anestis Bechtsoudisd9680532015-09-06 17:37:05 +0300161 LOGMSG_P(l_ERROR, "Couldn't create a temporary file '%s'", fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000162 return false;
163 }
164
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000165 LOGMSG(l_DEBUG, "Created '%f' as an input file", fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000166
167 if (hfuzz->inputFile) {
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000168 size_t fileSz =
169 files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz);
170 if (fileSz == 0UL) {
171 LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]);
172 unlink(fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000173 return false;
174 }
175
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000176 if (files_writeToFd(dstfd, fuzzer->dynamicFile, fileSz) == false) {
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000177 close(dstfd);
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000178 unlink(fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000179 return false;
180 }
robert.swiecki3d505e22010-10-14 01:17:17 +0000181 }
182
robert.swiecki3d505e22010-10-14 01:17:17 +0000183 close(dstfd);
184
robert.swiecki@gmail.combb2b4aa2015-03-05 01:48:46 +0000185 pid_t pid = fork();
robert.swiecki3bb518c2010-10-14 00:48:24 +0000186 if (pid == -1) {
robert.swiecki@gmail.com8a9df0e2015-02-13 17:08:06 +0000187 LOGMSG_P(l_ERROR, "Couldn't vfork");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000188 return false;
189 }
190
191 if (!pid) {
192 /*
robert.swiecki@gmail.comcdf18f92015-02-11 22:22:18 +0000193 * child performs the external file modifications
robert.swiecki3bb518c2010-10-14 00:48:24 +0000194 */
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000195 execl(hfuzz->externalCommand, hfuzz->externalCommand, fuzzer->fileName, NULL);
196 LOGMSG_P(l_FATAL, "Couldn't execute '%s %s'", hfuzz->externalCommand, fuzzer->fileName);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000197 return false;
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000198 }
robert.swiecki@gmail.com8a9df0e2015-02-13 17:08:06 +0000199
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000200 /*
201 * parent waits until child is done fuzzing the input file
202 */
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000203 int childStatus;
204 int flags = 0;
robert.swiecki@gmail.coma2291182015-02-13 16:56:27 +0000205#if defined(__WNOTHREAD)
206 flags |= __WNOTHREAD;
robert.swiecki@gmail.com8a9df0e2015-02-13 17:08:06 +0000207#endif /* defined(__WNOTHREAD) */
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000208 while (wait4(pid, &childStatus, flags, NULL) != pid) ;
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000209 if (WIFEXITED(childStatus)) {
210 LOGMSG(l_DEBUG, "External command exited with status %d", WEXITSTATUS(childStatus));
211 return true;
212 }
213 if (WIFSIGNALED(childStatus)) {
robert.swiecki@gmail.coma2291182015-02-13 16:56:27 +0000214 LOGMSG(l_ERROR, "External command terminated with signal %d", WTERMSIG(childStatus));
robert.swiecki3d505e22010-10-14 01:17:17 +0000215 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000216 }
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000217 LOGMSG(l_FATAL, "External command terminated abnormally, status: %d", childStatus);
218 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000219
220 abort(); /* NOTREACHED */
221}
222
Jagger190f0dc2015-09-05 16:41:22 +0200223static void fuzz_fuzzLoop(honggfuzz_t * hfuzz)
224{
225 fuzzer_t fuzzer = {
226 .pid = 0,
227 .timeStartedMillis = util_timeNowMillis(),
228 .pc = 0ULL,
229 .backtrace = 0ULL,
230 .access = 0ULL,
231 .exception = 0,
232 .dynamicFileSz = 0,
233 .dynamicFile = malloc(hfuzz->maxFileSz),
Jagger4eda06e2015-09-05 16:45:21 +0200234 .branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0},
Jagger190f0dc2015-09-05 16:41:22 +0200235 .report = {'\0'}
236 };
237 if (fuzzer.dynamicFile == NULL) {
238 LOGMSG(l_FATAL, "malloc(%zu) failed", hfuzz->maxFileSz);
239 }
240
241 int rnd_index = util_rndGet(0, hfuzz->fileCnt - 1);
242 strncpy(fuzzer.origFileName, files_basename(hfuzz->files[rnd_index]), PATH_MAX);
243 fuzz_getFileName(hfuzz, fuzzer.fileName);
244
245 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
246 if (!fuzz_prepareFileDynamically(hfuzz, &fuzzer, rnd_index)) {
247 exit(EXIT_FAILURE);
248 }
249 } else if (hfuzz->externalCommand != NULL) {
250 if (!fuzz_prepareFileExternally(hfuzz, &fuzzer, rnd_index)) {
251 exit(EXIT_FAILURE);
252 }
253 } else {
254 if (!fuzz_prepareFile(hfuzz, &fuzzer, rnd_index)) {
255 exit(EXIT_FAILURE);
256 }
257 }
258
259#if defined(_HF_ARCH_LINUX) && defined(__NR_fork)
260#include <unistd.h>
261#include <sys/syscall.h>
262 fuzzer.pid = syscall(__NR_fork);
263#else /* defined(_HF_ARCH_LINUX) */
264 fuzzer.pid = fork();
265#endif /* defined(_HF_ARCH_LINUX) */
266
267 if (fuzzer.pid == -1) {
268 LOGMSG_P(l_FATAL, "Couldn't fork");
269 exit(EXIT_FAILURE);
270 }
271
272 if (!fuzzer.pid) {
273 /*
274 * Ok, kill the parent if this fails
275 */
276 if (!arch_launchChild(hfuzz, fuzzer.fileName)) {
277 LOGMSG(l_ERROR, "Error launching child process, killing parent");
278 exit(EXIT_FAILURE);
279 }
280 }
281
282 LOGMSG(l_INFO, "Launched new process, pid: %d, (concurrency: %d)", fuzzer.pid,
283 hfuzz->threadsMax);
284
285 arch_reapChild(hfuzz, &fuzzer);
286 unlink(fuzzer.fileName);
287
288 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
289 MX_LOCK(&hfuzz->dynamicFile_mutex);
290
291 LOGMSG(l_INFO,
292 "File size (New/Best): %zu/%zu, Perf feedback (instr/branch/block-edge/custom): Best: [%"
293 PRIu64 ",%" PRIu64 ",%" PRIu64 ",%" PRIu64 "] / New: [%" PRIu64 ",%" PRIu64 ",%"
294 PRIu64 ",%" PRIu64 "]", fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz,
295 hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2],
296 hfuzz->branchBestCnt[3], fuzzer.branchCnt[0], fuzzer.branchCnt[1],
297 fuzzer.branchCnt[2], fuzzer.branchCnt[3]);
298
299 int64_t diff0 = hfuzz->branchBestCnt[0] - fuzzer.branchCnt[0];
300 int64_t diff1 = hfuzz->branchBestCnt[1] - fuzzer.branchCnt[1];
301 int64_t diff2 = hfuzz->branchBestCnt[2] - fuzzer.branchCnt[2];
302 int64_t diff3 = hfuzz->branchBestCnt[3] - fuzzer.branchCnt[3];
303
304 if (diff2 < 0) {
305 diff0 = hfuzz->branchBestCnt[0] = fuzzer.branchCnt[0] = 0;
306 diff1 = hfuzz->branchBestCnt[1] = fuzzer.branchCnt[1] = 0;
307 diff3 = hfuzz->branchBestCnt[3] = fuzzer.branchCnt[3] = 0;
308 }
309
310 if (diff0 <= hfuzz->dynamicRegressionCnt && diff1 <= hfuzz->dynamicRegressionCnt
311 && diff2 <= hfuzz->dynamicRegressionCnt && diff3 <= hfuzz->dynamicRegressionCnt) {
312
Jagger0764ad72015-09-06 01:11:08 +0200313 LOGMSG(l_INFO,
Jagger190f0dc2015-09-05 16:41:22 +0200314 "New BEST feedback: File Size (New/Old): %zu/%zu', Perf feedback (Curr, High): %"
315 PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 ",%" PRId64 "/%" PRId64 "/%"
316 PRId64 "/%" PRId64, fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz,
317 fuzzer.branchCnt[0], fuzzer.branchCnt[1], fuzzer.branchCnt[2],
318 fuzzer.branchCnt[3], hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1],
319 hfuzz->branchBestCnt[2], hfuzz->branchBestCnt[3]);
320
321 memcpy(hfuzz->dynamicFileBest, fuzzer.dynamicFile, fuzzer.dynamicFileSz);
322
323 hfuzz->dynamicFileBestSz = fuzzer.dynamicFileSz;
324 hfuzz->branchBestCnt[0] =
325 fuzzer.branchCnt[0] >
326 hfuzz->branchBestCnt[0] ? fuzzer.branchCnt[0] : hfuzz->branchBestCnt[0];
327 hfuzz->branchBestCnt[1] =
328 fuzzer.branchCnt[1] >
329 hfuzz->branchBestCnt[1] ? fuzzer.branchCnt[1] : hfuzz->branchBestCnt[1];
330 hfuzz->branchBestCnt[2] =
331 fuzzer.branchCnt[2] >
332 hfuzz->branchBestCnt[2] ? fuzzer.branchCnt[2] : hfuzz->branchBestCnt[2];
333 hfuzz->branchBestCnt[3] =
334 fuzzer.branchCnt[3] >
335 hfuzz->branchBestCnt[3] ? fuzzer.branchCnt[3] : hfuzz->branchBestCnt[3];
336
Anestis Bechtsoudisd9680532015-09-06 17:37:05 +0300337 char currentBest[PATH_MAX], currentBestTmp[PATH_MAX];
338 snprintf(currentBest, PATH_MAX, "%s/CURRENT_BEST", hfuzz->workDir);
339 snprintf(currentBestTmp, PATH_MAX, "%s/.tmp.CURRENT_BEST", hfuzz->workDir);
340
Jagger190f0dc2015-09-05 16:41:22 +0200341 if (files_writeBufToFile
Anestis Bechtsoudisd9680532015-09-06 17:37:05 +0300342 (currentBestTmp, fuzzer.dynamicFile, fuzzer.dynamicFileSz,
Jagger190f0dc2015-09-05 16:41:22 +0200343 O_WRONLY | O_CREAT | O_TRUNC)) {
Anestis Bechtsoudisd9680532015-09-06 17:37:05 +0300344 rename(currentBestTmp, currentBest);
Jagger190f0dc2015-09-05 16:41:22 +0200345 }
346 }
347 MX_UNLOCK(&hfuzz->dynamicFile_mutex);
348 }
349
350 report_Report(hfuzz, fuzzer.report);
351 free(fuzzer.dynamicFile);
352
353}
354
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000355static void *fuzz_threadNew(void *arg)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000356{
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000357 honggfuzz_t *hfuzz = (honggfuzz_t *) arg;
Jaggerea39a8f2015-09-05 00:57:22 +0200358 for (;;) {
Jagger421aca82015-09-05 14:09:47 +0200359 MX_LOCK(&hfuzz->threads_mutex);
Jaggera81f7e02015-09-05 02:42:05 +0200360 if (hfuzz->mutationsMax && hfuzz->mutationsCnt >= hfuzz->mutationsMax) {
Jaggerea39a8f2015-09-05 00:57:22 +0200361 hfuzz->threadsFinished++;
Jagger421aca82015-09-05 14:09:47 +0200362 MX_UNLOCK(&hfuzz->threads_mutex);
Jaggerea39a8f2015-09-05 00:57:22 +0200363 sem_post(hfuzz->sem);
364 return NULL;
365 }
Jagger0764ad72015-09-06 01:11:08 +0200366 __sync_fetch_and_add(&hfuzz->mutationsCnt, 1UL);
Jagger421aca82015-09-05 14:09:47 +0200367 MX_UNLOCK(&hfuzz->threads_mutex);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000368
Jagger190f0dc2015-09-05 16:41:22 +0200369 fuzz_fuzzLoop(hfuzz);
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000370 }
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000371}
372
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000373static void fuzz_runThread(honggfuzz_t * hfuzz, void *(*thread) (void *))
374{
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000375 pthread_attr_t attr;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000376
robert.swiecki@gmail.com6f5c2392015-02-16 18:13:09 +0000377 pthread_attr_init(&attr);
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000378 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000379 pthread_attr_setstacksize(&attr, _HF_PTHREAD_STACKSIZE);
robert.swiecki@gmail.com011981f2015-02-17 19:06:44 +0000380 pthread_attr_setguardsize(&attr, (size_t) sysconf(_SC_PAGESIZE));
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000381
robert.swiecki@gmail.com01b6dd42015-02-16 18:11:28 +0000382 pthread_t t;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000383 if (pthread_create(&t, &attr, thread, (void *)hfuzz) < 0) {
384 LOGMSG_P(l_FATAL, "Couldn't create a new thread");
385 }
386
387 return;
388}
389
Jagger0764ad72015-09-06 01:11:08 +0200390bool fuzz_setupTimer(void)
391{
392 struct itimerval it = {
393 .it_value = {.tv_sec = 1,.tv_usec = 0},
394 .it_interval = {.tv_sec = 1,.tv_usec = 0},
395 };
396 if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
397 LOGMSG_P(l_ERROR, "setitimer(ITIMER_REAL)");
398 return false;
399 }
400 struct sigaction sa = {
401 .sa_handler = SIG_IGN,
402 .sa_flags = 0,
403 .sa_restorer = NULL,
404 };
405 sigemptyset(&sa.sa_mask);
406 if (sigaction(SIGALRM, &sa, NULL) == -1) {
407 LOGMSG_P(l_ERROR, "sigaction(SIGALRM)");
408 return false;
409 }
410 return true;
411
412 return true;
413}
414
robert.swiecki3bb518c2010-10-14 00:48:24 +0000415void fuzz_main(honggfuzz_t * hfuzz)
416{
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000417 struct sigaction sa = {
robert.swiecki@gmail.com77294502015-04-23 15:41:15 +0000418 .sa_sigaction = fuzz_sigHandler,
419 .sa_flags = SA_SIGINFO,
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000420 };
421 sigemptyset(&sa.sa_mask);
422 if (sigaction(SIGTERM, &sa, NULL) == -1) {
Jaggerea39a8f2015-09-05 00:57:22 +0200423 LOGMSG_P(l_FATAL, "sigaction(SIGTERM) failed");
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000424 }
425 if (sigaction(SIGINT, &sa, NULL) == -1) {
Jaggerea39a8f2015-09-05 00:57:22 +0200426 LOGMSG_P(l_FATAL, "sigaction(SIGINT) failed");
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000427 }
428 if (sigaction(SIGQUIT, &sa, NULL) == -1) {
Jaggerea39a8f2015-09-05 00:57:22 +0200429 LOGMSG_P(l_FATAL, "sigaction(SIGQUIT) failed");
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000430 }
Jagger0764ad72015-09-06 01:11:08 +0200431 if (fuzz_setupTimer() == false) {
432 LOGMSG(l_FATAL, "fuzz_setupTimer()");
433 }
Anestis Bechtsoudisc1f6faa2015-07-31 05:32:19 +0300434 // Android doesn't support named semaphores
435#if !defined(__ANDROID__)
tlogic@gmail.com479f0f92015-04-15 18:03:16 +0000436 /*
437 * In OS X semName cannot exceed SEM_NAME_LEN characters otherwise
438 * sem_open() will fail with ENAMETOOLONG. Apple, doesn't define
439 * SEM_NAME_LEN in any header file so we define it here using the value
440 * of PSEMNAMLEN from bsd/kern/posix_sem.c.
441 */
robert.swiecki@gmail.comdf286942015-04-15 21:45:25 +0000442#define _HF_SEM_NAME_LEN 31
443 char semName[_HF_SEM_NAME_LEN];
444 snprintf(semName, sizeof(semName), "/hgfz.%d.%" PRIx64, getpid(), util_rndGet(1, 1ULL << 62));
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000445
Jaggerea39a8f2015-09-05 00:57:22 +0200446 hfuzz->sem = sem_open(semName, O_CREAT, 0644, 0);
Anestis Bechtsoudisc1f6faa2015-07-31 05:32:19 +0300447
448#else /* !defined(__ANDROID__) */
449 sem_t semName;
Jaggerea39a8f2015-09-05 00:57:22 +0200450 if (sem_init(&semName, 1, 0)) {
Anestis Bechtsoudisc1f6faa2015-07-31 05:32:19 +0300451 LOGMSG(l_FATAL, "sem_init() failed");
452 }
453 hfuzz->sem = &semName;
454#endif /* defined(__ANDROID__) */
Anestis Bechtsoudiscfc39fb2015-08-06 10:31:36 +0300455
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000456 if (hfuzz->sem == SEM_FAILED) {
457 LOGMSG_P(l_FATAL, "sem_open() failed");
robert.swiecki@gmail.come7635392015-02-11 16:17:49 +0000458 }
robert.swiecki@gmail.come4683202015-04-02 00:10:52 +0000459
robert.swiecki@gmail.com956276a2015-04-16 16:51:52 +0000460 if (!arch_archInit(hfuzz)) {
461 LOGMSG(l_FATAL, "Couldn't prepare arch for fuzzing");
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000462 }
463
Jaggerea39a8f2015-09-05 00:57:22 +0200464 for (size_t i = 0; i < hfuzz->threadsMax; i++) {
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000465 fuzz_runThread(hfuzz, fuzz_threadNew);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000466 }
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000467
Jaggerea39a8f2015-09-05 00:57:22 +0200468 for (;;) {
469 if (sem_wait(hfuzz->sem) == -1 && errno != EINTR) {
470 LOGMSG_P(l_FATAL, "sem_wait() failed");
471 }
472 if (fuzz_sigReceived > 0) {
473 break;
474 }
Jagger0764ad72015-09-06 01:11:08 +0200475
Jagger1df23442015-09-06 03:02:21 +0200476 if (hfuzz->useScreen) {
477 display_Display(hfuzz);
478 }
Jagger0764ad72015-09-06 01:11:08 +0200479
Jagger421aca82015-09-05 14:09:47 +0200480 MX_LOCK(&hfuzz->threads_mutex);
Jaggerea39a8f2015-09-05 00:57:22 +0200481 if (hfuzz->threadsFinished == hfuzz->threadsMax) {
Jagger421aca82015-09-05 14:09:47 +0200482 MX_UNLOCK(&hfuzz->threads_mutex);
Jaggerea39a8f2015-09-05 00:57:22 +0200483 break;
484 }
Jagger421aca82015-09-05 14:09:47 +0200485 MX_UNLOCK(&hfuzz->threads_mutex);
Jaggerea39a8f2015-09-05 00:57:22 +0200486 }
487
488 LOGMSG(l_INFO, "Finished fuzzing %zu times", hfuzz->mutationsCnt);
robert.swiecki@gmail.comcf4e8d02015-04-23 15:53:39 +0000489
490 if (fuzz_sigReceived > 0) {
robert.swiecki@gmail.com92fe8cd2015-04-25 01:33:33 +0000491 LOGMSG(l_INFO, "Signal %d received, terminating", fuzz_sigReceived);
robert.swiecki@gmail.comcf4e8d02015-04-23 15:53:39 +0000492 signal(SIGTERM, SIG_DFL);
493 signal(SIGINT, SIG_DFL);
494 signal(SIGQUIT, SIG_DFL);
495 raise(fuzz_sigReceived);
496 }
Jaggerea39a8f2015-09-05 00:57:22 +0200497#ifdef __ANDROID__
498 sem_destroy(&semName);
499#else
500 sem_unlink(semName);
501#endif
robert.swiecki@gmail.com9c77bb12015-04-23 15:35:28 +0000502 exit(EXIT_SUCCESS);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000503}