blob: c984e72f9fd5294c7215c520b63b4409b09d588f [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"
robert.swiecki3bb518c2010-10-14 00:48:24 +000049#include "files.h"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000050#include "log.h"
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +000051#include "mangle.h"
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +000052#include "report.h"
53#include "util.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000054
robert.swiecki3bb518c2010-10-14 00:48:24 +000055static void fuzz_getFileName(honggfuzz_t * hfuzz, char *fileName)
56{
robert.swieckiba512632011-01-28 11:57:26 +000057 struct timeval tv;
58 gettimeofday(&tv, NULL);
59
robert.swiecki@gmail.com6f319912015-02-28 05:01:37 +000060 snprintf(fileName, PATH_MAX, ".honggfuzz.%d.%lu.%llx.%s", (int)getpid(),
61 (unsigned long int)tv.tv_sec, (unsigned long long int)util_rndGet(0, 1ULL << 62),
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +000062 hfuzz->fileExtn);
robert.swiecki3bb518c2010-10-14 00:48:24 +000063
64 return;
65}
66
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +000067static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index)
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000068{
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +000069 while (pthread_mutex_lock(&hfuzz->dynamicFile_mutex)) ;
70
robert.swiecki@gmail.com7aad7172015-03-03 04:34:15 +000071 if (hfuzz->inputFile && hfuzz->branchBestCnt[0] == 0 && hfuzz->branchBestCnt[1] == 0
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +000072 && hfuzz->branchBestCnt[2] == 0 && hfuzz->branchBestCnt[3] == 0) {
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +000073 size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], hfuzz->dynamicFileBest,
74 hfuzz->maxFileSz);
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000075 if (fileSz == 0) {
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +000076 while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ;
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000077 LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]);
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +000078 return false;
79 }
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000080 hfuzz->dynamicFileBestSz = fileSz;
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +000081 }
82
robert.swiecki@gmail.com060a9dd2015-02-28 06:37:27 +000083 if (hfuzz->dynamicFileBestSz > hfuzz->maxFileSz) {
84 LOGMSG(l_FATAL, "Current BEST file Sz > maxFileSz (%zu > %zu)", hfuzz->dynamicFileBestSz,
85 hfuzz->maxFileSz);
86 }
87
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000088 fuzzer->dynamicFileSz = hfuzz->dynamicFileBestSz;
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +000089 memcpy(fuzzer->dynamicFile, hfuzz->dynamicFileBest, hfuzz->dynamicFileBestSz);
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000090
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +000091 while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ;
92
robert.swiecki@gmail.com141c4522015-02-19 15:49:23 +000093 /* The first pass should be on an empty/initial file */
robert.swiecki@gmail.comf845d4d2015-03-05 02:46:33 +000094 if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +000095 || hfuzz->branchBestCnt[3] > 0) {
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +000096 mangle_Resize(hfuzz, &fuzzer->dynamicFileSz);
robert.swiecki@gmail.com36700b52015-02-22 05:03:16 +000097 mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz);
robert.swiecki@gmail.com141c4522015-02-19 15:49:23 +000098 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +000099
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000100 if (files_writeBufToFile
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000101 (fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz,
102 O_WRONLY | O_CREAT | O_EXCL | O_TRUNC) == false) {
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000103 LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName);
robert.swiecki@gmail.com3b6c6292015-02-26 11:48:46 +0000104 return false;
105 }
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000106
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000107 return true;
robert.swiecki@gmail.comd7aed312015-02-03 21:26:37 +0000108}
109
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000110static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000111{
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000112 size_t fileSz =
113 files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz);
114 if (fileSz == 0UL) {
115 LOGMSG(l_ERROR, "Couldn't read contents of '%s'", hfuzz->files[rnd_index]);
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000116 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000117 }
118
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000119 mangle_Resize(hfuzz, &fileSz);
120 mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fileSz);
robert.swiecki@gmail.comc070b942015-02-25 18:29:19 +0000121
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000122 if (files_writeBufToFile
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000123 (fuzzer->fileName, fuzzer->dynamicFile, fileSz, O_WRONLY | O_CREAT | O_EXCL) == false) {
robert.swiecki@gmail.comdc8403e2015-03-01 01:33:00 +0000124 LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName);
robert.swiecki@gmail.come7680522015-02-22 22:22:37 +0000125 return false;
126 }
127
robert.swiecki3bb518c2010-10-14 00:48:24 +0000128 return true;
129}
130
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000131static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000132{
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000133 int dstfd = open(fuzzer->fileName, O_CREAT | O_EXCL | O_RDWR, 0644);
robert.swiecki3d505e22010-10-14 01:17:17 +0000134 if (dstfd == -1) {
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000135 LOGMSG_P(l_ERROR, "Couldn't create a temporary file '%s' in the current directory",
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000136 fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000137 return false;
138 }
139
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000140 LOGMSG(l_DEBUG, "Created '%f' as an input file", fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000141
142 if (hfuzz->inputFile) {
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000143 size_t fileSz =
144 files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz);
145 if (fileSz == 0UL) {
146 LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]);
147 unlink(fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000148 return false;
149 }
150
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000151 if (files_writeToFd(dstfd, fuzzer->dynamicFile, fileSz) == false) {
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000152 close(dstfd);
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000153 unlink(fuzzer->fileName);
robert.swiecki@gmail.comebc1cac2011-07-02 03:15:51 +0000154 return false;
155 }
robert.swiecki3d505e22010-10-14 01:17:17 +0000156 }
157
robert.swiecki3d505e22010-10-14 01:17:17 +0000158 close(dstfd);
159
robert.swiecki@gmail.combb2b4aa2015-03-05 01:48:46 +0000160 pid_t pid = fork();
robert.swiecki3bb518c2010-10-14 00:48:24 +0000161 if (pid == -1) {
robert.swiecki@gmail.com8a9df0e2015-02-13 17:08:06 +0000162 LOGMSG_P(l_ERROR, "Couldn't vfork");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000163 return false;
164 }
165
166 if (!pid) {
167 /*
robert.swiecki@gmail.comcdf18f92015-02-11 22:22:18 +0000168 * child performs the external file modifications
robert.swiecki3bb518c2010-10-14 00:48:24 +0000169 */
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000170 execl(hfuzz->externalCommand, hfuzz->externalCommand, fuzzer->fileName, NULL);
171 LOGMSG_P(l_FATAL, "Couldn't execute '%s %s'", hfuzz->externalCommand, fuzzer->fileName);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000172 return false;
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000173 }
robert.swiecki@gmail.com8a9df0e2015-02-13 17:08:06 +0000174
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000175 /*
176 * parent waits until child is done fuzzing the input file
177 */
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000178 int childStatus;
179 int flags = 0;
robert.swiecki@gmail.coma2291182015-02-13 16:56:27 +0000180#if defined(__WNOTHREAD)
181 flags |= __WNOTHREAD;
robert.swiecki@gmail.com8a9df0e2015-02-13 17:08:06 +0000182#endif /* defined(__WNOTHREAD) */
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000183 while (wait4(pid, &childStatus, flags, NULL) != pid) ;
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000184 if (WIFEXITED(childStatus)) {
185 LOGMSG(l_DEBUG, "External command exited with status %d", WEXITSTATUS(childStatus));
186 return true;
187 }
188 if (WIFSIGNALED(childStatus)) {
robert.swiecki@gmail.coma2291182015-02-13 16:56:27 +0000189 LOGMSG(l_ERROR, "External command terminated with signal %d", WTERMSIG(childStatus));
robert.swiecki3d505e22010-10-14 01:17:17 +0000190 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000191 }
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000192 LOGMSG(l_FATAL, "External command terminated abnormally, status: %d", childStatus);
193 return false;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000194
195 abort(); /* NOTREACHED */
196}
197
robert.swiecki@gmail.com6ff9af82015-02-11 18:52:05 +0000198static int fuzz_numOfProc(honggfuzz_t * hfuzz)
199{
200 int i;
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000201 sem_getvalue(hfuzz->sem, &i);
robert.swiecki@gmail.com6ff9af82015-02-11 18:52:05 +0000202 return hfuzz->threadsMax - i;
203}
204
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000205static void *fuzz_threadNew(void *arg)
robert.swiecki3bb518c2010-10-14 00:48:24 +0000206{
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000207 honggfuzz_t *hfuzz = (honggfuzz_t *) arg;
208 fuzzer_t fuzzer = {
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000209 .pid = 0,
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000210 .timeStarted = time(NULL),
211 .pc = 0ULL,
212 .backtrace = 0ULL,
213 .access = 0ULL,
214 .exception = 0,
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000215 .dynamicFileSz = 0,
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000216 .dynamicFile = malloc(hfuzz->maxFileSz),
robert.swiecki@gmail.com4be26672015-03-05 03:36:50 +0000217 .branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0},
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000218 .report = {'\0'}
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000219 };
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000220 if (fuzzer.dynamicFile == NULL) {
221 LOGMSG(l_FATAL, "malloc(%zu) failed", hfuzz->maxFileSz);
222 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000223
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000224 int rnd_index = util_rndGet(0, hfuzz->fileCnt - 1);
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000225 strncpy(fuzzer.origFileName, files_basename(hfuzz->files[rnd_index]), PATH_MAX);
226 fuzz_getFileName(hfuzz, fuzzer.fileName);
groebert@google.com1c7e3b02013-06-19 09:27:38 +0000227
robert.swiecki@gmail.comcac22fd2015-02-19 14:03:28 +0000228 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
robert.swiecki@gmail.com624233e2015-02-18 10:26:05 +0000229 if (!fuzz_prepareFileDynamically(hfuzz, &fuzzer, rnd_index)) {
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000230 exit(EXIT_FAILURE);
231 }
232 } else if (hfuzz->externalCommand != NULL) {
robert.swiecki@gmail.com20851202015-03-01 01:48:15 +0000233 if (!fuzz_prepareFileExternally(hfuzz, &fuzzer, rnd_index)) {
robert.swiecki@gmail.com6ff9af82015-02-11 18:52:05 +0000234 exit(EXIT_FAILURE);
235 }
236 } else {
robert.swiecki@gmail.com4a7a9d82015-03-01 01:25:16 +0000237 if (!fuzz_prepareFile(hfuzz, &fuzzer, rnd_index)) {
robert.swiecki@gmail.com6ff9af82015-02-11 18:52:05 +0000238 exit(EXIT_FAILURE);
239 }
robert.swiecki@gmail.com1f98a162015-02-11 15:09:22 +0000240 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000241
robert.swiecki5fa9d902015-02-25 15:31:56 +0000242#if defined(_HF_ARCH_LINUX)
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +0000243#include <unistd.h>
244#include <sys/syscall.h>
245 fuzzer.pid = syscall(__NR_fork);
robert.swiecki@gmail.com4fc19692015-02-25 15:45:11 +0000246#else /* defined(_HF_ARCH_LINUX) */
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000247 fuzzer.pid = fork();
robert.swiecki5fa9d902015-02-25 15:31:56 +0000248#endif /* defined(_HF_ARCH_LINUX) */
robert.swiecki@gmail.comdfde1c72015-02-18 13:22:55 +0000249
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000250 if (fuzzer.pid == -1) {
robert.swiecki3bb518c2010-10-14 00:48:24 +0000251 LOGMSG_P(l_FATAL, "Couldn't fork");
252 exit(EXIT_FAILURE);
253 }
254
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000255 if (!fuzzer.pid) {
robert.swiecki3bb518c2010-10-14 00:48:24 +0000256 /*
robert.swiecki@gmail.com6ff9af82015-02-11 18:52:05 +0000257 * Ok, kill the parent if this fails
robert.swiecki3bb518c2010-10-14 00:48:24 +0000258 */
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000259 if (!arch_launchChild(hfuzz, fuzzer.fileName)) {
robert.swiecki@gmail.com6f5c2392015-02-16 18:13:09 +0000260 LOGMSG(l_ERROR, "Error launching child process, killing parent");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000261 exit(EXIT_FAILURE);
262 }
263 }
264
robert.swiecki@gmail.combb5d2642015-02-25 20:00:00 +0000265 LOGMSG(l_INFO, "Launched new process, pid: %d, (%d/%d)", fuzzer.pid, fuzz_numOfProc(hfuzz),
266 hfuzz->threadsMax);
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000267
268 arch_reapChild(hfuzz, &fuzzer);
269 unlink(fuzzer.fileName);
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000270
robert.swiecki@gmail.comcac22fd2015-02-19 14:03:28 +0000271 if (hfuzz->dynFileMethod != _HF_DYNFILE_NONE) {
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +0000272 while (pthread_mutex_lock(&hfuzz->dynamicFile_mutex)) ;
robert.swiecki@gmail.com90f36e62015-03-01 15:13:54 +0000273
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000274 int64_t diff0 = hfuzz->branchBestCnt[0] - fuzzer.branchCnt[0];
275 int64_t diff1 = hfuzz->branchBestCnt[1] - fuzzer.branchCnt[1];
276 int64_t diff2 = hfuzz->branchBestCnt[2] - fuzzer.branchCnt[2];
robert.swiecki@gmail.comf845d4d2015-03-05 02:46:33 +0000277 int64_t diff3 = hfuzz->branchBestCnt[3] - fuzzer.branchCnt[3];
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000278
279 if (diff0 <= hfuzz->dynamicRegressionCnt && diff1 <= hfuzz->dynamicRegressionCnt
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000280 && diff2 <= hfuzz->dynamicRegressionCnt && diff3 <= hfuzz->dynamicRegressionCnt) {
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000281
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000282 LOGMSG(l_INFO,
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000283 "New BEST feedback: File Size (New/Old): %zu/%zu', Perf feedback (Curr, High): %"
robert.swiecki@gmail.comf845d4d2015-03-05 02:46:33 +0000284 PRId64 "/%" PRId64 "/%" PRId64 "/%" PRId64 ", %" PRId64 "/%" PRId64 "/%" PRId64
285 "/%" PRId64, fuzzer.dynamicFileSz, hfuzz->dynamicFileBestSz, fuzzer.branchCnt[0],
286 fuzzer.branchCnt[1], fuzzer.branchCnt[2], fuzzer.branchCnt[3],
287 hfuzz->branchBestCnt[0], hfuzz->branchBestCnt[1], hfuzz->branchBestCnt[2],
288 hfuzz->branchBestCnt[3]);
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000289
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000290 memcpy(hfuzz->dynamicFileBest, fuzzer.dynamicFile, fuzzer.dynamicFileSz);
robert.swiecki@gmail.com90f36e62015-03-01 15:13:54 +0000291
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000292 hfuzz->dynamicFileBestSz = fuzzer.dynamicFileSz;
robert.swiecki@gmail.com81e26dc2015-03-03 04:26:04 +0000293 hfuzz->branchBestCnt[0] =
294 fuzzer.branchCnt[0] >
295 hfuzz->branchBestCnt[0] ? fuzzer.branchCnt[0] : hfuzz->branchBestCnt[0];
296 hfuzz->branchBestCnt[1] =
297 fuzzer.branchCnt[1] >
298 hfuzz->branchBestCnt[1] ? fuzzer.branchCnt[1] : hfuzz->branchBestCnt[1];
299 hfuzz->branchBestCnt[2] =
300 fuzzer.branchCnt[2] >
301 hfuzz->branchBestCnt[2] ? fuzzer.branchCnt[2] : hfuzz->branchBestCnt[2];
robert.swiecki@gmail.comf845d4d2015-03-05 02:46:33 +0000302 hfuzz->branchBestCnt[3] =
303 fuzzer.branchCnt[3] >
304 hfuzz->branchBestCnt[3] ? fuzzer.branchCnt[3] : hfuzz->branchBestCnt[3];
robert.swiecki@gmail.com85a0a952015-02-19 01:58:39 +0000305
robert.swiecki@gmail.comba92e192015-02-21 02:14:07 +0000306#define _HF_CURRENT_BEST "CURRENT_BEST"
307#define _HF_CURRENT_BEST_TMP ".tmp.CURRENT_BEST"
robert.swiecki@gmail.comf3fbf032015-03-01 01:52:11 +0000308 if (files_writeBufToFile
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000309 (_HF_CURRENT_BEST_TMP, fuzzer.dynamicFile, fuzzer.dynamicFileSz,
310 O_WRONLY | O_CREAT | O_TRUNC)) {
robert.swiecki@gmail.comf3fbf032015-03-01 01:52:11 +0000311 rename(_HF_CURRENT_BEST_TMP, _HF_CURRENT_BEST);
312 } else {
313 unlink(_HF_CURRENT_BEST_TMP);
robert.swiecki@gmail.comba92e192015-02-21 02:14:07 +0000314 }
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000315 }
robert.swiecki@gmail.com41d8e052015-02-19 01:10:41 +0000316 while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ;
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000317 }
318
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000319 report_Report(hfuzz, fuzzer.report);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000320 free(fuzzer.dynamicFile);
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000321
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000322 sem_post(hfuzz->sem);
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000323
324 return NULL;
325}
326
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000327static void *fuzz_threadPid(void *arg)
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000328{
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000329 honggfuzz_t *hfuzz = (honggfuzz_t *) arg;
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000330 if (!arch_archInit(hfuzz)) {
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000331 LOGMSG(l_FATAL, "Couldn't prepare parent for fuzzing");
robert.swiecki@gmail.com882900b2015-02-11 13:56:22 +0000332 }
333
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000334 fuzzer_t fuzzer = {
335 .pid = hfuzz->pid,
336 .timeStarted = time(NULL),
337 .pc = 0ULL,
338 .backtrace = 0ULL,
339 .access = 0ULL,
340 .exception = 0,
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000341 .dynamicFileSz = 0,
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000342 .dynamicFile = malloc(hfuzz->maxFileSz),
robert.swiecki@gmail.com62e34ae2015-03-05 03:39:32 +0000343 .branchCnt = {[0 ... (ARRAYSIZE(fuzzer.branchCnt) - 1)] = 0}
344 ,
robert.swiecki@gmail.comd4dd4df2015-02-18 00:50:12 +0000345 .report = {'\0'}
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000346 };
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000347 if (fuzzer.dynamicFile == NULL) {
348 LOGMSG(l_FATAL, "malloc(%zu) failed", hfuzz->maxFileSz);
349 }
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000350
351 char fileName[] = ".honggfuzz.empty.XXXXXX";
352 int fd;
353 if ((fd = mkstemp(fileName)) == -1) {
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000354 free(fuzzer.dynamicFile);
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000355 LOGMSG_P(l_ERROR, "Couldn't create a temporary file");
356 return NULL;
357 }
358 close(fd);
359
360 strncpy(fuzzer.origFileName, "PID_FUZZING", PATH_MAX);
361 strncpy(fuzzer.fileName, fileName, PATH_MAX);
362
363 arch_reapChild(hfuzz, &fuzzer);
364 unlink(fuzzer.fileName);
robert.swiecki@gmail.come7190b92015-02-14 23:05:42 +0000365 report_Report(hfuzz, fuzzer.report);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000366 free(fuzzer.dynamicFile);
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000367
368 // There's no more hfuzz->pid to analyze. Just exit
369 LOGMSG(l_INFO, "PID: %d exited. Exiting", fuzzer.pid);
370 exit(EXIT_SUCCESS);
371
372 return NULL;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000373}
374
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000375static void fuzz_runThread(honggfuzz_t * hfuzz, void *(*thread) (void *))
376{
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000377 pthread_attr_t attr;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000378
robert.swiecki@gmail.com6f5c2392015-02-16 18:13:09 +0000379 pthread_attr_init(&attr);
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000380 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
robert.swiecki@gmail.com441089a2015-02-23 13:14:07 +0000381 pthread_attr_setstacksize(&attr, _HF_PTHREAD_STACKSIZE);
robert.swiecki@gmail.com011981f2015-02-17 19:06:44 +0000382 pthread_attr_setguardsize(&attr, (size_t) sysconf(_SC_PAGESIZE));
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000383
robert.swiecki@gmail.com01b6dd42015-02-16 18:11:28 +0000384 pthread_t t;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000385 if (pthread_create(&t, &attr, thread, (void *)hfuzz) < 0) {
386 LOGMSG_P(l_FATAL, "Couldn't create a new thread");
387 }
388
389 return;
390}
391
robert.swiecki3bb518c2010-10-14 00:48:24 +0000392void fuzz_main(honggfuzz_t * hfuzz)
393{
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000394 char semName[PATH_MAX];
robert.swiecki5fa9d902015-02-25 15:31:56 +0000395 snprintf(semName, sizeof(semName), "/honggfuzz.%d.%d.%" PRIx64, getpid(),
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +0000396 (int)time(NULL), util_rndGet(1, 1ULL << 62));
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000397
robert.swiecki@gmail.com757ee192015-02-13 16:54:02 +0000398 hfuzz->sem = sem_open(semName, O_CREAT, 0644, hfuzz->threadsMax);
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000399 if (hfuzz->sem == SEM_FAILED) {
400 LOGMSG_P(l_FATAL, "sem_open() failed");
robert.swiecki@gmail.come7635392015-02-11 16:17:49 +0000401 }
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000402 // If we're doing a PID fuzzing, the parent of the PID will be a
403 // dedicated thread anyway
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000404 if (hfuzz->pid) {
405 fuzz_runThread(hfuzz, fuzz_threadPid);
406 } else {
robert.swiecki@gmail.com6d6f7562015-02-17 22:18:51 +0000407 if (!arch_archInit(hfuzz)) {
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000408 LOGMSG(l_FATAL, "Couldn't prepare parent for fuzzing");
409 }
robert.swiecki@gmail.comef829fa2011-06-22 13:51:57 +0000410 }
411
robert.swiecki3bb518c2010-10-14 00:48:24 +0000412 for (;;) {
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000413 if (sem_wait(hfuzz->sem) == -1) {
robert.swiecki@gmail.come507cb62015-02-11 17:14:49 +0000414 LOGMSG_P(l_FATAL, "sem_wait() failed");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000415 }
robert.swiecki@gmail.come507cb62015-02-11 17:14:49 +0000416
417 if (hfuzz->mutationsMax && (hfuzz->mutationsCnt >= hfuzz->mutationsMax)) {
robert.swiecki@gmail.com89068552015-02-28 05:18:25 +0000418#if defined(_HF_ARCH_DARWIN)
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000419 /*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +0000420 * Sleep a bit to let any running fuzzers terminate
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +0000421 */
groebert@google.com20e368f2015-02-13 14:19:25 +0000422 usleep(1.2 * hfuzz->tmOut * 1000000);
robert.swiecki@gmail.com89068552015-02-28 05:18:25 +0000423#else /* defined(_HF_ARCH_DARWIN) */
424 while (fuzz_numOfProc(hfuzz) > 1) {
robert.swiecki@gmail.comc1fdcfb2015-02-28 05:26:38 +0000425 usleep(10000);
robert.swiecki@gmail.com89068552015-02-28 05:18:25 +0000426 }
427#endif /* defined(_HF_ARCH_DARWIN) */
robert.swiecki@gmail.come507cb62015-02-11 17:14:49 +0000428 LOGMSG(l_INFO, "Finished fuzzing %ld times.", hfuzz->mutationsMax);
robert.swiecki@gmail.com9bc725e2015-02-13 12:40:06 +0000429 sem_destroy(hfuzz->sem);
robert.swiecki@gmail.come507cb62015-02-11 17:14:49 +0000430 exit(EXIT_SUCCESS);
431 }
432
433 hfuzz->mutationsCnt++;
robert.swiecki@gmail.comc8443142015-02-13 13:46:40 +0000434 fuzz_runThread(hfuzz, fuzz_threadNew);
robert.swiecki3bb518c2010-10-14 00:48:24 +0000435 }
436}