blob: 8ad926e8322b181743495845331ee97b9aba9cd8 [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
Robert Swiecki241a7412017-05-24 01:53:15 +020040#include "libcommon/common.h"
41#include "libcommon/log.h"
42#include "libcommon/files.h"
43#include "libcommon/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 Swiecki4332ae92017-05-23 23:06:04 +0200151 .nullifyStdio = true,
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 Swiecki069b48f2017-05-31 01:00:08 +0200189 .exitUponCrash = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200190
Robert Swiecki531438a2016-09-13 19:05:11 +0200191 .dictionaryFile = NULL,
192 .dictionaryCnt = 0,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100193 .dictqCurrent = NULL,
Robert Swiecki531438a2016-09-13 19:05:11 +0200194
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100195 .state = _HF_STATE_UNSET,
Jaggerb7fa3ee2016-08-21 19:46:26 +0200196 .feedback = NULL,
Robert Swieckibc7532e2016-08-20 00:34:17 +0200197 .bbFd = -1,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100198
Robert Swieckie586c1f2016-03-14 18:46:03 +0100199 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100200 .dynfileqCnt = 0U,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100201 .dynfileqCurrent = NULL,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100202
Robert Swiecki37498fd2017-03-12 21:12:54 +0100203 .feedback_mutex = PTHREAD_MUTEX_INITIALIZER,
204
Robert Swieckia88f96f2015-10-09 16:47:39 +0200205 .mutationsCnt = 0,
206 .crashesCnt = 0,
207 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200208 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200209 .blCrashesCnt = 0,
210 .timeoutedCnt = 0,
211
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100212 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200213 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100214 .hitBBCnt = 0ULL,
215 .totalBBCnt = 0ULL,
216 .dsoCnt = 0ULL,
217 .iDsoCnt = 0ULL,
218 .newBBCnt = 0ULL,
219 .crashesCnt = 0ULL,
220 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200221
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200222 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100223 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100224 .asanOpts = NULL,
225 .msanOpts = NULL,
226 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200227 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100228 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100229 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100230 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100231
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700232 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
233
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100234 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200235 .linux = {
Jaggerab26e702016-03-22 04:28:00 +0100236 .hwCnts = {
237 .cpuInstrCnt = 0ULL,
238 .cpuBranchCnt = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100239 .bbCnt = 0ULL,
240 .newBBCnt = 0ULL,
Jagger34789a72016-09-08 00:36:09 +0200241 .softCntPc = 0ULL,
242 .softCntCmp = 0ULL,
Jaggerab26e702016-03-22 04:28:00 +0100243 },
244 .dynamicCutOffAddr = ~(0ULL),
245 .disableRandomization = true,
246 .ignoreAddr = NULL,
247 .numMajorFrames = 7,
248 .pid = 0,
249 .pidFile = NULL,
250 .pidCmd = NULL,
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300251 .symsBlFile = NULL,
252 .symsBlCnt = 0,
253 .symsBl = NULL,
254 .symsWlFile = NULL,
255 .symsWlCnt = 0,
256 .symsWl = NULL,
Robert Swiecki846ccd72017-01-12 17:52:23 +0100257 .cloneFlags = 0,
Robert Swiecki37d27ca2017-03-30 14:43:54 +0200258 .kernelOnly = false,
Robert Swiecki1c9d8092017-06-01 02:39:09 +0200259 .exeFd = -1,
Jaggerab26e702016-03-22 04:28:00 +0100260 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200261 };
262 /* *INDENT-ON* */
263
Robert Swieckiafb16102017-03-13 22:14:31 +0100264 TAILQ_INIT(&hfuzz->dynfileq);
265 TAILQ_INIT(&hfuzz->dictq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100266
Robert Swieckia88f96f2015-10-09 16:47:39 +0200267 /* *INDENT-OFF* */
268 struct custom_option custom_opts[] = {
269 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
Jagger1b2d4822016-09-25 16:19:45 +0200270 {{"input", required_argument, NULL, 'f'}, "Path to a directory containing initial file corpus"},
Robert Swieckiebdb2a52017-05-23 23:00:56 +0200271 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (use hfuzz_cc/hfuzz-clang to compile code)"},
272 {{"instrument", no_argument, NULL, 'z'}, "Enable compile-time instrumentation (use hfuzz_cc/hfuzz-clang to compile code)"},
273 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Robert Swiecki4332ae92017-05-23 23:06:04 +0200274 {{"keep_output", no_argument, NULL, 'Q'}, "Don't close children's stdin, stdout, stderr; can be noisy"},
Jagger54c96a22016-03-30 23:13:30 +0200275 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
Jagger2664f542016-09-28 14:37:00 +0200276 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: number of CPUs / 2)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200277 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200278 {{"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 +0200279 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200280 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100281 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200282 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
283 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300284 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Robert Swieckid32018f2016-10-11 22:58:22 +0200285 {{"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 +0200286 {{"wordlist", required_argument, NULL, 'w'}, "Wordlist file (tokens delimited by NUL-bytes)"},
287 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Robert Swieckiee266ac2016-10-03 02:25:59 +0200288 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command producing fuzz files (instead of internal mutators)"},
289 {{"pprocess_cmd", required_argument, NULL, 0x104}, "External command postprocessing files produced by internal mutators"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200290 {{"iterations", required_argument, NULL, 'N'}, "Number of fuzzing iterations (default: '0' [no limit])"},
Robert Swiecki03ef5312015-10-09 18:25:40 +0200291 {{"rlimit_as", required_argument, NULL, 0x100}, "Per process memory limit in MiB (default: '0' [no limit])"},
dyjakanebfd24e2015-10-16 19:24:32 +0100292 {{"report", required_argument, NULL, 'R'}, "Write report to this file (default: '" _HF_REPORT_FILE "')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200293 {{"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 +0100294 {{"clear_env", no_argument, NULL, 0x101}, "Clear all environment variables before executing the binary"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200295 {{"env", required_argument, NULL, 'E'}, "Pass this environment variable, can be used multiple times"},
Jagger54c96a22016-03-30 23:13:30 +0200296 {{"save_all", no_argument, NULL, 'u'}, "Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames"},
Jagger7ff92fa2016-03-22 04:13:50 +0100297 {{"msan_report_umrs", no_argument, NULL, 0x102}, "Report MSAN's UMRS (uninitialized memory access)"},
Gergely Nagy5d47c732016-12-12 23:51:51 +0100298 {{"tmout_sigvtalrm", no_argument, NULL, 'T'}, "Use SIGVTALRM to kill timeouting processes (default: use SIGKILL)"},
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200299 {{"sanitizers", no_argument, NULL, 'S'}, "Enable sanitizers settings (default: false)"},
300 {{"monitor_sigabrt", required_argument, NULL, 0x105}, "Monitor SIGABRT (default: 'false for Android - 'true for other platforms)"},
Robert Swiecki44f6b192017-02-15 20:24:55 +0100301 {{"no_fb_timeout", required_argument, NULL, 0x106}, "Skip feedback if the process has timeouted (default: 'false')"},
Robert Swiecki069b48f2017-05-31 01:00:08 +0200302 {{"exit_upon_crash", no_argument, NULL, 0x107}, "Exit upon seeing the first crash (default: 'false')"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200303
304#if defined(_HF_ARCH_LINUX)
Anestis Bechtsoudisfafb3332016-10-31 08:57:16 +0200305 {{"linux_symbols_bl", required_argument, NULL, 0x504}, "Symbols blacklist filter file (one entry per line)"},
306 {{"linux_symbols_wl", required_argument, NULL, 0x505}, "Symbols whitelist filter file (one entry per line)"},
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200307 {{"linux_pid", required_argument, NULL, 'p'}, "Attach to a pid (and its thread group)"},
Robert Swieckifab69162016-03-31 15:41:36 +0200308 {{"linux_file_pid", required_argument, NULL, 0x502}, "Attach to pid (and its thread group) read from file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200309 {{"linux_addr_low_limit", required_argument, NULL, 0x500}, "Address limit (from si.si_addr) below which crashes are not reported, (default: '0')"},
310 {{"linux_keep_aslr", no_argument, NULL, 0x501}, "Don't disable ASLR randomization, might be useful with MSAN"},
Jaggerae6a4452015-10-14 17:34:43 +0200311 {{"linux_perf_ignore_above", required_argument, NULL, 0x503}, "Ignore perf events which report IPs above this address"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200312 {{"linux_perf_instr", no_argument, NULL, 0x510}, "Use PERF_COUNT_HW_INSTRUCTIONS perf"},
313 {{"linux_perf_branch", no_argument, NULL, 0x511}, "Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf"},
Jagger39bd2b02016-02-04 01:16:15 +0100314 {{"linux_perf_bts_block", no_argument, NULL, 0x512}, "Use Intel BTS to count unique blocks"},
315 {{"linux_perf_bts_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
Robert Swiecki8499c662016-11-01 18:02:52 +0100316 {{"linux_perf_ipt_block", no_argument, NULL, 0x514}, "Use Intel Processor Trace to count unique blocks (requires libipt.so)"},
Robert Swiecki37d27ca2017-03-30 14:43:54 +0200317 {{"linux_perf_kernel_only", no_argument, NULL, 0x515}, "Gather kernel-only coverage with Intel PT and with Intel BTS"},
Robert Swiecki846ccd72017-01-12 17:52:23 +0100318 {{"linux_ns_net", no_argument, NULL, 0x0530}, "Use Linux NET namespace isolation"},
319 {{"linux_ns_pid", no_argument, NULL, 0x0531}, "Use Linux PID namespace isolation"},
320 {{"linux_ns_ipc", no_argument, NULL, 0x0532}, "Use Linux IPC namespace isolation"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200321#endif // defined(_HF_ARCH_LINUX)
322 {{0, 0, 0, 0}, NULL},
323 };
324 /* *INDENT-ON* */
325
326 struct option opts[ARRAYSIZE(custom_opts)];
327 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
328 opts[i] = custom_opts[i].opt;
329 }
330
331 enum llevel_t ll = INFO;
332 const char *logfile = NULL;
333 int opt_index = 0;
334 for (;;) {
Robert Swiecki4332ae92017-05-23 23:06:04 +0200335 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 +0200336 &opt_index);
337 if (c < 0)
338 break;
339
340 switch (c) {
341 case 'h':
342 case '?':
343 cmdlineUsage(argv[0], custom_opts);
344 break;
345 case 'f':
Jagger1b2d4822016-09-25 16:19:45 +0200346 hfuzz->inputDir = optarg;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200347 break;
Robert Swiecki4332ae92017-05-23 23:06:04 +0200348 case 'Q':
349 hfuzz->nullifyStdio = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200350 break;
351 case 'v':
352 hfuzz->useScreen = false;
353 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700354 case 'V':
355 hfuzz->useVerifier = true;
356 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200357 case 's':
358 hfuzz->fuzzStdin = true;
359 break;
360 case 'u':
361 hfuzz->saveUnique = false;
362 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200363 case 'l':
364 logfile = optarg;
365 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200366 case 'd':
367 ll = atoi(optarg);
368 break;
369 case 'e':
370 hfuzz->fileExtn = optarg;
371 break;
372 case 'W':
373 hfuzz->workDir = optarg;
374 break;
375 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100376 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200377 break;
378 case 'c':
379 hfuzz->externalCommand = optarg;
380 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200381 case 'C':
382 hfuzz->useSanCov = true;
383 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200384 case 'S':
385 hfuzz->enableSanitizers = true;
386 break;
Jagger4aac9fe2016-08-28 17:35:48 +0200387 case 'z':
388 hfuzz->dynFileMethod |= _HF_DYNFILE_SOFT;
389 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200390 case 'F':
391 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
392 break;
393 case 't':
394 hfuzz->tmOut = atol(optarg);
395 break;
396 case 'R':
397 hfuzz->reportFile = optarg;
398 break;
399 case 'n':
400 hfuzz->threadsMax = atol(optarg);
401 break;
402 case 'N':
403 hfuzz->mutationsMax = atol(optarg);
404 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200405 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200406 hfuzz->asLimit = strtoull(optarg, NULL, 0);
407 break;
Jagger80041fe2016-03-10 21:32:35 +0100408 case 0x101:
409 hfuzz->clearEnv = true;
410 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100411 case 0x102:
412 hfuzz->msanReportUMRS = true;
413 break;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200414 case 0x103:
Jagger1b2d4822016-09-25 16:19:45 +0200415 hfuzz->covDir = optarg;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200416 break;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200417 case 0x104:
418 hfuzz->postExternalCommand = optarg;
419 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200420 case 0x105:
421 if ((strcasecmp(optarg, "0") == 0) || (strcasecmp(optarg, "false") == 0)) {
422 hfuzz->monitorSIGABRT = false;
423 } else {
424 hfuzz->monitorSIGABRT = true;
425 }
426 break;
Robert Swiecki44f6b192017-02-15 20:24:55 +0100427 case 0x106:
428 hfuzz->skipFeedbackOnTimeout = true;
429 break;
Robert Swiecki069b48f2017-05-31 01:00:08 +0200430 case 0x107:
431 hfuzz->exitUponCrash = true;
432 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200433 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200434 hfuzz->persistent = true;
435 break;
Gergely Nagy5d47c732016-12-12 23:51:51 +0100436 case 'T':
Robert Swieckie84b6452016-12-12 12:42:04 +0100437 hfuzz->tmout_vtalrm = true;
438 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200439 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200440 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200441 LOG_E("-p '%s' is not a number", optarg);
442 return false;
443 }
Jagger247c3b42016-03-21 23:24:05 +0100444 hfuzz->linux.pid = atoi(optarg);
445 if (hfuzz->linux.pid < 1) {
446 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200447 return false;
448 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200449 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200450 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100451 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200452 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200453 case 'E':
454 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
455 if (hfuzz->envs[i] == NULL) {
456 hfuzz->envs[i] = optarg;
457 break;
458 }
459 }
460 break;
461 case 'w':
462 hfuzz->dictionaryFile = optarg;
463 break;
464 case 'B':
465 hfuzz->blacklistFile = optarg;
466 break;
Robert Swiecki846ccd72017-01-12 17:52:23 +0100467#if defined(_HF_ARCH_LINUX)
Robert Swieckia88f96f2015-10-09 16:47:39 +0200468 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100469 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200470 break;
471 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100472 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200473 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200474 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100475 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200476 break;
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300477 case 0x504:
478 hfuzz->linux.symsBlFile = optarg;
479 break;
480 case 0x505:
481 hfuzz->linux.symsWlFile = optarg;
482 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200483 case 0x510:
484 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
485 break;
486 case 0x511:
487 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
488 break;
489 case 0x512:
Jagger3abc5602016-02-04 00:53:43 +0100490 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_BLOCK;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200491 break;
492 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100493 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200494 break;
495 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100496 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
497 break;
Robert Swiecki37d27ca2017-03-30 14:43:54 +0200498 case 0x515:
499 hfuzz->linux.kernelOnly = true;
500 break;
Robert Swiecki846ccd72017-01-12 17:52:23 +0100501 case 0x530:
502 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWNET);
503 break;
504 case 0x531:
505 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWPID);
506 break;
507 case 0x532:
508 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWIPC);
509 break;
510#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200511 default:
512 cmdlineUsage(argv[0], custom_opts);
513 return false;
514 break;
515 }
516 }
Jagger72f258b2015-10-09 23:09:01 +0200517
Robert Swieckia88f96f2015-10-09 16:47:39 +0200518 if (logInitLogFile(logfile, ll) == false) {
519 return false;
520 }
521
522 hfuzz->cmdline = &argv[optind];
523 if (hfuzz->cmdline[0] == NULL) {
524 LOG_E("No fuzz command provided");
525 cmdlineUsage(argv[0], custom_opts);
526 return false;
527 }
528
Robert Swiecki0f937af2016-03-30 18:19:16 +0200529 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200530 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200531 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200532 return false;
533 }
534
Robert Swiecki5b775b22017-04-28 16:19:15 +0200535 if (hfuzz->fuzzStdin && hfuzz->persistent) {
Robert Swieckid633fe02017-04-28 17:40:27 +0200536 LOG_E
537 ("Stdin fuzzing (-s) and persistent fuzzing (-P) cannot be specified at the same time");
538 return false;
Robert Swiecki5b775b22017-04-28 16:19:15 +0200539 }
540
Robert Swiecki71b73722016-09-05 15:18:25 +0200541 if (hfuzz->threadsMax >= _HF_THREAD_MAX) {
542 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", hfuzz->threadsMax,
543 _HF_THREAD_MAX);
544 return false;
545 }
546
Robert Swieckia88f96f2015-10-09 16:47:39 +0200547 if (strchr(hfuzz->fileExtn, '/')) {
548 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
549 return false;
550 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200551
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200552 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200553 if (!files_exists(hfuzz->workDir)) {
554 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
555 return false;
556 }
557 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200558
Jagger247c3b42016-03-21 23:24:05 +0100559 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
560 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
561 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200562 hfuzz->threadsMax = 1;
563 }
564
Robert Swieckia96d78d2016-03-14 16:50:50 +0100565 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200566 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200567 }
568
Anestis Bechtsoudisc1a0d9f2016-12-29 11:34:10 +0200569 /*
570 * 'enableSanitizers' can be auto enabled when 'useSanCov', although it's probably
571 * better to let user know about the features that each flag control.
572 */
573 if (hfuzz->useSanCov == true && hfuzz->enableSanitizers == false) {
574 LOG_E("Sanitizer coverage cannot be used without enabling sanitizers '-S/--sanitizers'");
575 return false;
576 }
577
Robert Swieckiaa87aae2017-02-09 03:04:51 +0100578 LOG_I("PID: %d, inputDir '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Anestis Bechtsoudisecab7762016-12-27 18:27:30 +0200579 "externalCommand: '%s', tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn: '%s', "
580 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d, monitorSIGABRT: '%s'",
Robert Swieckiaa87aae2017-02-09 03:04:51 +0100581 (int)getpid(), hfuzz->inputDir,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200582 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100583 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200584 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, hfuzz->tmOut,
Jagger247c3b42016-03-21 23:24:05 +0100585 hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn,
Anestis Bechtsoudisac366a12016-12-28 12:38:44 +0200586 hfuzz->asLimit, hfuzz->cmdline[0], hfuzz->linux.pid, cmdlineYesNo(hfuzz->monitorSIGABRT));
Robert Swieckia88f96f2015-10-09 16:47:39 +0200587
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100588 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100589 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
590 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
Robert Swieckif2d9c3a2016-11-03 02:13:54 +0100591 if (strlen(hfuzz->cmdline_txt) == (sizeof(hfuzz->cmdline_txt) - 1)) {
592 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 3] = '.';
593 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 2] = '.';
594 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 1] = '.';
595 }
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100596 }
597
Robert Swieckia88f96f2015-10-09 16:47:39 +0200598 return true;
599}