static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { while (pthread_mutex_lock(&hfuzz->dynamicFile_mutex)) ; if (hfuzz->inputFile && hfuzz->branchBestCnt[0] == 0 && hfuzz->branchBestCnt[1] == 0 && hfuzz->branchBestCnt[2] == 0 && hfuzz->branchBestCnt[3] == 0) { size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], hfuzz->dynamicFileBest, hfuzz->maxFileSz); if (fileSz == 0) { while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ; LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]); return false; } hfuzz->dynamicFileBestSz = fileSz; } if (hfuzz->dynamicFileBestSz > hfuzz->maxFileSz) { LOGMSG(l_FATAL, "Current BEST file Sz > maxFileSz (%zu > %zu)", hfuzz->dynamicFileBestSz, hfuzz->maxFileSz); } fuzzer->dynamicFileSz = hfuzz->dynamicFileBestSz; memcpy(fuzzer->dynamicFile, hfuzz->dynamicFileBest, hfuzz->dynamicFileBestSz); while (pthread_mutex_unlock(&hfuzz->dynamicFile_mutex)) ; /* The first pass should be on an empty/initial file */ if (hfuzz->branchBestCnt[0] > 0 || hfuzz->branchBestCnt[1] > 0 || hfuzz->branchBestCnt[2] > 0 || hfuzz->branchBestCnt[3] > 0) { mangle_Resize(hfuzz, fuzzer->dynamicFile, &fuzzer->dynamicFileSz); mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz); } if (files_writeBufToFile (fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC) == false) { LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName); return false; } return true; }
static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz); if (fileSz == 0UL) { LOGMSG(l_ERROR, "Couldn't read contents of '%s'", hfuzz->files[rnd_index]); return false; } mangle_Resize(hfuzz, fuzzer->dynamicFile, &fileSz); mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fileSz); if (files_writeBufToFile (fuzzer->fileName, fuzzer->dynamicFile, fileSz, O_WRONLY | O_CREAT | O_EXCL) == false) { LOGMSG(l_ERROR, "Couldn't write buffer to file '%s'", fuzzer->fileName); return false; } return true; }
static size_t arch_perfGetMmapBufSz(honggfuzz_t * hfuzz) { char mlock_len[128]; size_t sz = files_readFileToBufMax("/proc/sys/kernel/perf_event_mlock_kb", (uint8_t *) mlock_len, sizeof(mlock_len) - 1); if (sz == 0U) { LOG_F("Couldn't read '/proc/sys/kernel/perf_event_mlock_kb'"); } mlock_len[sz] = '\0'; size_t ret = (strtoul(mlock_len, NULL, 10) * 1024) / hfuzz->threadsMax; for (size_t i = 1; i < 31; i++) { size_t mask = (1U << i); size_t maskret = (ret & ~(mask - 1)); if (maskret == mask) { LOG_D("perf_mmap_buf_size = %zu", maskret); return maskret; } } LOG_F("Couldn't find the proper size of the perf mmap buffer"); return false; }
static bool fuzz_prepareFile(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz); if (fileSz == 0UL) { LOG_E("Couldn't read contents of '%s'", hfuzz->files[rnd_index]); return false; } /* If flip rate is 0.0, early abort file mangling */ if (hfuzz->flipRate != 0.0L) { mangle_Resize(hfuzz, fuzzer->dynamicFile, &fileSz); mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fileSz); } if (files_writeBufToFile (fuzzer->fileName, fuzzer->dynamicFile, fileSz, O_WRONLY | O_CREAT | O_EXCL) == false) { LOG_E("Couldn't write buffer to file '%s'", fuzzer->fileName); return false; } return true; }
static bool fuzz_prepareFileExternally(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { int dstfd = open(fuzzer->fileName, O_CREAT | O_EXCL | O_RDWR, 0644); if (dstfd == -1) { LOGMSG_P(l_ERROR, "Couldn't create a temporary file '%s' in the current directory", fuzzer->fileName); return false; } LOGMSG(l_DEBUG, "Created '%f' as an input file", fuzzer->fileName); if (hfuzz->inputFile) { size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], fuzzer->dynamicFile, hfuzz->maxFileSz); if (fileSz == 0UL) { LOGMSG(l_ERROR, "Couldn't read '%s'", hfuzz->files[rnd_index]); unlink(fuzzer->fileName); return false; } if (files_writeToFd(dstfd, fuzzer->dynamicFile, fileSz) == false) { close(dstfd); unlink(fuzzer->fileName); return false; } } close(dstfd); pid_t pid = fork(); if (pid == -1) { LOGMSG_P(l_ERROR, "Couldn't vfork"); return false; } if (!pid) { /* * child performs the external file modifications */ execl(hfuzz->externalCommand, hfuzz->externalCommand, fuzzer->fileName, NULL); LOGMSG_P(l_FATAL, "Couldn't execute '%s %s'", hfuzz->externalCommand, fuzzer->fileName); return false; } /* * parent waits until child is done fuzzing the input file */ int childStatus; int flags = 0; #if defined(__WNOTHREAD) flags |= __WNOTHREAD; #endif /* defined(__WNOTHREAD) */ while (wait4(pid, &childStatus, flags, NULL) != pid) ; if (WIFEXITED(childStatus)) { LOGMSG(l_DEBUG, "External command exited with status %d", WEXITSTATUS(childStatus)); return true; } if (WIFSIGNALED(childStatus)) { LOGMSG(l_ERROR, "External command terminated with signal %d", WTERMSIG(childStatus)); return false; } LOGMSG(l_FATAL, "External command terminated abnormally, status: %d", childStatus); return false; abort(); /* NOTREACHED */ }
static bool fuzz_prepareFileDynamically(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int rnd_index) { MX_LOCK(&hfuzz->dynamicFile_mutex); /* If max dynamicFile iterations counter, pick new seed file when working with input file corpus */ if (hfuzz->inputFile && __sync_fetch_and_add(&hfuzz->dynFileIterExpire, 0UL) >= _HF_MAX_DYNFILE_ITER) { size_t fileSz = files_readFileToBufMax(hfuzz->files[rnd_index], hfuzz->dynamicFileBest, hfuzz->maxFileSz); if (fileSz == 0) { MX_UNLOCK(&hfuzz->dynamicFile_mutex); LOG_E("Couldn't read '%s'", hfuzz->files[rnd_index]); return false; } hfuzz->dynamicFileBestSz = fileSz; /* Reset counter since new seed pick */ __sync_fetch_and_and(&hfuzz->dynFileIterExpire, 0UL); fuzz_resetFeedbackCnts(hfuzz); /* * In order to have accurate comparison base for coverage, first iteration * of a new seed is executed without mangling. Also workersBlock_mutex mutex * is maintain until execution is finished to ensure that other threads will * work against the same coverage data vs. original seed. */ hfuzz->isDynFileLocked = true; } else if (hfuzz->inputFile == NULL && (fuzz_isPerfCntsSet(hfuzz) == false)) { /* * When working with an empty input file corpus (allowed if perf feedback enabled for Linux archs), * first iteration is executed without mangling. First iteration need to be executed by one thread * blocking other workers from continuing until finished. */ hfuzz->isDynFileLocked = true; } if (hfuzz->dynamicFileBestSz > hfuzz->maxFileSz) { LOG_F("Current BEST file Sz > maxFileSz (%zu > %zu)", hfuzz->dynamicFileBestSz, hfuzz->maxFileSz); } fuzzer->dynamicFileSz = hfuzz->dynamicFileBestSz; memcpy(fuzzer->dynamicFile, hfuzz->dynamicFileBest, hfuzz->dynamicFileBestSz); MX_UNLOCK(&hfuzz->dynamicFile_mutex); /* * true isDynFileLocked indicates first run for a new seed, so skip mangling * without unlocking threads block mutex. */ MX_LOCK(&hfuzz->workersBlock_mutex); if (hfuzz->isDynFileLocked) { goto skipMangling; } MX_UNLOCK(&hfuzz->workersBlock_mutex); /* * if flip rate is 0.0, early abort file mangling. This will leave perf counters * with values equal to dry runs against input corpus. */ if (hfuzz->flipRate == 0.0L) { goto skipMangling; } mangle_Resize(hfuzz, fuzzer->dynamicFile, &fuzzer->dynamicFileSz); mangle_mangleContent(hfuzz, fuzzer->dynamicFile, fuzzer->dynamicFileSz); skipMangling: if (files_writeBufToFile (fuzzer->fileName, fuzzer->dynamicFile, fuzzer->dynamicFileSz, O_WRONLY | O_CREAT | O_EXCL | O_TRUNC) == false) { LOG_E("Couldn't write buffer to file '%s'", fuzzer->fileName); return false; } return true; }