blob: 68b92275d977650e8074c4339f4f77c7757562dc [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 Swiecki846ccd72017-01-12 17:52:23 +010030#if defined(_HF_ARCH_LINUX)
31#include <sched.h>
32#endif /* defined(_HF_ARCH_LINUX) */
33#include <signal.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020034#include <stdlib.h>
35#include <stdio.h>
36#include <string.h>
Robert Swiecki3bfc33c2016-03-14 18:12:41 +010037#include <sys/queue.h>
Robert Swieckia88f96f2015-10-09 16:47:39 +020038#include <unistd.h>
39
40#include "common.h"
41#include "log.h"
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +020042#include "files.h"
Robert Swiecki72d2bef2016-01-19 14:39:26 +010043#include "util.h"
Robert Swieckia88f96f2015-10-09 16:47:39 +020044
45struct custom_option {
46 struct option opt;
47 const char *descr;
48};
49
50static bool checkFor_FILE_PLACEHOLDER(char **args)
51{
52 for (int x = 0; args[x]; x++) {
53 if (strstr(args[x], _HF_FILE_PLACEHOLDER))
54 return true;
55 }
56 return false;
57}
58
59static const char *cmdlineYesNo(bool yes)
60{
61 return (yes ? "true" : "false");
62}
63
64static void cmdlineHelp(const char *pname, struct custom_option *opts)
65{
66 LOG_HELP_BOLD("Usage: %s [options] -- path_to_command [args]", pname);
67 LOG_HELP_BOLD("Options:");
68 for (int i = 0; opts[i].opt.name; i++) {
Robert Swieckif3a5f6a2016-03-16 14:47:30 +010069 if (isprint(opts[i].opt.val) && opts[i].opt.val < 0x80) {
Robert Swieckia88f96f2015-10-09 16:47:39 +020070 LOG_HELP_BOLD(" --%s%s%c %s", opts[i].opt.name,
71 "|-", opts[i].opt.val,
Robert Swieckibf063db2016-02-16 18:42:00 +010072 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020073 } else {
74 LOG_HELP_BOLD(" --%s %s", opts[i].opt.name,
Robert Swieckibf063db2016-02-16 18:42:00 +010075 opts[i].opt.has_arg == required_argument ? "VALUE" : "");
Robert Swieckia88f96f2015-10-09 16:47:39 +020076 }
77 LOG_HELP("\t%s", opts[i].descr);
78 }
Jagger32127372015-10-09 23:07:38 +020079 LOG_HELP_BOLD("\nExamples:");
80 LOG_HELP(" Run the binary over a mutated file chosen from the directory");
81 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
82 LOG_HELP(" As above, provide input over STDIN:");
Robert Swiecki72d2bef2016-01-19 14:39:26 +010083 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -s -- /usr/bin/djpeg");
Jaggerba92b4b2016-03-16 02:24:17 +010084 LOG_HELP(" Use SANCOV to maximize code coverage:");
85 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -C -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
Jaggere848cc72016-09-19 02:28:52 +020086 LOG_HELP(" Use compile-time instrumentation (libhfuzz/instrument.c):");
87 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -z -- /usr/bin/tiffinfo -D " _HF_FILE_PLACEHOLDER);
Robert Swieckia2d5be32016-10-11 22:52:42 +020088 LOG_HELP(" Use persistent mode (libhfuzz/persistent.c):");
Jaggere848cc72016-09-19 02:28:52 +020089 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -- /usr/bin/tiffinfo_persistent");
Robert Swiecki43f0b282016-11-01 18:06:40 +010090 LOG_HELP
91 (" Use persistent mode (libhfuzz/persistent.c) and compile-time instrumentation (libhfuzz/instrument.c):");
Robert Swiecki14129492016-11-01 18:04:32 +010092 LOG_HELP_BOLD(" " PROG_NAME " -f input_dir -P -z -- /usr/bin/tiffinfo_persistent");
Robert Swieckia88f96f2015-10-09 16:47:39 +020093#if defined(_HF_ARCH_LINUX)
Jagger32127372015-10-09 23:07:38 +020094 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of instructions:");
Jagger72f258b2015-10-09 23:09:01 +020095 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_instr -- /usr/bin/tiffinfo -D "
96 _HF_FILE_PLACEHOLDER);
Jagger32127372015-10-09 23:07:38 +020097 LOG_HELP(" Run the binary over a dynamic file, maximize total no. of branches:");
Jagger72f258b2015-10-09 23:09:01 +020098 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_branch -- /usr/bin/tiffinfo -D "
99 _HF_FILE_PLACEHOLDER);
Robert Swiecki349cb9e2016-10-14 21:36:42 +0200100 LOG_HELP(" Run the binary over a dynamic file, maximize unique code blocks via BTS:");
101 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_block -- /usr/bin/tiffinfo -D "
102 _HF_FILE_PLACEHOLDER);
103 LOG_HELP(" Run the binary over a dynamic file, maximize unique branches (edges) via BTS:");
Robert Swiecki43f0b282016-11-01 18:06:40 +0100104 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_edge -- /usr/bin/tiffinfo -D "
105 _HF_FILE_PLACEHOLDER);
Robert Swiecki349cb9e2016-10-14 21:36:42 +0200106 LOG_HELP
Robert Swiecki8499c662016-11-01 18:02:52 +0100107 (" 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 +0200108 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ipt_block -- /usr/bin/tiffinfo -D "
Jagger72f258b2015-10-09 23:09:01 +0200109 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200110#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200111}
112
113static void cmdlineUsage(const char *pname, struct custom_option *opts)
114{
115 cmdlineHelp(pname, opts);
116 exit(0);
117}
118
Robert Swieckia88f96f2015-10-09 16:47:39 +0200119rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
120{
121 struct rlimit cur;
122 if (getrlimit(res, &cur) == -1) {
123 PLOG_F("getrlimit(%d)", res);
124 }
125 if (strcasecmp(optarg, "max") == 0) {
126 return cur.rlim_max;
127 }
128 if (strcasecmp(optarg, "def") == 0) {
129 return cur.rlim_cur;
130 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200131 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200132 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
133 }
134 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200135 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200136 PLOG_F("strtoul('%s', 0)", optarg);
137 }
138 return val;
139}
140
141bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
142{
143 /* *INDENT-OFF* */
144 (*hfuzz) = (honggfuzz_t) {
145 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100146 .cmdline_txt[0] = '\0',
Jagger1b2d4822016-09-25 16:19:45 +0200147 .inputDir = NULL,
Robert Swiecki92a31362017-02-24 16:21:40 +0100148 .inputDirP = NULL,
149 .fileCnt = 0,
150 .fileCntDone = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200151 .nullifyStdio = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200152 .fuzzStdin = false,
153 .saveUnique = true,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100154 .useScreen = true,
155 .useVerifier = false,
156 .timeStart = time(NULL),
Robert Swieckia88f96f2015-10-09 16:47:39 +0200157 .fileExtn = "fuzz",
158 .workDir = ".",
Jagger1b2d4822016-09-25 16:19:45 +0200159 .covDir = NULL,
Robert Swieckia96d78d2016-03-14 16:50:50 +0100160 .origFlipRate = 0.001f,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200161 .externalCommand = NULL,
Robert Swieckiee266ac2016-10-03 02:25:59 +0200162 .postExternalCommand = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200163 .blacklistFile = NULL,
164 .blacklistCnt = 0,
165 .blacklist = NULL,
Jaggerf4a60562016-09-25 15:40:23 +0200166 .maxFileSz = 0UL,
Jaggerba92b4b2016-03-16 02:24:17 +0100167 .tmOut = 10,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200168 .mutationsMax = 0,
169 .threadsFinished = 0,
Jagger2664f542016-09-28 14:37:00 +0200170 .threadsMax = (sysconf(_SC_NPROCESSORS_ONLN) <= 1) ? 1 : sysconf(_SC_NPROCESSORS_ONLN) / 2,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200171 .reportFile = NULL,
172 .asLimit = 0ULL,
Jagger80041fe2016-03-10 21:32:35 +0100173 .clearEnv = false,
Jaggerab26e702016-03-22 04:28:00 +0100174 .envs = {
175 [0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,
176 },
Robert Swiecki0f937af2016-03-30 18:19:16 +0200177 .persistent = false,
Robert Swieckie84b6452016-12-12 12:42:04 +0100178 .tmout_vtalrm = false,
Robert Swiecki44f6b192017-02-15 20:24:55 +0100179 .skipFeedbackOnTimeout = false,
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200180 .enableSanitizers = false,
181#if defined(__ANDROID__)
182 .monitorSIGABRT = false,
183#else
184 .monitorSIGABRT = true,
185#endif
Robert Swiecki0ec98112017-02-03 02:08:14 +0100186 .threadsActiveCnt = 0,
Robert Swiecki89b84472017-02-12 22:20:10 +0100187 .mainPid = getpid(),
Robert Swiecki8d01b012017-02-19 15:48:11 +0100188 .terminating = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200189
Robert Swiecki531438a2016-09-13 19:05:11 +0200190 .dictionaryFile = NULL,
191 .dictionaryCnt = 0,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100192 .dictqCurrent = NULL,
Robert Swiecki531438a2016-09-13 19:05:11 +0200193
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100194 .state = _HF_STATE_UNSET,
Jaggerb7fa3ee2016-08-21 19:46:26 +0200195 .feedback = NULL,
Robert Swieckibc7532e2016-08-20 00:34:17 +0200196 .bbFd = -1,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100197
Robert Swieckie586c1f2016-03-14 18:46:03 +0100198 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100199 .dynfileqCnt = 0U,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100200 .dynfileqCurrent = NULL,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100201
Robert Swiecki37498fd2017-03-12 21:12:54 +0100202 .feedback_mutex = PTHREAD_MUTEX_INITIALIZER,
203
Robert Swieckia88f96f2015-10-09 16:47:39 +0200204 .mutationsCnt = 0,
205 .crashesCnt = 0,
206 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200207 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200208 .blCrashesCnt = 0,
209 .timeoutedCnt = 0,
210
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100211 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200212 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100213 .hitBBCnt = 0ULL,
214 .totalBBCnt = 0ULL,
215 .dsoCnt = 0ULL,
216 .iDsoCnt = 0ULL,
217 .newBBCnt = 0ULL,
218 .crashesCnt = 0ULL,
219 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200220
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200221 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100222 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100223 .asanOpts = NULL,
224 .msanOpts = NULL,
225 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200226 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100227 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100228 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100229 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100230
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700231 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
232
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100233 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200234 .linux = {
Jaggerab26e702016-03-22 04:28:00 +0100235 .hwCnts = {
236 .cpuInstrCnt = 0ULL,
237 .cpuBranchCnt = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100238 .bbCnt = 0ULL,
239 .newBBCnt = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200240 .softCntPc = 0ULL,
241 .softCntCmp = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100242 },
243 .dynamicCutOffAddr = ~(0ULL),
244 .disableRandomization = true,
245 .ignoreAddr = NULL,
246 .numMajorFrames = 7,
247 .pid = 0,
248 .pidFile = NULL,
249 .pidCmd = NULL,
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300250 .symsBlFile = NULL,
251 .symsBlCnt = 0,
252 .symsBl = NULL,
253 .symsWlFile = NULL,
254 .symsWlCnt = 0,
255 .symsWl = NULL,
Robert Swiecki846ccd72017-01-12 17:52:23 +0100256 .cloneFlags = 0,
Jaggerab26e702016-03-22 04:28:00 +0100257 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200258 };
259 /* *INDENT-ON* */
260
Robert Swieckiafb16102017-03-13 22:14:31 +0100261 TAILQ_INIT(&hfuzz->dynfileq);
262 TAILQ_INIT(&hfuzz->dictq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100263
Robert Swieckia88f96f2015-10-09 16:47:39 +0200264 /* *INDENT-OFF* */
265 struct custom_option custom_opts[] = {
266 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
Jagger1b2d4822016-09-25 16:19:45 +0200267 {{"input", required_argument, NULL, 'f'}, "Path to a directory containing initial file corpus"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200268 {{"nullify_stdio", no_argument, NULL, 'q'}, "Null-ify children's stdin, stdout, stderr; make them quiet"},
Jagger54c96a22016-03-30 23:13:30 +0200269 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
Jagger2664f542016-09-28 14:37:00 +0200270 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: number of CPUs / 2)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200271 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200272 {{"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 +0200273 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200274 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100275 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200276 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
277 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300278 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Robert Swieckid32018f2016-10-11 22:58:22 +0200279 {{"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 +0200280 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
281 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Robert Swieckiee266ac2016-10-03 02:25:59 +0200282 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command producing fuzz files (instead of internal mutators)"},
283 {{"pprocess_cmd", required_argument, NULL, 0x104}, "External command postprocessing files produced by internal mutators"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200284 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200285 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100286 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200287 {{"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 +0100288 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200289 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger54c96a22016-03-30 23:13:30 +0200290 {{"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 +0100291 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Robert Swieckif05b1cd2016-11-01 18:05:45 +0100292 {{"instrument", no_argument, NULL, 'z'}, "Enable compile-time instrumentation (link with libhfuzz/libhfuzz.a)"},
Jagger7ff92fa2016-03-22 04:13:50 +0100293 {{"msan_report_umrs", no_argument, NULL, 0x102}, "Report MSAN's UMRS (uninitialized memory access)"},
Robert Swieckif05b1cd2016-11-01 18:05:45 +0100294 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (link with libhfuzz/libhfuzz.a)"},
Gergely Nagy5d47c732016-12-12 23:51:51 +0100295 {{"tmout_sigvtalrm", no_argument, NULL, 'T'}, "Use SIGVTALRM to kill timeouting processes (default: use SIGKILL)"},
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200296 {{"sanitizers", no_argument, NULL, 'S'}, "Enable sanitizers settings (default: false)"},
297 {{"monitor_sigabrt", required_argument, NULL, 0x105}, "Monitor SIGABRT (default: 'false for Android - 'true for other platforms)"},
Robert Swiecki44f6b192017-02-15 20:24:55 +0100298 {{"no_fb_timeout", required_argument, NULL, 0x106}, "Skip feedback if the process has timeouted (default: 'false')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200299
300#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudisfafb3332016-10-31 08:57:16 +0200301 {{"linux_symbols_bl", required_argument, NULL, 0x504}, "Symbols blacklist filter file (one entry per line)"},
302 {{"linux_symbols_wl", required_argument, NULL, 0x505}, "Symbols whitelist filter file (one entry per line)"},
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200303 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
Robert Swieckifab69162016-03-31 15:41:36 +0200304 {{"linux_file_pid", required_argument, NULL, 0x502}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200305 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
306 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
Jaggerae6a4452015-10-14 17:34:43 +0200307 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200308 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
309 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100310 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
311 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
Robert Swiecki8499c662016-11-01 18:02:52 +0100312 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks (requires libipt.so)"},
Robert Swiecki846ccd72017-01-12 17:52:23 +0100313 {{"linux_ns_net", no_argument, NULL, 0x0530}, "Use Linux NET namespace isolation"},
314 {{"linux_ns_pid", no_argument, NULL, 0x0531}, "Use Linux PID namespace isolation"},
315 {{"linux_ns_ipc", no_argument, NULL, 0x0532}, "Use Linux IPC namespace isolation"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200316#endif // defined(_HF_ARCH_LINUX)
317 {{0, 0, 0, 0}, NULL},
318 };
319 /* *INDENT-ON* */
320
321 struct option opts[ARRAYSIZE(custom_opts)];
322 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
323 opts[i] = custom_opts[i].opt;
324 }
325
326 enum llevel_t ll = INFO;
327 const char *logfile = NULL;
328 int opt_index = 0;
329 for (;;) {
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200330 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 +0200331 &opt_index);
332 if (c < 0)
333 break;
334
335 switch (c) {
336 case 'h':
337 case '?':
338 cmdlineUsage(argv[0], custom_opts);
339 break;
340 case 'f':
Jagger1b2d4822016-09-25 16:19:45 +0200341 hfuzz->inputDir = optarg;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200342 break;
343 case 'q':
344 hfuzz->nullifyStdio = true;
345 break;
346 case 'v':
347 hfuzz->useScreen = false;
348 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700349 case 'V':
350 hfuzz->useVerifier = true;
351 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200352 case 's':
353 hfuzz->fuzzStdin = true;
354 break;
355 case 'u':
356 hfuzz->saveUnique = false;
357 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200358 case 'l':
359 logfile = optarg;
360 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200361 case 'd':
362 ll = atoi(optarg);
363 break;
364 case 'e':
365 hfuzz->fileExtn = optarg;
366 break;
367 case 'W':
368 hfuzz->workDir = optarg;
369 break;
370 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100371 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200372 break;
373 case 'c':
374 hfuzz->externalCommand = optarg;
375 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200376 case 'C':
377 hfuzz->useSanCov = true;
378 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200379 case 'S':
380 hfuzz->enableSanitizers = true;
381 break;
Jagger4aac9fe2016-08-28 17:35:48 +0200382 case 'z':
383 hfuzz->dynFileMethod |= _HF_DYNFILE_SOFT;
384 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200385 case 'F':
386 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
387 break;
388 case 't':
389 hfuzz->tmOut = atol(optarg);
390 break;
391 case 'R':
392 hfuzz->reportFile = optarg;
393 break;
394 case 'n':
395 hfuzz->threadsMax = atol(optarg);
396 break;
397 case 'N':
398 hfuzz->mutationsMax = atol(optarg);
399 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200400 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200401 hfuzz->asLimit = strtoull(optarg, NULL, 0);
402 break;
Jagger80041fe2016-03-10 21:32:35 +0100403 case 0x101:
404 hfuzz->clearEnv = true;
405 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100406 case 0x102:
407 hfuzz->msanReportUMRS = true;
408 break;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200409 case 0x103:
Jagger1b2d4822016-09-25 16:19:45 +0200410 hfuzz->covDir = optarg;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200411 break;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200412 case 0x104:
413 hfuzz->postExternalCommand = optarg;
414 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200415 case 0x105:
416 if ((strcasecmp(optarg, "0") == 0) || (strcasecmp(optarg, "false") == 0)) {
417 hfuzz->monitorSIGABRT = false;
418 } else {
419 hfuzz->monitorSIGABRT = true;
420 }
421 break;
Robert Swiecki44f6b192017-02-15 20:24:55 +0100422 case 0x106:
423 hfuzz->skipFeedbackOnTimeout = true;
424 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200425 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200426 hfuzz->persistent = true;
427 break;
Gergely Nagy5d47c732016-12-12 23:51:51 +0100428 case 'T':
Robert Swieckie84b6452016-12-12 12:42:04 +0100429 hfuzz->tmout_vtalrm = true;
430 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200431 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200432 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200433 LOG_E("-p '%s' is not a number", optarg);
434 return false;
435 }
Jagger247c3b42016-03-21 23:24:05 +0100436 hfuzz->linux.pid = atoi(optarg);
437 if (hfuzz->linux.pid < 1) {
438 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200439 return false;
440 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200441 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200442 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100443 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200444 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200445 case 'E':
446 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
447 if (hfuzz->envs[i] == NULL) {
448 hfuzz->envs[i] = optarg;
449 break;
450 }
451 }
452 break;
453 case 'w':
454 hfuzz->dictionaryFile = optarg;
455 break;
456 case 'B':
457 hfuzz->blacklistFile = optarg;
458 break;
Robert Swiecki846ccd72017-01-12 17:52:23 +0100459#if defined(_HF_ARCH_LINUX)
Robert Swieckia88f96f2015-10-09 16:47:39 +0200460 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100461 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200462 break;
463 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100464 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200465 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200466 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100467 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200468 break;
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300469 case 0x504:
470 hfuzz->linux.symsBlFile = optarg;
471 break;
472 case 0x505:
473 hfuzz->linux.symsWlFile = optarg;
474 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200475 case 0x510:
476 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
477 break;
478 case 0x511:
479 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
480 break;
481 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100482 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200483 break;
484 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100485 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200486 break;
487 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100488 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
489 break;
Robert Swiecki846ccd72017-01-12 17:52:23 +0100490 case 0x530:
491 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWNET);
492 break;
493 case 0x531:
494 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWPID);
495 break;
496 case 0x532:
497 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWIPC);
498 break;
499#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200500 default:
501 cmdlineUsage(argv[0], custom_opts);
502 return false;
503 break;
504 }
505 }
Jagger72f258b2015-10-09 23:09:01 +0200506
Robert Swieckia88f96f2015-10-09 16:47:39 +0200507 if (logInitLogFile(logfile, ll) == false) {
508 return false;
509 }
510
511 hfuzz->cmdline = &argv[optind];
512 if (hfuzz->cmdline[0] == NULL) {
513 LOG_E("No fuzz command provided");
514 cmdlineUsage(argv[0], custom_opts);
515 return false;
516 }
517
Robert Swiecki0f937af2016-03-30 18:19:16 +0200518 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200519 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200520 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200521 return false;
522 }
523
Robert Swiecki71b73722016-09-05 15:18:25 +0200524 if (hfuzz->threadsMax >= _HF_THREAD_MAX) {
525 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", hfuzz->threadsMax,
526 _HF_THREAD_MAX);
527 return false;
528 }
529
Robert Swieckia88f96f2015-10-09 16:47:39 +0200530 if (strchr(hfuzz->fileExtn, '/')) {
531 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
532 return false;
533 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200534
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200535 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200536 if (!files_exists(hfuzz->workDir)) {
537 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
538 return false;
539 }
540 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200541
Jagger247c3b42016-03-21 23:24:05 +0100542 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
543 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
544 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200545 hfuzz->threadsMax = 1;
546 }
547
Robert Swieckia96d78d2016-03-14 16:50:50 +0100548 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200549 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200550 }
551
Anestis Bechtsoudisc1a0d9f2016-12-29 11:34:10 +0200552 /*
553 * 'enableSanitizers' can be auto enabled when 'useSanCov', although it's probably
554 * better to let user know about the features that each flag control.
555 */
556 if (hfuzz->useSanCov == true && hfuzz->enableSanitizers == false) {
557 LOG_E("Sanitizer coverage cannot be used without enabling sanitizers '-S/--sanitizers'");
558 return false;
559 }
560
Robert Swieckiaa87aae2017-02-09 03:04:51 +0100561 LOG_I("PID: %d, inputDir '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Anestis Bechtsoudisecab7762016-12-27 18:27:30 +0200562 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn: '%s', "
563 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d, monitorSIGABRT: '%s'",
Robert Swieckiaa87aae2017-02-09 03:04:51 +0100564 (int)getpid(), hfuzz->inputDir,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200565 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100566 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200567 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
Jagger247c3b42016-03-21 23:24:05 +0100568 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn,
Anestis Bechtsoudisac366a12016-12-28 12:38:44 +0200569 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->linux.pid, cmdlineYesNo(hfuzz->monitorSIGABRT));
Robert Swieckia88f96f2015-10-09 16:47:39 +0200570
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100571 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100572 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
573 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
Robert Swieckif2d9c3a2016-11-03 02:13:54 +0100574 if (strlen(hfuzz->cmdline_txt) == (sizeof(hfuzz->cmdline_txt) - 1)) {
575 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 3] = '.';
576 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 2] = '.';
577 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 1] = '.';
578 }
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100579 }
580
Robert Swieckia88f96f2015-10-09 16:47:39 +0200581 return true;
582}