diff options
author | Christian Heitman <cheitman@quarkslab.com> | 2023-05-10 14:43:19 -0300 |
---|---|---|
committer | Christian Heitman <cheitman@quarkslab.com> | 2023-09-15 13:55:48 -0300 |
commit | b1cc0186ff02a26b4d20aa55ba90157c458d419f (patch) | |
tree | e8c86f63ab3c7040e22a78f3e7ce0f88d83ab4c6 | |
parent | f1159430e8832abc9c301fd89e29b7320ad1befd (diff) | |
download | honggfuzz-b1cc0186ff02a26b4d20aa55ba90157c458d419f.tar.gz |
Add --dynamic_input command-line option
-rw-r--r-- | cmdline.c | 4 | ||||
-rw-r--r-- | honggfuzz.c | 5 | ||||
-rw-r--r-- | honggfuzz.h | 1 | ||||
-rw-r--r-- | input.c | 120 | ||||
-rw-r--r-- | input.h | 2 |
5 files changed, 132 insertions, 0 deletions
@@ -527,6 +527,7 @@ bool cmdlineParse(int argc, char* argv[], honggfuzz_t* hfuzz) { { { "export_feedback", no_argument, NULL, 0x10E }, "Export the coverage feedback structure as ./hfuzz-feedback" }, { { "const_feedback", required_argument, NULL, 0x112 }, "Use constant integer/string values from fuzzed programs to mangle input files via a dynamic dictionary (default: true)" }, { { "pin_thread_cpu", required_argument, NULL, 0x114 }, "Pin a single execution thread to this many consecutive CPUs (default: 0 = no CPU pinning)" }, + { { "dynamic_input", required_argument, NULL, 0x115 }, "Path to a directory containing the dynamic file corpus" }, #if defined(_HF_ARCH_LINUX) { { "linux_symbols_bl", required_argument, NULL, 0x504 }, "Symbols blocklist filter file (one entry per line)" }, @@ -809,6 +810,9 @@ bool cmdlineParse(int argc, char* argv[], honggfuzz_t* hfuzz) { hfuzz->arch_linux.disableRandomization = false; break; #endif + case 0x115: + hfuzz->io.dynamicInputDir = optarg; + break; default: cmdlineHelp(argv[0], custom_opts); return false; diff --git a/honggfuzz.c b/honggfuzz.c index b554b47e..83e4a855 100644 --- a/honggfuzz.c +++ b/honggfuzz.c @@ -264,6 +264,11 @@ static uint8_t mainThreadLoop(honggfuzz_t* hfuzz) { setupMainThreadTimer(); for (;;) { + if (hfuzz->io.dynamicInputDir) { + LOG_D("Loading files from the dynamic input queue..."); + input_enqueueDynamicInputs(hfuzz); + } + if (hfuzz->display.useScreen) { if (ATOMIC_XCHG(clearWin, false)) { display_clear(); diff --git a/honggfuzz.h b/honggfuzz.h index eee7b81f..d7793f5a 100644 --- a/honggfuzz.h +++ b/honggfuzz.h @@ -217,6 +217,7 @@ typedef struct { dynfile_t* dynfileq2Current; TAILQ_HEAD(dyns_t, _dynfile_t) dynfileq; bool exportFeedback; + const char* dynamicInputDir; } io; struct { int argc; @@ -31,6 +31,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sys/mman.h> #include <sys/queue.h> #include <sys/stat.h> #include <unistd.h> @@ -574,6 +575,125 @@ bool input_prepareDynamicInput(run_t* run, bool needs_mangle) { return true; } +bool input_dynamicQueueGetNext(char fname[PATH_MAX], DIR* dynamicDirPtr, char *dynamicWorkDir) { + static pthread_mutex_t input_mutex = PTHREAD_MUTEX_INITIALIZER; + MX_SCOPED_LOCK(&input_mutex); + + for (;;) { + errno = 0; + struct dirent* entry = readdir(dynamicDirPtr); + if (entry == NULL && errno == EINTR) { + continue; + } + if (entry == NULL && errno != 0) { + PLOG_W("readdir_r('%s')", dynamicWorkDir); + return false; + } + if (entry == NULL) { + return false; + } + char path[PATH_MAX]; + snprintf(path, PATH_MAX, "%s/%s", dynamicWorkDir, entry->d_name); + struct stat st; + if (stat(path, &st) == -1) { + LOG_W("Couldn't stat() the '%s' file", path); + continue; + } + if (!S_ISREG(st.st_mode)) { + LOG_D("'%s' is not a regular file, skipping", path); + continue; + } + + snprintf(fname, PATH_MAX, "%s/%s", dynamicWorkDir, entry->d_name); + return true; + } +} + +void input_enqueueDynamicInputs(honggfuzz_t* hfuzz) { + char dynamicWorkDir[PATH_MAX]; + + snprintf(dynamicWorkDir, sizeof(dynamicWorkDir), "%s", hfuzz->io.dynamicInputDir); + + int dynamicDirFd = TEMP_FAILURE_RETRY(open(dynamicWorkDir, O_DIRECTORY | O_RDONLY | O_CLOEXEC)); + if (dynamicDirFd == -1) { + PLOG_W("open('%s', O_DIRECTORY|O_RDONLY|O_CLOEXEC)", dynamicWorkDir); + return; + } + + DIR* dynamicDirPtr; + if ((dynamicDirPtr = fdopendir(dynamicDirFd)) == NULL) { + PLOG_W("fdopendir(dir='%s', fd=%d)", dynamicWorkDir, dynamicDirFd); + close(dynamicDirFd); + return; + } + + char dynamicInputFileName[PATH_MAX]; + for (;;) { + if (!input_dynamicQueueGetNext(dynamicInputFileName, dynamicDirPtr, dynamicWorkDir)) { + break; + } + + int dynamicFileFd; + if ((dynamicFileFd = open(dynamicInputFileName, O_RDWR)) == -1) { + PLOG_E("Error opening dynamic input file: %s", dynamicInputFileName); + continue; + } + + /* Get file status. */ + struct stat dynamicFileStat; + size_t dynamicFileSz; + + if (fstat(dynamicFileFd, &dynamicFileStat) == -1) { + PLOG_E("Error getting file status: %s", dynamicInputFileName); + close(dynamicFileFd); + continue; + } + + dynamicFileSz = dynamicFileStat.st_size; + + uint8_t* dynamicFile = (uint8_t *) mmap(NULL, dynamicFileSz, PROT_READ | PROT_WRITE, MAP_SHARED, dynamicFileFd, 0); + + if (dynamicFile == MAP_FAILED) { + PLOG_E("Error mapping dynamic input file: %s", dynamicInputFileName); + close(dynamicFileFd); + continue; + } + + LOG_I("Loading dynamic input file: %s (%lu)", dynamicInputFileName, dynamicFileSz); + + run_t tmp_run; + tmp_run.global = hfuzz; + dynfile_t tmp_dynfile = { + .size = dynamicFileSz, + .cov = {0xff, 0xff, 0xff, 0xff}, + .idx = 0, + .fd = -1, + .timeExecUSecs = 1, + .path = "", + .data = dynamicFile, + }; + tmp_run.timeStartedUSecs = util_timeNowUSecs() -1; + memcpy(tmp_dynfile.path, dynamicInputFileName, PATH_MAX); + tmp_run.dynfile = &tmp_dynfile; + input_addDynamicInput(&tmp_run); + //input_addDynamicInput(hfuzz, dynamicFile, dynamicFileSz, (uint64_t[4]){0xff, 0xff, 0xff, 0xff}, dynamicInputFileName); + + /* Unmap input file. */ + if (munmap((void *) dynamicFile, dynamicFileSz) == -1) { + PLOG_E("Error unmapping input file!"); + } + + /* Close input file. */ + if (close(dynamicFileFd) == -1) { + PLOG_E("Error closing input file!"); + } + + /* Remove enqueued file from the directory. */ + unlink(dynamicInputFileName); + } + closedir(dynamicDirPtr); +} + const uint8_t* input_getRandomInputAsBuf(run_t* run, size_t* len) { if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) { LOG_W( @@ -49,5 +49,7 @@ extern bool input_removeStaticFile(const char* dir, const char* name); extern bool input_prepareExternalFile(run_t* run); extern bool input_postProcessFile(run_t* run, const char* cmd); extern bool input_prepareDynamicFileForMinimization(run_t* run); +extern bool input_dynamicQueueGetNext(char fname[PATH_MAX], DIR* dynamicDirPtr, char *dynamicWorkDir); +extern void input_enqueueDynamicInputs(honggfuzz_t* hfuzz); #endif /* ifndef _HF_INPUT_H_ */ |