Home | History | Annotate | Download | only in honggfuzz
      1 /*
      2  *
      3  * honggfuzz - core structures and macros
      4  * -----------------------------------------
      5  *
      6  * Author: Robert Swiecki <swiecki (at) google.com>
      7  *
      8  * Copyright 2010-2018 by Google Inc. All Rights Reserved.
      9  *
     10  * Licensed under the Apache License, Version 2.0 (the "License"); you may
     11  * not use this file except in compliance with the License. You may obtain
     12  * a copy of the License at
     13  *
     14  * http://www.apache.org/licenses/LICENSE-2.0
     15  *
     16  * Unless required by applicable law or agreed to in writing, software
     17  * distributed under the License is distributed on an "AS IS" BASIS,
     18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
     19  * implied. See the License for the specific language governing
     20  * permissions and limitations under the License.
     21  *
     22  */
     23 
     24 #ifndef _HF_HONGGFUZZ_H_
     25 #define _HF_HONGGFUZZ_H_
     26 
     27 #include <dirent.h>
     28 #include <inttypes.h>
     29 #include <limits.h>
     30 #include <pthread.h>
     31 #include <stdbool.h>
     32 #include <stdint.h>
     33 #include <sys/param.h>
     34 #include <sys/queue.h>
     35 #include <sys/types.h>
     36 #include <time.h>
     37 
     38 #include "libhfcommon/util.h"
     39 
     40 #define PROG_NAME "honggfuzz"
     41 #define PROG_VERSION "1.8"
     42 
     43 /* Name of the template which will be replaced with the proper name of the file */
     44 #define _HF_FILE_PLACEHOLDER "___FILE___"
     45 
     46 /* Default name of the report created with some architectures */
     47 #define _HF_REPORT_FILE "HONGGFUZZ.REPORT.TXT"
     48 
     49 /* Default stack-size of created threads. */
     50 #define _HF_PTHREAD_STACKSIZE (1024ULL * 1024ULL * 2ULL) /* 2MB */
     51 
     52 /* Name of envvar which indicates sequential number of fuzzer */
     53 #define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO"
     54 
     55 /* Name of envvar which indicates that the netDriver should be used */
     56 #define _HF_THREAD_NETDRIVER_ENV "HFUZZ_USE_NETDRIVER"
     57 
     58 /* Name of envvar which indicates honggfuzz's log level in use */
     59 #define _HF_LOG_LEVEL_ENV "HFUZZ_LOG_LEVEL"
     60 
     61 /* Number of crash verifier iterations before tag crash as stable */
     62 #define _HF_VERIFIER_ITER 5
     63 
     64 /* Size (in bytes) for report data to be stored in stack before written to file */
     65 #define _HF_REPORT_SIZE 8192
     66 
     67 /* Perf bitmap size */
     68 #define _HF_PERF_BITMAP_SIZE_16M (1024U * 1024U * 16U)
     69 #define _HF_PERF_BITMAP_BITSZ_MASK 0x7FFFFFFULL
     70 /* Maximum number of PC guards (=trace-pc-guard) we support */
     71 #define _HF_PC_GUARD_MAX (1024ULL * 1024ULL * 64ULL)
     72 
     73 /* Maximum size of the input file in bytes (128 MiB) */
     74 #define _HF_INPUT_MAX_SIZE (1024ULL * 1024ULL * 128ULL)
     75 
     76 /* FD used to log inside the child process */
     77 #define _HF_LOG_FD 1020
     78 /* FD used to represent the input file */
     79 #define _HF_INPUT_FD 1021
     80 /* FD used to pass feedback bitmap a process */
     81 #define _HF_BITMAP_FD 1022
     82 /* FD used to pass data to a persistent process */
     83 #define _HF_PERSISTENT_FD 1023
     84 
     85 /* Message indicating that the fuzzed process is ready for new data */
     86 static const uint8_t HFReadyTag = 'R';
     87 
     88 /* Maximum number of active fuzzing threads */
     89 #define _HF_THREAD_MAX 1024U
     90 
     91 /* Persistent-binary signature - if found within file, it means it's a persistent mode binary */
     92 #define _HF_PERSISTENT_SIG "\x01_LIBHFUZZ_PERSISTENT_BINARY_SIGNATURE_\x02\xFF"
     93 /* HF NetDriver signature - if found within file, it means it's a NetDriver-based binary */
     94 #define _HF_NETDRIVER_SIG "\x01_LIBHFUZZ_NETDRIVER_BINARY_SIGNATURE_\x02\xFF"
     95 
     96 typedef enum {
     97     _HF_DYNFILE_NONE = 0x0,
     98     _HF_DYNFILE_INSTR_COUNT = 0x1,
     99     _HF_DYNFILE_BRANCH_COUNT = 0x2,
    100     _HF_DYNFILE_BTS_EDGE = 0x10,
    101     _HF_DYNFILE_IPT_BLOCK = 0x20,
    102     _HF_DYNFILE_SOFT = 0x40,
    103 } dynFileMethod_t;
    104 
    105 typedef struct {
    106     uint64_t cpuInstrCnt;
    107     uint64_t cpuBranchCnt;
    108     uint64_t bbCnt;
    109     uint64_t newBBCnt;
    110     uint64_t softCntPc;
    111     uint64_t softCntEdge;
    112     uint64_t softCntCmp;
    113 } hwcnt_t;
    114 
    115 typedef struct {
    116     uint32_t capacity;
    117     uint32_t* pChunks;
    118     uint32_t nChunks;
    119 } bitmap_t;
    120 
    121 /* Memory map struct */
    122 typedef struct __attribute__((packed)) {
    123     uint64_t start;          // region start addr
    124     uint64_t end;            // region end addr
    125     uint64_t base;           // region base addr
    126     char mapName[NAME_MAX];  // bin/DSO name
    127     uint64_t bbCnt;
    128     uint64_t newBBCnt;
    129 } memMap_t;
    130 
    131 /* Trie node data struct */
    132 typedef struct __attribute__((packed)) {
    133     bitmap_t* pBM;
    134 } trieData_t;
    135 
    136 /* Trie node struct */
    137 typedef struct node {
    138     char key;
    139     trieData_t data;
    140     struct node* next;
    141     struct node* prev;
    142     struct node* children;
    143     struct node* parent;
    144 } node_t;
    145 
    146 /* EOF Sanitizer coverage specific data structures */
    147 
    148 typedef enum {
    149     _HF_STATE_UNSET = 0,
    150     _HF_STATE_STATIC = 1,
    151     _HF_STATE_DYNAMIC_DRY_RUN = 2,
    152     _HF_STATE_DYNAMIC_MAIN = 3,
    153 } fuzzState_t;
    154 
    155 struct dynfile_t {
    156     uint8_t* data;
    157     size_t size;
    158     TAILQ_ENTRY(dynfile_t)
    159     pointers;
    160 };
    161 
    162 struct strings_t {
    163     char* s;
    164     size_t len;
    165     TAILQ_ENTRY(strings_t)
    166     pointers;
    167 };
    168 
    169 typedef struct {
    170     bool pcGuardMap[_HF_PC_GUARD_MAX];
    171     uint8_t bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
    172     uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
    173     uint64_t pidFeedbackPc[_HF_THREAD_MAX];
    174     uint64_t pidFeedbackEdge[_HF_THREAD_MAX];
    175     uint64_t pidFeedbackCmp[_HF_THREAD_MAX];
    176 } feedback_t;
    177 
    178 typedef struct {
    179     struct {
    180         size_t threadsMax;
    181         size_t threadsFinished;
    182         uint32_t threadsActiveCnt;
    183         pthread_t mainThread;
    184         pid_t mainPid;
    185         pthread_t threads[_HF_THREAD_MAX];
    186     } threads;
    187     struct {
    188         const char* inputDir;
    189         DIR* inputDirPtr;
    190         size_t fileCnt;
    191         const char* fileExtn;
    192         bool fileCntDone;
    193         const char* workDir;
    194         const char* crashDir;
    195         const char* covDirAll;
    196         const char* covDirNew;
    197         bool saveUnique;
    198         size_t dynfileqCnt;
    199         pthread_rwlock_t dynfileq_mutex;
    200         TAILQ_HEAD(dyns_t, dynfile_t) dynfileq;
    201     } io;
    202     struct {
    203         int argc;
    204         const char* const* cmdline;
    205         bool nullifyStdio;
    206         bool fuzzStdin;
    207         const char* externalCommand;
    208         const char* postExternalCommand;
    209         bool netDriver;
    210         bool persistent;
    211         uint64_t asLimit;
    212         uint64_t rssLimit;
    213         uint64_t dataLimit;
    214         uint64_t coreLimit;
    215         bool clearEnv;
    216         char* envs[128];
    217         sigset_t waitSigSet;
    218     } exe;
    219     struct {
    220         time_t timeStart;
    221         time_t runEndTime;
    222         time_t tmOut;
    223         time_t lastCovUpdate;
    224         bool tmoutVTALRM;
    225     } timing;
    226     struct {
    227         const char* dictionaryFile;
    228         TAILQ_HEAD(strq_t, strings_t) dictq;
    229         size_t dictionaryCnt;
    230         size_t mutationsMax;
    231         unsigned mutationsPerRun;
    232         size_t maxFileSz;
    233     } mutate;
    234     struct {
    235         bool useScreen;
    236         char cmdline_txt[65];
    237         int64_t lastDisplayMillis;
    238     } display;
    239     struct {
    240         bool useVerifier;
    241         bool exitUponCrash;
    242         const char* reportFile;
    243         pthread_mutex_t report_mutex;
    244         bool monitorSIGABRT;
    245         size_t dynFileIterExpire;
    246         bool only_printable;
    247     } cfg;
    248     struct {
    249         bool enable;
    250     } sanitizer;
    251     struct {
    252         fuzzState_t state;
    253         feedback_t* feedbackMap;
    254         int bbFd;
    255         pthread_mutex_t feedback_mutex;
    256         const char* blacklistFile;
    257         uint64_t* blacklist;
    258         size_t blacklistCnt;
    259         bool skipFeedbackOnTimeout;
    260         dynFileMethod_t dynFileMethod;
    261     } feedback;
    262     struct {
    263         size_t mutationsCnt;
    264         size_t crashesCnt;
    265         size_t uniqueCrashesCnt;
    266         size_t verifiedCrashesCnt;
    267         size_t blCrashesCnt;
    268         size_t timeoutedCnt;
    269     } cnts;
    270     struct {
    271         bool enabled;
    272         int serverSocket;
    273         int clientSocket;
    274     } socketFuzzer;
    275     /* For the Linux code */
    276     struct {
    277         int exeFd;
    278         hwcnt_t hwCnts;
    279         uint64_t dynamicCutOffAddr;
    280         bool disableRandomization;
    281         void* ignoreAddr;
    282         size_t numMajorFrames;
    283         const char* symsBlFile;
    284         char** symsBl;
    285         size_t symsBlCnt;
    286         const char* symsWlFile;
    287         char** symsWl;
    288         size_t symsWlCnt;
    289         uintptr_t cloneFlags;
    290         bool kernelOnly;
    291         bool useClone;
    292     } linux;
    293     /* For the NetBSD code */
    294     struct {
    295         void* ignoreAddr;
    296         size_t numMajorFrames;
    297         const char* symsBlFile;
    298         char** symsBl;
    299         size_t symsBlCnt;
    300         const char* symsWlFile;
    301         char** symsWl;
    302         size_t symsWlCnt;
    303     } netbsd;
    304 } honggfuzz_t;
    305 
    306 typedef enum {
    307     _HF_RS_UNKNOWN = 0,
    308     _HF_RS_WAITING_FOR_INITIAL_READY = 1,
    309     _HF_RS_WAITING_FOR_READY = 2,
    310     _HF_RS_SEND_DATA = 3,
    311 } runState_t;
    312 
    313 typedef struct {
    314     honggfuzz_t* global;
    315     pid_t pid;
    316     int64_t timeStartedMillis;
    317     char origFileName[PATH_MAX];
    318     char crashFileName[PATH_MAX];
    319     uint64_t pc;
    320     uint64_t backtrace;
    321     uint64_t access;
    322     int exception;
    323     char report[_HF_REPORT_SIZE];
    324     bool mainWorker;
    325     unsigned mutationsPerRun;
    326     struct dynfile_t* dynfileqCurrent;
    327     uint8_t* dynamicFile;
    328     size_t dynamicFileSz;
    329     int dynamicFileFd;
    330     int dynamicFileCopyFd;
    331     uint32_t fuzzNo;
    332     int persistentSock;
    333     bool waitingForReady;
    334     runState_t runState;
    335     bool tmOutSignaled;
    336 #if !defined(_HF_ARCH_DARWIN)
    337     timer_t timerId;
    338 #endif  // !defined(_HF_ARCH_DARWIN)
    339 
    340     struct {
    341         /* For Linux code */
    342         uint8_t* perfMmapBuf;
    343         uint8_t* perfMmapAux;
    344         hwcnt_t hwCnts;
    345         int cpuInstrFd;
    346         int cpuBranchFd;
    347         int cpuIptBtsFd;
    348     } linux;
    349 
    350     struct {
    351         /* For NetBSD code */
    352         uint8_t* perfMmapBuf;
    353         uint8_t* perfMmapAux;
    354         hwcnt_t hwCnts;
    355         int cpuInstrFd;
    356         int cpuBranchFd;
    357         int cpuIptBtsFd;
    358     } netbsd;
    359 } run_t;
    360 
    361 /*
    362  * Go-style defer scoped implementation
    363  *
    364  * When compiled with clang, use: -fblocks -lBlocksRuntime
    365  *
    366  * Example of use:
    367  *
    368  * {
    369  *   int fd = open(fname, O_RDONLY);
    370  *   if (fd == -1) {
    371  *     error(....);
    372  *     return;
    373  *   }
    374  *   defer { close(fd); };
    375  *   ssize_t sz = read(fd, buf, sizeof(buf));
    376  *   ...
    377  *   ...
    378  * }
    379  *
    380  */
    381 
    382 #define __STRMERGE(a, b) a##b
    383 #define _STRMERGE(a, b) __STRMERGE(a, b)
    384 #ifdef __clang__
    385 #if __has_extension(blocks)
    386 static void __attribute__((unused)) __clang_cleanup_func(void (^*dfunc)(void)) {
    387     (*dfunc)();
    388 }
    389 
    390 #define defer                                        \
    391     void (^_STRMERGE(__defer_f_, __COUNTER__))(void) \
    392         __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^
    393 
    394 #else /* __has_extension(blocks) */
    395 #define defer UNIMPLEMENTED - NO - SUPPORT - FOR - BLOCKS - IN - YOUR - CLANG - ENABLED
    396 #endif /*  __has_extension(blocks) */
    397 #else  /* !__clang__, e.g.: gcc */
    398 
    399 #define __block
    400 #define _DEFER(a, count)                                                                      \
    401     auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)));         \
    402     int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) \
    403         __attribute__((unused));                                                              \
    404     void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
    405 #define defer _DEFER(a, __COUNTER__)
    406 #endif /* ifdef __clang__ */
    407 
    408 /* Block scoped mutexes */
    409 #define MX_SCOPED_LOCK(m) \
    410     MX_LOCK(m);           \
    411     defer {               \
    412         MX_UNLOCK(m);     \
    413     }
    414 
    415 #define MX_SCOPED_RWLOCK_READ(m) \
    416     MX_RWLOCK_READ(m);           \
    417     defer {                      \
    418         MX_RWLOCK_UNLOCK(m);     \
    419     }
    420 #define MX_SCOPED_RWLOCK_WRITE(m) \
    421     MX_RWLOCK_WRITE(m);           \
    422     defer {                       \
    423         MX_RWLOCK_UNLOCK(m);      \
    424     }
    425 
    426 #endif
    427