1 /*
2  *
3  * honggfuzz - core structures and macros
4  * -----------------------------------------
5  *
6  * Author: Robert Swiecki <swiecki@google.com>
7  *
8  * Copyright 2010-2018 by Google Inc. All Rights Reserved.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License"); you may
11  * not use this file except in compliance with the License. You may obtain
12  * a copy of the License at
13  *
14  * http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
19  * implied. See the License for the specific language governing
20  * permissions and limitations under the License.
21  *
22  */
23 
24 #ifndef _HF_HONGGFUZZ_H_
25 #define _HF_HONGGFUZZ_H_
26 
27 #include <dirent.h>
28 #include <inttypes.h>
29 #include <limits.h>
30 #include <pthread.h>
31 #include <signal.h>
32 #include <stdbool.h>
33 #include <stdint.h>
34 #include <sys/param.h>
35 #include <sys/queue.h>
36 #include <sys/types.h>
37 #include <time.h>
38 
39 #include "libhfcommon/util.h"
40 
41 #define PROG_NAME    "honggfuzz"
42 #define PROG_VERSION "2.4"
43 
44 /* Name of the template which will be replaced with the proper name of the file */
45 #define _HF_FILE_PLACEHOLDER "___FILE___"
46 
47 /* Default name of the report created with some architectures */
48 #define _HF_REPORT_FILE "HONGGFUZZ.REPORT.TXT"
49 
50 /* Default stack-size of created threads. */
51 #define _HF_PTHREAD_STACKSIZE (1024ULL * 1024ULL * 2ULL) /* 2MB */
52 
53 /* Name of envvar which indicates sequential number of fuzzer */
54 #define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO"
55 
56 /* Name of envvar which indicates that the netDriver should be used */
57 #define _HF_THREAD_NETDRIVER_ENV "HFUZZ_USE_NETDRIVER"
58 
59 /* Name of envvar which indicates honggfuzz's log level in use */
60 #define _HF_LOG_LEVEL_ENV "HFUZZ_LOG_LEVEL"
61 
62 /* Number of crash verifier iterations before tag crash as stable */
63 #define _HF_VERIFIER_ITER 5
64 
65 /* Size (in bytes) for report data to be stored in stack before written to file */
66 #define _HF_REPORT_SIZE 32768
67 
68 /* Perf bitmap size */
69 #define _HF_PERF_BITMAP_SIZE_16M   (1024U * 1024U * 16U)
70 #define _HF_PERF_BITMAP_BITSZ_MASK 0x7FFFFFFULL
71 /* Maximum number of PC guards (=trace-pc-guard) we support */
72 #define _HF_PC_GUARD_MAX (1024ULL * 1024ULL * 64ULL)
73 
74 /* Maximum size of the input file in bytes (1 MiB) */
75 #define _HF_INPUT_MAX_SIZE (1024ULL * 1024ULL)
76 
77 /* Default maximum size of produced inputs */
78 #define _HF_INPUT_DEFAULT_SIZE (1024ULL * 8)
79 
80 /* Per-thread bitmap */
81 #define _HF_PERTHREAD_BITMAP_FD 1018
82 /* FD used to report back used int/str constants from the fuzzed process */
83 #define _HF_CMP_BITMAP_FD 1019
84 /* FD used to log inside the child process */
85 #define _HF_LOG_FD 1020
86 /* FD used to represent the input file */
87 #define _HF_INPUT_FD 1021
88 /* FD used to pass coverage feedback from the fuzzed process */
89 #define _HF_COV_BITMAP_FD 1022
90 #define _HF_BITMAP_FD     _HF_COV_BITMAP_FD /* Old name for _HF_COV_BITMAP_FD */
91 /* FD used to pass data to a persistent process */
92 #define _HF_PERSISTENT_FD 1023
93 
94 /* Input file as a string */
95 #define _HF_INPUT_FILE_PATH "/dev/fd/" HF_XSTR(_HF_INPUT_FD)
96 
97 /* Maximum number of supported execve() args */
98 #define _HF_ARGS_MAX 2048
99 
100 /* Message indicating that the fuzzed process is ready for new data */
101 static const uint8_t HFReadyTag = 'R';
102 
103 /* Maximum number of active fuzzing threads */
104 #define _HF_THREAD_MAX 1024U
105 
106 /* Persistent-binary signature - if found within file, it means it's a persistent mode binary */
107 #define _HF_PERSISTENT_SIG "\x01_LIBHFUZZ_PERSISTENT_BINARY_SIGNATURE_\x02\xFF"
108 /* HF NetDriver signature - if found within file, it means it's a NetDriver-based binary */
109 #define _HF_NETDRIVER_SIG "\x01_LIBHFUZZ_NETDRIVER_BINARY_SIGNATURE_\x02\xFF"
110 
111 /* printf() nonmonetary separator. According to MacOSX's man it's supported there as well */
112 #define _HF_NONMON_SEP "'"
113 
114 typedef enum {
115     _HF_DYNFILE_NONE         = 0x0,
116     _HF_DYNFILE_INSTR_COUNT  = 0x1,
117     _HF_DYNFILE_BRANCH_COUNT = 0x2,
118     _HF_DYNFILE_BTS_EDGE     = 0x10,
119     _HF_DYNFILE_IPT_BLOCK    = 0x20,
120     _HF_DYNFILE_SOFT         = 0x40,
121 } dynFileMethod_t;
122 
123 typedef struct {
124     uint64_t cpuInstrCnt;
125     uint64_t cpuBranchCnt;
126     uint64_t bbCnt;
127     uint64_t newBBCnt;
128     uint64_t softCntPc;
129     uint64_t softCntEdge;
130     uint64_t softCntCmp;
131 } hwcnt_t;
132 
133 typedef enum {
134     _HF_STATE_UNSET = 0,
135     _HF_STATE_STATIC,
136     _HF_STATE_DYNAMIC_DRY_RUN,
137     _HF_STATE_DYNAMIC_MAIN,
138     _HF_STATE_DYNAMIC_MINIMIZE,
139 } fuzzState_t;
140 
141 typedef enum {
142     HF_MAYBE = -1,
143     HF_NO    = 0,
144     HF_YES   = 1,
145 } tristate_t;
146 
147 struct _dynfile_t {
148     size_t             size;
149     uint64_t           cov[4];
150     size_t             idx;
151     int                fd;
152     uint64_t           timeExecUSecs;
153     char               path[PATH_MAX];
154     struct _dynfile_t* src;
155     uint32_t           refs;
156     uint8_t*           data;
157     TAILQ_ENTRY(_dynfile_t) pointers;
158 };
159 
160 typedef struct _dynfile_t dynfile_t;
161 
162 struct strings_t {
163     size_t len;
164     TAILQ_ENTRY(strings_t) pointers;
165     char s[];
166 };
167 
168 typedef struct {
169     uint8_t  pcGuardMap[_HF_PC_GUARD_MAX];
170     uint8_t  bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
171     uint32_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
172     uint64_t pidNewPC[_HF_THREAD_MAX];
173     uint64_t pidNewEdge[_HF_THREAD_MAX];
174     uint64_t pidNewCmp[_HF_THREAD_MAX];
175     uint64_t guardNb;
176     uint64_t pidTotalPC[_HF_THREAD_MAX];
177     uint64_t pidTotalEdge[_HF_THREAD_MAX];
178     uint64_t pidTotalCmp[_HF_THREAD_MAX];
179 } feedback_t;
180 
181 typedef struct {
182     uint32_t cnt;
183     struct {
184         uint8_t  val[32];
185         uint32_t len;
186     } valArr[1024 * 16];
187 } cmpfeedback_t;
188 
189 typedef struct {
190     struct {
191         size_t    threadsMax;
192         size_t    threadsFinished;
193         uint32_t  threadsActiveCnt;
194         pthread_t mainThread;
195         pid_t     mainPid;
196         pthread_t threads[_HF_THREAD_MAX];
197     } threads;
198     struct {
199         const char* inputDir;
200         const char* outputDir;
201         DIR*        inputDirPtr;
202         size_t      fileCnt;
203         size_t      testedFileCnt;
204         const char* fileExtn;
205         size_t      maxFileSz;
206         size_t      newUnitsAdded;
207         char        workDir[PATH_MAX];
208         const char* crashDir;
209         const char* covDirNew;
210         bool        saveUnique;
211         bool        saveSmaller;
212         size_t      dynfileqMaxSz;
213         size_t      dynfileqCnt;
214         dynfile_t*  dynfileqCurrent;
215         dynfile_t*  dynfileq2Current;
216         TAILQ_HEAD(dyns_t, _dynfile_t) dynfileq;
217         bool exportFeedback;
218     } io;
219     struct {
220         int                argc;
221         const char* const* cmdline;
222         bool               nullifyStdio;
223         bool               fuzzStdin;
224         const char*        externalCommand;
225         const char*        postExternalCommand;
226         const char*        feedbackMutateCommand;
227         bool               netDriver;
228         bool               persistent;
229         uint64_t           asLimit;
230         uint64_t           rssLimit;
231         uint64_t           dataLimit;
232         uint64_t           coreLimit;
233         uint64_t           stackLimit;
234         bool               clearEnv;
235         char*              env_ptrs[128];
236         char               env_vals[128][4096];
237         sigset_t           waitSigSet;
238     } exe;
239     struct {
240         time_t  timeStart;
241         time_t  runEndTime;
242         time_t  tmOut;
243         time_t  lastCovUpdate;
244         int64_t timeOfLongestUnitUSecs;
245         bool    tmoutVTALRM;
246     } timing;
247     struct {
248         struct {
249             uint8_t val[512];
250             size_t  len;
251         } dictionary[8192];
252         size_t      dictionaryCnt;
253         const char* dictionaryFile;
254         size_t      mutationsMax;
255         unsigned    mutationsPerRun;
256         size_t      maxInputSz;
257     } mutate;
258     struct {
259         bool    useScreen;
260         char    cmdline_txt[65];
261         int64_t lastDisplayUSecs;
262     } display;
263     struct {
264         bool        useVerifier;
265         bool        exitUponCrash;
266         uint8_t     exitCodeUponCrash;
267         const char* reportFile;
268         size_t      dynFileIterExpire;
269         bool        only_printable;
270         bool        minimize;
271         bool        switchingToFDM;
272     } cfg;
273     struct {
274         bool enable;
275         bool del_report;
276     } sanitizer;
277     struct {
278         fuzzState_t     state;
279         feedback_t*     covFeedbackMap;
280         int             covFeedbackFd;
281         cmpfeedback_t*  cmpFeedbackMap;
282         int             cmpFeedbackFd;
283         bool            cmpFeedback;
284         const char*     blocklistFile;
285         uint64_t*       blocklist;
286         size_t          blocklistCnt;
287         bool            skipFeedbackOnTimeout;
288         uint64_t        maxCov[4];
289         dynFileMethod_t dynFileMethod;
290         hwcnt_t         hwCnts;
291     } feedback;
292     struct {
293         size_t mutationsCnt;
294         size_t crashesCnt;
295         size_t uniqueCrashesCnt;
296         size_t verifiedCrashesCnt;
297         size_t blCrashesCnt;
298         size_t timeoutedCnt;
299     } cnts;
300     struct {
301         bool enabled;
302         int  serverSocket;
303         int  clientSocket;
304     } socketFuzzer;
305     struct {
306         pthread_rwlock_t dynfileq;
307         pthread_mutex_t  feedback;
308         pthread_mutex_t  report;
309         pthread_mutex_t  state;
310         pthread_mutex_t  input;
311         pthread_mutex_t  timing;
312     } mutex;
313 
314     /* For the Linux code */
315     struct {
316         int         exeFd;
317         uint64_t    dynamicCutOffAddr;
318         bool        disableRandomization;
319         void*       ignoreAddr;
320         const char* symsBlFile;
321         char**      symsBl;
322         size_t      symsBlCnt;
323         const char* symsWlFile;
324         char**      symsWl;
325         size_t      symsWlCnt;
326         uintptr_t   cloneFlags;
327         tristate_t  useNetNs;
328         bool        kernelOnly;
329         bool        useClone;
330     } arch_linux;
331     /* For the NetBSD code */
332     struct {
333         void*       ignoreAddr;
334         const char* symsBlFile;
335         char**      symsBl;
336         size_t      symsBlCnt;
337         const char* symsWlFile;
338         char**      symsWl;
339         size_t      symsWlCnt;
340     } arch_netbsd;
341 } honggfuzz_t;
342 
343 typedef enum {
344     _HF_RS_UNKNOWN                   = 0,
345     _HF_RS_WAITING_FOR_INITIAL_READY = 1,
346     _HF_RS_WAITING_FOR_READY         = 2,
347     _HF_RS_SEND_DATA                 = 3,
348 } runState_t;
349 
350 typedef struct {
351     honggfuzz_t* global;
352     pid_t        pid;
353     int64_t      timeStartedUSecs;
354     char         crashFileName[PATH_MAX];
355     uint64_t     pc;
356     uint64_t     backtrace;
357     uint64_t     access;
358     int          exception;
359     char         report[_HF_REPORT_SIZE];
360     bool         mainWorker;
361     unsigned     mutationsPerRun;
362     dynfile_t*   dynfile;
363     bool         staticFileTryMore;
364     uint32_t     fuzzNo;
365     int          persistentSock;
366     runState_t   runState;
367     bool         tmOutSignaled;
368     char*        args[_HF_ARGS_MAX + 1];
369     int          perThreadCovFeedbackFd;
370     unsigned     triesLeft;
371     dynfile_t*   current;
372 #if !defined(_HF_ARCH_DARWIN)
373     timer_t timerId;
374 #endif    // !defined(_HF_ARCH_DARWIN)
375     hwcnt_t hwCnts;
376 
377     struct {
378         /* For Linux code */
379         uint8_t* perfMmapBuf;
380         uint8_t* perfMmapAux;
381         int      cpuInstrFd;
382         int      cpuBranchFd;
383         int      cpuIptBtsFd;
384     } arch_linux;
385 } run_t;
386 
387 #endif
388