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-2017 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 "libcommon/util.h"
     39 
     40 #define PROG_NAME "honggfuzz"
     41 #define PROG_VERSION "1.3"
     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 (1024 * 1024 * 2) /* 2MB */
     51 
     52 /* Name of envvar which indicates sequential number of fuzzer */
     53 #define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO"
     54 
     55 /* Number of crash verifier iterations before tag crash as stable */
     56 #define _HF_VERIFIER_ITER 5
     57 
     58 /* Size (in bytes) for report data to be stored in stack before written to file */
     59 #define _HF_REPORT_SIZE 8192
     60 
     61 /* Perf bitmap size */
     62 #define _HF_PERF_BITMAP_SIZE_16M (1024U * 1024U * 16U)
     63 #define _HF_PERF_BITMAP_BITSZ_MASK 0x7ffffff
     64 /* Maximum number of PC guards (=trace-pc-guard) we support */
     65 #define _HF_PC_GUARD_MAX (1024U * 1024U * 16U)
     66 
     67 /* FD used to pass feedback bitmap a process */
     68 #define _HF_BITMAP_FD 1022
     69 /* FD used to pass data to a persistent process */
     70 #define _HF_PERSISTENT_FD 1023
     71 /* Maximum number of active fuzzing threads */
     72 #define _HF_THREAD_MAX 1024U
     73 
     74 typedef enum {
     75     _HF_DYNFILE_NONE = 0x0,
     76     _HF_DYNFILE_INSTR_COUNT = 0x1,
     77     _HF_DYNFILE_BRANCH_COUNT = 0x2,
     78     _HF_DYNFILE_BTS_EDGE = 0x10,
     79     _HF_DYNFILE_IPT_BLOCK = 0x20,
     80     _HF_DYNFILE_SOFT = 0x40,
     81 } dynFileMethod_t;
     82 
     83 typedef struct {
     84     uint64_t cpuInstrCnt;
     85     uint64_t cpuBranchCnt;
     86     uint64_t bbCnt;
     87     uint64_t newBBCnt;
     88     uint64_t softCntPc;
     89     uint64_t softCntEdge;
     90     uint64_t softCntCmp;
     91 } hwcnt_t;
     92 
     93 /* Sanitizer coverage specific data structures */
     94 typedef struct {
     95     uint64_t hitBBCnt;
     96     uint64_t totalBBCnt;
     97     uint64_t dsoCnt;
     98     uint64_t iDsoCnt;
     99     uint64_t newBBCnt;
    100     uint64_t crashesCnt;
    101 } sancovcnt_t;
    102 
    103 typedef struct {
    104     uint32_t capacity;
    105     uint32_t* pChunks;
    106     uint32_t nChunks;
    107 } bitmap_t;
    108 
    109 /* Memory map struct */
    110 typedef struct __attribute__((packed)) {
    111     uint64_t start;          // region start addr
    112     uint64_t end;            // region end addr
    113     uint64_t base;           // region base addr
    114     char mapName[NAME_MAX];  // bin/DSO name
    115     uint64_t bbCnt;
    116     uint64_t newBBCnt;
    117 } memMap_t;
    118 
    119 /* Trie node data struct */
    120 typedef struct __attribute__((packed)) {
    121     bitmap_t* pBM;
    122 } trieData_t;
    123 
    124 /* Trie node struct */
    125 typedef struct node {
    126     char key;
    127     trieData_t data;
    128     struct node* next;
    129     struct node* prev;
    130     struct node* children;
    131     struct node* parent;
    132 } node_t;
    133 
    134 /* EOF Sanitizer coverage specific data structures */
    135 
    136 typedef struct {
    137     char* asanOpts;
    138     char* msanOpts;
    139     char* ubsanOpts;
    140 } sanOpts_t;
    141 
    142 typedef enum {
    143     _HF_STATE_UNSET = 0,
    144     _HF_STATE_STATIC = 1,
    145     _HF_STATE_DYNAMIC_PRE = 2,
    146     _HF_STATE_DYNAMIC_MAIN = 3,
    147 } fuzzState_t;
    148 
    149 struct dynfile_t {
    150     uint8_t* data;
    151     size_t size;
    152     TAILQ_ENTRY(dynfile_t)
    153     pointers;
    154 };
    155 
    156 struct strings_t {
    157     char* s;
    158     size_t len;
    159     TAILQ_ENTRY(strings_t)
    160     pointers;
    161 };
    162 
    163 typedef struct {
    164     bool pcGuardMap[_HF_PC_GUARD_MAX];
    165     uint8_t bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
    166     uint8_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
    167     uint64_t pidFeedbackPc[_HF_THREAD_MAX];
    168     uint64_t pidFeedbackEdge[_HF_THREAD_MAX];
    169     uint64_t pidFeedbackCmp[_HF_THREAD_MAX];
    170 } feedback_t;
    171 
    172 typedef struct {
    173     struct {
    174         const char* inputDir;
    175         DIR* inputDirPtr;
    176         size_t fileCnt;
    177         const char* fileExtn;
    178         bool fileCntDone;
    179         const char* workDir;
    180         const char* crashDir;
    181         const char* covDirAll;
    182         const char* covDirNew;
    183         bool saveUnique;
    184     } io;
    185     struct {
    186         const char* const* cmdline;
    187         bool nullifyStdio;
    188         bool fuzzStdin;
    189         char* externalCommand;
    190         char* postExternalCommand;
    191         uint64_t asLimit;
    192         uint64_t rssLimit;
    193         uint64_t dataLimit;
    194         bool clearEnv;
    195         char* envs[128];
    196     } exe;
    197     struct {
    198         size_t threadsMax;
    199         size_t threadsFinished;
    200         uint32_t threadsActiveCnt;
    201         pthread_t mainThread;
    202         pid_t mainPid;
    203     } threads;
    204     struct {
    205         time_t timeStart;
    206         time_t runEndTime;
    207         time_t tmOut;
    208         bool tmoutVTALRM;
    209     } timing;
    210     bool useScreen;
    211     bool useVerifier;
    212     char cmdline_txt[61];
    213     unsigned mutationsPerRun;
    214     const char* blacklistFile;
    215     uint64_t* blacklist;
    216     size_t blacklistCnt;
    217     size_t mutationsMax;
    218     size_t maxFileSz;
    219     char* reportFile;
    220     bool persistent;
    221     bool skipFeedbackOnTimeout;
    222     bool enableSanitizers;
    223     bool monitorSIGABRT;
    224     bool exitUponCrash;
    225     const char* dictionaryFile;
    226     TAILQ_HEAD(strq_t, strings_t) dictq;
    227     size_t dictionaryCnt;
    228     struct strings_t* dictqCurrent;
    229 
    230     fuzzState_t state;
    231     feedback_t* feedback;
    232     int bbFd;
    233 
    234     size_t dynfileqCnt;
    235     TAILQ_HEAD(dyns_t, dynfile_t) dynfileq;
    236     pthread_rwlock_t dynfileq_mutex;
    237 
    238     pthread_mutex_t feedback_mutex;
    239 
    240     struct {
    241         size_t mutationsCnt;
    242         size_t crashesCnt;
    243         size_t uniqueCrashesCnt;
    244         size_t verifiedCrashesCnt;
    245         size_t blCrashesCnt;
    246         size_t timeoutedCnt;
    247     } cnts;
    248 
    249     dynFileMethod_t dynFileMethod;
    250     sancovcnt_t sanCovCnts;
    251     pthread_mutex_t sanCov_mutex;
    252     sanOpts_t sanOpts;
    253     size_t dynFileIterExpire;
    254     bool useSanCov;
    255     node_t* covMetadata;
    256 
    257     pthread_mutex_t report_mutex;
    258 
    259     /* For the Linux code */
    260     struct {
    261         int exeFd;
    262         hwcnt_t hwCnts;
    263         uint64_t dynamicCutOffAddr;
    264         bool disableRandomization;
    265         void* ignoreAddr;
    266         size_t numMajorFrames;
    267         pid_t pid;
    268         const char* pidFile;
    269         char pidCmd[55];
    270         const char* symsBlFile;
    271         char** symsBl;
    272         size_t symsBlCnt;
    273         const char* symsWlFile;
    274         char** symsWl;
    275         size_t symsWlCnt;
    276         uintptr_t cloneFlags;
    277         bool kernelOnly;
    278         bool useClone;
    279     } linux;
    280 } honggfuzz_t;
    281 
    282 typedef struct {
    283     honggfuzz_t* global;
    284     pid_t pid;
    285     pid_t persistentPid;
    286     fuzzState_t state;
    287     int64_t timeStartedMillis;
    288     const char* origFileName;
    289     char fileName[PATH_MAX];
    290     char crashFileName[PATH_MAX];
    291     uint64_t pc;
    292     uint64_t backtrace;
    293     uint64_t access;
    294     int exception;
    295     char report[_HF_REPORT_SIZE];
    296     bool mainWorker;
    297     unsigned mutationsPerRun;
    298     struct dynfile_t* dynfileqCurrent;
    299     uint8_t* dynamicFile;
    300     size_t dynamicFileSz;
    301     uint32_t fuzzNo;
    302     int persistentSock;
    303     bool tmOutSignaled;
    304 #if !defined(_HF_ARCH_DARWIN)
    305     timer_t timerId;
    306 #endif  // !defined(_HF_ARCH_DARWIN)
    307 
    308     sancovcnt_t sanCovCnts;
    309 
    310     struct {
    311         /* For Linux code */
    312         uint8_t* perfMmapBuf;
    313         uint8_t* perfMmapAux;
    314         hwcnt_t hwCnts;
    315         pid_t attachedPid;
    316         int cpuInstrFd;
    317         int cpuBranchFd;
    318         int cpuIptBtsFd;
    319     } linux;
    320 } run_t;
    321 
    322 /* Go-style defer implementation */
    323 #define __STRMERGE(a, b) a##b
    324 #define _STRMERGE(a, b) __STRMERGE(a, b)
    325 #ifdef __clang__
    326 #if __has_extension(blocks)
    327 static void __attribute__((unused)) __clang_cleanup_func(void (^*dfunc)(void)) { (*dfunc)(); }
    328 
    329 #define defer                                        \
    330     void (^_STRMERGE(__defer_f_, __COUNTER__))(void) \
    331         __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^
    332 #else /* __has_extension(blocks) */
    333 #define defer UNIMPLEMENTED - NO - SUPPORT - FOR - BLOCKS - IN - YOUR - CLANG - ENABLED
    334 #endif /*  __has_extension(blocks) */
    335 #else  /* __clang */
    336 #define __block
    337 #define _DEFER(a, count)                                                                      \
    338     auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)));         \
    339     int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) \
    340         __attribute__((unused));                                                              \
    341     void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
    342 #define defer _DEFER(a, __COUNTER__)
    343 #endif /* __clang */
    344 
    345 #define MX_SCOPED_LOCK(m) \
    346     MX_LOCK(m);           \
    347     defer { MX_UNLOCK(m); }
    348 
    349 #define MX_SCOPED_RWLOCK_READ(m) \
    350     MX_RWLOCK_READ(m);           \
    351     defer { MX_RWLOCK_UNLOCK(m); }
    352 #define MX_SCOPED_RWLOCK_WRITE(m) \
    353     MX_RWLOCK_WRITE(m);           \
    354     defer { MX_RWLOCK_UNLOCK(m); }
    355 
    356 #endif
    357