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