blob: fe90af27924847e1de7d3e183305aeab177de04d [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 Swieckic8c32db2015-10-09 18:06:22 +020026#include <inttypes.h>
robert.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000027#include <getopt.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.swiecki@gmail.comba85c3e2015-02-02 14:55:16 +000032#include <time.h>
33#include <unistd.h>
robert.swiecki3bb518c2010-10-14 00:48:24 +000034
35#include "common.h"
Robert Swieckic8c32db2015-10-09 18:06:22 +020036#include "cmdline.h"
Jagger08816fd2016-03-11 01:32:38 +010037#include "display.h"
robert.swiecki3bb518c2010-10-14 00:48:24 +000038#include "log.h"
39#include "files.h"
40#include "fuzz.h"
41#include "util.h"
42
Jagger08816fd2016-03-11 01:32:38 +010043static int sigReceived = 0;
44
Robert Swieckic6a48b12016-03-11 17:41:57 +010045/*
46 * CygWin/MinGW incorrectly copies stack during fork(), so we need to keep some
47 * structures in the data section
48 */
49honggfuzz_t hfuzz;
Robert Swieckic6a48b12016-03-11 17:41:57 +010050
Jagger08816fd2016-03-11 01:32:38 +010051void sigHandler(int sig)
52{
53 /* We should not terminate upon SIGALRM delivery */
54 if (sig == SIGALRM) {
55 return;
56 }
57
Robert Swiecki8d01b012017-02-19 15:48:11 +010058 if (ATOMIC_GET(sigReceived) != 0) {
59 static const char *const sigMsg = "Repeated termination signal caugth\n";
60 if (write(STDERR_FILENO, sigMsg, strlen(sigMsg) + 1) == -1) {
61 };
62 _exit(EXIT_FAILURE);
63 }
64
65 ATOMIC_SET(sigReceived, sig);
Jagger08816fd2016-03-11 01:32:38 +010066}
67
68static void setupTimer(void)
69{
70 struct itimerval it = {
Robert Swiecki37778e02016-03-15 15:45:28 +010071 .it_value = {.tv_sec = 1,.tv_usec = 0},
Robert Swiecki05783bb2016-07-26 15:43:48 +020072 .it_interval = {.tv_sec = 1,.tv_usec = 0},
Jagger08816fd2016-03-11 01:32:38 +010073 };
74 if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
75 PLOG_F("setitimer(ITIMER_REAL)");
76 }
77}
78
79static void setupSignalsPreThr(void)
80{
Jaggerfbd4ae12016-09-02 02:26:02 +020081 /* Block signals which should be handled or blocked in the main thread */
Jagger33cce5d2016-04-16 20:10:36 +020082 sigset_t ss;
Jagger090de222016-04-16 20:05:13 +020083 sigemptyset(&ss);
Jagger08816fd2016-03-11 01:32:38 +010084 sigaddset(&ss, SIGTERM);
85 sigaddset(&ss, SIGINT);
86 sigaddset(&ss, SIGQUIT);
Jagger33cce5d2016-04-16 20:10:36 +020087 sigaddset(&ss, SIGALRM);
Jaggerac75f262016-08-20 12:38:20 +020088 sigaddset(&ss, SIGPIPE);
Jaggerfbd4ae12016-09-02 02:26:02 +020089 sigaddset(&ss, SIGIO);
Robert Swiecki746eaf02017-03-01 23:49:48 +010090 sigaddset(&ss, SIGCHLD);
Jagger08816fd2016-03-11 01:32:38 +010091 if (sigprocmask(SIG_BLOCK, &ss, NULL) != 0) {
92 PLOG_F("pthread_sigmask(SIG_BLOCK)");
93 }
Jagger848c4fc2016-03-11 01:34:53 +010094}
Jagger08816fd2016-03-11 01:32:38 +010095
Jagger848c4fc2016-03-11 01:34:53 +010096static void setupSignalsPostThr(void)
97{
Jagger08816fd2016-03-11 01:32:38 +010098 struct sigaction sa = {
99 .sa_handler = sigHandler,
100 .sa_flags = 0,
101 };
102 sigemptyset(&sa.sa_mask);
103 if (sigaction(SIGTERM, &sa, NULL) == -1) {
104 PLOG_F("sigaction(SIGTERM) failed");
105 }
106 if (sigaction(SIGINT, &sa, NULL) == -1) {
107 PLOG_F("sigaction(SIGINT) failed");
108 }
109 if (sigaction(SIGQUIT, &sa, NULL) == -1) {
110 PLOG_F("sigaction(SIGQUIT) failed");
111 }
Jagger33cce5d2016-04-16 20:10:36 +0200112 if (sigaction(SIGALRM, &sa, NULL) == -1) {
113 PLOG_F("sigaction(SIGQUIT) failed");
114 }
Jagger08816fd2016-03-11 01:32:38 +0100115 /* Unblock signals which should be handled by the main thread */
116 sigset_t ss;
117 sigemptyset(&ss);
118 sigaddset(&ss, SIGTERM);
119 sigaddset(&ss, SIGINT);
120 sigaddset(&ss, SIGQUIT);
Jagger3846dfc2016-04-16 20:06:16 +0200121 sigaddset(&ss, SIGALRM);
Jagger08816fd2016-03-11 01:32:38 +0100122 if (sigprocmask(SIG_UNBLOCK, &ss, NULL) != 0) {
Jagger33cce5d2016-04-16 20:10:36 +0200123 PLOG_F("pthread_sigmask(SIG_UNBLOCK)");
Jagger08816fd2016-03-11 01:32:38 +0100124 }
125}
126
robert.swiecki3bb518c2010-10-14 00:48:24 +0000127int main(int argc, char **argv)
128{
Robert Swieckic6a48b12016-03-11 17:41:57 +0100129 /*
130 * Work around CygWin/MinGW
131 */
Robert Swiecki37778e02016-03-15 15:45:28 +0100132 char **myargs = (char **)util_Malloc(sizeof(char *) * (argc + 1));
Anestis Bechtsoudisa4198732016-04-27 12:27:39 +0300133 defer {
134 free(myargs);
135 };
Jagger1ebc6dc2016-03-12 01:39:09 +0100136
137 int i;
138 for (i = 0U; i < argc; i++) {
Robert Swieckic6a48b12016-03-11 17:41:57 +0100139 myargs[i] = argv[i];
140 }
141 myargs[i] = NULL;
142
143 if (cmdlineParse(argc, myargs, &hfuzz) == false) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200144 LOG_F("Parsing of the cmd-line arguments failed");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000145 }
146
Robert Swiecki1f1ce172017-02-10 03:43:00 +0100147 if (hfuzz.useScreen) {
148 display_init();
149 }
150
robert.swiecki3bb518c2010-10-14 00:48:24 +0000151 if (!files_init(&hfuzz)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200152 LOG_F("Couldn't load input files");
robert.swiecki3bb518c2010-10-14 00:48:24 +0000153 exit(EXIT_FAILURE);
154 }
155
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000156 if (hfuzz.dictionaryFile && (files_parseDictionary(&hfuzz) == false)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200157 LOG_F("Couldn't parse dictionary file ('%s')", hfuzz.dictionaryFile);
robert.swiecki@gmail.com4f1124f2015-04-21 17:12:22 +0000158 }
159
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300160 if (hfuzz.blacklistFile && (files_parseBlacklist(&hfuzz) == false)) {
Robert Swieckic8c32db2015-10-09 18:06:22 +0200161 LOG_F("Couldn't parse stackhash blacklist file ('%s')", hfuzz.blacklistFile);
Anestis Bechtsoudisd59af692015-09-21 15:15:05 +0300162 }
Anestis Bechtsoudis00be1892016-10-31 09:29:44 +0200163#define hfuzzl hfuzz.linux
Anestis Bechtsoudis3dce6ac2016-10-31 08:51:14 +0200164 if (hfuzzl.symsBlFile &&
165 ((hfuzzl.symsBlCnt = files_parseSymbolFilter(hfuzzl.symsBlFile, &hfuzzl.symsBl)) == 0)) {
166 LOG_F("Couldn't parse symbols blacklist file ('%s')", hfuzzl.symsBlFile);
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300167 }
168
Anestis Bechtsoudis3dce6ac2016-10-31 08:51:14 +0200169 if (hfuzzl.symsWlFile &&
170 ((hfuzzl.symsWlCnt = files_parseSymbolFilter(hfuzzl.symsWlFile, &hfuzzl.symsWl)) == 0)) {
171 LOG_F("Couldn't parse symbols whitelist file ('%s')", hfuzzl.symsWlFile);
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300172 }
Anestis Bechtsoudis00be1892016-10-31 09:29:44 +0200173
Robert Swieckie4d63d42016-11-01 00:40:51 +0100174 if (hfuzz.dynFileMethod != _HF_DYNFILE_NONE) {
175 hfuzz.feedback = files_mapSharedMem(sizeof(feedback_t), &hfuzz.bbFd, hfuzz.workDir);
176 if (hfuzz.feedback == MAP_FAILED) {
177 LOG_F("files_mapSharedMem(sz=%zu, dir='%s') failed", sizeof(feedback_t), hfuzz.workDir);
178 }
179 }
180
robert.swiecki3bb518c2010-10-14 00:48:24 +0000181 /*
182 * So far so good
183 */
Robert Swiecki33fb2842017-02-19 05:39:50 +0100184 pthread_t threads[hfuzz.threadsMax];
185
Robert Swiecki37778e02016-03-15 15:45:28 +0100186 setupSignalsPreThr();
Robert Swiecki33fb2842017-02-19 05:39:50 +0100187 fuzz_threadsStart(&hfuzz, threads);
Jagger08816fd2016-03-11 01:32:38 +0100188 setupSignalsPostThr();
robert.swiecki3bb518c2010-10-14 00:48:24 +0000189
Robert Swiecki37778e02016-03-15 15:45:28 +0100190 setupTimer();
Jagger08816fd2016-03-11 01:32:38 +0100191 for (;;) {
192 if (hfuzz.useScreen) {
193 display_display(&hfuzz);
194 }
Robert Swiecki8d01b012017-02-19 15:48:11 +0100195 if (ATOMIC_GET(sigReceived) > 0) {
Jagger08816fd2016-03-11 01:32:38 +0100196 break;
197 }
Jaggerd34417d2016-03-16 01:26:54 +0100198 if (ATOMIC_GET(hfuzz.threadsFinished) >= hfuzz.threadsMax) {
Jagger08816fd2016-03-11 01:32:38 +0100199 break;
200 }
201 pause();
202 }
203
Robert Swiecki98b10562017-02-09 23:58:13 +0100204 if (hfuzz.useScreen) {
Robert Swiecki1f1ce172017-02-10 03:43:00 +0100205 display_fini();
Robert Swiecki98b10562017-02-09 23:58:13 +0100206 }
207
Robert Swiecki8d01b012017-02-19 15:48:11 +0100208 if (ATOMIC_GET(sigReceived) > 0) {
209 LOG_I("Signal %d (%s) received, terminating", ATOMIC_GET(sigReceived),
210 strsignal(ATOMIC_GET(sigReceived)));
211 ATOMIC_SET(hfuzz.terminating, true);
Jagger08816fd2016-03-11 01:32:38 +0100212 }
213
Robert Swiecki33fb2842017-02-19 05:39:50 +0100214 fuzz_threadsStop(&hfuzz, threads);
215
Jagger08816fd2016-03-11 01:32:38 +0100216 /* Clean-up global buffers */
Jagger08816fd2016-03-11 01:32:38 +0100217 if (hfuzz.blacklist) {
218 free(hfuzz.blacklist);
219 }
Anestis Bechtsoudisba68b382016-10-29 20:44:15 +0300220 if (hfuzz.linux.symsBl) {
221 free(hfuzz.linux.symsBl);
222 }
223 if (hfuzz.linux.symsWl) {
224 free(hfuzz.linux.symsWl);
225 }
Jagger08816fd2016-03-11 01:32:38 +0100226 if (hfuzz.sanOpts.asanOpts) {
227 free(hfuzz.sanOpts.asanOpts);
228 }
229 if (hfuzz.sanOpts.ubsanOpts) {
230 free(hfuzz.sanOpts.ubsanOpts);
231 }
232 if (hfuzz.sanOpts.msanOpts) {
233 free(hfuzz.sanOpts.msanOpts);
234 }
Jagger247c3b42016-03-21 23:24:05 +0100235 if (hfuzz.linux.pidCmd) {
236 free(hfuzz.linux.pidCmd);
Jagger08816fd2016-03-11 01:32:38 +0100237 }
238
Robert Swiecki37778e02016-03-15 15:45:28 +0100239 return EXIT_SUCCESS;
robert.swiecki3bb518c2010-10-14 00:48:24 +0000240}