• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2    american fuzzy lop++ - forkserver header
3    ----------------------------------------
4 
5    Originally written by Michal Zalewski
6 
7    Forkserver design by Jann Horn <jannhorn@googlemail.com>
8 
9    Now maintained by Marc Heuse <mh@mh-sec.de>,
10                      Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
11                      Andrea Fioraldi <andreafioraldi@gmail.com>,
12                      Dominik Maier <mail@dmnk.co>>
13 
14    Copyright 2016, 2017 Google Inc. All rights reserved.
15    Copyright 2019-2022 AFLplusplus Project. All rights reserved.
16 
17    Licensed under the Apache License, Version 2.0 (the "License");
18    you may not use this file except in compliance with the License.
19    You may obtain a copy of the License at:
20 
21      https://www.apache.org/licenses/LICENSE-2.0
22 
23    Shared code that implements a forkserver. This is used by the fuzzer
24    as well the other components like afl-tmin.
25 
26  */
27 
28 #ifndef __AFL_FORKSERVER_H
29 #define __AFL_FORKSERVER_H
30 
31 #include <stdio.h>
32 #include <stdbool.h>
33 
34 #include "types.h"
35 
36 #ifdef __linux__
37 /**
38  * Nyx related typedefs taken from libnyx.h
39  */
40 
41 typedef enum NyxReturnValue {
42 
43   Normal,
44   Crash,
45   Asan,
46   Timout,
47   InvalidWriteToPayload,
48   Error,
49   IoError,
50   Abort,
51 
52 } NyxReturnValue;
53 
54 typedef struct {
55 
56   void *(*nyx_new)(const char *sharedir, const char *workdir, uint32_t cpu_id,
57                    uint32_t input_buffer_size,
58                    bool     input_buffer_write_protection);
59   void *(*nyx_new_parent)(const char *sharedir, const char *workdir,
60                           uint32_t cpu_id, uint32_t input_buffer_size,
61                           bool input_buffer_write_protection);
62   void *(*nyx_new_child)(const char *sharedir, const char *workdir,
63                          uint32_t cpu_id, uint32_t worker_id);
64   void (*nyx_shutdown)(void *qemu_process);
65   void (*nyx_option_set_reload_mode)(void *qemu_process, bool enable);
66   void (*nyx_option_set_timeout)(void *qemu_process, uint8_t timeout_sec,
67                                  uint32_t timeout_usec);
68   void (*nyx_option_apply)(void *qemu_process);
69   void (*nyx_set_afl_input)(void *qemu_process, uint8_t *buffer, uint32_t size);
70   enum NyxReturnValue (*nyx_exec)(void *qemu_process);
71   uint8_t *(*nyx_get_bitmap_buffer)(void *qemu_process);
72   size_t (*nyx_get_bitmap_buffer_size)(void *qemu_process);
73   uint32_t (*nyx_get_aux_string)(void *nyx_process, uint8_t *buffer,
74                                  uint32_t size);
75 
76 } nyx_plugin_handler_t;
77 
78 #endif
79 
80 typedef struct afl_forkserver {
81 
82   /* a program that includes afl-forkserver needs to define these */
83 
84   u8 *trace_bits;                       /* SHM with instrumentation bitmap  */
85 
86   s32 fsrv_pid,                         /* PID of the fork server           */
87       child_pid,                        /* PID of the fuzzed program        */
88       child_status,                     /* waitpid result for the child     */
89       out_dir_fd;                       /* FD of the lock file              */
90 
91   s32 out_fd,                           /* Persistent fd for fsrv->out_file */
92       dev_urandom_fd,                   /* Persistent fd for /dev/urandom   */
93 
94       dev_null_fd,                      /* Persistent fd for /dev/null      */
95       fsrv_ctl_fd,                      /* Fork server control pipe (write) */
96       fsrv_st_fd;                       /* Fork server status pipe (read)   */
97 
98   u32 exec_tmout;                       /* Configurable exec timeout (ms)   */
99   u32 init_tmout;                       /* Configurable init timeout (ms)   */
100   u32 map_size;                         /* map size used by the target      */
101   u32 real_map_size;                    /* real map size, unaligned         */
102   u32 snapshot;                         /* is snapshot feature used         */
103   u64 mem_limit;                        /* Memory cap for child (MB)        */
104 
105   u64 total_execs;                      /* How often run_target was called  */
106 
107   u8 *out_file,                         /* File to fuzz, if any             */
108       *target_path;                     /* Path of the target               */
109 
110   FILE *plot_file;                      /* Gnuplot output file              */
111 
112   /* Note: last_run_timed_out is u32 to send it to the child as 4 byte array */
113   u32 last_run_timed_out;               /* Traced process timed out?        */
114 
115   u8 last_kill_signal;                  /* Signal that killed the child     */
116 
117   bool use_shmem_fuzz;                  /* use shared mem for test cases    */
118 
119   bool support_shmem_fuzz;              /* set by afl-fuzz                  */
120 
121   bool use_fauxsrv;                     /* Fauxsrv for non-forking targets? */
122 
123   bool qemu_mode;                       /* if running in qemu mode or not   */
124 
125   bool frida_mode;                     /* if running in frida mode or not   */
126 
127   bool frida_asan;                    /* if running with asan in frida mode */
128 
129   bool cs_mode;                      /* if running in CoreSight mode or not */
130 
131   bool use_stdin;                       /* use stdin for sending data       */
132 
133   bool no_unlink;                       /* do not unlink cur_input          */
134 
135   bool uses_asan;                       /* Target uses ASAN?                */
136 
137   bool debug;                           /* debug mode?                      */
138 
139   bool uses_crash_exitcode;             /* Custom crash exitcode specified? */
140   u8   crash_exitcode;                  /* The crash exitcode specified     */
141 
142   u32 *shmem_fuzz_len;                  /* length of the fuzzing test case  */
143 
144   u8 *shmem_fuzz;                       /* allocated memory for fuzzing     */
145 
146   char *cmplog_binary;                  /* the name of the cmplog binary    */
147 
148   /* persistent mode replay functionality */
149   u32 persistent_record;                /* persistent replay setting        */
150 #ifdef AFL_PERSISTENT_RECORD
151   u32  persistent_record_idx;           /* persistent replay cache ptr      */
152   u32  persistent_record_cnt;           /* persistent replay counter        */
153   u8 * persistent_record_dir;
154   u8 **persistent_record_data;
155   u32 *persistent_record_len;
156   s32  persistent_record_pid;
157 #endif
158 
159   /* Function to kick off the forkserver child */
160   void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
161 
162   u8 *afl_ptr;                          /* for autodictionary: afl ptr      */
163 
164   void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
165 
166   u8 kill_signal;
167   u8 persistent_mode;
168 
169 #ifdef __linux__
170   nyx_plugin_handler_t *nyx_handlers;
171   char *                out_dir_path;    /* path to the output directory     */
172   u8                    nyx_mode;        /* if running in nyx mode or not    */
173   bool                  nyx_parent;      /* create initial snapshot          */
174   bool                  nyx_standalone;  /* don't serialize the snapshot     */
175   void *                nyx_runner;      /* nyx runner object                */
176   u32                   nyx_id;          /* nyx runner id (0 -> master)      */
177   u32                   nyx_bind_cpu_id; /* nyx runner cpu id                */
178   char *                nyx_aux_string;
179 #endif
180 
181 } afl_forkserver_t;
182 
183 typedef enum fsrv_run_result {
184 
185   /* 00 */ FSRV_RUN_OK = 0,
186   /* 01 */ FSRV_RUN_TMOUT,
187   /* 02 */ FSRV_RUN_CRASH,
188   /* 03 */ FSRV_RUN_ERROR,
189   /* 04 */ FSRV_RUN_NOINST,
190   /* 05 */ FSRV_RUN_NOBITS,
191 
192 } fsrv_run_result_t;
193 
194 void afl_fsrv_init(afl_forkserver_t *fsrv);
195 void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
196 void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
197                     volatile u8 *stop_soon_p, u8 debug_child_output);
198 u32  afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
199                           volatile u8 *stop_soon_p, u8 debug_child_output);
200 void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len);
201 fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
202                                       volatile u8 *stop_soon_p);
203 void              afl_fsrv_killall(void);
204 void              afl_fsrv_deinit(afl_forkserver_t *fsrv);
205 void              afl_fsrv_kill(afl_forkserver_t *fsrv);
206 
207 #ifdef __APPLE__
208   #define MSG_FORK_ON_APPLE                                                    \
209     "    - On MacOS X, the semantics of fork() syscalls are non-standard and " \
210     "may\n"                                                                    \
211     "      break afl-fuzz performance optimizations when running "             \
212     "platform-specific\n"                                                      \
213     "      targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n"
214 #else
215   #define MSG_FORK_ON_APPLE ""
216 #endif
217 
218 #ifdef RLIMIT_AS
219   #define MSG_ULIMIT_USAGE "      ( ulimit -Sv $[%llu << 10];"
220 #else
221   #define MSG_ULIMIT_USAGE "      ( ulimit -Sd $[%llu << 10];"
222 #endif                                                        /* ^RLIMIT_AS */
223 
224 #endif
225 
226