1 /*
2 *
3 * honggfuzz - the main file
4 * -----------------------------------------
5 *
6 * Author:
7 * Robert Swiecki <swiecki@google.com>
8 * Felix Gröbert <groebert@google.com>
9 *
10 * Copyright 2010-2015 by Google Inc. All Rights Reserved.
11 *
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
14 * a copy of the License at
15 *
16 * http://www.apache.org/licenses/LICENSE-2.0
17 *
18 * 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.
23 *
24 */
25
26 #include <inttypes.h>
27 #include <getopt.h>
28 #include <signal.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <time.h>
33 #include <unistd.h>
34
35 #include "common.h"
36 #include "cmdline.h"
37 #include "display.h"
38 #include "log.h"
39 #include "files.h"
40 #include "fuzz.h"
41 #include "util.h"
42
43 static int sigReceived = 0;
44
45 /*
46 * CygWin/MinGW incorrectly copies stack during fork(), so we need to keep some
47 * structures in the data section
48 */
49 honggfuzz_t hfuzz;
50
sigHandler(int sig)51 void sigHandler(int sig)
52 {
53 /* We should not terminate upon SIGALRM delivery */
54 if (sig == SIGALRM) {
55 return;
56 }
57
58 sigReceived = sig;
59 }
60
setupTimer(void)61 static void setupTimer(void)
62 {
63 struct itimerval it = {
64 .it_value = {.tv_sec = 1,.tv_usec = 0},
65 .it_interval = {.tv_sec = 1,.tv_usec = 0},
66 };
67 if (setitimer(ITIMER_REAL, &it, NULL) == -1) {
68 PLOG_F("setitimer(ITIMER_REAL)");
69 }
70 }
71
setupSignalsPreThr(void)72 static void setupSignalsPreThr(void)
73 {
74 /* Block signals which should be handled by the main thread */
75 sigset_t ss;
76 sigemptyset(&ss);
77 sigaddset(&ss, SIGTERM);
78 sigaddset(&ss, SIGINT);
79 sigaddset(&ss, SIGQUIT);
80 sigaddset(&ss, SIGALRM);
81 if (sigprocmask(SIG_BLOCK, &ss, NULL) != 0) {
82 PLOG_F("pthread_sigmask(SIG_BLOCK)");
83 }
84 }
85
setupSignalsPostThr(void)86 static void setupSignalsPostThr(void)
87 {
88 struct sigaction sa = {
89 .sa_handler = sigHandler,
90 .sa_flags = 0,
91 };
92 sigemptyset(&sa.sa_mask);
93 if (sigaction(SIGTERM, &sa, NULL) == -1) {
94 PLOG_F("sigaction(SIGTERM) failed");
95 }
96 if (sigaction(SIGINT, &sa, NULL) == -1) {
97 PLOG_F("sigaction(SIGINT) failed");
98 }
99 if (sigaction(SIGQUIT, &sa, NULL) == -1) {
100 PLOG_F("sigaction(SIGQUIT) failed");
101 }
102 if (sigaction(SIGALRM, &sa, NULL) == -1) {
103 PLOG_F("sigaction(SIGALRM) failed");
104 }
105 /* Unblock signals which should be handled by the main thread */
106 sigset_t ss;
107 sigemptyset(&ss);
108 sigaddset(&ss, SIGTERM);
109 sigaddset(&ss, SIGINT);
110 sigaddset(&ss, SIGQUIT);
111 sigaddset(&ss, SIGALRM);
112 if (sigprocmask(SIG_UNBLOCK, &ss, NULL) != 0) {
113 PLOG_F("pthread_sigmask(SIG_BLOCK)");
114 }
115 }
116
main(int argc,char ** argv)117 int main(int argc, char **argv)
118 {
119 /*
120 * Work around CygWin/MinGW
121 */
122 char **myargs = (char **)util_Malloc(sizeof(char *) * (argc + 1));
123
124 int i;
125 for (i = 0U; i < argc; i++) {
126 myargs[i] = argv[i];
127 }
128 myargs[i] = NULL;
129
130 if (cmdlineParse(argc, myargs, &hfuzz) == false) {
131 LOG_F("Parsing of the cmd-line arguments failed");
132 }
133
134 if (!files_init(&hfuzz)) {
135 LOG_F("Couldn't load input files");
136 exit(EXIT_FAILURE);
137 }
138
139 if (hfuzz.dictionaryFile && (files_parseDictionary(&hfuzz) == false)) {
140 LOG_F("Couldn't parse dictionary file ('%s')", hfuzz.dictionaryFile);
141 }
142
143 if (hfuzz.blacklistFile && (files_parseBlacklist(&hfuzz) == false)) {
144 LOG_F("Couldn't parse stackhash blacklist file ('%s')", hfuzz.blacklistFile);
145 }
146
147 /*
148 * So far so good
149 */
150 setupSignalsPreThr();
151 fuzz_threads(&hfuzz);
152 setupSignalsPostThr();
153
154 setupTimer();
155 for (;;) {
156 if (hfuzz.useScreen) {
157 display_display(&hfuzz);
158 }
159 if (sigReceived > 0) {
160 break;
161 }
162 if (__sync_fetch_and_add(&hfuzz.threadsFinished, 0UL) >= hfuzz.threadsMax) {
163 break;
164 }
165 pause();
166 }
167
168 if (sigReceived > 0) {
169 LOG_I("Signal %d (%s) received, terminating", sigReceived, strsignal(sigReceived));
170 }
171
172 /* Clean-up global buffers */
173 free(hfuzz.files);
174 if (hfuzz.dictionary) {
175 for (size_t i = 0; i < hfuzz.dictionaryCnt; i++) {
176 free(hfuzz.dictionary[i]);
177 }
178 free(hfuzz.dictionary);
179 }
180 if (hfuzz.blacklist) {
181 free(hfuzz.blacklist);
182 }
183 if (hfuzz.sanOpts.asanOpts) {
184 free(hfuzz.sanOpts.asanOpts);
185 }
186 if (hfuzz.sanOpts.ubsanOpts) {
187 free(hfuzz.sanOpts.ubsanOpts);
188 }
189 if (hfuzz.sanOpts.msanOpts) {
190 free(hfuzz.sanOpts.msanOpts);
191 }
192 if (hfuzz.pidCmd) {
193 free(hfuzz.pidCmd);
194 }
195
196 return EXIT_SUCCESS;
197 }
198