blob: a47b9e17b368fd46c22281057b227a8336964496 [file] [log] [blame]
Robert Swieckia88f96f2015-10-09 16:47:39 +02001/*
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>
Robert Swieckia88f96f2015-10-09 16:47:39 +020028#include <inttypes.h>
29#include <limits.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020030#include <stdlib.h>
31#include <stdio.h>
32#include <string.h>
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010033#include <sys/queue.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020034#include <unistd.h>
35
36#include "common.h"
37#include "log.h"
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +020038#include "files.h"
Robert Swiecki72d2bef2016-01-19 14:39:26 +010039#include "util.h"
Robert Swieckia88f96f2015-10-09 16:47:39 +020040
41struct custom_option {
42 struct option opt;
43 const char *descr;
44};
45
46static bool checkFor_FILE_PLACEHOLDER(char **args)
47{
48 for (int x = 0; args[x]; x++) {
49 if (strstr(args[x], _HF_FILE_PLACEHOLDER))
50 return true;
51 }
52 return false;
53}
54
55static const char *cmdlineYesNo(bool yes)
56{
57 return (yes ? "true" : "false");
58}
59
60static void cmdlineHelp(const char *pname, struct custom_option *opts)
61{
62 LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
63 LOG_HELP_BOLD("Options:");
64 for (int i = 0; opts[i].opt.name; i++) {
Robert Swieckif3a5f6a2016-03-16 14:47:30 +010065 if (isprint(opts[i].opt.val) && opts[i].opt.val < 0x80) {
Robert Swieckia88f96f2015-10-09 16:47:39 +020066 LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name,
67 "|-", opts[i].opt.val,
Robert Swieckibf063db2016-02-16 18:42:00 +010068 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020069 } else {
70 LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
Robert Swieckibf063db2016-02-16 18:42:00 +010071 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020072 }
73 LOG_HELP("\t%s", opts[i].descr);
74 }
Jagger32127372015-10-09 23:07:38 +020075 LOG_HELP_BOLD("\nExamples:");
76 LOG_HELP(" Run the binary over a mutated file chosen from the directory");
77 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
78 LOG_HELP(" As above, provide input over STDIN:");
Robert Swiecki72d2bef2016-01-19 14:39:26 +010079 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg");
Jaggerba92b4b2016-03-16 02:24:17 +010080 LOG_HELP(" Use SANCOV to maximize code coverage:");
81 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -C -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
Jaggere848cc72016-09-19 02:28:52 +020082 LOG_HELP(" Use compile-time instrumentation (libhfuzz/instrument.c):");
83 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -z -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
Robert Swieckia2d5be32016-10-11 22:52:42 +020084 LOG_HELP(" Use persistent mode (libhfuzz/persistent.c):");
Jaggere848cc72016-09-19 02:28:52 +020085 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -- /usr/bin/tiffinfo_persistent");
Robert Swiecki43f0b282016-11-01 18:06:40 +010086 LOG_HELP
87 (" Use persistent mode (libhfuzz/persistent.c) and compile-time instrumentation (libhfuzz/instrument.c):");
Robert Swiecki14129492016-11-01 18:04:32 +010088 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -z -- /usr/bin/tiffinfo_persistent");
Robert Swieckia88f96f2015-10-09 16:47:39 +020089#if defined(_HF_ARCH_LINUX)
Jagger32127372015-10-09 23:07:38 +020090 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
Jagger72f258b2015-10-09 23:09:01 +020091 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_instr -- /usr/bin/tiffinfo -D "
92 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020093 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of branches:");
Jagger72f258b2015-10-09 23:09:01 +020094 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
95 _HF_FILE_PLACEHOLDER);
Robert Swiecki349cb9e2016-10-14 21:36:42 +020096 LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks via BTS:");
97 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_block -- /usr/bin/tiffinfo -D "
98 _HF_FILE_PLACEHOLDER);
99 LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges) via BTS:");
Robert Swiecki43f0b282016-11-01 18:06:40 +0100100 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_edge -- /usr/bin/tiffinfo -D "
101 _HF_FILE_PLACEHOLDER);
Robert Swiecki349cb9e2016-10-14 21:36:42 +0200102 LOG_HELP
Robert Swiecki8499c662016-11-01 18:02:52 +0100103 (" Run the binary over a dynamic file, maximize unique code blocks via Intel Processor Trace (requires libipt.so):");
Robert Swiecki349cb9e2016-10-14 21:36:42 +0200104 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ipt_block -- /usr/bin/tiffinfo -D "
Jagger72f258b2015-10-09 23:09:01 +0200105 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200106#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200107}
108
109static void cmdlineUsage(const char *pname, struct custom_option *opts)
110{
111 cmdlineHelp(pname, opts);
112 exit(0);
113}
114
Robert Swieckia88f96f2015-10-09 16:47:39 +0200115rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
116{
117 struct rlimit cur;
118 if (getrlimit(res, &cur) == -1) {
119 PLOG_F("getrlimit(%d)", res);
120 }
121 if (strcasecmp(optarg, "max") == 0) {
122 return cur.rlim_max;
123 }
124 if (strcasecmp(optarg, "def") == 0) {
125 return cur.rlim_cur;
126 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200127 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200128 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
129 }
130 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200131 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200132 PLOG_F("strtoul('%s', 0)", optarg);
133 }
134 return val;
135}
136
137bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
138{
139 /* *INDENT-OFF* */
140 (*hfuzz) = (honggfuzz_t) {
141 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100142 .cmdline_txt[0] = '\0',
Jagger1b2d4822016-09-25 16:19:45 +0200143 .inputDir = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200144 .nullifyStdio = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200145 .fuzzStdin = false,
146 .saveUnique = true,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100147 .useScreen = true,
148 .useVerifier = false,
149 .timeStart = time(NULL),
Robert Swieckia88f96f2015-10-09 16:47:39 +0200150 .fileExtn = "fuzz",
151 .workDir = ".",
Jagger1b2d4822016-09-25 16:19:45 +0200152 .covDir = NULL,
Robert Swieckia96d78d2016-03-14 16:50:50 +0100153 .origFlipRate = 0.001f,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200154 .externalCommand = NULL,
Robert Swieckiee266ac2016-10-03 02:25:59 +0200155 .postExternalCommand = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200156 .blacklistFile = NULL,
157 .blacklistCnt = 0,
158 .blacklist = NULL,
Jaggerf4a60562016-09-25 15:40:23 +0200159 .maxFileSz = 0UL,
Jaggerba92b4b2016-03-16 02:24:17 +0100160 .tmOut = 10,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200161 .mutationsMax = 0,
162 .threadsFinished = 0,
Jagger2664f542016-09-28 14:37:00 +0200163 .threadsMax = (sysconf(_SC_NPROCESSORS_ONLN) <= 1) ? 1 : sysconf(_SC_NPROCESSORS_ONLN) / 2,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200164 .reportFile = NULL,
165 .asLimit = 0ULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200166 .fileCnt = 0,
Robert Swiecki05354ca2016-03-15 19:10:23 +0100167 .lastFileIndex = 0,
168 .doneFileIndex = 0,
Jagger80041fe2016-03-10 21:32:35 +0100169 .clearEnv = false,
Jaggerab26e702016-03-22 04:28:00 +0100170 .envs = {
171 [0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,
172 },
Robert Swiecki0f937af2016-03-30 18:19:16 +0200173 .persistent = false,
Robert Swieckie84b6452016-12-12 12:42:04 +0100174 .tmout_vtalrm = false,
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200175 .enableSanitizers = false,
176#if defined(__ANDROID__)
177 .monitorSIGABRT = false,
178#else
179 .monitorSIGABRT = true,
180#endif
Robert Swieckia88f96f2015-10-09 16:47:39 +0200181
Robert Swiecki531438a2016-09-13 19:05:11 +0200182 .dictionaryFile = NULL,
183 .dictionaryCnt = 0,
184
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100185 .state = _HF_STATE_UNSET,
Jaggerb7fa3ee2016-08-21 19:46:26 +0200186 .feedback = NULL,
Robert Swieckibc7532e2016-08-20 00:34:17 +0200187 .bbFd = -1,
Robert Swieckie586c1f2016-03-14 18:46:03 +0100188 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100189 .dynfileqCnt = 0U,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100190
Robert Swieckia88f96f2015-10-09 16:47:39 +0200191 .mutationsCnt = 0,
192 .crashesCnt = 0,
193 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200194 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200195 .blCrashesCnt = 0,
196 .timeoutedCnt = 0,
197
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100198 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200199 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100200 .hitBBCnt = 0ULL,
201 .totalBBCnt = 0ULL,
202 .dsoCnt = 0ULL,
203 .iDsoCnt = 0ULL,
204 .newBBCnt = 0ULL,
205 .crashesCnt = 0ULL,
206 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200207
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200208 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100209 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100210 .asanOpts = NULL,
211 .msanOpts = NULL,
212 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200213 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100214 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100215 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100216 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100217
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700218 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
219
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100220 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200221 .linux = {
Jaggerab26e702016-03-22 04:28:00 +0100222 .hwCnts = {
223 .cpuInstrCnt = 0ULL,
224 .cpuBranchCnt = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100225 .bbCnt = 0ULL,
226 .newBBCnt = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200227 .softCntPc = 0ULL,
228 .softCntCmp = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100229 },
230 .dynamicCutOffAddr = ~(0ULL),
231 .disableRandomization = true,
232 .ignoreAddr = NULL,
233 .numMajorFrames = 7,
234 .pid = 0,
235 .pidFile = NULL,
236 .pidCmd = NULL,
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300237 .symsBlFile = NULL,
238 .symsBlCnt = 0,
239 .symsBl = NULL,
240 .symsWlFile = NULL,
241 .symsWlCnt = 0,
242 .symsWl = NULL,
Jaggerab26e702016-03-22 04:28:00 +0100243 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200244 };
245 /* *INDENT-ON* */
246
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100247 TAILQ_INIT(&hfuzz->dynfileq);
Robert Swiecki3a572262016-10-04 01:48:34 +0200248 TAILQ_INIT(&hfuzz->dictq);
Robert Swieckie8f8e8d2016-10-03 23:51:32 +0200249 TAILQ_INIT(&hfuzz->fileq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100250
Robert Swieckia88f96f2015-10-09 16:47:39 +0200251 /* *INDENT-OFF* */
252 struct custom_option custom_opts[] = {
253 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
Jagger1b2d4822016-09-25 16:19:45 +0200254 {{"input", required_argument, NULL, 'f'}, "Path to a directory containing initial file corpus"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200255 {{"nullify_stdio", no_argument, NULL, 'q'}, "Null-ify children's stdin, stdout, stderr; make them quiet"},
Jagger54c96a22016-03-30 23:13:30 +0200256 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
Jagger2664f542016-09-28 14:37:00 +0200257 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: number of CPUs / 2)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200258 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200259 {{"mutation_rate", required_argument, NULL, 'r'}, "Maximal mutation rate in relation to the file size, (default: '0.001')"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200260 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200261 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100262 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200263 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
264 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300265 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Robert Swieckid32018f2016-10-11 22:58:22 +0200266 {{"covdir", required_argument, NULL, 0x103}, "New coverage is written to a separate directory (default: use the input directory)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200267 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
268 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Robert Swieckiee266ac2016-10-03 02:25:59 +0200269 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command producing fuzz files (instead of internal mutators)"},
270 {{"pprocess_cmd", required_argument, NULL, 0x104}, "External command postprocessing files produced by internal mutators"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200271 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200272 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100273 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200274 {{"max_file_size", required_argument, NULL, 'F'}, "Maximal size of files processed by the fuzzer in bytes (default: '1048576')"},
Jagger80041fe2016-03-10 21:32:35 +0100275 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200276 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger54c96a22016-03-30 23:13:30 +0200277 {{"save_all", no_argument, NULL, 'u'}, "Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames"},
Jagger3db1d952016-03-10 02:02:46 +0100278 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Robert Swieckif05b1cd2016-11-01 18:05:45 +0100279 {{"instrument", no_argument, NULL, 'z'}, "Enable compile-time instrumentation (link with libhfuzz/libhfuzz.a)"},
Jagger7ff92fa2016-03-22 04:13:50 +0100280 {{"msan_report_umrs", no_argument, NULL, 0x102}, "Report MSAN's UMRS (uninitialized memory access)"},
Robert Swieckif05b1cd2016-11-01 18:05:45 +0100281 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (link with libhfuzz/libhfuzz.a)"},
Gergely Nagy5d47c732016-12-12 23:51:51 +0100282 {{"tmout_sigvtalrm", no_argument, NULL, 'T'}, "Use SIGVTALRM to kill timeouting processes (default: use SIGKILL)"},
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200283 {{"sanitizers", no_argument, NULL, 'S'}, "Enable sanitizers settings (default: false)"},
284 {{"monitor_sigabrt", required_argument, NULL, 0x105}, "Monitor SIGABRT (default: 'false for Android - 'true for other platforms)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200285
286#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudisfafb3332016-10-31 08:57:16 +0200287 {{"linux_symbols_bl", required_argument, NULL, 0x504}, "Symbols blacklist filter file (one entry per line)"},
288 {{"linux_symbols_wl", required_argument, NULL, 0x505}, "Symbols whitelist filter file (one entry per line)"},
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200289 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
Robert Swieckifab69162016-03-31 15:41:36 +0200290 {{"linux_file_pid", required_argument, NULL, 0x502}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200291 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
292 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
Jaggerae6a4452015-10-14 17:34:43 +0200293 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200294 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
295 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100296 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
297 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
Robert Swiecki8499c662016-11-01 18:02:52 +0100298 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks (requires libipt.so)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200299#endif // defined(_HF_ARCH_LINUX)
300 {{0, 0, 0, 0}, NULL},
301 };
302 /* *INDENT-ON* */
303
304 struct option opts[ARRAYSIZE(custom_opts)];
305 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
306 opts[i] = custom_opts[i].opt;
307 }
308
309 enum llevel_t ll = INFO;
310 const char *logfile = NULL;
311 int opt_index = 0;
312 for (;;) {
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200313 int c = getopt_long(argc, argv, "-?hqvVsuPf:d:e:W:r:c:F:t:R:n:N:l:p:g:E:w:B:CzTS", opts,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200314 &opt_index);
315 if (c < 0)
316 break;
317
318 switch (c) {
319 case 'h':
320 case '?':
321 cmdlineUsage(argv[0], custom_opts);
322 break;
323 case 'f':
Jagger1b2d4822016-09-25 16:19:45 +0200324 hfuzz->inputDir = optarg;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200325 break;
326 case 'q':
327 hfuzz->nullifyStdio = true;
328 break;
329 case 'v':
330 hfuzz->useScreen = false;
331 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700332 case 'V':
333 hfuzz->useVerifier = true;
334 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200335 case 's':
336 hfuzz->fuzzStdin = true;
337 break;
338 case 'u':
339 hfuzz->saveUnique = false;
340 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200341 case 'l':
342 logfile = optarg;
343 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200344 case 'd':
345 ll = atoi(optarg);
346 break;
347 case 'e':
348 hfuzz->fileExtn = optarg;
349 break;
350 case 'W':
351 hfuzz->workDir = optarg;
352 break;
353 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100354 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200355 break;
356 case 'c':
357 hfuzz->externalCommand = optarg;
358 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200359 case 'C':
360 hfuzz->useSanCov = true;
361 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200362 case 'S':
363 hfuzz->enableSanitizers = true;
364 break;
Jagger4aac9fe2016-08-28 17:35:48 +0200365 case 'z':
366 hfuzz->dynFileMethod |= _HF_DYNFILE_SOFT;
367 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200368 case 'F':
369 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
370 break;
371 case 't':
372 hfuzz->tmOut = atol(optarg);
373 break;
374 case 'R':
375 hfuzz->reportFile = optarg;
376 break;
377 case 'n':
378 hfuzz->threadsMax = atol(optarg);
379 break;
380 case 'N':
381 hfuzz->mutationsMax = atol(optarg);
382 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200383 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200384 hfuzz->asLimit = strtoull(optarg, NULL, 0);
385 break;
Jagger80041fe2016-03-10 21:32:35 +0100386 case 0x101:
387 hfuzz->clearEnv = true;
388 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100389 case 0x102:
390 hfuzz->msanReportUMRS = true;
391 break;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200392 case 0x103:
Jagger1b2d4822016-09-25 16:19:45 +0200393 hfuzz->covDir = optarg;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200394 break;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200395 case 0x104:
396 hfuzz->postExternalCommand = optarg;
397 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200398 case 0x105:
399 if ((strcasecmp(optarg, "0") == 0) || (strcasecmp(optarg, "false") == 0)) {
400 hfuzz->monitorSIGABRT = false;
401 } else {
402 hfuzz->monitorSIGABRT = true;
403 }
404 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200405 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200406 hfuzz->persistent = true;
407 break;
Gergely Nagy5d47c732016-12-12 23:51:51 +0100408 case 'T':
Robert Swieckie84b6452016-12-12 12:42:04 +0100409 hfuzz->tmout_vtalrm = true;
410 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200411 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200412 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200413 LOG_E("-p '%s' is not a number", optarg);
414 return false;
415 }
Jagger247c3b42016-03-21 23:24:05 +0100416 hfuzz->linux.pid = atoi(optarg);
417 if (hfuzz->linux.pid < 1) {
418 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200419 return false;
420 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200421 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200422 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100423 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200424 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200425 case 'E':
426 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
427 if (hfuzz->envs[i] == NULL) {
428 hfuzz->envs[i] = optarg;
429 break;
430 }
431 }
432 break;
433 case 'w':
434 hfuzz->dictionaryFile = optarg;
435 break;
436 case 'B':
437 hfuzz->blacklistFile = optarg;
438 break;
439 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100440 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200441 break;
442 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100443 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200444 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200445 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100446 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200447 break;
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300448 case 0x504:
449 hfuzz->linux.symsBlFile = optarg;
450 break;
451 case 0x505:
452 hfuzz->linux.symsWlFile = optarg;
453 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200454 case 0x510:
455 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
456 break;
457 case 0x511:
458 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
459 break;
460 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100461 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200462 break;
463 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100464 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200465 break;
466 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100467 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
468 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200469 default:
470 cmdlineUsage(argv[0], custom_opts);
471 return false;
472 break;
473 }
474 }
Jagger72f258b2015-10-09 23:09:01 +0200475
Robert Swieckia88f96f2015-10-09 16:47:39 +0200476 if (logInitLogFile(logfile, ll) == false) {
477 return false;
478 }
479
480 hfuzz->cmdline = &argv[optind];
481 if (hfuzz->cmdline[0] == NULL) {
482 LOG_E("No fuzz command provided");
483 cmdlineUsage(argv[0], custom_opts);
484 return false;
485 }
486
Robert Swiecki0f937af2016-03-30 18:19:16 +0200487 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200488 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200489 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200490 return false;
491 }
492
Robert Swiecki71b73722016-09-05 15:18:25 +0200493 if (hfuzz->threadsMax >= _HF_THREAD_MAX) {
494 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", hfuzz->threadsMax,
495 _HF_THREAD_MAX);
496 return false;
497 }
498
Robert Swieckia88f96f2015-10-09 16:47:39 +0200499 if (strchr(hfuzz->fileExtn, '/')) {
500 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
501 return false;
502 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200503
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200504 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200505 if (!files_exists(hfuzz->workDir)) {
506 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
507 return false;
508 }
509 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200510
Jagger247c3b42016-03-21 23:24:05 +0100511 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
512 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
513 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200514 hfuzz->threadsMax = 1;
515 }
516
Robert Swieckia96d78d2016-03-14 16:50:50 +0100517 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200518 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200519 }
520
Jagger1b2d4822016-09-25 16:19:45 +0200521 LOG_I("inputDir '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Anestis Bechtsoudisecab7762016-12-27 18:27:30 +0200522 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn: '%s', "
523 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d, monitorSIGABRT: '%s'",
Jagger1b2d4822016-09-25 16:19:45 +0200524 hfuzz->inputDir,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200525 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100526 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200527 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
Jagger247c3b42016-03-21 23:24:05 +0100528 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn,
Anestis Bechtsoudisac366a12016-12-28 12:38:44 +0200529 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->linux.pid, cmdlineYesNo(hfuzz->monitorSIGABRT));
Robert Swieckia88f96f2015-10-09 16:47:39 +0200530
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100531 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100532 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
533 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
Robert Swieckif2d9c3a2016-11-03 02:13:54 +0100534 if (strlen(hfuzz->cmdline_txt) == (sizeof(hfuzz->cmdline_txt) - 1)) {
535 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 3] = '.';
536 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 2] = '.';
537 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 1] = '.';
538 }
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100539 }
540
Robert Swieckia88f96f2015-10-09 16:47:39 +0200541 return true;
542}