summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Heitman <cheitman@quarkslab.com>2023-05-10 14:43:19 -0300
committerChristian Heitman <cheitman@quarkslab.com>2023-09-15 13:55:48 -0300
commitb1cc0186ff02a26b4d20aa55ba90157c458d419f (patch)
treee8c86f63ab3c7040e22a78f3e7ce0f88d83ab4c6
parentf1159430e8832abc9c301fd89e29b7320ad1befd (diff)
downloadhonggfuzz-b1cc0186ff02a26b4d20aa55ba90157c458d419f.tar.gz
Add --dynamic_input command-line option
-rw-r--r--cmdline.c4
-rw-r--r--honggfuzz.c5
-rw-r--r--honggfuzz.h1
-rw-r--r--input.c120
-rw-r--r--input.h2
5 files changed, 132 insertions, 0 deletions
diff --git a/cmdline.c b/cmdline.c
index 3eb9933f..9c924882 100644
--- a/cmdline.c
+++ b/cmdline.c
@@ -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;
diff --git a/input.c b/input.c
index 4a935300..bd6b1e43 100644
--- a/input.c
+++ b/input.c
@@ -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(
diff --git a/input.h b/input.h
index 3163223b..9106583f 100644
--- a/input.h
+++ b/input.h
@@ -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_ */