1 /*
2  *
3  * honggfuzz - core structures and macros
4  * -----------------------------------------
5  *
6  * Author: Robert Swiecki <swiecki@google.com>
7  *
8  * Copyright 2010-2017 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 <stdbool.h>
32 #include <stdint.h>
33 #include <sys/param.h>
34 #include <sys/queue.h>
35 #include <sys/types.h>
36 #include <time.h>
37 
38 #include "libcommon/util.h"
39 
40 #define PROG_NAME "honggfuzz"
41 #define PROG_VERSION "1.3"
42 
43 /* Name of the template which will be replaced with the proper name of the file */
44 #define _HF_FILE_PLACEHOLDER "___FILE___"
45 
46 /* Default name of the report created with some architectures */
47 #define _HF_REPORT_FILE "HONGGFUZZ.REPORT.TXT"
48 
49 /* Default stack-size of created threads. */
50 #define _HF_PTHREAD_STACKSIZE (1024 * 1024 * 2) /* 2MB */
51 
52 /* Name of envvar which indicates sequential number of fuzzer */
53 #define _HF_THREAD_NO_ENV "HFUZZ_THREAD_NO"
54 
55 /* Number of crash verifier iterations before tag crash as stable */
56 #define _HF_VERIFIER_ITER 5
57 
58 /* Size (in bytes) for report data to be stored in stack before written to file */
59 #define _HF_REPORT_SIZE 8192
60 
61 /* Perf bitmap size */
62 #define _HF_PERF_BITMAP_SIZE_16M (1024U * 1024U * 16U)
63 #define _HF_PERF_BITMAP_BITSZ_MASK 0x7ffffff
64 /* Maximum number of PC guards (=trace-pc-guard) we support */
65 #define _HF_PC_GUARD_MAX (1024U * 1024U * 16U)
66 
67 /* FD used to pass feedback bitmap a process */
68 #define _HF_BITMAP_FD 1022
69 /* FD used to pass data to a persistent process */
70 #define _HF_PERSISTENT_FD 1023
71 /* Maximum number of active fuzzing threads */
72 #define _HF_THREAD_MAX 1024U
73 
74 typedef enum {
75     _HF_DYNFILE_NONE = 0x0,
76     _HF_DYNFILE_INSTR_COUNT = 0x1,
77     _HF_DYNFILE_BRANCH_COUNT = 0x2,
78     _HF_DYNFILE_BTS_EDGE = 0x10,
79     _HF_DYNFILE_IPT_BLOCK = 0x20,
80     _HF_DYNFILE_SOFT = 0x40,
81 } dynFileMethod_t;
82 
83 typedef struct {
84     uint64_t cpuInstrCnt;
85     uint64_t cpuBranchCnt;
86     uint64_t bbCnt;
87     uint64_t newBBCnt;
88     uint64_t softCntPc;
89     uint64_t softCntEdge;
90     uint64_t softCntCmp;
91 } hwcnt_t;
92 
93 /* Sanitizer coverage specific data structures */
94 typedef struct {
95     uint64_t hitBBCnt;
96     uint64_t totalBBCnt;
97     uint64_t dsoCnt;
98     uint64_t iDsoCnt;
99     uint64_t newBBCnt;
100     uint64_t crashesCnt;
101 } sancovcnt_t;
102 
103 typedef struct {
104     uint32_t capacity;
105     uint32_t* pChunks;
106     uint32_t nChunks;
107 } bitmap_t;
108 
109 /* Memory map struct */
110 typedef struct __attribute__((packed)) {
111     uint64_t start;          // region start addr
112     uint64_t end;            // region end addr
113     uint64_t base;           // region base addr
114     char mapName[NAME_MAX];  // bin/DSO name
115     uint64_t bbCnt;
116     uint64_t newBBCnt;
117 } memMap_t;
118 
119 /* Trie node data struct */
120 typedef struct __attribute__((packed)) {
121     bitmap_t* pBM;
122 } trieData_t;
123 
124 /* Trie node struct */
125 typedef struct node {
126     char key;
127     trieData_t data;
128     struct node* next;
129     struct node* prev;
130     struct node* children;
131     struct node* parent;
132 } node_t;
133 
134 /* EOF Sanitizer coverage specific data structures */
135 
136 typedef struct {
137     char* asanOpts;
138     char* msanOpts;
139     char* ubsanOpts;
140 } sanOpts_t;
141 
142 typedef enum {
143     _HF_STATE_UNSET = 0,
144     _HF_STATE_STATIC = 1,
145     _HF_STATE_DYNAMIC_PRE = 2,
146     _HF_STATE_DYNAMIC_MAIN = 3,
147 } fuzzState_t;
148 
149 struct dynfile_t {
150     uint8_t* data;
151     size_t size;
152     TAILQ_ENTRY(dynfile_t)
153     pointers;
154 };
155 
156 struct strings_t {
157     char* s;
158     size_t len;
159     TAILQ_ENTRY(strings_t)
160     pointers;
161 };
162 
163 typedef struct {
164     bool pcGuardMap[_HF_PC_GUARD_MAX];
165     uint8_t bbMapPc[_HF_PERF_BITMAP_SIZE_16M];
166     uint8_t bbMapCmp[_HF_PERF_BITMAP_SIZE_16M];
167     uint64_t pidFeedbackPc[_HF_THREAD_MAX];
168     uint64_t pidFeedbackEdge[_HF_THREAD_MAX];
169     uint64_t pidFeedbackCmp[_HF_THREAD_MAX];
170 } feedback_t;
171 
172 typedef struct {
173     struct {
174         const char* inputDir;
175         DIR* inputDirPtr;
176         size_t fileCnt;
177         const char* fileExtn;
178         bool fileCntDone;
179         const char* workDir;
180         const char* crashDir;
181         const char* covDirAll;
182         const char* covDirNew;
183         bool saveUnique;
184     } io;
185     struct {
186         const char* const* cmdline;
187         bool nullifyStdio;
188         bool fuzzStdin;
189         char* externalCommand;
190         char* postExternalCommand;
191         uint64_t asLimit;
192         uint64_t rssLimit;
193         uint64_t dataLimit;
194         bool clearEnv;
195         char* envs[128];
196     } exe;
197     struct {
198         size_t threadsMax;
199         size_t threadsFinished;
200         uint32_t threadsActiveCnt;
201         pthread_t mainThread;
202         pid_t mainPid;
203     } threads;
204     struct {
205         time_t timeStart;
206         time_t runEndTime;
207         time_t tmOut;
208         bool tmoutVTALRM;
209     } timing;
210     bool useScreen;
211     bool useVerifier;
212     char cmdline_txt[61];
213     unsigned mutationsPerRun;
214     const char* blacklistFile;
215     uint64_t* blacklist;
216     size_t blacklistCnt;
217     size_t mutationsMax;
218     size_t maxFileSz;
219     char* reportFile;
220     bool persistent;
221     bool skipFeedbackOnTimeout;
222     bool enableSanitizers;
223     bool monitorSIGABRT;
224     bool exitUponCrash;
225     const char* dictionaryFile;
226     TAILQ_HEAD(strq_t, strings_t) dictq;
227     size_t dictionaryCnt;
228     struct strings_t* dictqCurrent;
229 
230     fuzzState_t state;
231     feedback_t* feedback;
232     int bbFd;
233 
234     size_t dynfileqCnt;
235     TAILQ_HEAD(dyns_t, dynfile_t) dynfileq;
236     pthread_rwlock_t dynfileq_mutex;
237 
238     pthread_mutex_t feedback_mutex;
239 
240     struct {
241         size_t mutationsCnt;
242         size_t crashesCnt;
243         size_t uniqueCrashesCnt;
244         size_t verifiedCrashesCnt;
245         size_t blCrashesCnt;
246         size_t timeoutedCnt;
247     } cnts;
248 
249     dynFileMethod_t dynFileMethod;
250     sancovcnt_t sanCovCnts;
251     pthread_mutex_t sanCov_mutex;
252     sanOpts_t sanOpts;
253     size_t dynFileIterExpire;
254     bool useSanCov;
255     node_t* covMetadata;
256 
257     pthread_mutex_t report_mutex;
258 
259     /* For the Linux code */
260     struct {
261         int exeFd;
262         hwcnt_t hwCnts;
263         uint64_t dynamicCutOffAddr;
264         bool disableRandomization;
265         void* ignoreAddr;
266         size_t numMajorFrames;
267         pid_t pid;
268         const char* pidFile;
269         char pidCmd[55];
270         const char* symsBlFile;
271         char** symsBl;
272         size_t symsBlCnt;
273         const char* symsWlFile;
274         char** symsWl;
275         size_t symsWlCnt;
276         uintptr_t cloneFlags;
277         bool kernelOnly;
278         bool useClone;
279     } linux;
280 } honggfuzz_t;
281 
282 typedef struct {
283     honggfuzz_t* global;
284     pid_t pid;
285     pid_t persistentPid;
286     fuzzState_t state;
287     int64_t timeStartedMillis;
288     const char* origFileName;
289     char fileName[PATH_MAX];
290     char crashFileName[PATH_MAX];
291     uint64_t pc;
292     uint64_t backtrace;
293     uint64_t access;
294     int exception;
295     char report[_HF_REPORT_SIZE];
296     bool mainWorker;
297     unsigned mutationsPerRun;
298     struct dynfile_t* dynfileqCurrent;
299     uint8_t* dynamicFile;
300     size_t dynamicFileSz;
301     uint32_t fuzzNo;
302     int persistentSock;
303     bool tmOutSignaled;
304 #if !defined(_HF_ARCH_DARWIN)
305     timer_t timerId;
306 #endif  // !defined(_HF_ARCH_DARWIN)
307 
308     sancovcnt_t sanCovCnts;
309 
310     struct {
311         /* For Linux code */
312         uint8_t* perfMmapBuf;
313         uint8_t* perfMmapAux;
314         hwcnt_t hwCnts;
315         pid_t attachedPid;
316         int cpuInstrFd;
317         int cpuBranchFd;
318         int cpuIptBtsFd;
319     } linux;
320 } run_t;
321 
322 /* Go-style defer implementation */
323 #define __STRMERGE(a, b) a##b
324 #define _STRMERGE(a, b) __STRMERGE(a, b)
325 #ifdef __clang__
326 #if __has_extension(blocks)
327 static void __attribute__((unused)) __clang_cleanup_func(void (^*dfunc)(void)) { (*dfunc)(); }
328 
329 #define defer                                        \
330     void (^_STRMERGE(__defer_f_, __COUNTER__))(void) \
331         __attribute__((cleanup(__clang_cleanup_func))) __attribute__((unused)) = ^
332 #else /* __has_extension(blocks) */
333 #define defer UNIMPLEMENTED - NO - SUPPORT - FOR - BLOCKS - IN - YOUR - CLANG - ENABLED
334 #endif /*  __has_extension(blocks) */
335 #else  /* __clang */
336 #define __block
337 #define _DEFER(a, count)                                                                      \
338     auto void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)));         \
339     int _STRMERGE(__defer_var_, count) __attribute__((cleanup(_STRMERGE(__defer_f_, count)))) \
340         __attribute__((unused));                                                              \
341     void _STRMERGE(__defer_f_, count)(void* _defer_arg __attribute__((unused)))
342 #define defer _DEFER(a, __COUNTER__)
343 #endif /* __clang */
344 
345 #define MX_SCOPED_LOCK(m) \
346     MX_LOCK(m);           \
347     defer { MX_UNLOCK(m); }
348 
349 #define MX_SCOPED_RWLOCK_READ(m) \
350     MX_RWLOCK_READ(m);           \
351     defer { MX_RWLOCK_UNLOCK(m); }
352 #define MX_SCOPED_RWLOCK_WRITE(m) \
353     MX_RWLOCK_WRITE(m);           \
354     defer { MX_RWLOCK_UNLOCK(m); }
355 
356 #endif
357