mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-16 11:58:08 +00:00
compcov levels to enable the instrumentation of only immediates
This commit is contained in:
@ -18,15 +18,19 @@ For optimized binaries this is an issue, those functions are often inlined
|
||||
and this module is not capable to log the coverage in this case.
|
||||
|
||||
If you have the source code of the fuzzing target you should nto use this
|
||||
library and QEMU but build ot with afl-clang-fast and the laf-intel options.
|
||||
library and QEMU but build it with afl-clang-fast and the laf-intel options.
|
||||
|
||||
To use this library make sure to preload it with AFL_PRELOAD.
|
||||
|
||||
export AFL_PRELOAD=/path/to/libcompcov.so
|
||||
export AFL_QEMU_COMPCOV=1
|
||||
export AFL_COMPCOV_LEVEL=1
|
||||
|
||||
afl-fuzz -Q -i input -o output <your options> -- <target args>
|
||||
|
||||
The AFL_COMPCOV_LEVEL tells to QEMU and libcompcov how to log comaprisons.
|
||||
Level 1 logs just comparison with immediates / read-only memory and level 2
|
||||
logs all the comparisons.
|
||||
|
||||
The library make use of https://github.com/ouadev/proc_maps_parser and so it is
|
||||
Linux specific. However this is not a strict dependency, other UNIX operating
|
||||
systems can be supported simply replacing the code related to the
|
||||
|
@ -45,6 +45,8 @@ static void *__compcov_code_start,
|
||||
|
||||
static u8 *__compcov_afl_map;
|
||||
|
||||
static u32 __compcov_level;
|
||||
|
||||
static int (*__libc_strcmp)(const char*, const char*);
|
||||
static int (*__libc_strncmp)(const char*, const char*, size_t);
|
||||
static int (*__libc_strcasecmp)(const char*, const char*);
|
||||
@ -54,6 +56,28 @@ static int (*__libc_memcmp)(const void*, const void*, size_t);
|
||||
static int debug_fd = -1;
|
||||
|
||||
|
||||
#define MAX_MAPPINGS 1024
|
||||
|
||||
static struct mapping {
|
||||
void *st, *en;
|
||||
} __compcov_ro[MAX_MAPPINGS];
|
||||
|
||||
static u32 __compcov_ro_cnt;
|
||||
|
||||
|
||||
/* Check an address against the list of read-only mappings. */
|
||||
|
||||
static u8 __compcov_is_ro(const void* ptr) {
|
||||
|
||||
u32 i;
|
||||
|
||||
for (i = 0; i < __compcov_ro_cnt; i++)
|
||||
if (ptr >= __compcov_ro[i].st && ptr <= __compcov_ro[i].en) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static size_t __strlen2(const char *s1, const char *s2, size_t max_length) {
|
||||
// from https://github.com/googleprojectzero/CompareCoverage
|
||||
|
||||
@ -71,6 +95,15 @@ static void __compcov_load(void) {
|
||||
__libc_strcasecmp = dlsym(RTLD_NEXT, "strcasecmp");
|
||||
__libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp");
|
||||
__libc_memcmp = dlsym(RTLD_NEXT, "memcmp");
|
||||
|
||||
if (getenv("AFL_QEMU_COMPCOV")) {
|
||||
|
||||
__compcov_level = 1;
|
||||
}
|
||||
if (getenv("AFL_COMPCOV_LEVEL")) {
|
||||
|
||||
__compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL"));
|
||||
}
|
||||
|
||||
char *id_str = getenv(SHM_ENV_VAR);
|
||||
int shm_id;
|
||||
@ -110,6 +143,12 @@ static void __compcov_load(void) {
|
||||
__compcov_code_end = maps_tmp->addr_end;
|
||||
}
|
||||
}
|
||||
|
||||
if ((maps_tmp->is_w && !maps_tmp->is_r) || __compcov_ro_cnt == MAX_MAPPINGS)
|
||||
continue;
|
||||
|
||||
__compcov_ro[__compcov_ro_cnt].st = maps_tmp->addr_start;
|
||||
__compcov_ro[__compcov_ro_cnt].en = maps_tmp->addr_end;
|
||||
}
|
||||
|
||||
pmparser_free(maps);
|
||||
@ -149,7 +188,8 @@ int strcmp(const char* str1, const char* str2) {
|
||||
|
||||
void* retaddr = __builtin_return_address(0);
|
||||
|
||||
if (__compcov_is_in_bound(retaddr)) {
|
||||
if (__compcov_is_in_bound(retaddr) && !(__compcov_level < 2 &&
|
||||
!__compcov_is_ro(str1) && !__compcov_is_ro(str2))) {
|
||||
|
||||
size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
|
||||
|
||||
@ -173,7 +213,8 @@ int strncmp(const char* str1, const char* str2, size_t len) {
|
||||
|
||||
void* retaddr = __builtin_return_address(0);
|
||||
|
||||
if (__compcov_is_in_bound(retaddr)) {
|
||||
if (__compcov_is_in_bound(retaddr) && !(__compcov_level < 2 &&
|
||||
!__compcov_is_ro(str1) && !__compcov_is_ro(str2))) {
|
||||
|
||||
size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
|
||||
n = MIN(n, len);
|
||||
@ -198,7 +239,8 @@ int strcasecmp(const char* str1, const char* str2) {
|
||||
|
||||
void* retaddr = __builtin_return_address(0);
|
||||
|
||||
if (__compcov_is_in_bound(retaddr)) {
|
||||
if (__compcov_is_in_bound(retaddr) && !(__compcov_level < 2 &&
|
||||
!__compcov_is_ro(str1) && !__compcov_is_ro(str2))) {
|
||||
/* Fallback to strcmp, maybe improve in future */
|
||||
|
||||
size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
|
||||
@ -223,7 +265,8 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
|
||||
|
||||
void* retaddr = __builtin_return_address(0);
|
||||
|
||||
if (__compcov_is_in_bound(retaddr)) {
|
||||
if (__compcov_is_in_bound(retaddr) && !(__compcov_level < 2 &&
|
||||
!__compcov_is_ro(str1) && !__compcov_is_ro(str2))) {
|
||||
/* Fallback to strncmp, maybe improve in future */
|
||||
|
||||
size_t n = __strlen2(str1, str2, MAX_CMP_LENGTH +1);
|
||||
@ -249,7 +292,8 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
|
||||
|
||||
void* retaddr = __builtin_return_address(0);
|
||||
|
||||
if (__compcov_is_in_bound(retaddr)) {
|
||||
if (__compcov_is_in_bound(retaddr) && !(__compcov_level < 2 &&
|
||||
!__compcov_is_ro(mem1) && !__compcov_is_ro(mem2))) {
|
||||
|
||||
size_t n = len;
|
||||
|
||||
|
@ -66,7 +66,7 @@ abi_ulong afl_entry_point, /* ELF entry point (_start) */
|
||||
afl_start_code, /* .text start pointer */
|
||||
afl_end_code; /* .text end pointer */
|
||||
|
||||
u8 afl_enable_compcov;
|
||||
u8 afl_compcov_level;
|
||||
|
||||
/* Set in the child process in forkserver mode: */
|
||||
|
||||
@ -159,9 +159,14 @@ static void afl_setup(void) {
|
||||
|
||||
}
|
||||
|
||||
/* Maintain for compatibility */
|
||||
if (getenv("AFL_QEMU_COMPCOV")) {
|
||||
|
||||
afl_enable_compcov = 1;
|
||||
afl_compcov_level = 1;
|
||||
}
|
||||
if (getenv("AFL_COMPCOV_LEVEL")) {
|
||||
|
||||
afl_compcov_level = atoi(getenv("AFL_COMPCOV_LEVEL"));
|
||||
}
|
||||
|
||||
/* pthread_atfork() seems somewhat broken in util/rcu.c, and I'm
|
||||
|
@ -40,7 +40,7 @@
|
||||
extern unsigned char *afl_area_ptr;
|
||||
extern unsigned int afl_inst_rms;
|
||||
extern abi_ulong afl_start_code, afl_end_code;
|
||||
extern u8 afl_enable_compcov;
|
||||
extern u8 afl_compcov_level;
|
||||
|
||||
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
|
||||
TCGv_i64 arg1, TCGv_i64 arg2);
|
||||
@ -95,11 +95,14 @@ static void afl_compcov_log_64(target_ulong cur_loc, target_ulong arg1,
|
||||
|
||||
|
||||
static void afl_gen_compcov(target_ulong cur_loc, TCGv_i64 arg1, TCGv_i64 arg2,
|
||||
TCGMemOp ot) {
|
||||
TCGMemOp ot, int is_imm) {
|
||||
|
||||
void *func;
|
||||
|
||||
if (!afl_enable_compcov || cur_loc > afl_end_code || cur_loc < afl_start_code)
|
||||
if (!afl_compcov_level || cur_loc > afl_end_code || cur_loc < afl_start_code)
|
||||
return;
|
||||
|
||||
if (!is_imm && afl_compcov_level < 2)
|
||||
return;
|
||||
|
||||
switch (ot) {
|
||||
|
@ -15,11 +15,11 @@ index 0dd5fbe4..b95d341e 100644
|
||||
tcg_gen_atomic_fetch_add_tl(s1->cc_srcT, s1->A0, s1->T0,
|
||||
s1->mem_index, ot | MO_LE);
|
||||
tcg_gen_sub_tl(s1->T0, s1->cc_srcT, s1->T1);
|
||||
+ afl_gen_compcov(s1->pc, s1->cc_srcT, s1->T1, ot);
|
||||
+ afl_gen_compcov(s1->pc, s1->cc_srcT, s1->T1, ot, d == OR_EAX);
|
||||
} else {
|
||||
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
|
||||
tcg_gen_sub_tl(s1->T0, s1->T0, s1->T1);
|
||||
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot);
|
||||
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot, d == OR_EAX);
|
||||
gen_op_st_rm_T0_A0(s1, ot, d);
|
||||
}
|
||||
gen_op_update2_cc(s1);
|
||||
@ -27,7 +27,7 @@ index 0dd5fbe4..b95d341e 100644
|
||||
tcg_gen_mov_tl(cpu_cc_src, s1->T1);
|
||||
tcg_gen_mov_tl(s1->cc_srcT, s1->T0);
|
||||
tcg_gen_sub_tl(cpu_cc_dst, s1->T0, s1->T1);
|
||||
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot);
|
||||
+ afl_gen_compcov(s1->pc, s1->T0, s1->T1, ot, d == OR_EAX);
|
||||
set_cc_op(s1, CC_OP_SUBB + ot);
|
||||
break;
|
||||
}
|
||||
|
Reference in New Issue
Block a user