/* * * honggfuzz - core structures and macros * ----------------------------------------- * * Author: Robert Swiecki * * Copyright 2010-2018 by Google Inc. All Rights Reserved. * * Licensed under the Apache License, Version 2.0 (the "License"); you may * not use this file except in compliance with the License. You may obtain * a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or * implied. See the License for the specific language governing * permissions and limitations under the License. * */ #ifndef _HF_HONGGFUZZ_H_ #define _HF_HONGGFUZZ_H_ #include #include #include #include #include #include #include #include #include #include #include #include "libhfcommon/util.h" #define PROG_NAME "honggfuzz" #define PROG_VERSION "2.2" /* Name of the template which will be replaced with the proper name of the file */ #define _HF_FILE_PLACEHOLDER "___FILE___" /* Default name of the report created with some architectures */ #define _HF_REPORT_FILE "HONGGFUZZ.REPORT.TXT" /* Default stack-size of created threads. */ #define _HF_PTHREAD_STACKSIZE (1024ULL * 1024ULL * 2ULL) /* 2MB */ /* Name of envvar which indicates sequential number of fuzzer */ #define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO" /* Name of envvar which indicates that the netDriver should be used */ #define _HF_THREAD_NETDRIVER_ENV "HFUZZ_USE_NETDRIVER" /* Name of envvar which indicates honggfuzz's log level in use */ #define _HF_LOG_LEVEL_ENV "HFUZZ_LOG_LEVEL" /* Number of crash verifier iterations before tag crash as stable */ #define _HF_VERIFIER_ITER 5 /* Size (in bytes) for report data to be stored in stack before written to file */ #define _HF_REPORT_SIZE 32768 /* Perf bitmap size */ #define _HF_PERF_BITMAP_SIZE_16M (1024U * 1024U * 16U) #define _HF_PERF_BITMAP_BITSZ_MASK 0x7FFFFFFULL /* Maximum number of PC guards (=trace-pc-guard) we support */ #define _HF_PC_GUARD_MAX (1024ULL * 1024ULL * 64ULL) /* Maximum size of the input file in bytes (1 MiB) */ #define _HF_INPUT_MAX_SIZE (1024ULL * 1024ULL) /* Default maximum size of produced inputs */ #define _HF_INPUT_DEFAULT_SIZE (1024ULL * 8) /* Per-thread bitmap */ #define _HF_PERTHREAD_BITMAP_FD 1018 /* FD used to report back used int/str constants from the fuzzed process */ #define _HF_CMP_BITMAP_FD 1019 /* FD used to log inside the child process */ #define _HF_LOG_FD 1020 /* FD used to represent the input file */ #define _HF_INPUT_FD 1021 /* FD used to pass coverage feedback from the fuzzed process */ #define _HF_COV_BITMAP_FD 1022 #define _HF_BITMAP_FD _HF_COV_BITMAP_FD /* Old name for _HF_COV_BITMAP_FD */ /* FD used to pass data to a persistent process */ #define _HF_PERSISTENT_FD 1023 /* Input file as a string */ #define _HF_INPUT_FILE_PATH "/dev/fd/" HF_XSTR(_HF_INPUT_FD) /* Maximum number of supported execve() args */ #define _HF_ARGS_MAX 512 /* Message indicating that the fuzzed process is ready for new data */ static const uint8_t HFReadyTag = 'R'; /* Maximum number of active fuzzing threads */ #define _HF_THREAD_MAX 1024U /* Persistent-binary signature - if found within file, it means it's a persistent mode binary */ #define _HF_PERSISTENT_SIG "\x01_LIBHFUZZ_PERSISTENT_BINARY_SIGNATURE_\x02\xFF" /* HF NetDriver signature - if found within file, it means it's a NetDriver-based binary */ #define _HF_NETDRIVER_SIG "\x01_LIBHFUZZ_NETDRIVER_BINARY_SIGNATURE_\x02\xFF" /* printf() nonmonetary separator. According to MacOSX's man it's supported there as well */ #define _HF_NONMON_SEP "'" typedef enum { _HF_DYNFILE_NONE = 0x0, _HF_DYNFILE_INSTR_COUNT = 0x1, _HF_DYNFILE_BRANCH_COUNT = 0x2, _HF_DYNFILE_BTS_EDGE = 0x10, _HF_DYNFILE_IPT_BLOCK = 0x20, _HF_DYNFILE_SOFT = 0x40, } dynFileMethod_t; typedef struct { uint64_t cpuInstrCnt; uint64_t cpuBranchCnt; uint64_t bbCnt; uint64_t newBBCnt; uint64_t softCntPc; uint64_t softCntEdge; uint64_t softCntCmp; } hwcnt_t; typedef enum { _HF_STATE_UNSET = 0, _HF_STATE_STATIC, _HF_STATE_DYNAMIC_DRY_RUN, _HF_STATE_DYNAMIC_MAIN, _HF_STATE_DYNAMIC_MINIMIZE, } fuzzState_t; typedef enum { HF_MAYBE = -1, HF_NO = 0, HF_YES = 1, } tristate_t; struct _dynfile_t { size_t size; uint64_t cov[4]; size_t idx; int fd; uint64_t timeExecUSecs; char path[PATH_MAX]; struct _dynfile_t* src; uint32_t refs; uint8_t* data; TAILQ_ENTRY(_dynfile_t) pointers; }; typedef struct _dynfile_t dynfile_t; struct strings_t { size_t len; TAILQ_ENTRY(strings_t) pointers; char s[]; }; typedef struct { uint8_t pcGuardMap[_HF_PC_GUARD_MAX]; uint8_t bbMapPc[_HF_PERF_BITMAP_SIZE_16M]; uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M]; uint64_t pidNewPC[_HF_THREAD_MAX]; uint64_t pidNewEdge[_HF_THREAD_MAX]; uint64_t pidNewCmp[_HF_THREAD_MAX]; uint64_t guardNb; uint64_t pidTotalPC[_HF_THREAD_MAX]; uint64_t pidTotalEdge[_HF_THREAD_MAX]; uint64_t pidTotalCmp[_HF_THREAD_MAX]; } feedback_t; typedef struct { uint32_t cnt; struct { uint8_t val[32]; uint32_t len; } valArr[1024 * 16]; } cmpfeedback_t; typedef struct { struct { size_t threadsMax; size_t threadsFinished; uint32_t threadsActiveCnt; pthread_t mainThread; pid_t mainPid; pthread_t threads[_HF_THREAD_MAX]; } threads; struct { const char* inputDir; const char* outputDir; DIR* inputDirPtr; size_t fileCnt; size_t testedFileCnt; const char* fileExtn; size_t maxFileSz; size_t newUnitsAdded; char workDir[PATH_MAX]; const char* crashDir; const char* covDirNew; bool saveUnique; size_t dynfileqMaxSz; size_t dynfileqCnt; dynfile_t* dynfileqCurrent; dynfile_t* dynfileq2Current; TAILQ_HEAD(dyns_t, _dynfile_t) dynfileq; bool exportFeedback; } io; struct { int argc; const char* const* cmdline; bool nullifyStdio; bool fuzzStdin; const char* externalCommand; const char* postExternalCommand; const char* feedbackMutateCommand; bool netDriver; bool persistent; uint64_t asLimit; uint64_t rssLimit; uint64_t dataLimit; uint64_t coreLimit; uint64_t stackLimit; bool clearEnv; char* env_ptrs[128]; char env_vals[128][4096]; sigset_t waitSigSet; } exe; struct { time_t timeStart; time_t runEndTime; time_t tmOut; time_t lastCovUpdate; int64_t timeOfLongestUnitUSecs; bool tmoutVTALRM; } timing; struct { struct { uint8_t val[256]; size_t len; } dictionary[1024]; size_t dictionaryCnt; const char* dictionaryFile; size_t mutationsMax; unsigned mutationsPerRun; size_t maxInputSz; } mutate; struct { bool useScreen; char cmdline_txt[65]; int64_t lastDisplayUSecs; } display; struct { bool useVerifier; bool exitUponCrash; const char* reportFile; size_t dynFileIterExpire; bool only_printable; bool minimize; bool switchingToFDM; } cfg; struct { bool enable; bool del_report; } sanitizer; struct { fuzzState_t state; feedback_t* covFeedbackMap; int covFeedbackFd; cmpfeedback_t* cmpFeedbackMap; int cmpFeedbackFd; bool cmpFeedback; const char* blacklistFile; uint64_t* blacklist; size_t blacklistCnt; bool skipFeedbackOnTimeout; uint64_t maxCov[4]; dynFileMethod_t dynFileMethod; hwcnt_t hwCnts; } feedback; struct { size_t mutationsCnt; size_t crashesCnt; size_t uniqueCrashesCnt; size_t verifiedCrashesCnt; size_t blCrashesCnt; size_t timeoutedCnt; } cnts; struct { bool enabled; int serverSocket; int clientSocket; } socketFuzzer; struct { pthread_rwlock_t dynfileq; pthread_mutex_t feedback; pthread_mutex_t report; pthread_mutex_t state; pthread_mutex_t input; pthread_mutex_t timing; } mutex; /* For the Linux code */ struct { int exeFd; uint64_t dynamicCutOffAddr; bool disableRandomization; void* ignoreAddr; const char* symsBlFile; char** symsBl; size_t symsBlCnt; const char* symsWlFile; char** symsWl; size_t symsWlCnt; uintptr_t cloneFlags; tristate_t useNetNs; bool kernelOnly; bool useClone; } arch_linux; /* For the NetBSD code */ struct { void* ignoreAddr; const char* symsBlFile; char** symsBl; size_t symsBlCnt; const char* symsWlFile; char** symsWl; size_t symsWlCnt; } arch_netbsd; } honggfuzz_t; typedef enum { _HF_RS_UNKNOWN = 0, _HF_RS_WAITING_FOR_INITIAL_READY = 1, _HF_RS_WAITING_FOR_READY = 2, _HF_RS_SEND_DATA = 3, } runState_t; typedef struct { honggfuzz_t* global; pid_t pid; int64_t timeStartedUSecs; char crashFileName[PATH_MAX]; uint64_t pc; uint64_t backtrace; uint64_t access; int exception; char report[_HF_REPORT_SIZE]; bool mainWorker; unsigned mutationsPerRun; dynfile_t* dynfile; bool staticFileTryMore; uint32_t fuzzNo; int persistentSock; runState_t runState; bool tmOutSignaled; char* args[_HF_ARGS_MAX + 1]; int perThreadCovFeedbackFd; unsigned triesLeft; dynfile_t* current; #if !defined(_HF_ARCH_DARWIN) timer_t timerId; #endif // !defined(_HF_ARCH_DARWIN) hwcnt_t hwCnts; struct { /* For Linux code */ uint8_t* perfMmapBuf; uint8_t* perfMmapAux; int cpuInstrFd; int cpuBranchFd; int cpuIptBtsFd; } arch_linux; } run_t; #endif