blob: 12a5e5aa89c80cd11beab0ea60d2fab6551ed3f1 [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 branches (edges) via BTS:");
Robert Swiecki43f0b282016-11-01 18:06:40 +0100101 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_bts_edge -- /usr/bin/tiffinfo -D "
102 _HF_FILE_PLACEHOLDER);
Robert Swiecki349cb9e2016-10-14 21:36:42 +0200103 LOG_HELP
Robert Swiecki8499c662016-11-01 18:02:52 +0100104 (" 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 +0200105 LOG_HELP_BOLD(" " PROG_NAME " --linux_perf_ipt_block -- /usr/bin/tiffinfo -D "
Jagger72f258b2015-10-09 23:09:01 +0200106 _HF_FILE_PLACEHOLDER);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200107#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200108}
109
110static void cmdlineUsage(const char *pname, struct custom_option *opts)
111{
112 cmdlineHelp(pname, opts);
113 exit(0);
114}
115
Robert Swieckia88f96f2015-10-09 16:47:39 +0200116rlim_t cmdlineParseRLimit(int res, const char *optarg, unsigned long mul)
117{
118 struct rlimit cur;
119 if (getrlimit(res, &cur) == -1) {
120 PLOG_F("getrlimit(%d)", res);
121 }
122 if (strcasecmp(optarg, "max") == 0) {
123 return cur.rlim_max;
124 }
125 if (strcasecmp(optarg, "def") == 0) {
126 return cur.rlim_cur;
127 }
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200128 if (util_isANumber(optarg) == false) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200129 LOG_F("RLIMIT %d needs a numeric or 'max'/'def' value ('%s' provided)", res, optarg);
130 }
131 rlim_t val = strtoul(optarg, NULL, 0) * mul;
Jagger2bd61b72015-10-10 05:23:32 +0200132 if ((unsigned long)val == ULONG_MAX && errno != 0) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200133 PLOG_F("strtoul('%s', 0)", optarg);
134 }
135 return val;
136}
137
138bool cmdlineParse(int argc, char *argv[], honggfuzz_t * hfuzz)
139{
140 /* *INDENT-OFF* */
141 (*hfuzz) = (honggfuzz_t) {
142 .cmdline = NULL,
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100143 .cmdline_txt[0] = '\0',
Jagger1b2d4822016-09-25 16:19:45 +0200144 .inputDir = NULL,
Robert Swiecki92a31362017-02-24 16:21:40 +0100145 .inputDirP = NULL,
146 .fileCnt = 0,
147 .fileCntDone = false,
Robert Swiecki4332ae92017-05-23 23:06:04 +0200148 .nullifyStdio = true,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200149 .fuzzStdin = false,
150 .saveUnique = true,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100151 .useScreen = true,
152 .useVerifier = false,
153 .timeStart = time(NULL),
Robert Swieckia88f96f2015-10-09 16:47:39 +0200154 .fileExtn = "fuzz",
155 .workDir = ".",
Jagger1b2d4822016-09-25 16:19:45 +0200156 .covDir = NULL,
Robert Swieckia96d78d2016-03-14 16:50:50 +0100157 .origFlipRate = 0.001f,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200158 .externalCommand = NULL,
Robert Swieckiee266ac2016-10-03 02:25:59 +0200159 .postExternalCommand = NULL,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200160 .blacklistFile = NULL,
161 .blacklistCnt = 0,
162 .blacklist = NULL,
Jaggerf4a60562016-09-25 15:40:23 +0200163 .maxFileSz = 0UL,
Jaggerba92b4b2016-03-16 02:24:17 +0100164 .tmOut = 10,
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200165 .runEndTime = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200166 .mutationsMax = 0,
167 .threadsFinished = 0,
Jagger2664f542016-09-28 14:37:00 +0200168 .threadsMax = (sysconf(_SC_NPROCESSORS_ONLN) <= 1) ? 1 : sysconf(_SC_NPROCESSORS_ONLN) / 2,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200169 .reportFile = NULL,
170 .asLimit = 0ULL,
Jagger80041fe2016-03-10 21:32:35 +0100171 .clearEnv = false,
Jaggerab26e702016-03-22 04:28:00 +0100172 .envs = {
173 [0 ... (ARRAYSIZE(hfuzz->envs) - 1)] = NULL,
174 },
Robert Swiecki0f937af2016-03-30 18:19:16 +0200175 .persistent = false,
Robert Swieckie84b6452016-12-12 12:42:04 +0100176 .tmout_vtalrm = false,
Robert Swiecki44f6b192017-02-15 20:24:55 +0100177 .skipFeedbackOnTimeout = false,
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200178 .enableSanitizers = false,
179#if defined(__ANDROID__)
180 .monitorSIGABRT = false,
181#else
182 .monitorSIGABRT = true,
183#endif
Robert Swiecki0ec98112017-02-03 02:08:14 +0100184 .threadsActiveCnt = 0,
Robert Swiecki89b84472017-02-12 22:20:10 +0100185 .mainPid = getpid(),
Robert Swiecki8d01b012017-02-19 15:48:11 +0100186 .terminating = false,
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200187 .exitUponCrash = false,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200188
Robert Swiecki531438a2016-09-13 19:05:11 +0200189 .dictionaryFile = NULL,
190 .dictionaryCnt = 0,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100191 .dictqCurrent = NULL,
Robert Swiecki531438a2016-09-13 19:05:11 +0200192
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100193 .state = _HF_STATE_UNSET,
Jaggerb7fa3ee2016-08-21 19:46:26 +0200194 .feedback = NULL,
Robert Swieckibc7532e2016-08-20 00:34:17 +0200195 .bbFd = -1,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100196
Robert Swieckie586c1f2016-03-14 18:46:03 +0100197 .dynfileq_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100198 .dynfileqCnt = 0U,
Robert Swiecki9f5f9432017-03-09 01:48:04 +0100199 .dynfileqCurrent = NULL,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100200
Robert Swiecki37498fd2017-03-12 21:12:54 +0100201 .feedback_mutex = PTHREAD_MUTEX_INITIALIZER,
202
Robert Swieckia88f96f2015-10-09 16:47:39 +0200203 .mutationsCnt = 0,
204 .crashesCnt = 0,
205 .uniqueCrashesCnt = 0,
Anestis Bechtsoudis79b799e2015-11-01 00:02:25 +0200206 .verifiedCrashesCnt = 0,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200207 .blCrashesCnt = 0,
208 .timeoutedCnt = 0,
209
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100210 .dynFileMethod = _HF_DYNFILE_NONE,
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200211 .sanCovCnts = {
Jaggerab26e702016-03-22 04:28:00 +0100212 .hitBBCnt = 0ULL,
213 .totalBBCnt = 0ULL,
214 .dsoCnt = 0ULL,
215 .iDsoCnt = 0ULL,
216 .newBBCnt = 0ULL,
217 .crashesCnt = 0ULL,
218 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200219
Anestis Bechtsoudisa16f70f2016-01-03 13:03:21 +0200220 .sanCov_mutex = PTHREAD_MUTEX_INITIALIZER,
Robert Swiecki23ec02a2016-01-19 18:47:45 +0100221 .sanOpts = {
Jaggerab26e702016-03-22 04:28:00 +0100222 .asanOpts = NULL,
223 .msanOpts = NULL,
224 .ubsanOpts = NULL,
Anestis Bechtsoudis61b5ab12016-01-08 16:07:02 +0200225 },
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100226 .useSanCov = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100227 .covMetadata = NULL,
Jagger247c3b42016-03-21 23:24:05 +0100228 .msanReportUMRS = false,
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100229
Haris Andrianakisc9a71332016-05-09 21:56:30 -0700230 .report_mutex = PTHREAD_MUTEX_INITIALIZER,
231
Robert Swiecki6c9f6822016-03-14 16:12:27 +0100232 /* Linux code */
Robert Swieckifab69162016-03-31 15:41:36 +0200233 .linux = {
Robert Swiecki3377e1c2017-06-01 18:01:57 +0200234 .exeFd = -1,
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,
Robert Swiecki37d27ca2017-03-30 14:43:54 +0200257 .kernelOnly = false,
Robert Swiecki810d2c92017-06-01 21:37:27 +0200258 .useClone = true,
Jaggerab26e702016-03-22 04:28:00 +0100259 },
Robert Swieckia88f96f2015-10-09 16:47:39 +0200260 };
261 /* *INDENT-ON* */
262
Robert Swieckiafb16102017-03-13 22:14:31 +0100263 TAILQ_INIT(&hfuzz->dynfileq);
264 TAILQ_INIT(&hfuzz->dictq);
Robert Swiecki3bfc33c2016-03-14 18:12:41 +0100265
Robert Swieckia88f96f2015-10-09 16:47:39 +0200266 /* *INDENT-OFF* */
267 struct custom_option custom_opts[] = {
268 {{"help", no_argument, NULL, 'h'}, "Help plz.."},
Jagger1b2d4822016-09-25 16:19:45 +0200269 {{"input", required_argument, NULL, 'f'}, "Path to a directory containing initial file corpus"},
Robert Swieckiebdb2a52017-05-23 23:00:56 +0200270 {{"persistent", no_argument, NULL, 'P'}, "Enable persistent fuzzing (use hfuzz_cc/hfuzz-clang to compile code)"},
271 {{"instrument", no_argument, NULL, 'z'}, "Enable compile-time instrumentation (use hfuzz_cc/hfuzz-clang to compile code)"},
272 {{"sancov", no_argument, NULL, 'C'}, "Enable sanitizer coverage feedback"},
Robert Swiecki4332ae92017-05-23 23:06:04 +0200273 {{"keep_output", no_argument, NULL, 'Q'}, "Don't close children's stdin, stdout, stderr; can be noisy"},
Jagger54c96a22016-03-30 23:13:30 +0200274 {{"timeout", required_argument, NULL, 't'}, "Timeout in seconds (default: '10')"},
Jagger2664f542016-09-28 14:37:00 +0200275 {{"threads", required_argument, NULL, 'n'}, "Number of concurrent fuzzing threads (default: number of CPUs / 2)"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200276 {{"stdin_input", no_argument, NULL, 's'}, "Provide fuzzing input on STDIN, instead of ___FILE___"},
Jagger54c96a22016-03-30 23:13:30 +0200277 {{"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 +0200278 {{"logfile", required_argument, NULL, 'l'}, "Log file"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200279 {{"verbose", no_argument, NULL, 'v'}, "Disable ANSI console; use simple log output"},
Jagger5ff08ac2016-02-09 22:15:58 +0100280 {{"verifier", no_argument, NULL, 'V'}, "Enable crashes verifier"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200281 {{"debug_level", required_argument, NULL, 'd'}, "Debug level (0 - FATAL ... 4 - DEBUG), (default: '3' [INFO])"},
282 {{"extension", required_argument, NULL, 'e'}, "Input file extension (e.g. 'swf'), (default: 'fuzz')"},
Anestis Bechtsoudisbfcba122016-04-28 10:55:20 +0300283 {{"workspace", required_argument, NULL, 'W'}, "Workspace directory to save crashes & runtime files (default: '.')"},
Robert Swieckid32018f2016-10-11 22:58:22 +0200284 {{"covdir", required_argument, NULL, 0x103}, "New coverage is written to a separate directory (default: use the input directory)"},
Robert Swieckibf95adc2017-06-02 03:55:45 +0200285 {{"dict", required_argument, NULL, 'w'}, "Dictionary file. Format:http://llvm.org/docs/LibFuzzer.html#dictionaries"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200286 {{"stackhash_bl", required_argument, NULL, 'B'}, "Stackhashes blacklist file (one entry per line)"},
Robert Swieckiee266ac2016-10-03 02:25:59 +0200287 {{"mutate_cmd", required_argument, NULL, 'c'}, "External command producing fuzz files (instead of internal mutators)"},
288 {{"pprocess_cmd", required_argument, NULL, 0x104}, "External command postprocessing files produced by internal mutators"},
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200289 {{"run_time", required_argument, NULL, 0x109}, "Number of seconds this fuzzing session will last (default: '0' [no limit])"},
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_edge", no_argument, NULL, 0x513}, "Use Intel BTS to count unique edges"},
Robert Swiecki8499c662016-11-01 18:02:52 +0100315 {{"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 +0200316 {{"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 +0100317 {{"linux_ns_net", no_argument, NULL, 0x0530}, "Use Linux NET namespace isolation"},
318 {{"linux_ns_pid", no_argument, NULL, 0x0531}, "Use Linux PID namespace isolation"},
319 {{"linux_ns_ipc", no_argument, NULL, 0x0532}, "Use Linux IPC namespace isolation"},
Robert Swieckia88f96f2015-10-09 16:47:39 +0200320#endif // defined(_HF_ARCH_LINUX)
321 {{0, 0, 0, 0}, NULL},
322 };
323 /* *INDENT-ON* */
324
325 struct option opts[ARRAYSIZE(custom_opts)];
326 for (unsigned i = 0; i < ARRAYSIZE(custom_opts); i++) {
327 opts[i] = custom_opts[i].opt;
328 }
329
330 enum llevel_t ll = INFO;
331 const char *logfile = NULL;
332 int opt_index = 0;
333 for (;;) {
Robert Swiecki4332ae92017-05-23 23:06:04 +0200334 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 +0200335 &opt_index);
336 if (c < 0)
337 break;
338
339 switch (c) {
340 case 'h':
341 case '?':
342 cmdlineUsage(argv[0], custom_opts);
343 break;
344 case 'f':
Jagger1b2d4822016-09-25 16:19:45 +0200345 hfuzz->inputDir = optarg;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200346 break;
Robert Swiecki4332ae92017-05-23 23:06:04 +0200347 case 'Q':
348 hfuzz->nullifyStdio = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200349 break;
350 case 'v':
351 hfuzz->useScreen = false;
352 break;
Anestis Bechtsoudis0cde66f2015-10-11 19:37:11 -0700353 case 'V':
354 hfuzz->useVerifier = true;
355 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200356 case 's':
357 hfuzz->fuzzStdin = true;
358 break;
359 case 'u':
360 hfuzz->saveUnique = false;
361 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200362 case 'l':
363 logfile = optarg;
364 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200365 case 'd':
366 ll = atoi(optarg);
367 break;
368 case 'e':
369 hfuzz->fileExtn = optarg;
370 break;
371 case 'W':
372 hfuzz->workDir = optarg;
373 break;
374 case 'r':
Robert Swieckia96d78d2016-03-14 16:50:50 +0100375 hfuzz->origFlipRate = strtod(optarg, NULL);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200376 break;
377 case 'c':
378 hfuzz->externalCommand = optarg;
379 break;
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200380 case 'C':
381 hfuzz->useSanCov = true;
382 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200383 case 'S':
384 hfuzz->enableSanitizers = true;
385 break;
Jagger4aac9fe2016-08-28 17:35:48 +0200386 case 'z':
387 hfuzz->dynFileMethod |= _HF_DYNFILE_SOFT;
388 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200389 case 'F':
390 hfuzz->maxFileSz = strtoul(optarg, NULL, 0);
391 break;
392 case 't':
393 hfuzz->tmOut = atol(optarg);
394 break;
395 case 'R':
396 hfuzz->reportFile = optarg;
397 break;
398 case 'n':
399 hfuzz->threadsMax = atol(optarg);
400 break;
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200401 case 0x109:
402 {
403 time_t p = atol(optarg);
404 if (p > 0) {
405 hfuzz->runEndTime = time(NULL) + p;
406 }
407 }
408 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200409 case 'N':
410 hfuzz->mutationsMax = atol(optarg);
411 break;
Robert Swiecki03ef5312015-10-09 18:25:40 +0200412 case 0x100:
Robert Swieckia88f96f2015-10-09 16:47:39 +0200413 hfuzz->asLimit = strtoull(optarg, NULL, 0);
414 break;
Jagger80041fe2016-03-10 21:32:35 +0100415 case 0x101:
416 hfuzz->clearEnv = true;
417 break;
Jagger7ff92fa2016-03-22 04:13:50 +0100418 case 0x102:
419 hfuzz->msanReportUMRS = true;
420 break;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200421 case 0x103:
Jagger1b2d4822016-09-25 16:19:45 +0200422 hfuzz->covDir = optarg;
Robert Swieckidac8cf12016-09-22 15:36:28 +0200423 break;
Robert Swieckiee266ac2016-10-03 02:25:59 +0200424 case 0x104:
425 hfuzz->postExternalCommand = optarg;
426 break;
Anestis Bechtsoudise5f09f82016-12-27 16:06:05 +0200427 case 0x105:
428 if ((strcasecmp(optarg, "0") == 0) || (strcasecmp(optarg, "false") == 0)) {
429 hfuzz->monitorSIGABRT = false;
430 } else {
431 hfuzz->monitorSIGABRT = true;
432 }
433 break;
Robert Swiecki44f6b192017-02-15 20:24:55 +0100434 case 0x106:
435 hfuzz->skipFeedbackOnTimeout = true;
436 break;
Robert Swiecki069b48f2017-05-31 01:00:08 +0200437 case 0x107:
438 hfuzz->exitUponCrash = true;
439 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200440 case 'P':
Robert Swiecki0f937af2016-03-30 18:19:16 +0200441 hfuzz->persistent = true;
442 break;
Gergely Nagy5d47c732016-12-12 23:51:51 +0100443 case 'T':
Robert Swieckie84b6452016-12-12 12:42:04 +0100444 hfuzz->tmout_vtalrm = true;
445 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200446 case 'p':
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200447 if (util_isANumber(optarg) == false) {
Jagger9c4d1622015-10-16 01:40:17 +0200448 LOG_E("-p '%s' is not a number", optarg);
449 return false;
450 }
Jagger247c3b42016-03-21 23:24:05 +0100451 hfuzz->linux.pid = atoi(optarg);
452 if (hfuzz->linux.pid < 1) {
453 LOG_E("-p '%d' is invalid", hfuzz->linux.pid);
Jagger9c4d1622015-10-16 01:40:17 +0200454 return false;
455 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200456 break;
Robert Swieckifab69162016-03-31 15:41:36 +0200457 case 0x502:
Jagger247c3b42016-03-21 23:24:05 +0100458 hfuzz->linux.pidFile = optarg;
Anestis Bechtsoudis413cb132016-02-07 12:59:00 +0200459 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200460 case 'E':
461 for (size_t i = 0; i < ARRAYSIZE(hfuzz->envs); i++) {
462 if (hfuzz->envs[i] == NULL) {
463 hfuzz->envs[i] = optarg;
464 break;
465 }
466 }
467 break;
468 case 'w':
469 hfuzz->dictionaryFile = optarg;
470 break;
471 case 'B':
472 hfuzz->blacklistFile = optarg;
473 break;
Robert Swiecki846ccd72017-01-12 17:52:23 +0100474#if defined(_HF_ARCH_LINUX)
Robert Swieckia88f96f2015-10-09 16:47:39 +0200475 case 0x500:
Jagger247c3b42016-03-21 23:24:05 +0100476 hfuzz->linux.ignoreAddr = (void *)strtoul(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200477 break;
478 case 0x501:
Jagger247c3b42016-03-21 23:24:05 +0100479 hfuzz->linux.disableRandomization = false;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200480 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200481 case 0x503:
Jagger247c3b42016-03-21 23:24:05 +0100482 hfuzz->linux.dynamicCutOffAddr = strtoull(optarg, NULL, 0);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200483 break;
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300484 case 0x504:
485 hfuzz->linux.symsBlFile = optarg;
486 break;
487 case 0x505:
488 hfuzz->linux.symsWlFile = optarg;
489 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200490 case 0x510:
491 hfuzz->dynFileMethod |= _HF_DYNFILE_INSTR_COUNT;
492 break;
493 case 0x511:
494 hfuzz->dynFileMethod |= _HF_DYNFILE_BRANCH_COUNT;
495 break;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200496 case 0x513:
Jagger3abc5602016-02-04 00:53:43 +0100497 hfuzz->dynFileMethod |= _HF_DYNFILE_BTS_EDGE;
Robert Swieckia88f96f2015-10-09 16:47:39 +0200498 break;
499 case 0x514:
Jagger39bd2b02016-02-04 01:16:15 +0100500 hfuzz->dynFileMethod |= _HF_DYNFILE_IPT_BLOCK;
501 break;
Robert Swiecki37d27ca2017-03-30 14:43:54 +0200502 case 0x515:
503 hfuzz->linux.kernelOnly = true;
504 break;
Robert Swiecki846ccd72017-01-12 17:52:23 +0100505 case 0x530:
506 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWNET);
507 break;
508 case 0x531:
509 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWPID);
510 break;
511 case 0x532:
512 hfuzz->linux.cloneFlags |= (CLONE_NEWUSER | CLONE_NEWIPC);
513 break;
514#endif /* defined(_HF_ARCH_LINUX) */
Robert Swieckia88f96f2015-10-09 16:47:39 +0200515 default:
516 cmdlineUsage(argv[0], custom_opts);
517 return false;
518 break;
519 }
520 }
Jagger72f258b2015-10-09 23:09:01 +0200521
Robert Swieckia88f96f2015-10-09 16:47:39 +0200522 if (logInitLogFile(logfile, ll) == false) {
523 return false;
524 }
525
526 hfuzz->cmdline = &argv[optind];
527 if (hfuzz->cmdline[0] == NULL) {
528 LOG_E("No fuzz command provided");
529 cmdlineUsage(argv[0], custom_opts);
530 return false;
531 }
532
Robert Swiecki0f937af2016-03-30 18:19:16 +0200533 if (!hfuzz->fuzzStdin && !hfuzz->persistent && !checkFor_FILE_PLACEHOLDER(hfuzz->cmdline)) {
Robert Swieckia88f96f2015-10-09 16:47:39 +0200534 LOG_E("You must specify '" _HF_FILE_PLACEHOLDER
Robert Swiecki0f937af2016-03-30 18:19:16 +0200535 "' when the -s (stdin fuzzing) or --persistent options are not set");
Robert Swieckia88f96f2015-10-09 16:47:39 +0200536 return false;
537 }
538
Robert Swiecki5b775b22017-04-28 16:19:15 +0200539 if (hfuzz->fuzzStdin && hfuzz->persistent) {
Robert Swieckid633fe02017-04-28 17:40:27 +0200540 LOG_E
541 ("Stdin fuzzing (-s) and persistent fuzzing (-P) cannot be specified at the same time");
542 return false;
Robert Swiecki5b775b22017-04-28 16:19:15 +0200543 }
544
Robert Swiecki71b73722016-09-05 15:18:25 +0200545 if (hfuzz->threadsMax >= _HF_THREAD_MAX) {
546 LOG_E("Too many fuzzing threads specified %zu (>= _HF_THREAD_MAX (%u))", hfuzz->threadsMax,
547 _HF_THREAD_MAX);
548 return false;
549 }
550
Robert Swieckia88f96f2015-10-09 16:47:39 +0200551 if (strchr(hfuzz->fileExtn, '/')) {
552 LOG_E("The file extension contains the '/' character: '%s'", hfuzz->fileExtn);
553 return false;
554 }
Anestis Bechtsoudisbe0ac7b2015-12-26 15:38:47 +0200555
Anestis Bechtsoudis8f4aa612015-12-27 12:06:19 +0200556 if (hfuzz->workDir[0] != '.' || strlen(hfuzz->workDir) > 2) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200557 if (!files_exists(hfuzz->workDir)) {
558 LOG_E("Provided workspace directory '%s' doesn't exist", hfuzz->workDir);
559 return false;
560 }
561 }
Robert Swieckia88f96f2015-10-09 16:47:39 +0200562
Jagger247c3b42016-03-21 23:24:05 +0100563 if (hfuzz->linux.pid > 0 || hfuzz->linux.pidFile) {
564 LOG_I("PID=%d specified, lowering maximum number of concurrent threads to 1",
565 hfuzz->linux.pid);
Robert Swieckia88f96f2015-10-09 16:47:39 +0200566 hfuzz->threadsMax = 1;
567 }
568
Robert Swieckia96d78d2016-03-14 16:50:50 +0100569 if (hfuzz->origFlipRate == 0.0L && hfuzz->useVerifier) {
Anestis Bechtsoudisc8e7f6e2015-12-26 14:48:48 +0200570 LOG_I("Verifier enabled with 0.0 flipRate, activating dry run mode");
Anestis Bechtsoudis46ea10e2015-11-07 18:16:25 +0200571 }
572
Anestis Bechtsoudisc1a0d9f2016-12-29 11:34:10 +0200573 /*
574 * 'enableSanitizers' can be auto enabled when 'useSanCov', although it's probably
575 * better to let user know about the features that each flag control.
576 */
577 if (hfuzz->useSanCov == true && hfuzz->enableSanitizers == false) {
578 LOG_E("Sanitizer coverage cannot be used without enabling sanitizers '-S/--sanitizers'");
579 return false;
580 }
581
Robert Swieckiaa87aae2017-02-09 03:04:51 +0100582 LOG_I("PID: %d, inputDir '%s', nullifyStdio: %s, fuzzStdin: %s, saveUnique: %s, flipRate: %lf, "
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200583 "externalCommand: '%s', runEndTime: %d tmOut: %ld, mutationsMax: %zu, threadsMax: %zu, fileExtn: '%s', "
Anestis Bechtsoudisecab7762016-12-27 18:27:30 +0200584 "memoryLimit: 0x%" PRIx64 "(MiB), fuzzExe: '%s', fuzzedPid: %d, monitorSIGABRT: '%s'",
Robert Swieckiaa87aae2017-02-09 03:04:51 +0100585 (int)getpid(), hfuzz->inputDir,
Robert Swieckia88f96f2015-10-09 16:47:39 +0200586 cmdlineYesNo(hfuzz->nullifyStdio), cmdlineYesNo(hfuzz->fuzzStdin),
Robert Swieckia96d78d2016-03-14 16:50:50 +0100587 cmdlineYesNo(hfuzz->saveUnique), hfuzz->origFlipRate,
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200588 hfuzz->externalCommand == NULL ? "NULL" : hfuzz->externalCommand, (int)hfuzz->runEndTime,
589 hfuzz->tmOut, hfuzz->mutationsMax, hfuzz->threadsMax, hfuzz->fileExtn, hfuzz->asLimit,
590 hfuzz->cmdline[0], hfuzz->linux.pid, cmdlineYesNo(hfuzz->monitorSIGABRT));
Robert Swieckia88f96f2015-10-09 16:47:39 +0200591
Robert Swiecki2aaa52b2016-01-19 14:40:47 +0100592 snprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), "%s", hfuzz->cmdline[0]);
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100593 for (size_t i = 1; hfuzz->cmdline[i]; i++) {
594 util_ssnprintf(hfuzz->cmdline_txt, sizeof(hfuzz->cmdline_txt), " %s", hfuzz->cmdline[i]);
Robert Swieckif2d9c3a2016-11-03 02:13:54 +0100595 if (strlen(hfuzz->cmdline_txt) == (sizeof(hfuzz->cmdline_txt) - 1)) {
596 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 3] = '.';
597 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 2] = '.';
598 hfuzz->cmdline_txt[sizeof(hfuzz->cmdline_txt) - 1] = '.';
599 }
Robert Swiecki72d2bef2016-01-19 14:39:26 +0100600 }
601
Robert Swieckia88f96f2015-10-09 16:47:39 +0200602 return true;
603}