1 /* 2 3 honggfuzz - cmdline parsing 4 5 ----------------------------------------- 6 7 Copyright 2014 Google Inc. All Rights Reserved. 8 9 Licensed under the Apache License, Version 2.0 (the "License"); 10 you may not use this file except in compliance with the License. 11 You may obtain a copy of the License at 12 13 http://www.apache.org/licenses/LICENSE-2.0 14 15 Unless required by applicable law or agreed to in writing, software 16 distributed under the License is distributed on an "AS IS" BASIS, 17 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18 See the License for the specific language governing permissions and 19 limitations under the License. 20 21 */ 22 23 #include "cmdline.h" 24 25 #include <ctype.h> 26 #include <errno.h> 27 #include <getopt.h> 28 #include <inttypes.h> 29 #include <limits.h> 30 #if defined(_HF_ARCH_LINUX) 31 #include <sched.h> 32 #endif /* defined(_HF_ARCH_LINUX) */ 33 #include <signal.h> 34 #include <stdint.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <sys/mman.h> 39 #include <sys/queue.h> 40 #include <sys/stat.h> 41 #include <sys/types.h> 42 #include <unistd.h> 43 44 #include "display.h" 45 #include "libhfcommon/common.h" 46 #include "libhfcommon/files.h" 47 #include "libhfcommon/log.h" 48 #include "libhfcommon/util.h" 49 50 struct custom_option { 51 struct option opt; 52 const char* descr; 53 }; 54 55 static bool checkFor_FILE_PLACEHOLDER(const char* const* args) { 56 for (int x = 0; args[x]; x++) { 57 if (strstr(args[x], _HF_FILE_PLACEHOLDER)) return true; 58 } 59 return false; 60 } 61 62 static bool cmdlineCheckBinaryType(honggfuzz_t* hfuzz) { 63 int fd; 64 off_t fileSz; 65 uint8_t* map = files_mapFile(hfuzz->exe.cmdline[0], &fileSz, &fd, /* isWriteable= */ false); 66 if (!map) { 67 /* It's not a critical error */ 68 return true; 69 } 70 defer { 71 if (munmap(map, fileSz) == -1) { 72 PLOG_W("munmap(%p, %zu)", map, (size_t)fileSz); 73 } 74 close(fd); 75 }; 76 77 if (memmem(map, fileSz, _HF_PERSISTENT_SIG, strlen(_HF_PERSISTENT_SIG))) { 78 LOG_I("Persistent signature found in '%s'. Enabling persistent fuzzing mode", 79 hfuzz->exe.cmdline[0]); 80 hfuzz->exe.persistent = true; 81 } 82 if (memmem(map, fileSz, _HF_NETDRIVER_SIG, strlen(_HF_NETDRIVER_SIG))) { 83 LOG_I("NetDriver signature found '%s'", hfuzz->exe.cmdline[0]); 84 hfuzz->exe.netDriver = true; 85 } 86 return true; 87 } 88 89 static const char* cmdlineYesNo(bool yes) { 90 return (yes ? "true" : "false"); 91 } 92 93 static void cmdlineHelp(const char* pname, struct custom_option* opts) { 94 LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname); 95 LOG_HELP_BOLD("Options:"); 96 for (int i = 0; opts[i].opt.name; i++) { 97 if (isprint(opts[i].opt.val) && opts[i].opt.val < 0x80) { 98 LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name, "|-", opts[i].opt.val, 99 opts[i].opt.has_arg == required_argument ? "VALUE" : ""); 100 } else { 101 LOG_HELP_BOLD(" --%s %s", opts[i].opt.name, 102 opts[i].opt.has_arg == required_argument ? "VALUE" : ""); 103 } 104 LOG_HELP("\t%s", opts[i].descr); 105 } 106 LOG_HELP_BOLD("\nExamples:"); 107 LOG_HELP( 108 " Run the binary over a mutated file chosen from the directory. Disable fuzzing feedback " 109 "(static mode):"); 110 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -x -- /usr/bin/djpeg " _HF_FILE_PLACEHOLDER); 111 LOG_HELP(" As above, provide input over STDIN:"); 112 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -x -s -- /usr/bin/djpeg"); 113 LOG_HELP(" Use compile-time instrumentation (-fsanitize-coverage=trace-pc-guard,...):"); 114 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -- /usr/bin/djpeg " _HF_FILE_PLACEHOLDER); 115 LOG_HELP(" Use persistent mode w/o instrumentation:"); 116 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -x -- /usr/bin/djpeg_persistent_mode"); 117 LOG_HELP(" Use persistent mode and compile-time (-fsanitize-coverage=trace-pc-guard,...) " 118 "instrumentation:"); 119 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -- /usr/bin/djpeg_persistent_mode"); 120 #if defined(_HF_ARCH_LINUX) 121 LOG_HELP( 122 " Run the binary with dynamically generate inputs, maximize total no. of instructions:"); 123 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_instr -- /usr/bin/djpeg " _HF_FILE_PLACEHOLDER); 124 LOG_HELP(" As above, maximize total no. of branches:"); 125 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_branch -- /usr/bin/djpeg " _HF_FILE_PLACEHOLDER); 126 LOG_HELP(" As above, maximize unique branches (edges) via Intel BTS:"); 127 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_edge -- /usr/bin/djpeg " _HF_FILE_PLACEHOLDER); 128 LOG_HELP( 129 " As above, maximize unique code blocks via Intel Processor Trace (requires libipt.so):"); 130 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ipt_block -- /usr/bin/djpeg " _HF_FILE_PLACEHOLDER); 131 #endif /* defined(_HF_ARCH_LINUX) */ 132 } 133 134 static void cmdlineUsage(const char* pname, struct custom_option* opts) { 135 cmdlineHelp(pname, opts); 136 exit(0); 137 } 138 139 bool cmdlineAddEnv(honggfuzz_t* hfuzz, char* env) { 140 size_t enveqlen = strlen(env); 141 const char* eqpos = strchr(env, '='); 142 if (eqpos) { 143 enveqlen = (uintptr_t)eqpos - (uintptr_t)env + 1; 144 } 145 146 for (size_t i = 0; i < ARRAYSIZE(hfuzz->exe.envs); i++) { 147 if (hfuzz->exe.envs[i] == NULL) { 148 LOG_D("Adding envar '%s'", env); 149 hfuzz->exe.envs[i] = env; 150 return true; 151 } 152 if (strncmp(hfuzz->exe.envs[i], env, enveqlen) == 0) { 153 LOG_W("Replacing envar '%s' with '%s'", hfuzz->exe.envs[i], env); 154 hfuzz->exe.envs[i] = env; 155 return true; 156 } 157 } 158 LOG_E("No more space for new envars (max.%zu)", ARRAYSIZE(hfuzz->exe.envs)); 159 return false; 160 } 161 162 rlim_t cmdlineParseRLimit(int res, const char* optarg, unsigned long mul) { 163 struct rlimit cur; 164 if (getrlimit(res, &cur) == -1) { 165 PLOG_F("getrlimit(%d)", res); 166 } 167 if (strcasecmp(optarg, "max") == 0) { 168 return cur.rlim_max; 169 } 170 if (strcasecmp(optarg, "def") == 0) { 171 return cur.rlim_cur; 172 } 173 if (util_isANumber(optarg) == false) { 174 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg); 175 } 176 rlim_t val = strtoul(optarg, NULL, 0) * mul; 177 if ((unsigned long)val == ULONG_MAX && errno != 0) { 178 PLOG_F("strtoul('%s', 0)", optarg); 179 } 180 return val; 181 } 182 183 static bool cmdlineVerify(honggfuzz_t* hfuzz) { 184 if (!cmdlineCheckBinaryType(hfuzz)) { 185 LOG_E("Couldn't test binary for signatures"); 186 return false; 187 } 188 189 if (!hfuzz->exe.fuzzStdin && !hfuzz->exe.persistent && 190 !checkFor_FILE_PLACEHOLDER(hfuzz->exe.cmdline)) { 191 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER 192 "' if the -s (stdin fuzzing) or --persistent options are not set"); 193 return false; 194 } 195 196 if (hfuzz->exe.fuzzStdin && hfuzz->exe.persistent) { 197 LOG_E( 198 "Stdin fuzzing (-s) and persistent fuzzing (-P) cannot be specified at the same time"); 199 return false; 200 } 201 202 if (hfuzz->threads.threadsMax >= _HF_THREAD_MAX) { 203 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", 204 hfuzz->threads.threadsMax, _HF_THREAD_MAX); 205 return false; 206 } 207 208 if (strchr(hfuzz->io.fileExtn, '/')) { 209 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->io.fileExtn); 210 return false; 211 } 212 213 if (hfuzz->io.workDir == NULL) { 214 hfuzz->io.workDir = "."; 215 } 216 if (mkdir(hfuzz->io.workDir, 0700) == -1 && errno != EEXIST) { 217 PLOG_E("Couldn't create the workspace directory '%s'", hfuzz->io.workDir); 218 return false; 219 } 220 if (hfuzz->io.crashDir == NULL) { 221 hfuzz->io.crashDir = hfuzz->io.workDir; 222 } 223 if (mkdir(hfuzz->io.crashDir, 0700) && errno != EEXIST) { 224 PLOG_E("Couldn't create the crash directory '%s'", hfuzz->io.crashDir); 225 return false; 226 } 227 228 if (hfuzz->mutate.mutationsPerRun == 0U && hfuzz->cfg.useVerifier) { 229 LOG_I("Verifier enabled with mutationsPerRun == 0, activating the dry run mode"); 230 } 231 232 if (hfuzz->mutate.maxFileSz > _HF_INPUT_MAX_SIZE) { 233 LOG_E("Maximum file size '%zu' bigger than the maximum size '%zu'", hfuzz->mutate.maxFileSz, 234 (size_t)_HF_INPUT_MAX_SIZE); 235 return false; 236 } 237 238 return true; 239 } 240 241 bool cmdlineParse(int argc, char* argv[], honggfuzz_t* hfuzz) { 242 *hfuzz = (honggfuzz_t){ 243 .threads = 244 { 245 .threadsFinished = 0, 246 .threadsMax = 247 (sysconf(_SC_NPROCESSORS_ONLN) <= 1) ? 1 : sysconf(_SC_NPROCESSORS_ONLN) / 2, 248 .threadsActiveCnt = 0, 249 .mainThread = pthread_self(), 250 .mainPid = getpid(), 251 }, 252 .io = 253 { 254 .inputDir = NULL, 255 .inputDirPtr = NULL, 256 .fileCnt = 0, 257 .fileCntDone = false, 258 .fileExtn = "fuzz", 259 .workDir = NULL, 260 .crashDir = NULL, 261 .covDirAll = NULL, 262 .covDirNew = NULL, 263 .saveUnique = true, 264 .dynfileqCnt = 0U, 265 .dynfileq_mutex = PTHREAD_RWLOCK_INITIALIZER, 266 }, 267 .exe = 268 { 269 .argc = 0, 270 .cmdline = NULL, 271 .nullifyStdio = true, 272 .fuzzStdin = false, 273 .externalCommand = NULL, 274 .postExternalCommand = NULL, 275 .persistent = false, 276 .netDriver = false, 277 .asLimit = 0U, 278 .rssLimit = 0U, 279 .dataLimit = 0U, 280 .clearEnv = false, 281 .envs = {}, 282 }, 283 .timing = 284 { 285 .timeStart = time(NULL), 286 .runEndTime = 0, 287 .tmOut = 10, 288 .tmoutVTALRM = false, 289 .lastCovUpdate = time(NULL), 290 }, 291 .mutate = 292 { 293 .mutationsMax = 0, 294 .dictionaryFile = NULL, 295 .dictionaryCnt = 0, 296 .mutationsPerRun = 6U, 297 .maxFileSz = 0UL, 298 }, 299 .display = 300 { 301 .useScreen = true, 302 .lastDisplayMillis = util_timeNowMillis(), 303 .cmdline_txt[0] = '\0', 304 }, 305 .cfg = 306 { 307 .useVerifier = false, 308 .exitUponCrash = false, 309 .report_mutex = PTHREAD_MUTEX_INITIALIZER, 310 .reportFile = NULL, 311 .dynFileIterExpire = 0, 312 #if defined(__ANDROID__) 313 .monitorSIGABRT = false, 314 #else 315 .monitorSIGABRT = true, 316 #endif 317 .only_printable = false, 318 }, 319 .sanitizer = 320 { 321 .enable = false, 322 }, 323 .feedback = 324 { 325 .feedbackMap = NULL, 326 .feedback_mutex = PTHREAD_MUTEX_INITIALIZER, 327 .bbFd = -1, 328 .blacklistFile = NULL, 329 .blacklist = NULL, 330 .blacklistCnt = 0, 331 .skipFeedbackOnTimeout = false, 332 .dynFileMethod = _HF_DYNFILE_SOFT, 333 .state = _HF_STATE_UNSET, 334 }, 335 .cnts = 336 { 337 .mutationsCnt = 0, 338 .crashesCnt = 0, 339 .uniqueCrashesCnt = 0, 340 .verifiedCrashesCnt = 0, 341 .blCrashesCnt = 0, 342 .timeoutedCnt = 0, 343 }, 344 .socketFuzzer = 345 { 346 .enabled = false, 347 .serverSocket = -1, 348 .clientSocket = -1, 349 }, 350 351 /* Linux code */ 352 .linux = 353 { 354 .exeFd = -1, 355 .hwCnts = 356 { 357 .cpuInstrCnt = 0ULL, 358 .cpuBranchCnt = 0ULL, 359 .bbCnt = 0ULL, 360 .newBBCnt = 0ULL, 361 .softCntPc = 0ULL, 362 .softCntCmp = 0ULL, 363 }, 364 .dynamicCutOffAddr = ~(0ULL), 365 .disableRandomization = true, 366 .ignoreAddr = NULL, 367 .numMajorFrames = 7, 368 .symsBlFile = NULL, 369 .symsBlCnt = 0, 370 .symsBl = NULL, 371 .symsWlFile = NULL, 372 .symsWlCnt = 0, 373 .symsWl = NULL, 374 .cloneFlags = 0, 375 .kernelOnly = false, 376 .useClone = true, 377 }, 378 /* NetBSD code */ 379 .netbsd = 380 { 381 .ignoreAddr = NULL, 382 .numMajorFrames = 7, 383 .symsBlFile = NULL, 384 .symsBlCnt = 0, 385 .symsBl = NULL, 386 .symsWlFile = NULL, 387 .symsWlCnt = 0, 388 .symsWl = NULL, 389 }, 390 }; 391 392 TAILQ_INIT(&hfuzz->io.dynfileq); 393 TAILQ_INIT(&hfuzz->mutate.dictq); 394 395 // clang-format off 396 struct custom_option custom_opts[] = { 397 { { "help", no_argument, NULL, 'h' }, "Help plz.." }, 398 { { "input", required_argument, NULL, 'f' }, "Path to a directory containing initial file corpus" }, 399 { { "persistent", no_argument, NULL, 'P' }, "Enable persistent fuzzing (use hfuzz_cc/hfuzz-clang to compile code). This will be auto-detected!!!" }, 400 { { "instrument", no_argument, NULL, 'z' }, "*DEFAULT-MODE-BY-DEFAULT* Enable compile-time instrumentation (use hfuzz_cc/hfuzz-clang to compile code)" }, 401 { { "noinst", no_argument, NULL, 'x' }, "Static mode only, disable any instrumentation (hw/sw) feedback" }, 402 { { "keep_output", no_argument, NULL, 'Q' }, "Don't close children's stdin, stdout, stderr; can be noisy" }, 403 { { "timeout", required_argument, NULL, 't' }, "Timeout in seconds (default: 10)" }, 404 { { "threads", required_argument, NULL, 'n' }, "Number of concurrent fuzzing threads (default: number of CPUs / 2)" }, 405 { { "stdin_input", no_argument, NULL, 's' }, "Provide fuzzing input on STDIN, instead of ___FILE___" }, 406 { { "mutations_per_run", required_argument, NULL, 'r' }, "Maximal number of mutations per one run (default: 6)" }, 407 { { "logfile", required_argument, NULL, 'l' }, "Log file" }, 408 { { "verbose", no_argument, NULL, 'v' }, "Disable ANSI console; use simple log output" }, 409 { { "verifier", no_argument, NULL, 'V' }, "Enable crashes verifier" }, 410 { { "debug", no_argument, NULL, 'd' }, "Show debug messages (level >= 4)" }, 411 { { "quiet", no_argument, NULL, 'q' }, "Show only warnings and more serious messages (level <= 1)" }, 412 { { "extension", required_argument, NULL, 'e' }, "Input file extension (e.g. 'swf'), (default: 'fuzz')" }, 413 { { "workspace", required_argument, NULL, 'W' }, "Workspace directory to save crashes & runtime files (default: '.')" }, 414 { { "crashdir", required_argument, NULL, 0x600 }, "Directory where crashes are saved to (default: workspace directory)" }, 415 { { "covdir_all", required_argument, NULL, 0x601 }, "Coverage is written to a separate directory (default: input directory)" }, 416 { { "covdir_new", required_argument, NULL, 0x602 }, "New coverage (beyond the dry-run fuzzing phase) is written to this separate directory" }, 417 { { "dict", required_argument, NULL, 'w' }, "Dictionary file. Format:http://llvm.org/docs/LibFuzzer.html#dictionaries" }, 418 { { "stackhash_bl", required_argument, NULL, 'B' }, "Stackhashes blacklist file (one entry per line)" }, 419 { { "mutate_cmd", required_argument, NULL, 'c' }, "External command producing fuzz files (instead of internal mutators)" }, 420 { { "pprocess_cmd", required_argument, NULL, 0x104 }, "External command postprocessing files produced by internal mutators" }, 421 { { "run_time", required_argument, NULL, 0x109 }, "Number of seconds this fuzzing session will last (default: 0 [no limit])" }, 422 { { "iterations", required_argument, NULL, 'N' }, "Number of fuzzing iterations (default: 0 [no limit])" }, 423 { { "rlimit_as", required_argument, NULL, 0x100 }, "Per process RLIMIT_AS in MiB (default: 0 [no limit])" }, 424 { { "rlimit_rss", required_argument, NULL, 0x101 }, "Per process RLIMIT_RSS in MiB (default: 0 [no limit]). It will also set *SAN's soft_rss_limit_mb if used" }, 425 { { "rlimit_data", required_argument, NULL, 0x102 }, "Per process RLIMIT_DATA in MiB (default: 0 [no limit])" }, 426 { { "rlimit_core", required_argument, NULL, 0x103 }, "Per process RLIMIT_CORE in MiB (default: 0 [no cores are produced])" }, 427 { { "report", required_argument, NULL, 'R' }, "Write report to this file (default: '<workdir>/" _HF_REPORT_FILE "')" }, 428 { { "max_file_size", required_argument, NULL, 'F' }, "Maximal size of files processed by the fuzzer in bytes (default: 1048576)" }, 429 { { "clear_env", no_argument, NULL, 0x108 }, "Clear all environment variables before executing the binary" }, 430 { { "env", required_argument, NULL, 'E' }, "Pass this environment variable, can be used multiple times" }, 431 { { "save_all", no_argument, NULL, 'u' }, "Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames" }, 432 { { "tmout_sigvtalrm", no_argument, NULL, 'T' }, "Use SIGVTALRM to kill timeouting processes (default: use SIGKILL)" }, 433 { { "sanitizers", no_argument, NULL, 'S' }, "Enable sanitizers settings (default: false)" }, 434 { { "monitor_sigabrt", required_argument, NULL, 0x105 }, "Monitor SIGABRT (default: false for Android, true for other platforms)" }, 435 { { "no_fb_timeout", required_argument, NULL, 0x106 }, "Skip feedback if the process has timeouted (default: false)" }, 436 { { "exit_upon_crash", no_argument, NULL, 0x107 }, "Exit upon seeing the first crash (default: false)" }, 437 { { "socket_fuzzer", no_argument, NULL, 0x10B }, "Instrument external fuzzer via socket" }, 438 { { "netdriver", no_argument, NULL, 0x10C }, "Use netdriver (libhfnetdriver/). In most cases it will be autodetected through a binary signature" }, 439 { { "only_printable", no_argument, NULL, 'o' }, "Only generate printable inputs" }, 440 441 #if defined(_HF_ARCH_LINUX) 442 { { "linux_symbols_bl", required_argument, NULL, 0x504 }, "Symbols blacklist filter file (one entry per line)" }, 443 { { "linux_symbols_wl", required_argument, NULL, 0x505 }, "Symbols whitelist filter file (one entry per line)" }, 444 { { "linux_addr_low_limit", required_argument, NULL, 0x500 }, "Address limit (from si.si_addr) below which crashes are not reported, (default: 0)" }, 445 { { "linux_keep_aslr", no_argument, NULL, 0x501 }, "Don't disable ASLR randomization, might be useful with MSAN" }, 446 { { "linux_perf_ignore_above", required_argument, NULL, 0x503 }, "Ignore perf events which report IPs above this address" }, 447 { { "linux_perf_instr", no_argument, NULL, 0x510 }, "Use PERF_COUNT_HW_INSTRUCTIONS perf" }, 448 { { "linux_perf_branch", no_argument, NULL, 0x511 }, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf" }, 449 { { "linux_perf_bts_edge", no_argument, NULL, 0x513 }, "Use Intel BTS to count unique edges" }, 450 { { "linux_perf_ipt_block", no_argument, NULL, 0x514 }, "Use Intel Processor Trace to count unique blocks (requires libipt.so)" }, 451 { { "linux_perf_kernel_only", no_argument, NULL, 0x515 }, "Gather kernel-only coverage with Intel PT and with Intel BTS" }, 452 { { "linux_ns_net", no_argument, NULL, 0x0530 }, "Use Linux NET namespace isolation" }, 453 { { "linux_ns_pid", no_argument, NULL, 0x0531 }, "Use Linux PID namespace isolation" }, 454 { { "linux_ns_ipc", no_argument, NULL, 0x0532 }, "Use Linux IPC namespace isolation" }, 455 #endif // defined(_HF_ARCH_LINUX) 456 457 #if defined(_HF_ARCH_NETBSD) 458 { { "netbsd_symbols_bl", required_argument, NULL, 0x504 }, "Symbols blacklist filter file (one entry per line)" }, 459 { { "netbsd_symbols_wl", required_argument, NULL, 0x505 }, "Symbols whitelist filter file (one entry per line)" }, 460 { { "netbsd_addr_low_limit", required_argument, NULL, 0x500 }, "Address limit (from si.si_addr) below which crashes are not reported, (default: 0)" }, 461 #endif // defined(_HF_ARCH_NETBSD) 462 { { 0, 0, 0, 0 }, NULL }, 463 }; 464 // clang-format on 465 466 struct option opts[ARRAYSIZE(custom_opts)]; 467 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) { 468 opts[i] = custom_opts[i].opt; 469 } 470 471 enum llevel_t ll = INFO; 472 const char* logfile = NULL; 473 int opt_index = 0; 474 for (;;) { 475 int c = getopt_long( 476 argc, argv, "-?hQvVsuPxf:dqe:W:r:c:F:t:R:n:N:l:p:g:E:w:B:zTSo", opts, &opt_index); 477 if (c < 0) break; 478 479 switch (c) { 480 case 'h': 481 case '?': 482 cmdlineUsage(argv[0], custom_opts); 483 break; 484 case 'f': 485 hfuzz->io.inputDir = optarg; 486 if (hfuzz->io.covDirAll == NULL) { 487 hfuzz->io.covDirAll = optarg; 488 } 489 break; 490 case 'x': 491 hfuzz->feedback.dynFileMethod = _HF_DYNFILE_NONE; 492 break; 493 case 'Q': 494 hfuzz->exe.nullifyStdio = false; 495 break; 496 case 'v': 497 hfuzz->display.useScreen = false; 498 break; 499 case 'V': 500 hfuzz->cfg.useVerifier = true; 501 break; 502 case 's': 503 hfuzz->exe.fuzzStdin = true; 504 break; 505 case 'u': 506 hfuzz->io.saveUnique = false; 507 break; 508 case 'l': 509 logfile = optarg; 510 break; 511 case 'd': 512 ll = DEBUG; 513 break; 514 case 'q': 515 ll = WARNING; 516 break; 517 case 'e': 518 hfuzz->io.fileExtn = optarg; 519 break; 520 case 'W': 521 hfuzz->io.workDir = optarg; 522 break; 523 case 0x600: 524 hfuzz->io.crashDir = optarg; 525 break; 526 case 0x601: 527 hfuzz->io.covDirAll = optarg; 528 break; 529 case 0x602: 530 hfuzz->io.covDirNew = optarg; 531 break; 532 case 'r': 533 hfuzz->mutate.mutationsPerRun = strtoul(optarg, NULL, 10); 534 break; 535 case 'c': 536 hfuzz->exe.externalCommand = optarg; 537 break; 538 case 'S': 539 hfuzz->sanitizer.enable = true; 540 break; 541 case 0x10B: 542 hfuzz->socketFuzzer.enabled = true; 543 hfuzz->timing.tmOut = 0; // Disable process timeout checks 544 break; 545 case 0x10C: 546 hfuzz->exe.netDriver = true; 547 break; 548 case 'o': 549 hfuzz->cfg.only_printable = true; 550 break; 551 case 'z': 552 hfuzz->feedback.dynFileMethod |= _HF_DYNFILE_SOFT; 553 break; 554 case 'F': 555 hfuzz->mutate.maxFileSz = strtoul(optarg, NULL, 0); 556 break; 557 case 't': 558 hfuzz->timing.tmOut = atol(optarg); 559 break; 560 case 'R': 561 hfuzz->cfg.reportFile = optarg; 562 break; 563 case 'n': 564 hfuzz->threads.threadsMax = atol(optarg); 565 break; 566 case 0x109: { 567 time_t p = atol(optarg); 568 if (p > 0) { 569 hfuzz->timing.runEndTime = time(NULL) + p; 570 } 571 } break; 572 case 'N': 573 hfuzz->mutate.mutationsMax = atol(optarg); 574 break; 575 case 0x100: 576 hfuzz->exe.asLimit = strtoull(optarg, NULL, 0); 577 break; 578 case 0x101: 579 hfuzz->exe.rssLimit = strtoull(optarg, NULL, 0); 580 break; 581 case 0x102: 582 hfuzz->exe.dataLimit = strtoull(optarg, NULL, 0); 583 break; 584 case 0x103: 585 hfuzz->exe.coreLimit = strtoull(optarg, NULL, 0); 586 break; 587 case 0x104: 588 hfuzz->exe.postExternalCommand = optarg; 589 break; 590 case 0x105: 591 if ((strcasecmp(optarg, "0") == 0) || (strcasecmp(optarg, "false") == 0)) { 592 hfuzz->cfg.monitorSIGABRT = false; 593 } else { 594 hfuzz->cfg.monitorSIGABRT = true; 595 } 596 break; 597 case 0x106: 598 hfuzz->feedback.skipFeedbackOnTimeout = true; 599 break; 600 case 0x107: 601 hfuzz->cfg.exitUponCrash = true; 602 break; 603 case 0x108: 604 hfuzz->exe.clearEnv = true; 605 break; 606 case 'P': 607 hfuzz->exe.persistent = true; 608 break; 609 case 'T': 610 hfuzz->timing.tmoutVTALRM = true; 611 break; 612 case 'E': 613 if (!cmdlineAddEnv(hfuzz, optarg)) { 614 return false; 615 } 616 break; 617 case 'w': 618 hfuzz->mutate.dictionaryFile = optarg; 619 break; 620 case 'B': 621 hfuzz->feedback.blacklistFile = optarg; 622 break; 623 #if defined(_HF_ARCH_LINUX) 624 case 0x500: 625 hfuzz->linux.ignoreAddr = (void*)strtoul(optarg, NULL, 0); 626 break; 627 case 0x501: 628 hfuzz->linux.disableRandomization = false; 629 break; 630 case 0x503: 631 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0); 632 break; 633 case 0x504: 634 hfuzz->linux.symsBlFile = optarg; 635 break; 636 case 0x505: 637 hfuzz->linux.symsWlFile = optarg; 638 break; 639 case 0x510: 640 hfuzz->feedback.dynFileMethod |= _HF_DYNFILE_INSTR_COUNT; 641 break; 642 case 0x511: 643 hfuzz->feedback.dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT; 644 break; 645 case 0x513: 646 hfuzz->feedback.dynFileMethod |= _HF_DYNFILE_BTS_EDGE; 647 break; 648 case 0x514: 649 hfuzz->feedback.dynFileMethod |= _HF_DYNFILE_IPT_BLOCK; 650 break; 651 case 0x515: 652 hfuzz->linux.kernelOnly = true; 653 break; 654 case 0x530: 655 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWNET); 656 break; 657 case 0x531: 658 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWPID); 659 break; 660 case 0x532: 661 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWIPC); 662 break; 663 #endif /* defined(_HF_ARCH_LINUX) */ 664 #if defined(_HF_ARCH_NETBSD) 665 case 0x500: 666 hfuzz->netbsd.ignoreAddr = (void*)strtoul(optarg, NULL, 0); 667 break; 668 case 0x504: 669 hfuzz->netbsd.symsBlFile = optarg; 670 break; 671 case 0x505: 672 hfuzz->netbsd.symsWlFile = optarg; 673 break; 674 #endif /* defined(_HF_ARCH_NETBSD) */ 675 default: 676 cmdlineUsage(argv[0], custom_opts); 677 return false; 678 break; 679 } 680 } 681 682 logInitLogFile(logfile, -1, ll); 683 684 hfuzz->exe.argc = argc - optind; 685 hfuzz->exe.cmdline = (const char* const*)&argv[optind]; 686 if (hfuzz->exe.argc <= 0) { 687 LOG_E("No fuzz command provided"); 688 cmdlineUsage(argv[0], custom_opts); 689 return false; 690 } 691 if (!files_exists(hfuzz->exe.cmdline[0])) { 692 LOG_E("Your fuzzed binary '%s' doesn't seem to exist", hfuzz->exe.cmdline[0]); 693 return false; 694 } 695 if (!cmdlineVerify(hfuzz)) { 696 return false; 697 } 698 699 display_createTargetStr(hfuzz); 700 701 sigemptyset(&hfuzz->exe.waitSigSet); 702 sigaddset(&hfuzz->exe.waitSigSet, SIGIO); /* Persistent socket data */ 703 sigaddset(&hfuzz->exe.waitSigSet, SIGUSR1); /* Ping from the signal thread */ 704 705 LOG_I("cmdline:'%s', bin:'%s' inputDir:'%s', fuzzStdin:%s, mutationsPerRun:%u, " 706 "externalCommand:'%s', timeout:%ld, mutationsMax:%zu, threadsMax:%zu", 707 hfuzz->display.cmdline_txt, hfuzz->exe.cmdline[0], hfuzz->io.inputDir, 708 cmdlineYesNo(hfuzz->exe.fuzzStdin), hfuzz->mutate.mutationsPerRun, 709 !hfuzz->exe.externalCommand ? "" : hfuzz->exe.externalCommand, (long)hfuzz->timing.tmOut, 710 hfuzz->mutate.mutationsMax, hfuzz->threads.threadsMax); 711 712 return true; 713 } 714