Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1077)

Side by Side Diff: third_party/afl/src/llvm_mode/afl-llvm-rt.o.c

Issue 2075883002: Add American Fuzzy Lop (afl) to third_party/afl/ (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix nits Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 /*
2 american fuzzy lop - LLVM instrumentation bootstrap
3 ---------------------------------------------------
4
5 Written by Laszlo Szekeres <lszekeres@google.com> and
6 Michal Zalewski <lcamtuf@google.com>
7
8 LLVM integration design comes from Laszlo Szekeres.
9
10 Copyright 2015, 2016 Google Inc. All rights reserved.
11
12 Licensed under the Apache License, Version 2.0 (the "License");
13 you may not use this file except in compliance with the License.
14 You may obtain a copy of the License at:
15
16 http://www.apache.org/licenses/LICENSE-2.0
17
18 This code is the rewrite of afl-as.h's main_payload.
19
20 */
21
22 #include "../config.h"
23 #include "../types.h"
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <signal.h>
28 #include <unistd.h>
29 #include <assert.h>
30
31 #include <sys/mman.h>
32 #include <sys/shm.h>
33 #include <sys/wait.h>
34 #include <sys/types.h>
35
36
37 /* Globals needed by the injected instrumentation. The __afl_area_initial region
38 is used for instrumentation output before __afl_map_shm() has a chance to run .
39 It will end up as .comm, so it shouldn't be too wasteful. */
40
41 u8 __afl_area_initial[MAP_SIZE];
42 u8* __afl_area_ptr = __afl_area_initial;
43
44 __thread u32 __afl_prev_loc;
45
46
47 /* Running in persistent mode? */
48
49 static u8 is_persistent;
50
51
52 /* SHM setup. */
53
54 static void __afl_map_shm(void) {
55
56 u8 *id_str = getenv(SHM_ENV_VAR);
57
58 /* If we're running under AFL, attach to the appropriate region, replacing the
59 early-stage __afl_area_initial region that is needed to allow some really
60 hacky .init code to work correctly in projects such as OpenSSL. */
61
62 if (id_str) {
63
64 u32 shm_id = atoi(id_str);
65
66 __afl_area_ptr = shmat(shm_id, NULL, 0);
67
68 /* Whooooops. */
69
70 if (__afl_area_ptr == (void *)-1) _exit(1);
71
72 /* Write something into the bitmap so that even with low AFL_INST_RATIO,
73 our parent doesn't give up on us. */
74
75 __afl_area_ptr[0] = 1;
76
77 }
78
79 }
80
81
82 /* Fork server logic. */
83
84 static void __afl_start_forkserver(void) {
85
86 static u8 tmp[4];
87 s32 child_pid;
88
89 u8 child_stopped = 0;
90
91 /* Phone home and tell the parent that we're OK. If parent isn't there,
92 assume we're not running in forkserver mode and just execute program. */
93
94 if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
95
96 while (1) {
97
98 u32 was_killed;
99 int status;
100
101 /* Wait for parent by reading from the pipe. Abort if read fails. */
102
103 if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1);
104
105 /* If we stopped the child in persistent mode, but there was a race
106 condition and afl-fuzz already issued SIGKILL, write off the old
107 process. */
108
109 if (child_stopped && was_killed) {
110 child_stopped = 0;
111 if (waitpid(child_pid, &status, 0) < 0) _exit(1);
112 }
113
114 if (!child_stopped) {
115
116 /* Once woken up, create a clone of our process. */
117
118 child_pid = fork();
119 if (child_pid < 0) _exit(1);
120
121 /* In child process: close fds, resume execution. */
122
123 if (!child_pid) {
124
125 close(FORKSRV_FD);
126 close(FORKSRV_FD + 1);
127 return;
128
129 }
130
131 } else {
132
133 /* Special handling for persistent mode: if the child is alive but
134 currently stopped, simply restart it with SIGCONT. */
135
136 kill(child_pid, SIGCONT);
137 child_stopped = 0;
138
139 }
140
141 /* In parent process: write PID to pipe, then wait for child. */
142
143 if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) _exit(1);
144
145 if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0)
146 _exit(1);
147
148 /* In persistent mode, the child stops itself with SIGSTOP to indicate
149 a successful run. In this case, we want to wake it up without forking
150 again. */
151
152 if (WIFSTOPPED(status)) child_stopped = 1;
153
154 /* Relay wait status to pipe, then loop back. */
155
156 if (write(FORKSRV_FD + 1, &status, 4) != 4) _exit(1);
157
158 }
159
160 }
161
162
163 /* A simplified persistent mode handler, used as explained in README.llvm. */
164
165 int __afl_persistent_loop(unsigned int max_cnt) {
166
167 static u8 first_pass = 1;
168 static u32 cycle_cnt;
169
170 if (first_pass) {
171
172 cycle_cnt = max_cnt;
173 first_pass = 0;
174 return 1;
175
176 }
177
178 if (is_persistent && --cycle_cnt) {
179
180 raise(SIGSTOP);
181 return 1;
182
183 } else return 0;
184
185 }
186
187
188 /* This one can be called from user code when deferred forkserver mode
189 is enabled. */
190
191 void __afl_manual_init(void) {
192
193 static u8 init_done;
194
195 if (!init_done) {
196
197 __afl_map_shm();
198 __afl_start_forkserver();
199 init_done = 1;
200
201 }
202
203 }
204
205
206 static void __afl_trace_pc_init(void);
207
208
209 /* Proper initialization routine. */
210
211 __attribute__((constructor(0))) void __afl_auto_init(void) {
212
213 is_persistent = !!getenv(PERSIST_ENV_VAR);
214
215 __afl_trace_pc_init();
216
217 if (getenv(DEFER_ENV_VAR)) return;
218
219 __afl_manual_init();
220
221 }
222
223
224 /* The following stuff deals with support for -fsanitize-coverage=bb,trace-pc.
225 It remains non-operational in the traditional, plugin-backed LLVM mode.
226 For more info about 'trace-pc', see README.llvm.
227
228 The first function (__sanitizer_cov_trace_pc) is called back on every
229 basic block. Since LLVM is not giving us any stable IDs for the blocks,
230 we use 12 least significant bits of the return address (which should be
231 stable even with ASLR; more significant bits may vary across runs).
232
233 Since MAP_SIZE is usually larger than 12 bits, we "pad" it by combining
234 left-shifted __afl_prev_loc. This gives us a theoretical maximum of 24
235 bits, although instruction alignment likely reduces this somewhat. */
236
237
238 static u32 inst_ratio_scaled = MIN(4096, MAP_SIZE);
239
240 void __sanitizer_cov_trace_pc(void) {
241
242 u32 cur = ((u32)__builtin_return_address(0)) & MIN(4095, MAP_SIZE - 1);
243
244 if (cur > inst_ratio_scaled) return;
245
246 __afl_area_ptr[cur ^ __afl_prev_loc]++;
247
248 #if MAP_SIZE_POW2 > 12
249 __afl_prev_loc = cur << (MAP_SIZE_POW2 - 12);
250 #else
251 __afl_prev_loc = cur >> 1;
252 #endif /* ^MAP_SIZE_POW2 > 12 */
253
254 }
255
256
257 /* Init callback. Unfortunately, LLVM does not support compile-time
258 instrumentation density scaling, at least not just yet. This means
259 taking some performance hit by checking inst_ratio_scaled at runtime. */
260
261 static void __afl_trace_pc_init(void) {
262
263 u8* x = getenv("AFL_INST_RATIO");
264
265 if (!x) return;
266
267 inst_ratio_scaled = atoi(x);
268
269 if (!inst_ratio_scaled || inst_ratio_scaled > 100) {
270 fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n");
271 abort();
272 }
273
274 inst_ratio_scaled = inst_ratio_scaled * MIN(4096, MAP_SIZE) / 100;
275
276 }
277
278
279 /* Work around a short-lived bug in LLVM with -fsanitize-coverage=trace-pc. */
280
281 void __sanitizer_cov_module_init(void) __attribute__((weak));
282 void __sanitizer_cov_module_init(void) { }
283
OLDNEW
« no previous file with comments | « third_party/afl/src/llvm_mode/afl-clang-fast.c ('k') | third_party/afl/src/qemu_mode/README.qemu » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698