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