blob: ab870bab47053ad1548b0e3a8b7ae2b7d613932f [file] [log] [blame]
robert.swiecki3bb518c2010-10-14 00:48:24 +00001/*
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00002 *
robert.swiecki@gmail.com90e99112015-02-15 02:05:14 +00003 * honggfuzz - the main file
4 * -----------------------------------------
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00005 *
robert.swiecki@gmail.com8531f692015-02-17 12:25:36 +00006 * Author:
7 * Robert Swiecki <swiecki@google.com>
8 * Felix Gröbert <groebert@google.com>
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +00009 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000010 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000011 *
12 * Licensed under the Apache License, Version 2.0 (the "License"); you may
13 * not use this file except in compliance with the License. You may obtain
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000014 * a copy of the License at
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000015 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000016 * http://www.apache.org/licenses/LICENSE-2.0
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000017 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000018 * Unless required by applicable law or agreed to in writing, software
19 * distributed under the License is distributed on an "AS IS" BASIS,
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
21 * implied. See the License for the specific language governing
22 * permissions and limitations under the License.
robert.swiecki@gmail.com3b630b42015-02-16 10:53:53 +000023 *
robert.swiecki@gmail.com772b33d2015-02-14 20:35:00 +000024 */
robert.swiecki3bb518c2010-10-14 00:48:24 +000025
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000026#include <getopt.h>
Robert Swieckid0fa62c2017-09-28 18:11:05 +020027#include <inttypes.h>
Jagger08816fd2016-03-11 01:32:38 +010028#include <signal.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000029#include <stdio.h>
30#include <stdlib.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000031#include <string.h>
Robert Swiecki10eeb0a2017-09-28 15:42:52 +020032#include <sys/mman.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000033#include <time.h>
34#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000035
Robert Swieckic8c32db2015-10-09 18:06:22 +020036#include "cmdline.h"
Robert Swieckia375f4b2017-06-01 13:20:54 +020037#include "display.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000038#include "fuzz.h"
Robert Swiecki10eeb0a2017-09-28 15:42:52 +020039#include "input.h"
Robert Swieckid0fa62c2017-09-28 18:11:05 +020040#include "libcommon/common.h"
41#include "libcommon/files.h"
42#include "libcommon/log.h"
43#include "libcommon/util.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000044
Jagger08816fd2016-03-11 01:32:38 +010045static int sigReceived = 0;
46
Robert Swieckic6a48b12016-03-11 17:41:57 +010047/*
48 * CygWin/MinGW incorrectly copies stack during fork(), so we need to keep some
49 * structures in the data section
50 */
51honggfuzz_t hfuzz;
Robert Swieckic6a48b12016-03-11 17:41:57 +010052
Robert Swiecki35978ac2017-11-16 18:00:53 +010053static void exitWithMsg(const char* msg, int exit_code) {
Robert Swiecki3edbe822017-11-16 22:40:32 +010054 UNUSED ssize_t sz = write(STDERR_FILENO, msg, strlen(msg));
Robert Swiecki35978ac2017-11-16 18:00:53 +010055 exit(exit_code);
56 abort();
57}
58
Robert Swieckid50ed422017-11-13 23:32:26 +010059void sigHandler(int sig) {
Robert Swiecki1c9d8092017-06-01 02:39:09 +020060 /* We should not terminate upon SIGALRM delivery */
61 if (sig == SIGALRM) {
Robert Swiecki0dde76d2017-11-16 19:25:44 +010062 if (fuzz_shouldTerminate()) {
63 exitWithMsg("Terminating forcefully\n", EXIT_FAILURE);
Robert Swiecki35978ac2017-11-16 18:00:53 +010064 }
Jagger08816fd2016-03-11 01:32:38 +010065 return;
66 }
67
Robert Swiecki8d01b012017-02-19 15:48:11 +010068 if (ATOMIC_GET(sigReceived) != 0) {
Robert Swiecki35978ac2017-11-16 18:00:53 +010069 exitWithMsg("Repeated termination signal caugth\n", EXIT_FAILURE);
Robert Swiecki8d01b012017-02-19 15:48:11 +010070 }
71
72 ATOMIC_SET(sigReceived, sig);
Jagger08816fd2016-03-11 01:32:38 +010073}
74
Robert Swieckid50ed422017-11-13 23:32:26 +010075static void setupTimer(void) {
Jagger08816fd2016-03-11 01:32:38 +010076 struct itimerval it = {
Robert Swieckid50ed422017-11-13 23:32:26 +010077 .it_value = {.tv_sec = 1, .tv_usec = 0},
78 .it_interval = {.tv_sec = 1, .tv_usec = 0},
Jagger08816fd2016-03-11 01:32:38 +010079 };
80 if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
81 PLOG_F("setitimer(ITIMER_REAL)");
82 }
83}
84
Robert Swieckid50ed422017-11-13 23:32:26 +010085static void setupSignalsPreThr(void) {
Jaggerfbd4ae12016-09-02 02:26:02 +020086 /* Block signals which should be handled or blocked in the main thread */
Jagger33cce5d2016-04-16 20:10:36 +020087 sigset_t ss;
Jagger090de222016-04-16 20:05:13 +020088 sigemptyset(&ss);
Jagger08816fd2016-03-11 01:32:38 +010089 sigaddset(&ss, SIGTERM);
90 sigaddset(&ss, SIGINT);
91 sigaddset(&ss, SIGQUIT);
Jagger33cce5d2016-04-16 20:10:36 +020092 sigaddset(&ss, SIGALRM);
Jaggerac75f262016-08-20 12:38:20 +020093 sigaddset(&ss, SIGPIPE);
Jaggerfbd4ae12016-09-02 02:26:02 +020094 sigaddset(&ss, SIGIO);
Robert Swiecki746eaf02017-03-01 23:49:48 +010095 sigaddset(&ss, SIGCHLD);
Jagger08816fd2016-03-11 01:32:38 +010096 if (sigprocmask(SIG_BLOCK, &ss, NULL) != 0) {
97 PLOG_F("pthread_sigmask(SIG_BLOCK)");
98 }
Jagger848c4fc2016-03-11 01:34:53 +010099}
Jagger08816fd2016-03-11 01:32:38 +0100100
Robert Swieckid50ed422017-11-13 23:32:26 +0100101static void setupSignalsPostThr(void) {
Jagger08816fd2016-03-11 01:32:38 +0100102 struct sigaction sa = {
103 .sa_handler = sigHandler,
104 .sa_flags = 0,
105 };
106 sigemptyset(&sa.sa_mask);
107 if (sigaction(SIGTERM, &sa, NULL) == -1) {
108 PLOG_F("sigaction(SIGTERM) failed");
109 }
110 if (sigaction(SIGINT, &sa, NULL) == -1) {
111 PLOG_F("sigaction(SIGINT) failed");
112 }
113 if (sigaction(SIGQUIT, &sa, NULL) == -1) {
114 PLOG_F("sigaction(SIGQUIT) failed");
115 }
Jagger33cce5d2016-04-16 20:10:36 +0200116 if (sigaction(SIGALRM, &sa, NULL) == -1) {
117 PLOG_F("sigaction(SIGQUIT) failed");
118 }
Jagger08816fd2016-03-11 01:32:38 +0100119 /* Unblock signals which should be handled by the main thread */
120 sigset_t ss;
121 sigemptyset(&ss);
122 sigaddset(&ss, SIGTERM);
123 sigaddset(&ss, SIGINT);
124 sigaddset(&ss, SIGQUIT);
Jagger3846dfc2016-04-16 20:06:16 +0200125 sigaddset(&ss, SIGALRM);
Jagger08816fd2016-03-11 01:32:38 +0100126 if (sigprocmask(SIG_UNBLOCK, &ss, NULL) != 0) {
Jagger33cce5d2016-04-16 20:10:36 +0200127 PLOG_F("pthread_sigmask(SIG_UNBLOCK)");
Jagger08816fd2016-03-11 01:32:38 +0100128 }
129}
130
Robert Swieckid50ed422017-11-13 23:32:26 +0100131int main(int argc, char** argv) {
Robert Swieckic6a48b12016-03-11 17:41:57 +0100132 /*
133 * Work around CygWin/MinGW
134 */
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200135 char** myargs = (char**)util_Malloc(sizeof(char*) * (argc + 1));
Robert Swiecki0b566112017-10-17 17:39:07 +0200136 defer { free(myargs); };
Jagger1ebc6dc2016-03-12 01:39:09 +0100137
138 int i;
139 for (i = 0U; i < argc; i++) {
Robert Swieckic6a48b12016-03-11 17:41:57 +0100140 myargs[i] = argv[i];
141 }
142 myargs[i] = NULL;
143
144 if (cmdlineParse(argc, myargs, &hfuzz) == false) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200145 LOG_F("Parsing of the cmd-line arguments failed");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000146 }
147
Robert Swiecki1f1ce172017-02-10 03:43:00 +0100148 if (hfuzz.useScreen) {
149 display_init();
150 }
151
Robert Swiecki10eeb0a2017-09-28 15:42:52 +0200152 if (!input_init(&hfuzz)) {
Robert Swieckic1deec82017-04-27 02:42:12 +0200153 if (hfuzz.externalCommand) {
Robert Swieckid50ed422017-11-13 23:32:26 +0100154 LOG_I(
155 "No input file corpus loaded, the external command '%s' is responsible for "
156 "creating the fuzz files",
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200157 hfuzz.externalCommand);
Robert Swieckic1deec82017-04-27 02:42:12 +0200158 } else {
159 LOG_F("Couldn't load input files");
160 exit(EXIT_FAILURE);
161 }
robert.swiecki3bb518c2010-10-14 00:48:24 +0000162 }
163
Robert Swiecki10eeb0a2017-09-28 15:42:52 +0200164 if (hfuzz.dictionaryFile && (input_parseDictionary(&hfuzz) == false)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200165 LOG_F("Couldn't parse dictionary file ('%s')", hfuzz.dictionaryFile);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000166 }
167
Robert Swiecki10eeb0a2017-09-28 15:42:52 +0200168 if (hfuzz.blacklistFile && (input_parseBlacklist(&hfuzz) == false)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200169 LOG_F("Couldn't parse stackhash blacklist file ('%s')", hfuzz.blacklistFile);
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300170 }
Anestis Bechtsoudis00be1892016-10-31 09:29:44 +0200171#define hfuzzl hfuzz.linux
Robert Swieckid50ed422017-11-13 23:32:26 +0100172 if (hfuzzl.symsBlFile &&
173 ((hfuzzl.symsBlCnt = files_parseSymbolFilter(hfuzzl.symsBlFile, &hfuzzl.symsBl)) == 0)) {
Anestis Bechtsoudis3dce6ac2016-10-31 08:51:14 +0200174 LOG_F("Couldn't parse symbols blacklist file ('%s')", hfuzzl.symsBlFile);
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300175 }
176
Robert Swieckid50ed422017-11-13 23:32:26 +0100177 if (hfuzzl.symsWlFile &&
178 ((hfuzzl.symsWlCnt = files_parseSymbolFilter(hfuzzl.symsWlFile, &hfuzzl.symsWl)) == 0)) {
Anestis Bechtsoudis3dce6ac2016-10-31 08:51:14 +0200179 LOG_F("Couldn't parse symbols whitelist file ('%s')", hfuzzl.symsWlFile);
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300180 }
Anestis Bechtsoudis00be1892016-10-31 09:29:44 +0200181
Robert Swieckie4d63d42016-11-01 00:40:51 +0100182 if (hfuzz.dynFileMethod != _HF_DYNFILE_NONE) {
Robert Swiecki82c707c2017-11-14 16:36:23 +0100183 hfuzz.feedback = files_mapSharedMem(sizeof(feedback_t), &hfuzz.bbFd, hfuzz.io.workDir);
Robert Swieckie4d63d42016-11-01 00:40:51 +0100184 if (hfuzz.feedback == MAP_FAILED) {
Robert Swiecki82c707c2017-11-14 16:36:23 +0100185 LOG_F("files_mapSharedMem(sz=%zu, dir='%s') failed", sizeof(feedback_t),
186 hfuzz.io.workDir);
Robert Swieckie4d63d42016-11-01 00:40:51 +0100187 }
188 }
189
robert.swiecki3bb518c2010-10-14 00:48:24 +0000190 /*
Robert Swiecki3c01a0c2017-03-15 02:31:26 +0100191 * So far, so good
robert.swiecki3bb518c2010-10-14 00:48:24 +0000192 */
Robert Swiecki66b65122017-11-11 02:55:55 +0100193 pthread_t threads[hfuzz.threads.threadsMax];
Robert Swiecki33fb2842017-02-19 05:39:50 +0100194
Robert Swiecki37778e02016-03-15 15:45:28 +0100195 setupSignalsPreThr();
Robert Swiecki33fb2842017-02-19 05:39:50 +0100196 fuzz_threadsStart(&hfuzz, threads);
Jagger08816fd2016-03-11 01:32:38 +0100197 setupSignalsPostThr();
robert.swiecki3bb518c2010-10-14 00:48:24 +0000198
Robert Swiecki37778e02016-03-15 15:45:28 +0100199 setupTimer();
Jagger08816fd2016-03-11 01:32:38 +0100200 for (;;) {
201 if (hfuzz.useScreen) {
202 display_display(&hfuzz);
203 }
Robert Swiecki8d01b012017-02-19 15:48:11 +0100204 if (ATOMIC_GET(sigReceived) > 0) {
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200205 LOG_I("Signal %d (%s) received, terminating", ATOMIC_GET(sigReceived),
Robert Swiecki4e595fb2017-10-11 17:26:51 +0200206 strsignal(ATOMIC_GET(sigReceived)));
Jagger08816fd2016-03-11 01:32:38 +0100207 break;
208 }
Robert Swiecki66b65122017-11-11 02:55:55 +0100209 if (ATOMIC_GET(hfuzz.threads.threadsFinished) >= hfuzz.threads.threadsMax) {
Jagger08816fd2016-03-11 01:32:38 +0100210 break;
211 }
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200212 if (hfuzz.runEndTime > 0 && (time(NULL) > hfuzz.runEndTime)) {
213 LOG_I("Maximum run time reached, terminating");
Robert Swiecki0dde76d2017-11-16 19:25:44 +0100214 fuzz_setTerminating();
Robert Swieckic95cf2a2017-06-23 15:31:08 +0200215 break;
216 }
Jagger08816fd2016-03-11 01:32:38 +0100217 pause();
218 }
219
Robert Swiecki0dde76d2017-11-16 19:25:44 +0100220 fuzz_setTerminating();
Jagger08816fd2016-03-11 01:32:38 +0100221
Robert Swiecki33fb2842017-02-19 05:39:50 +0100222 fuzz_threadsStop(&hfuzz, threads);
223
Jagger08816fd2016-03-11 01:32:38 +0100224 /* Clean-up global buffers */
Jagger08816fd2016-03-11 01:32:38 +0100225 if (hfuzz.blacklist) {
226 free(hfuzz.blacklist);
227 }
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300228 if (hfuzz.linux.symsBl) {
229 free(hfuzz.linux.symsBl);
230 }
231 if (hfuzz.linux.symsWl) {
232 free(hfuzz.linux.symsWl);
233 }
Jagger08816fd2016-03-11 01:32:38 +0100234 if (hfuzz.sanOpts.asanOpts) {
235 free(hfuzz.sanOpts.asanOpts);
236 }
237 if (hfuzz.sanOpts.ubsanOpts) {
238 free(hfuzz.sanOpts.ubsanOpts);
239 }
240 if (hfuzz.sanOpts.msanOpts) {
241 free(hfuzz.sanOpts.msanOpts);
242 }
Jagger08816fd2016-03-11 01:32:38 +0100243
Robert Swiecki37778e02016-03-15 15:45:28 +0100244 return EXIT_SUCCESS;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000245}