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

Side by Side Diff: third_party/afl/src/qemu_mode/patches/afl-qemu-cpu-inl.h

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 - high-performance binary-only instrumentation
3 -----------------------------------------------------------------
4
5 Written by Andrew Griffiths <agriffiths@google.com> and
6 Michal Zalewski <lcamtuf@google.com>
7
8 Idea & design very much by Andrew Griffiths.
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 a shim patched into the separately-distributed source
19 code of QEMU 2.2.0. It leverages the built-in QEMU tracing functionality
20 to implement AFL-style instrumentation and to take care of the remaining
21 parts of the AFL fork server logic.
22
23 The resulting QEMU binary is essentially a standalone instrumentation
24 tool; for an example of how to leverage it for other purposes, you can
25 have a look at afl-showmap.c.
26
27 */
28
29 #include <sys/shm.h>
30 #include "../../config.h"
31
32 /***************************
33 * VARIOUS AUXILIARY STUFF *
34 ***************************/
35
36 /* A snippet patched into tb_find_slow to inform the parent process that
37 we have hit a new block that hasn't been translated yet, and to tell
38 it to translate within its own context, too (this avoids translation
39 overhead in the next forked-off copy). */
40
41 #define AFL_QEMU_CPU_SNIPPET1 do { \
42 afl_request_tsl(pc, cs_base, flags); \
43 } while (0)
44
45 /* This snippet kicks in when the instruction pointer is positioned at
46 _start and does the usual forkserver stuff, not very different from
47 regular instrumentation injected via afl-as.h. */
48
49 #define AFL_QEMU_CPU_SNIPPET2 do { \
50 if(tb->pc == afl_entry_point) { \
51 afl_setup(); \
52 afl_forkserver(env); \
53 } \
54 afl_maybe_log(tb->pc); \
55 } while (0)
56
57 /* We use one additional file descriptor to relay "needs translation"
58 messages between the child and the fork server. */
59
60 #define TSL_FD (FORKSRV_FD - 1)
61
62 /* This is equivalent to afl-as.h: */
63
64 static unsigned char *afl_area_ptr;
65
66 /* Exported variables populated by the code patched into elfload.c: */
67
68 abi_ulong afl_entry_point, /* ELF entry point (_start) */
69 afl_start_code, /* .text start pointer */
70 afl_end_code; /* .text end pointer */
71
72 /* Set in the child process in forkserver mode: */
73
74 static unsigned char afl_fork_child;
75 unsigned int afl_forksrv_pid;
76
77 /* Instrumentation ratio: */
78
79 static unsigned int afl_inst_rms = MAP_SIZE;
80
81 /* Function declarations. */
82
83 static void afl_setup(void);
84 static void afl_forkserver(CPUArchState*);
85 static inline void afl_maybe_log(abi_ulong);
86
87 static void afl_wait_tsl(CPUArchState*, int);
88 static void afl_request_tsl(target_ulong, target_ulong, uint64_t);
89
90 static TranslationBlock *tb_find_slow(CPUArchState*, target_ulong,
91 target_ulong, uint64_t);
92
93
94 /* Data structure passed around by the translate handlers: */
95
96 struct afl_tsl {
97 target_ulong pc;
98 target_ulong cs_base;
99 uint64_t flags;
100 };
101
102
103 /*************************
104 * ACTUAL IMPLEMENTATION *
105 *************************/
106
107
108 /* Set up SHM region and initialize other stuff. */
109
110 static void afl_setup(void) {
111
112 char *id_str = getenv(SHM_ENV_VAR),
113 *inst_r = getenv("AFL_INST_RATIO");
114
115 int shm_id;
116
117 if (inst_r) {
118
119 unsigned int r;
120
121 r = atoi(inst_r);
122
123 if (r > 100) r = 100;
124 if (!r) r = 1;
125
126 afl_inst_rms = MAP_SIZE * r / 100;
127
128 }
129
130 if (id_str) {
131
132 shm_id = atoi(id_str);
133 afl_area_ptr = shmat(shm_id, NULL, 0);
134
135 if (afl_area_ptr == (void*)-1) exit(1);
136
137 /* With AFL_INST_RATIO set to a low value, we want to touch the bitmap
138 so that the parent doesn't give up on us. */
139
140 if (inst_r) afl_area_ptr[0] = 1;
141
142
143 }
144
145 if (getenv("AFL_INST_LIBS")) {
146
147 afl_start_code = 0;
148 afl_end_code = (abi_ulong)-1;
149
150 }
151
152 }
153
154
155 /* Fork server logic, invoked once we hit _start. */
156
157 static void afl_forkserver(CPUArchState *env) {
158
159 static unsigned char tmp[4];
160
161 if (!afl_area_ptr) return;
162
163 /* Tell the parent that we're alive. If the parent doesn't want
164 to talk, assume that we're not running in forkserver mode. */
165
166 if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
167
168 afl_forksrv_pid = getpid();
169
170 /* All right, let's await orders... */
171
172 while (1) {
173
174 pid_t child_pid;
175 int status, t_fd[2];
176
177 /* Whoops, parent dead? */
178
179 if (read(FORKSRV_FD, tmp, 4) != 4) exit(2);
180
181 /* Establish a channel with child to grab translation commands. We'll
182 read from t_fd[0], child will write to TSL_FD. */
183
184 if (pipe(t_fd) || dup2(t_fd[1], TSL_FD) < 0) exit(3);
185 close(t_fd[1]);
186
187 child_pid = fork();
188 if (child_pid < 0) exit(4);
189
190 if (!child_pid) {
191
192 /* Child process. Close descriptors and run free. */
193
194 afl_fork_child = 1;
195 close(FORKSRV_FD);
196 close(FORKSRV_FD + 1);
197 close(t_fd[0]);
198 return;
199
200 }
201
202 /* Parent. */
203
204 close(TSL_FD);
205
206 if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);
207
208 /* Collect translation requests until child dies and closes the pipe. */
209
210 afl_wait_tsl(env, t_fd[0]);
211
212 /* Get and relay exit status to parent. */
213
214 if (waitpid(child_pid, &status, 0) < 0) exit(6);
215 if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
216
217 }
218
219 }
220
221
222 /* The equivalent of the tuple logging routine from afl-as.h. */
223
224 static inline void afl_maybe_log(abi_ulong cur_loc) {
225
226 static __thread abi_ulong prev_loc;
227
228 /* Optimize for cur_loc > afl_end_code, which is the most likely case on
229 Linux systems. */
230
231 if (cur_loc > afl_end_code || cur_loc < afl_start_code || !afl_area_ptr)
232 return;
233
234 /* Looks like QEMU always maps to fixed locations, so ASAN is not a
235 concern. Phew. But instruction addresses may be aligned. Let's mangle
236 the value to get something quasi-uniform. */
237
238 cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
239 cur_loc &= MAP_SIZE - 1;
240
241 /* Implement probabilistic instrumentation by looking at scrambled block
242 address. This keeps the instrumented locations stable across runs. */
243
244 if (cur_loc >= afl_inst_rms) return;
245
246 afl_area_ptr[cur_loc ^ prev_loc]++;
247 prev_loc = cur_loc >> 1;
248
249 }
250
251
252 /* This code is invoked whenever QEMU decides that it doesn't have a
253 translation of a particular block and needs to compute it. When this happens,
254 we tell the parent to mirror the operation, so that the next fork() has a
255 cached copy. */
256
257 static void afl_request_tsl(target_ulong pc, target_ulong cb, uint64_t flags) {
258
259 struct afl_tsl t;
260
261 if (!afl_fork_child) return;
262
263 t.pc = pc;
264 t.cs_base = cb;
265 t.flags = flags;
266
267 if (write(TSL_FD, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl))
268 return;
269
270 }
271
272
273 /* This is the other side of the same channel. Since timeouts are handled by
274 afl-fuzz simply killing the child, we can just wait until the pipe breaks. */
275
276 static void afl_wait_tsl(CPUArchState *env, int fd) {
277
278 struct afl_tsl t;
279
280 while (1) {
281
282 /* Broken pipe means it's time to return to the fork server routine. */
283
284 if (read(fd, &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl))
285 break;
286
287 tb_find_slow(env, t.pc, t.cs_base, t.flags);
288
289 }
290
291 close(fd);
292
293 }
294
OLDNEW
« no previous file with comments | « third_party/afl/src/qemu_mode/build_qemu_support.sh ('k') | third_party/afl/src/qemu_mode/patches/cpu-exec.diff » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698