From 132177209d345134211cf7d02b68138da4924ac4 Mon Sep 17 00:00:00 2001 From: JackGrence Date: Thu, 11 Mar 2021 16:11:19 +0800 Subject: [PATCH 1/2] Fix forkserver caching problem QEMU use env->hflags and env->btarget to fix delay slot problem. But unicornafl forgot it, will cause AFL++ crash at the calibration stage. I only fix for mips. Make my mips target happy. --- afl-unicorn-cpu-inl.h | 18 +++++++++++++++--- qemu/cpu-exec.c | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/afl-unicorn-cpu-inl.h b/afl-unicorn-cpu-inl.h index 097df48302..6b4e29f0c2 100644 --- a/afl-unicorn-cpu-inl.h +++ b/afl-unicorn-cpu-inl.h @@ -61,7 +61,7 @@ static inline uc_afl_ret afl_forkserver(CPUArchState*); static int afl_find_wifsignaled_id(void); static enum afl_child_ret afl_handle_child_requests(CPUArchState*); -static void afl_request_tsl(struct uc_struct* uc, target_ulong, target_ulong, uint64_t); +static void afl_request_tsl(CPUArchState *env, target_ulong, target_ulong, uint64_t); static uc_afl_ret afl_request_next(struct uc_struct* uc, bool found_crash); // static TranslationBlock* tb_find_slow(CPUArchState*, target_ulong, target_ulong, uint64_t); @@ -73,6 +73,10 @@ struct afl_tsl { target_ulong pc; target_ulong cs_base; uint64_t flags; +#if defined(TARGET_MIPS) + target_ulong hflags; + target_ulong btarget; +#endif }; @@ -378,18 +382,22 @@ static inline uc_afl_ret afl_forkserver(CPUArchState* env) { we tell the parent to mirror the operation, so that the next fork() has a cached copy. */ -static inline void afl_request_tsl(struct uc_struct* uc, target_ulong pc, target_ulong cb, uint64_t flags) { +static inline void afl_request_tsl(CPUArchState *env, target_ulong pc, target_ulong cb, uint64_t flags) { /* Dual use: if this func is not set, we're not a child process */ + struct uc_struct* uc = env->uc; if (uc->afl_child_request_next == NULL) return; - enum afl_child_ret tsl_req = AFL_CHILD_TSL_REQUEST; struct afl_tsl t = { .pc = pc, .cs_base = cb, .flags = flags, +#if defined(TARGET_MIPS) + .hflags = env->hflags, + .btarget = env->btarget, +#endif }; #if defined(AFL_DEBUG) @@ -479,6 +487,10 @@ static enum afl_child_ret afl_handle_child_requests(CPUArchState* env) { if (read(_R(env->uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) return AFL_CHILD_EXITED; // child is dead. // Cache. +#if defined(TARGET_MIPS) + env->hflags = t.hflags; + env->btarget = t.btarget; +#endif tb_find_slow(env, t.pc, t.cs_base, t.flags); } else { diff --git a/qemu/cpu-exec.c b/qemu/cpu-exec.c index 6211698a9e..8b8efba03c 100644 --- a/qemu/cpu-exec.c +++ b/qemu/cpu-exec.c @@ -459,7 +459,7 @@ static TranslationBlock *tb_find_slow(CPUArchState *env, target_ulong pc, } #if defined(UNICORN_AFL) - afl_request_tsl(env->uc, pc, cs_base, flags); + afl_request_tsl(env, pc, cs_base, flags); #endif found: From 07f480667698ffe1908c780c6c728961192432a0 Mon Sep 17 00:00:00 2001 From: JackGrence Date: Thu, 11 Mar 2021 22:42:55 +0800 Subject: [PATCH 2/2] Restore hflags --- afl-unicorn-cpu-inl.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/afl-unicorn-cpu-inl.h b/afl-unicorn-cpu-inl.h index 6b4e29f0c2..c774f9f43d 100644 --- a/afl-unicorn-cpu-inl.h +++ b/afl-unicorn-cpu-inl.h @@ -486,13 +486,24 @@ static enum afl_child_ret afl_handle_child_requests(CPUArchState* env) { // Child will send a tsl request next, that we have to cache. if (read(_R(env->uc->afl_child_pipe), &t, sizeof(struct afl_tsl)) != sizeof(struct afl_tsl)) return AFL_CHILD_EXITED; // child is dead. - // Cache. + // Prepare hflags for delay slot #if defined(TARGET_MIPS) + struct afl_tsl tmp; + tmp.hflags = env->hflags; + tmp.btarget = env->btarget; env->hflags = t.hflags; env->btarget = t.btarget; #endif + + // Cache. tb_find_slow(env, t.pc, t.cs_base, t.flags); + // Restore hflags +#if defined(TARGET_MIPS) + env->hflags = tmp.hflags; + env->btarget = tmp.btarget; +#endif + } else { fprintf(stderr, "[!] Unexpected response by child! %d. Please report this as bug for unicornafl.\n"