diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/afl-as.h | 4 | ||||
-rw-r--r-- | include/afl-fuzz.h | 241 | ||||
-rw-r--r-- | include/afl-prealloc.h | 5 | ||||
-rw-r--r-- | include/alloc-inl.h | 103 | ||||
-rw-r--r--[-rwxr-xr-x] | include/android-ashmem.h | 0 | ||||
-rw-r--r-- | include/cmplog.h | 5 | ||||
-rw-r--r-- | include/common.h | 64 | ||||
-rw-r--r-- | include/config.h | 16 | ||||
-rw-r--r-- | include/debug.h | 13 | ||||
-rw-r--r-- | include/forkserver.h | 22 | ||||
-rw-r--r-- | include/list.h | 51 | ||||
-rw-r--r-- | include/snapshot-inl.h | 59 | ||||
-rw-r--r-- | include/types.h | 24 |
13 files changed, 467 insertions, 140 deletions
diff --git a/include/afl-as.h b/include/afl-as.h index 7fc00ffe..a2bf1f9c 100644 --- a/include/afl-as.h +++ b/include/afl-as.h @@ -152,7 +152,7 @@ static const u8 *trampoline_fmt_64 = "/* --- END --- */\n" "\n"; -static const u8*main_payload_32 = +static const u8 *main_payload_32 = "\n" "/* --- AFL MAIN PAYLOAD (32-BIT) --- */\n" @@ -409,7 +409,7 @@ static const u8*main_payload_32 = #define CALL_L64(str) "call " str "@PLT\n" #endif /* ^__APPLE__ */ -static const u8* main_payload_64 = +static const u8 *main_payload_64 = "\n" "/* --- AFL MAIN PAYLOAD (64-BIT) --- */\n" diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 4e2deaa3..6cfb34ca 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -109,6 +109,8 @@ #define CASE_PREFIX "id_" #endif /* ^!SIMPLE_FILES */ +#define STAGE_BUF_SIZE (64) /* usable size for stage name buf in afl_state */ + extern s8 interesting_8[INTERESTING_8_LEN]; extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN]; extern s32 @@ -231,13 +233,12 @@ enum { /* 04 */ QUAD, /* Quadratic schedule */ /* 05 */ EXPLOIT, /* AFL's exploitation-based const. */ /* 06 */ MMOPT, /* Modified MOPT schedule */ + /* 07 */ RARE, /* Rare edges */ POWER_SCHEDULES_NUM }; -extern u8 *doc_path; /* gath to documentation dir */ - /* Python stuff */ #ifdef USE_PYTHON @@ -278,10 +279,32 @@ enum { /* 07 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY, /* 08 */ PY_FUNC_QUEUE_GET, /* 09 */ PY_FUNC_QUEUE_NEW_ENTRY, + /* 10 */ PY_FUNC_DEINIT, PY_FUNC_COUNT }; +typedef struct py_mutator { + + PyObject *py_module; + PyObject *py_functions[PY_FUNC_COUNT]; + void * afl_state; + void * py_data; + + u8 * fuzz_buf; + size_t fuzz_size; + + u8 * pre_save_buf; + size_t pre_save_size; + + u8 * trim_buf; + size_t trim_size; + + u8 * havoc_buf; + size_t havoc_size; + +} py_mutator_t; + #endif typedef struct MOpt_globals { @@ -308,7 +331,8 @@ typedef struct afl_env_vars { u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check, afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui, afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, - afl_bench_until_crash, afl_debug_child_output, afl_autoresume; + afl_bench_until_crash, afl_debug_child_output, afl_autoresume, + afl_cal_fast; u8 *afl_tmpdir, *afl_post_library, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_skip_crashes, @@ -420,7 +444,6 @@ typedef struct afl_state { no_arith, /* Skip most arithmetic ops */ shuffle_queue, /* Shuffle input queue? */ bitmap_changed, /* Time to update bitmap? */ - qemu_mode, /* Running in QEMU mode? */ unicorn_mode, /* Running in Unicorn mode? */ use_wine, /* Use WINE with QEMU mode */ skip_requested, /* Skip request, via SIGUSR1 */ @@ -463,11 +486,6 @@ typedef struct afl_state { unique_tmouts, /* Timeouts with unique signatures */ unique_hangs, /* Hangs with unique signatures */ total_execs, /* Total execve() calls */ - slowest_exec_ms, /* Slowest testcase non hang in ms */ - start_time, /* Unix start time (ms) */ - last_path_time, /* Time for most recent path (ms) */ - last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time, /* Time for most recent hang (ms) */ last_crash_execs, /* Exec counter at last crash */ queue_cycle, /* Queue round counter */ cycles_wo_finds, /* Cycles without any new paths */ @@ -475,15 +493,20 @@ typedef struct afl_state { bytes_trim_in, /* Bytes coming into the trimmer */ bytes_trim_out, /* Bytes coming outa the trimmer */ blocks_eff_total, /* Blocks subject to effector maps */ - blocks_eff_select; /* Blocks selected as fuzzable */ + blocks_eff_select, /* Blocks selected as fuzzable */ + start_time, /* Unix start time (ms) */ + last_path_time, /* Time for most recent path (ms) */ + last_crash_time, /* Time for most recent crash (ms) */ + last_hang_time; /* Time for most recent hang (ms) */ - u32 subseq_tmouts; /* Number of timeouts in a row */ + u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ + subseq_tmouts; /* Number of timeouts in a row */ u8 *stage_name, /* Name of the current fuzz stage */ *stage_short, /* Short stage name */ *syncing_party; /* Currently syncing with... */ - u8 stage_name_buf64[64]; /* A name buf with len 64 if needed */ + u8 stage_name_buf[STAGE_BUF_SIZE]; /* reused stagename buf with len 64 */ s32 stage_cur, stage_max; /* Stage progression */ s32 splicing_with; /* Splicing with which test case? */ @@ -532,35 +555,70 @@ typedef struct afl_state { struct extra_data *a_extras; /* Automatically selected extras */ u32 a_extras_cnt; /* Total number of tokens available */ - u8 *(*post_handler)(u8 *buf, u32 *len); + /* afl_postprocess API */ + void *(*post_init)(struct afl_state *afl); + size_t (*post_handler)(void *data, u8 *buf, u32 len, u8 **out_buf); + void *(*post_deinit)(void *data); + void *post_data; /* CmpLog */ - char *cmplog_binary; - s32 cmplog_child_pid, cmplog_fsrv_pid; + char * cmplog_binary; + afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */ /* Custom mutators */ struct custom_mutator *mutator; /* cmplog forkserver ids */ s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd; - + u32 cmplog_prev_timed_out; + struct afl_pass_stat* pass_stats; u8 describe_op_buf_256[256]; /* describe_op will use this to return a string up to 256 */ -#ifdef USE_PYTHON - /* Python Mutators */ - PyObject *py_module; - PyObject *py_functions[PY_FUNC_COUNT]; -#endif - #ifdef _AFL_DOCUMENT_MUTATIONS u8 do_document; u32 document_counter; #endif + void *maybe_add_auto; + + /* statistics file */ + double last_bitmap_cvg, last_stability, last_eps; + + /* plot file saves from last run */ + u32 plot_prev_qp, plot_prev_pf, plot_prev_pnf, plot_prev_ce, plot_prev_md; + u64 plot_prev_qc, plot_prev_uc, plot_prev_uh; + + u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs; + double stats_avg_exec; + + u8 clean_trace[MAP_SIZE]; + u8 clean_trace_custom[MAP_SIZE]; + u8 first_trace[MAP_SIZE]; + + /*needed for afl_fuzz_one */ + // TODO: see which we can reuse + u8 * out_buf; + size_t out_size; + + u8 * out_scratch_buf; + size_t out_scratch_size; + + u8 * eff_buf; + size_t eff_size; + + u8 * in_buf; + size_t in_size; + + u8 * in_scratch_buf; + size_t in_scratch_size; + + u8 * ex_buf; + size_t ex_size; + } afl_state_t; /* A global pointer to all instances is needed (for now) for signals to arrive @@ -572,33 +630,40 @@ struct custom_mutator { const char *name; void * dh; + u8 * pre_save_buf; + size_t pre_save_size; + + void *data; /* custom mutator data ptr */ /* hooks for the custom mutator function */ /** * Initialize the custom mutator. * - * (Optional) - * + * @param afl AFL instance. * @param seed Seed used for the mutation. + * @return pointer to internal data or NULL on error */ - void (*afl_custom_init)(afl_state_t *afl, unsigned int seed); + void *(*afl_custom_init)(afl_state_t *afl, unsigned int seed); /** * Perform custom mutations on a given input * * (Optional for now. Required in the future) * - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param data pointer returned in afl_custom_init for this fuzz case + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of the input/output data + * @param[out] out_buf the new buffer. We may reuse *buf if large enough. + * *out_buf = NULL is treated as FATAL. * @param[in] add_buf Buffer containing the additional test case * @param[in] add_buf_size Size of the additional test case * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. * @return Size of the mutated output. */ - size_t (*afl_custom_fuzz)(afl_state_t *afl, u8 **buf, size_t buf_size, + size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size); /** @@ -608,14 +673,15 @@ struct custom_mutator { * (Optional) If this functionality is not needed, simply don't define this * function. * + * @param[in] data pointer returned in afl_custom_init for this fuzz case * @param[in] buf Buffer containing the test case to be executed * @param[in] buf_size Size of the test case - * @param[out] out_buf Pointer to the buffer of storing the test case after - * processing. External library should allocate memory for out_buf. AFL++ - * will release the memory after saving the test case. - * @return Size of the output buffer after processing + * @param[out] out_buf Pointer to the buffer storing the test case after + * processing. External library should allocate memory for out_buf. + * It can chose to alter buf in-place, if the space is large enough. + * @return Size of the output buffer. */ - size_t (*afl_custom_pre_save)(afl_state_t *afl, u8 *buf, size_t buf_size, + size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size, u8 **out_buf); /** @@ -634,11 +700,13 @@ struct custom_mutator { * * (Optional) * + * @param data pointer returned in afl_custom_init for this fuzz case * @param buf Buffer containing the test case * @param buf_size Size of the test case - * @return The amount of possible iteration steps to trim the input + * @return The amount of possible iteration steps to trim the input. + * Negative on error. */ - u32 (*afl_custom_init_trim)(afl_state_t *afl, u8 *buf, size_t buf_size); + s32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size); /** * This method is called for each trimming operation. It doesn't have any @@ -651,12 +719,13 @@ struct custom_mutator { * * (Optional) * + * @param data pointer returned in afl_custom_init for this fuzz case * @param[out] out_buf Pointer to the buffer containing the trimmed test case. - * External library should allocate memory for out_buf. AFL++ will release - * the memory after saving the test case. - * @param[out] out_buf_size Pointer to the size of the trimmed test case + * The library can reuse a buffer for each call + * and will have to free the buf (for example in deinit) + * @return the size of the trimmed test case */ - void (*afl_custom_trim)(afl_state_t *afl, u8 **out_buf, size_t *out_buf_size); + size_t (*afl_custom_trim)(void *data, u8 **out_buf); /** * This method is called after each trim operation to inform you if your @@ -665,11 +734,12 @@ struct custom_mutator { * * (Optional) * + * @param data pointer returned in afl_custom_init for this fuzz case * @param success Indicates if the last trim operation was successful. * @return The next trim iteration index (from 0 to the maximum amount of - * steps returned in init_trim) + * steps returned in init_trim). Negative on error. */ - u32 (*afl_custom_post_trim)(afl_state_t *afl, u8 success); + s32 (*afl_custom_post_trim)(void *data, u8 success); /** * Perform a single custom mutation on a given input. @@ -677,15 +747,18 @@ struct custom_mutator { * * (Optional) * - * @param[inout] buf Pointer to the input data to be mutated and the mutated + * @param[in] data pointer returned in afl_custom_init for this fuzz case + * @param[in] buf Pointer to the input data to be mutated and the mutated * output * @param[in] buf_size Size of input data + * @param[out] out_buf The new buffer. It's legal to reuse *buf if it's < + * buf_size. * @param[in] max_size Maximum size of the mutated output. The mutation must * not produce data larger than max_size. - * @return Size of the mutated output. + * @return Size of the mutated output (out_size). */ - size_t (*afl_custom_havoc_mutation)(afl_state_t *afl, u8 **buf, - size_t buf_size, size_t max_size); + size_t (*afl_custom_havoc_mutation)(void *data, u8 *buf, size_t buf_size, + u8 **out_buf, size_t max_size); /** * Return the probability (in percentage) that afl_custom_havoc_mutation @@ -693,20 +766,22 @@ struct custom_mutator { * * (Optional) * + * @param data pointer returned in afl_custom_init for this fuzz case * @return The probability (0-100). */ - u8 (*afl_custom_havoc_mutation_probability)(afl_state_t *afl); + u8 (*afl_custom_havoc_mutation_probability)(void *data); /** * Determine whether the fuzzer should fuzz the current queue entry or not. * * (Optional) * + * @param data pointer returned in afl_custom_init for this fuzz case * @param filename File name of the test case in the queue entry * @return Return True(1) if the fuzzer will fuzz the queue entry, and * False(0) otherwise. */ - u8 (*afl_custom_queue_get)(afl_state_t *afl, const u8 *filename); + u8 (*afl_custom_queue_get)(void *data, const u8 *filename); /** * Allow for additional analysis (e.g. calling a different tool that does a @@ -714,13 +789,19 @@ struct custom_mutator { * * (Optional) * + * @param data pointer returned in afl_custom_init for this fuzz case * @param filename_new_queue File name of the new queue entry * @param filename_orig_queue File name of the original queue entry. This * argument can be NULL while initializing the fuzzer */ - void (*afl_custom_queue_new_entry)(afl_state_t *afl, - const u8 * filename_new_queue, - const u8 * filename_orig_queue); + void (*afl_custom_queue_new_entry)(void *data, const u8 *filename_new_queue, + const u8 *filename_orig_queue); + /** + * Deinitialize the custom mutator. + * + * @param data pointer returned in afl_custom_init for this fuzz case + */ + void (*afl_custom_deinit)(void *data); }; @@ -738,19 +819,17 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf); /* Python */ #ifdef USE_PYTHON -int init_py_module(afl_state_t *, u8 *); -void finalize_py_module(afl_state_t *); +void finalize_py_module(void *); -void init_py(afl_state_t *, unsigned int); -size_t fuzz_py(afl_state_t *, u8 **, size_t, u8 *, size_t, size_t); -size_t pre_save_py(afl_state_t *, u8 *, size_t, u8 **); -u32 init_trim_py(afl_state_t *, u8 *, size_t); -u32 post_trim_py(afl_state_t *, u8); -void trim_py(afl_state_t *, u8 **, size_t *); -size_t havoc_mutation_py(afl_state_t *, u8 **, size_t, size_t); -u8 havoc_mutation_probability_py(afl_state_t *); -u8 queue_get_py(afl_state_t *, const u8 *); -void queue_new_entry_py(afl_state_t *, const u8 *, const u8 *); +size_t pre_save_py(void *, u8 *, size_t, u8 **); +s32 init_trim_py(void *, u8 *, size_t); +s32 post_trim_py(void *, u8); +size_t trim_py(void *, u8 **); +size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t); +u8 havoc_mutation_probability_py(void *); +u8 queue_get_py(void *, const u8 *); +void queue_new_entry_py(void *, const u8 *, const u8 *); +void deinit_py(void *); #endif @@ -769,36 +848,29 @@ u32 calculate_score(afl_state_t *, struct queue_entry *); void read_bitmap(afl_state_t *, u8 *); void write_bitmap(afl_state_t *); -u32 count_bits(u8 *); -u32 count_bytes(u8 *); -u32 count_non_255_bytes(u8 *); +u32 count_bits(afl_state_t *, u8 *); +u32 count_bytes(afl_state_t *, u8 *); +u32 count_non_255_bytes(afl_state_t *, u8 *); #ifdef WORD_SIZE_64 -void simplify_trace(u64 *); -void classify_counts(u64 *); +void simplify_trace(afl_state_t *, u64 *); +void classify_counts(afl_state_t *, u64 *); #else -void simplify_trace(u32 *); -void classify_counts(u32 *); +void simplify_trace(afl_state_t *, u32 *); +void classify_counts(afl_state_t *, u32 *); #endif void init_count_class16(void); -void minimize_bits(u8 *, u8 *); +void minimize_bits(afl_state_t *, u8 *, u8 *); #ifndef SIMPLE_FILES u8 *describe_op(afl_state_t *, u8); #endif u8 save_if_interesting(afl_state_t *, void *, u32, u8); u8 has_new_bits(afl_state_t *, u8 *); -/* Misc */ - -u8 *DI(u64); -u8 *DF(double); -u8 *DMS(u64); -u8 *DTD(u64, u64); - /* Extras */ void load_extras_file(afl_state_t *, u8 *, u32 *, u32 *, u32); void load_extras(afl_state_t *, u8 *); -void maybe_add_auto(afl_state_t *, u8 *, u32); +void maybe_add_auto(void *, u8 *, u32); void save_auto(afl_state_t *); void load_auto(afl_state_t *); void destroy_extras(afl_state_t *); @@ -812,7 +884,7 @@ void show_init_stats(afl_state_t *); /* Run */ -u8 run_target(afl_state_t *, u32); +u8 run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); void write_to_testcase(afl_state_t *, void *, u32); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); void sync_fuzzers(afl_state_t *); @@ -856,8 +928,7 @@ void save_cmdline(afl_state_t *, u32, char **); /* CmpLog */ -void init_cmplog_forkserver(afl_state_t *afl); -u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len); +u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len); /* RedQueen */ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, @@ -868,16 +939,16 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, /* Generate a random number (from 0 to limit - 1). This may have slight bias. */ -static inline u32 UR(afl_state_t *afl, u32 limit) { +static inline u32 rand_below(afl_state_t *afl, u32 limit) { #ifdef HAVE_ARC4RANDOM - if (afl->fixed_seed) { return random() % limit; } + if (unlikely(afl->fixed_seed)) { return random() % limit; } /* The boundary not being necessarily a power of 2, we need to ensure the result uniformity. */ return arc4random_uniform(limit); #else - if (!afl->fixed_seed && unlikely(!afl->rand_cnt--)) { + if (unlikely(!afl->rand_cnt--) && likely(!afl->fixed_seed)) { ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed), "/dev/urandom"); @@ -893,7 +964,7 @@ static inline u32 UR(afl_state_t *afl, u32 limit) { static inline u32 get_rand_seed(afl_state_t *afl) { - if (afl->fixed_seed) return (u32)afl->init_seed; + if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed; return afl->rand_seed[0]; } @@ -901,7 +972,7 @@ static inline u32 get_rand_seed(afl_state_t *afl) { /* Find first power of two greater or equal to val (assuming val under 2^63). */ -static u64 next_p2(u64 val) { +static inline u64 next_p2(u64 val) { u64 ret = 1; while (val > ret) diff --git a/include/afl-prealloc.h b/include/afl-prealloc.h index ab86f0d7..66e6aadf 100644 --- a/include/afl-prealloc.h +++ b/include/afl-prealloc.h @@ -44,9 +44,8 @@ typedef enum prealloc_status { /* Adds the entry used for prealloc bookkeeping to this struct */ -#define PREALLOCABLE \ - ; \ - pre_status_t pre_status; /* prealloc status of this instance */ +/* prealloc status of this instance */ +#define PREALLOCABLE pre_status_t pre_status /* allocate an element of type *el_ptr, to this variable. Uses (and reuses) the given prealloc_buf before hitting libc's malloc. diff --git a/include/alloc-inl.h b/include/alloc-inl.h index c8783d96..d16e84bb 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -35,6 +35,9 @@ #include "types.h" #include "debug.h" +/* Initial size used for ck_maybe_grow */ +#define INITIAL_GROWTH_SIZE (64) + // Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators #ifndef _WANT_ORIGINAL_AFL_ALLOC @@ -82,7 +85,7 @@ static inline void *DFL_ck_alloc_nozero(u32 size) { - u8 *ret; + void *ret; if (!size) return NULL; @@ -124,7 +127,7 @@ static inline void DFL_ck_free(void *mem) { static inline void *DFL_ck_realloc(void *orig, u32 size) { - u8 *ret; + void *ret; if (!size) { @@ -179,7 +182,7 @@ static inline u8 *DFL_ck_strdup(u8 *str) { static inline void *DFL_ck_memdup(void *mem, u32 size) { - u8 *ret; + void *ret; if (!mem || !size) return NULL; @@ -764,5 +767,99 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, #endif /* _WANT_ORIGINAL_AFL_ALLOC */ +/* This function calculates the next power of 2 greater or equal its argument. + @return The rounded up power of 2 (if no overflow) or 0 on overflow. +*/ +static inline size_t next_pow2(size_t in) { + + if (in == 0 || in > (size_t)-1) + return 0; /* avoid undefined behaviour under-/overflow */ + size_t out = in - 1; + out |= out >> 1; + out |= out >> 2; + out |= out >> 4; + out |= out >> 8; + out |= out >> 16; + return out + 1; + +} + +/* This function makes sure *size is > size_needed after call. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will return NULL and free *buf if size_needed is <1 or realloc failed. + @return For convenience, this function returns *buf. + */ +static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { + + /* No need to realloc */ + if (likely(size_needed && *size >= size_needed)) return *buf; + + /* No initial size was set */ + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + + /* grow exponentially */ + size_t next_size = next_pow2(size_needed); + + /* handle overflow and zero size_needed */ + if (!next_size) { next_size = size_needed; } + + /* alloc */ + *buf = realloc(*buf, next_size); + *size = *buf ? next_size : 0; + + return *buf; + +} + +/* This function makes sure *size is > size_needed after call. + It will realloc *buf otherwise. + *size will grow exponentially as per: + https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/ + Will FATAL if size_needed is <1. + @return For convenience, this function returns *buf. + */ +static inline void *ck_maybe_grow(void **buf, size_t *size, + size_t size_needed) { + + /* Oops. found a bug? */ + if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size"); + + /* No need to realloc */ + if (likely(*size >= size_needed)) return *buf; + + /* No initial size was set */ + if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + + /* grow exponentially */ + size_t next_size = next_pow2(size_needed); + + /* handle overflow */ + if (!next_size) { next_size = size_needed; } + + /* alloc */ + *buf = ck_realloc(*buf, next_size); + *size = next_size; + + return *buf; + +} + +/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */ +static inline void swap_bufs(void **buf1, size_t *size1, void **buf2, + size_t *size2) { + + void * scratch_buf = *buf1; + size_t scratch_size = *size1; + *buf1 = *buf2; + *size1 = *size2; + *buf2 = scratch_buf; + *size2 = scratch_size; + +} + +#undef INITIAL_GROWTH_SIZE + #endif /* ! _HAVE_ALLOC_INL_H */ diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 3a0b9969..3a0b9969 100755..100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h diff --git a/include/cmplog.h b/include/cmplog.h index 36f8f2c5..74e6a3bb 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -29,6 +29,7 @@ #define _AFL_CMPLOG_H #include "config.h" +#include "forkserver.h" #define CMP_MAP_W 65536 #define CMP_MAP_H 256 @@ -74,5 +75,9 @@ struct cmp_map { }; +/* Execs the child */ + +void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv); + #endif diff --git a/include/common.h b/include/common.h index 28c11049..8dd66355 100644 --- a/include/common.h +++ b/include/common.h @@ -27,10 +27,17 @@ #ifndef __AFLCOMMON_H #define __AFLCOMMON_H +#include <stdio.h> +#include <string.h> +#include <unistd.h> #include <sys/time.h> #include "types.h" #include "stdbool.h" +/* STRINGIFY_VAL_SIZE_MAX will fit all stringify_ strings. */ + +#define STRINGIFY_VAL_SIZE_MAX (16) + void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin); void check_environment_vars(char **env); @@ -41,31 +48,62 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); +extern u8 be_quiet; +extern u8 *doc_path; /* path to documentation dir */ + /* Get unix time in milliseconds */ -static u64 get_cur_time(void) { +u64 get_cur_time(void); - struct timeval tv; - struct timezone tz; +/* Get unix time in microseconds */ - gettimeofday(&tv, &tz); +u64 get_cur_time_us(void); - return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000); +/* Describe integer. The buf should be + at least 6 bytes to fit all ints we randomly see. + Will return buf for convenience. */ -} +u8 *stringify_int(u8 *buf, size_t len, u64 val); -/* Get unix time in microseconds */ +/* Describe float. Similar as int. */ + +u8 *stringify_float(u8 *buf, size_t len, double val); + +/* Describe integer as memory size. */ + +u8 *stringify_mem_size(u8 *buf, size_t len, u64 val); + +/* Describe time delta as string. + Returns a pointer to buf for convenience. */ + +u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms); + +/* Unsafe Describe integer. The buf sizes are not checked. + This is unsafe but fast. + Will return buf for convenience. */ + +u8 *u_stringify_int(u8 *buf, u64 val); + +/* Unsafe describe float. Similar as unsafe int. */ + +u8 *u_stringify_float(u8 *buf, double val); -static u64 get_cur_time_us(void) { +/* Unsafe describe integer as memory size. */ - struct timeval tv; - struct timezone tz; +u8 *u_stringify_mem_size(u8 *buf, u64 val); - gettimeofday(&tv, &tz); +/* Unsafe describe time delta as string. + Returns a pointer to buf for convenience. */ - return (tv.tv_sec * 1000000ULL) + tv.tv_usec; +u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); -} +/* Wrapper for select() and read(), reading exactly len bytes. + Returns the time passed to read. + stop_soon should point to a variable indicating ctrl+c was pressed. + If the wait times out, returns timeout_ms + 1; + Returns 0 if an error occurred (fd closed, signal, ...); */ +u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, + volatile u8 *stop_soon_p); #endif diff --git a/include/config.h b/include/config.h index a87c5e84..f0274fd3 100644 --- a/include/config.h +++ b/include/config.h @@ -28,7 +28,7 @@ /* Version string: */ // c = release, d = volatile github dev, e = experimental branch -#define VERSION "++2.62d" +#define VERSION "++2.63d" /****************************************************** * * @@ -201,8 +201,8 @@ (first value), and to keep in memory as candidates. The latter should be much higher than the former. */ -#define USE_AUTO_EXTRAS 50 -#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) +#define USE_AUTO_EXTRAS 128 +#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64) /* Scaling factor for the effector map used to skip some of the more expensive deterministic steps. The actual divisor is set to @@ -400,5 +400,15 @@ #endif #endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ +/* Extended forkserver option values */ + +#define FS_OPT_ENABLED 0x8f000001 +#define FS_OPT_MAPSIZE 0x40000000 +#define FS_OPT_SNAPSHOT 0x20000000 +#define FS_OPT_AUTODICT 0x10000000 +#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) +#define FS_OPT_SET_MAPSIZE(x) \ + (x <= 1 || x > MAP_SIZE || x > 0x1000000 ? 0 : ((x - 1) << 1)) + #endif /* ! _HAVE_CONFIG_H */ diff --git a/include/debug.h b/include/debug.h index b3865c19..8824ff6b 100644 --- a/include/debug.h +++ b/include/debug.h @@ -28,10 +28,23 @@ #include "types.h" #include "config.h" +/* __FUNCTION__ is non-iso */ +#ifndef __FUNCTION__ +#ifdef __func__ +#define __FUNCTION__ __func__ +#else +#define __FUNCTION__ "func_unknown" +#endif +#endif + /******************* * Terminal colors * *******************/ +#ifndef MESSAGES_TO_STDOUT +#define MESSAGES_TO_STDOUT +#endif + #ifdef USE_COLOR #define cBLK "\x1b[0;30m" diff --git a/include/forkserver.h b/include/forkserver.h index 9802b216..6fbaf612 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -51,6 +51,8 @@ typedef struct afl_forkserver { fsrv_st_fd; /* Fork server status pipe (read) */ u32 exec_tmout; /* Configurable exec timeout (ms) */ + u32 map_size; /* map size used by the target */ + u32 snapshot; /* is snapshot feature used */ u64 mem_limit; /* Memory cap for child (MB) */ u8 *out_file, /* File to fuzz, if any */ @@ -62,13 +64,27 @@ typedef struct afl_forkserver { u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ + u32 prev_timed_out; /* if prev forkserver run timed out */ + + u8 qemu_mode; /* if running in qemu mode or not */ + + char *cmplog_binary; /* the name of the cmplog binary */ + + /* Function to kick off the forkserver child */ + void (*init_child_func)(struct afl_forkserver *fsrv, char **argv); + + u8 *function_opt; /* for autodictionary: afl ptr */ + + void (*function_ptr)(void *afl_tmp, u8 *mem, u32 len); + } afl_forkserver_t; -void handle_timeout(int sig); void afl_fsrv_init(afl_forkserver_t *fsrv); -void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv); +void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from); +void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, + volatile u8 *stop_soon_p, u8 debug_child_output); +void afl_fsrv_killall(void); void afl_fsrv_deinit(afl_forkserver_t *fsrv); -void afl_fsrv_killall(); #ifdef __APPLE__ #define MSG_FORK_ON_APPLE \ diff --git a/include/list.h b/include/list.h index 1190931f..bb985c4f 100644 --- a/include/list.h +++ b/include/list.h @@ -34,8 +34,8 @@ #include "debug.h" #include "afl-prealloc.h" -#define LIST_PREALLOC_SIZE \ - (64) /* How many elements to allocate before malloc is needed */ +/* How many elements to allocate before malloc is needed */ +#define LIST_PREALLOC_SIZE (64) typedef struct list_element { @@ -50,23 +50,24 @@ typedef struct list_element { typedef struct list { element_t element_prealloc_buf[LIST_PREALLOC_SIZE]; - u32 element_prealloc_count; + s32 element_prealloc_count; } list_t; static inline element_t *get_head(list_t *list) { - return &list->element_prealloc_buf[0]; + /* The first element is the head */ + return list->element_prealloc_buf; } -static void list_free_el(list_t *list, element_t *el) { +static inline void list_free_el(list_t *list, element_t *el) { PRE_FREE(el, list->element_prealloc_count); } -static void list_append(list_t *list, void *el) { +static inline void list_append(list_t *list, void *el) { element_t *head = get_head(list); if (!head->next) { @@ -97,23 +98,23 @@ static void list_append(list_t *list, void *el) { A return from this block will return from calling func. */ -#define LIST_FOREACH(list, type, block) \ - do { \ - \ - list_t * li = (list); \ - element_t *head = get_head((li)); \ - element_t *el_box = (head)->next; \ - if (!el_box) FATAL("foreach over uninitialized list"); \ - while (el_box != head) { \ - \ - type *el = (type *)((el_box)->data); \ - /* get next so el_box can be unlinked */ \ - element_t *next = el_box->next; \ - {block}; \ - el_box = next; \ - \ - } \ - \ +#define LIST_FOREACH(list, type, block) \ + do { \ + \ + list_t * li = (list); \ + element_t *head = get_head((li)); \ + element_t *el_box = (head)->next; \ + if (!el_box) FATAL("foreach over uninitialized list"); \ + while (el_box != head) { \ + \ + __attribute__((unused)) type *el = (type *)((el_box)->data); \ + /* get next so el_box can be unlinked */ \ + element_t *next = el_box->next; \ + {block}; \ + el_box = next; \ + \ + } \ + \ } while (0); /* In foreach: remove the current el from the list */ @@ -143,7 +144,7 @@ static void list_append(list_t *list, void *el) { /* remove an item from the list */ -static void list_remove(list_t *list, void *remove_me) { +static inline void list_remove(list_t *list, void *remove_me) { LIST_FOREACH(list, void, { @@ -165,7 +166,7 @@ static void list_remove(list_t *list, void *remove_me) { /* Returns true if el is in list */ -static bool list_contains(list_t *list, void *contains_me) { +static inline bool list_contains(list_t *list, void *contains_me) { LIST_FOREACH(list, void, { diff --git a/include/snapshot-inl.h b/include/snapshot-inl.h new file mode 100644 index 00000000..b73a001e --- /dev/null +++ b/include/snapshot-inl.h @@ -0,0 +1,59 @@ +/* + american fuzzy lop++ - snapshot helpers routines + ------------------------------------------------ + + Originally written by Michal Zalewski + + Forkserver design by Jann Horn <jannhorn@googlemail.com> + + Now maintained by Marc Heuse <mh@mh-sec.de>, + Heiko Eißfeldt <heiko.eissfeldt@hexco.de>, + Andrea Fioraldi <andreafioraldi@gmail.com>, + Dominik Maier <mail@dmnk.co> + + Copyright 2016, 2017 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + + http://www.apache.org/licenses/LICENSE-2.0 + + */ + +// From AFL-Snapshot-LKM/include/afl_snapshot.h (must be kept synced) + +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> + +#define AFL_SNAPSHOT_FILE_NAME "/dev/afl_snapshot" + +#define AFL_SNAPSHOT_IOCTL_MAGIC 44313 + +#define AFL_SNAPSHOT_IOCTL_DO _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 1) +#define AFL_SNAPSHOT_IOCTL_CLEAN _IO(AFL_SNAPSHOT_IOCTL_MAGIC, 2) + +static int afl_snapshot_dev_fd; + +static int afl_snapshot_init(void) { + + afl_snapshot_dev_fd = open(AFL_SNAPSHOT_FILE_NAME, 0); + return afl_snapshot_dev_fd; + +} + +static int afl_snapshot_do() { + + return ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_DO); + +} + +static int afl_snapshot_clean(void) { + + return ioctl(afl_snapshot_dev_fd, AFL_SNAPSHOT_IOCTL_CLEAN); + +} + diff --git a/include/types.h b/include/types.h index bd4bd05d..f2a12953 100644 --- a/include/types.h +++ b/include/types.h @@ -46,7 +46,7 @@ typedef uint32_t u32; */ -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) typedef unsigned long long u64; #else typedef uint64_t u64; @@ -58,8 +58,22 @@ typedef int32_t s32; typedef int64_t s64; #ifndef MIN -#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) -#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#define MIN(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + \ + }) +#define MAX(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + \ + }) #endif /* !MIN */ #define SWAP16(_x) \ @@ -120,9 +134,13 @@ typedef int64_t s64; #define likely(_x) (_x) #define unlikely(_x) (_x) #else +#ifndef likely #define likely(_x) __builtin_expect(!!(_x), 1) +#endif +#ifndef unlikely #define unlikely(_x) __builtin_expect(!!(_x), 0) #endif +#endif #endif /* ! _HAVE_TYPES_H */ |