1 /* 2 * 3 * honggfuzz - core structures and macros 4 * ----------------------------------------- 5 * 6 * Author: Robert Swiecki <swiecki@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.9" 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_SWITCH_TO_MAIN = 3, 153 _HF_STATE_DYNAMIC_MAIN = 4, 154 } fuzzState_t; 155 156 struct dynfile_t { 157 uint8_t* data; 158 size_t size; 159 TAILQ_ENTRY(dynfile_t) 160 pointers; 161 }; 162 163 struct strings_t { 164 char* s; 165 size_t len; 166 TAILQ_ENTRY(strings_t) 167 pointers; 168 }; 169 170 typedef struct { 171 bool pcGuardMap[_HF_PC_GUARD_MAX]; 172 uint8_t bbMapPc[_HF_PERF_BITMAP_SIZE_16M]; 173 uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M]; 174 uint64_t pidFeedbackPc[_HF_THREAD_MAX]; 175 uint64_t pidFeedbackEdge[_HF_THREAD_MAX]; 176 uint64_t pidFeedbackCmp[_HF_THREAD_MAX]; 177 } feedback_t; 178 179 typedef struct { 180 struct { 181 size_t threadsMax; 182 size_t threadsFinished; 183 uint32_t threadsActiveCnt; 184 pthread_t mainThread; 185 pid_t mainPid; 186 pthread_t threads[_HF_THREAD_MAX]; 187 } threads; 188 struct { 189 const char* inputDir; 190 DIR* inputDirPtr; 191 size_t fileCnt; 192 const char* fileExtn; 193 bool fileCntDone; 194 const char* workDir; 195 const char* crashDir; 196 const char* covDirAll; 197 const char* covDirNew; 198 bool saveUnique; 199 size_t dynfileqCnt; 200 pthread_rwlock_t dynfileq_mutex; 201 TAILQ_HEAD(dyns_t, dynfile_t) dynfileq; 202 } io; 203 struct { 204 int argc; 205 const char* const* cmdline; 206 bool nullifyStdio; 207 bool fuzzStdin; 208 const char* externalCommand; 209 const char* postExternalCommand; 210 const char* feedbackMutateCommand; 211 bool netDriver; 212 bool persistent; 213 uint64_t asLimit; 214 uint64_t rssLimit; 215 uint64_t dataLimit; 216 uint64_t coreLimit; 217 bool clearEnv; 218 char* envs[128]; 219 sigset_t waitSigSet; 220 } exe; 221 struct { 222 time_t timeStart; 223 time_t runEndTime; 224 time_t tmOut; 225 time_t lastCovUpdate; 226 bool tmoutVTALRM; 227 } timing; 228 struct { 229 const char* dictionaryFile; 230 TAILQ_HEAD(strq_t, strings_t) dictq; 231 size_t dictionaryCnt; 232 size_t mutationsMax; 233 unsigned mutationsPerRun; 234 size_t maxFileSz; 235 } mutate; 236 struct { 237 bool useScreen; 238 char cmdline_txt[65]; 239 int64_t lastDisplayMillis; 240 } display; 241 struct { 242 bool useVerifier; 243 bool exitUponCrash; 244 const char* reportFile; 245 pthread_mutex_t report_mutex; 246 bool monitorSIGABRT; 247 size_t dynFileIterExpire; 248 bool only_printable; 249 } cfg; 250 struct { 251 bool enable; 252 } sanitizer; 253 struct { 254 fuzzState_t state; 255 feedback_t* feedbackMap; 256 int bbFd; 257 pthread_mutex_t feedback_mutex; 258 const char* blacklistFile; 259 uint64_t* blacklist; 260 size_t blacklistCnt; 261 bool skipFeedbackOnTimeout; 262 dynFileMethod_t dynFileMethod; 263 } feedback; 264 struct { 265 size_t mutationsCnt; 266 size_t crashesCnt; 267 size_t uniqueCrashesCnt; 268 size_t verifiedCrashesCnt; 269 size_t blCrashesCnt; 270 size_t timeoutedCnt; 271 } cnts; 272 struct { 273 bool enabled; 274 int serverSocket; 275 int clientSocket; 276 } socketFuzzer; 277 /* For the Linux code */ 278 struct { 279 int exeFd; 280 hwcnt_t hwCnts; 281 uint64_t dynamicCutOffAddr; 282 bool disableRandomization; 283 void* ignoreAddr; 284 size_t numMajorFrames; 285 const char* symsBlFile; 286 char** symsBl; 287 size_t symsBlCnt; 288 const char* symsWlFile; 289 char** symsWl; 290 size_t symsWlCnt; 291 uintptr_t cloneFlags; 292 bool kernelOnly; 293 bool useClone; 294 } linux; 295 /* For the NetBSD code */ 296 struct { 297 void* ignoreAddr; 298 size_t numMajorFrames; 299 const char* symsBlFile; 300 char** symsBl; 301 size_t symsBlCnt; 302 const char* symsWlFile; 303 char** symsWl; 304 size_t symsWlCnt; 305 } netbsd; 306 } honggfuzz_t; 307 308 typedef enum { 309 _HF_RS_UNKNOWN = 0, 310 _HF_RS_WAITING_FOR_INITIAL_READY = 1, 311 _HF_RS_WAITING_FOR_READY = 2, 312 _HF_RS_SEND_DATA = 3, 313 } runState_t; 314 315 typedef struct { 316 honggfuzz_t* global; 317 pid_t pid; 318 int64_t timeStartedMillis; 319 char origFileName[PATH_MAX]; 320 char crashFileName[PATH_MAX]; 321 uint64_t pc; 322 uint64_t backtrace; 323 uint64_t access; 324 int exception; 325 char report[_HF_REPORT_SIZE]; 326 bool mainWorker; 327 unsigned mutationsPerRun; 328 struct dynfile_t* dynfileqCurrent; 329 uint8_t* dynamicFile; 330 size_t dynamicFileSz; 331 int dynamicFileFd; 332 int dynamicFileCopyFd; 333 uint32_t fuzzNo; 334 int persistentSock; 335 bool waitingForReady; 336 runState_t runState; 337 bool tmOutSignaled; 338 #if !defined(_HF_ARCH_DARWIN) 339 timer_t timerId; 340 #endif // !defined(_HF_ARCH_DARWIN) 341 342 struct { 343 /* For Linux code */ 344 uint8_t* perfMmapBuf; 345 uint8_t* perfMmapAux; 346 hwcnt_t hwCnts; 347 int cpuInstrFd; 348 int cpuBranchFd; 349 int cpuIptBtsFd; 350 } linux; 351 352 struct { 353 /* For NetBSD code */ 354 uint8_t* perfMmapBuf; 355 uint8_t* perfMmapAux; 356 hwcnt_t hwCnts; 357 int cpuInstrFd; 358 int cpuBranchFd; 359 int cpuIptBtsFd; 360 } netbsd; 361 } run_t; 362 363 /* 364 * Go-style defer scoped implementation 365 * 366 * When compiled with clang, use: -fblocks -lBlocksRuntime 367 * 368 * Example of use: 369 * 370 * { 371 * int fd = open(fname, O_RDONLY); 372 * if (fd == -1) { 373 * error(....); 374 * return; 375 * } 376 * defer { close(fd); }; 377 * ssize_t sz = read(fd, buf, sizeof(buf)); 378 * ... 379 * ... 380 * } 381 * 382 */ 383 384 #define __STRMERGE(a, b) a##b 385 #define _STRMERGE(a, b) __STRMERGE(a, b) 386 #ifdef __clang__ 387 #if __has_extension(blocks) 388 static void __attribute__((unused)) __clang_cleanup_func(void (^*dfunc)(void)) { 389 (*dfunc)(); 390 } 391 392 #define defer \ 393 void (^_STRMERGE(__defer_f_, __COUNTER__))(void) \ 394 __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^ 395 396 #else /* __has_extension(blocks) */ 397 #define defer UNIMPLEMENTED - NO - SUPPORT - FOR - BLOCKS - IN - YOUR - CLANG - ENABLED 398 #endif /* __has_extension(blocks) */ 399 #else /* !__clang__, e.g.: gcc */ 400 401 #define __block 402 #define _DEFER(a, count) \ 403 auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused))); \ 404 int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) \ 405 __attribute__((unused)); \ 406 void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused))) 407 #define defer _DEFER(a, __COUNTER__) 408 #endif /* ifdef __clang__ */ 409 410 /* Block scoped mutexes */ 411 #define MX_SCOPED_LOCK(m) \ 412 MX_LOCK(m); \ 413 defer { \ 414 MX_UNLOCK(m); \ 415 } 416 417 #define MX_SCOPED_RWLOCK_READ(m) \ 418 MX_RWLOCK_READ(m); \ 419 defer { \ 420 MX_RWLOCK_UNLOCK(m); \ 421 } 422 #define MX_SCOPED_RWLOCK_WRITE(m) \ 423 MX_RWLOCK_WRITE(m); \ 424 defer { \ 425 MX_RWLOCK_UNLOCK(m); \ 426 } 427 428 #endif 429