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