From d965c0f159256b10042a46a032dc56690baf5b45 Mon Sep 17 00:00:00 2001 From: lazymio Date: Mon, 25 Oct 2021 10:46:52 +0200 Subject: [PATCH] Use UCLOG and fix uc_afl_fuzz --- include/afl/afl-cpu-inl.h | 26 ++++++++++------ include/uc_priv.h | 5 +++ qemu/tcg/tcg.c | 64 +++++++++++++++++++-------------------- qemu/unicorn_common.h | 5 ++- uc.c | 38 ++++++++++++----------- 5 files changed, 78 insertions(+), 60 deletions(-) diff --git a/include/afl/afl-cpu-inl.h b/include/afl/afl-cpu-inl.h index 5a781e6f..fcb44b8e 100644 --- a/include/afl/afl-cpu-inl.h +++ b/include/afl/afl-cpu-inl.h @@ -75,8 +75,8 @@ struct afl_tsl { uint64_t flags; uint32_t cf_mask; #if defined(TARGET_MIPS) - TCGv_i32 hflags; - TCGv_i32 btarget; + target_ulong hflags; + target_ulong btarget; #endif }; @@ -390,6 +390,9 @@ static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong struct uc_struct* uc = cpu->uc; if (uc->afl_child_request_next == NULL) return; enum afl_child_ret tsl_req = AFL_CHILD_TSL_REQUEST; +#if defined(TARGET_MIPS) + CPUArchState* env = cpu->env_ptr; +#endif struct afl_tsl t = { .pc = pc, @@ -397,8 +400,8 @@ static inline void afl_request_tsl(CPUState *cpu, target_ulong pc, target_ulong .flags = flags, .cf_mask = cf_mask, #if defined(TARGET_MIPS) - .hflags = cpu->uc->tcg_ctx->hflags, - .btarget = cpu->uc->tcg_ctx->btarget, + .hflags = env->hflags, + .btarget = env->btarget, #endif }; @@ -469,6 +472,9 @@ static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { enum afl_child_ret child_msg; struct afl_tsl t; +#if defined(TARGET_MIPS) + CPUArchState* env = cpu->env_ptr; +#endif while (1) { @@ -491,10 +497,10 @@ static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { // Prepare hflags for delay slot #if defined(TARGET_MIPS) struct afl_tsl tmp; - tmp.hflags = cpu->uc->tcg_ctx->hflags; - tmp.btarget = cpu->uc->tcg_ctx->btarget; - cpu->uc->tcg_ctx->hflags = t.hflags; - cpu->uc->tcg_ctx->btarget = t.btarget; + tmp.hflags = env->hflags; + tmp.btarget = env->btarget; + env->hflags = t.hflags; + env->btarget = t.btarget; #endif // Cache. @@ -504,8 +510,8 @@ static enum afl_child_ret afl_handle_child_requests(CPUState* cpu) { // Restore hflags #if defined(TARGET_MIPS) - cpu->uc->tcg_ctx->hflags = tmp.hflags; - cpu->uc->tcg_ctx->btarget = tmp.btarget; + env->hflags = tmp.hflags; + env->btarget = tmp.btarget; #endif } else { diff --git a/include/uc_priv.h b/include/uc_priv.h index 4f1bf4a9..b881a666 100644 --- a/include/uc_priv.h +++ b/include/uc_priv.h @@ -35,6 +35,11 @@ #define UC_MODE_RISCV_MASK (UC_MODE_RISCV32|UC_MODE_RISCV64|UC_MODE_LITTLE_ENDIAN) #endif +#ifndef NDEBUG +#define UCLOG(...) fprintf(stderr, __VA_ARGS__) +#else +#define UCLOG(...) +#endif #define ARR_SIZE(a) (sizeof(a)/sizeof(a[0])) diff --git a/qemu/tcg/tcg.c b/qemu/tcg/tcg.c index 5fd5ff0f..6e4f3d49 100644 --- a/qemu/tcg/tcg.c +++ b/qemu/tcg/tcg.c @@ -1655,7 +1655,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) def = &s->tcg_op_defs[c]; if (c == INDEX_op_insn_start) { nb_oargs = 0; - printf(" ----"); + UCLOG(" ----"); for (i = 0; i < TARGET_INSN_START_WORDS; ++i) { target_ulong a; @@ -1664,7 +1664,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) #else a = op->args[i]; #endif - printf(" " TARGET_FMT_lx, a); + UCLOG(" " TARGET_FMT_lx, a); } } else if (c == INDEX_op_call) { /* variable number of arguments */ @@ -1673,11 +1673,11 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) nb_cargs = def->nb_cargs; /* function name, flags, out args */ - printf(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, + UCLOG(" %s %s,$0x%" TCG_PRIlx ",$%d", def->name, tcg_find_helper(s, op->args[nb_oargs + nb_iargs]), op->args[nb_oargs + nb_iargs + 1], nb_oargs); for (i = 0; i < nb_oargs; i++) { - printf(",%s", tcg_get_arg_str(s, buf, sizeof(buf), + UCLOG(",%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[i])); } for (i = 0; i < nb_iargs; i++) { @@ -1686,33 +1686,33 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) if (arg != TCG_CALL_DUMMY_ARG) { t = tcg_get_arg_str(s, buf, sizeof(buf), arg); } - printf(",%s", t); + UCLOG(",%s", t); } } else { - printf(" %s ", def->name); + UCLOG(" %s ", def->name); nb_oargs = def->nb_oargs; nb_iargs = def->nb_iargs; nb_cargs = def->nb_cargs; if (def->flags & TCG_OPF_VECTOR) { - printf("v%d,e%d,", 64 << TCGOP_VECL(op), + UCLOG("v%d,e%d,", 64 << TCGOP_VECL(op), 8 << TCGOP_VECE(op)); } k = 0; for (i = 0; i < nb_oargs; i++) { if (k != 0) { - printf(","); + UCLOG(","); } - printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), + UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } for (i = 0; i < nb_iargs; i++) { if (k != 0) { - printf(","); + UCLOG(","); } - printf("%s", tcg_get_arg_str(s, buf, sizeof(buf), + UCLOG("%s", tcg_get_arg_str(s, buf, sizeof(buf), op->args[k++])); } switch (c) { @@ -1728,9 +1728,9 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_cmpsel_vec: if (op->args[k] < ARRAY_SIZE(cond_name) && cond_name[op->args[k]]) { - printf(",%s", cond_name[op->args[k++]]); + UCLOG(",%s", cond_name[op->args[k++]]); } else { - printf(",$0x%" TCG_PRIlx, op->args[k++]); + UCLOG(",$0x%" TCG_PRIlx, op->args[k++]); } i = 1; break; @@ -1744,12 +1744,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned ix = get_mmuidx(oi); if (op & ~(MO_AMASK | MO_BSWAP | MO_SSIZE)) { - printf(",$0x%x,%u", op, ix); + UCLOG(",$0x%x,%u", op, ix); } else { const char *s_al, *s_op; s_al = alignment_name[(op & MO_AMASK) >> MO_ASHIFT]; s_op = ldst_name[op & (MO_BSWAP | MO_SSIZE)]; - printf(",%s%s,%u", s_al, s_op, ix); + UCLOG(",%s%s,%u", s_al, s_op, ix); } i = 1; } @@ -1764,7 +1764,7 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) case INDEX_op_brcond_i32: case INDEX_op_brcond_i64: case INDEX_op_brcond2_i32: - printf("%s$L%d", k ? "," : "", + UCLOG("%s$L%d", k ? "," : "", arg_label(op->args[k])->id); i++, k++; break; @@ -1772,12 +1772,12 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) break; } for (; i < nb_cargs; i++, k++) { - printf("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); + UCLOG("%s$0x%" TCG_PRIlx, k ? "," : "", op->args[k]); } if(c == INDEX_op_mov_i64){ struct TCGTemp* tp = arg_temp(op->args[1]); if (tp && tp->val_type == TEMP_VAL_MEM){ - printf(" mem_base=%p ", tp->mem_base); + UCLOG(" mem_base=%p ", tp->mem_base); } } } @@ -1786,19 +1786,19 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) unsigned life = op->life; if (life & (SYNC_ARG * 3)) { - printf(" sync:"); + UCLOG(" sync:"); for (i = 0; i < 2; ++i) { if (life & (SYNC_ARG << i)) { - printf(" %d", i); + UCLOG(" %d", i); } } } life /= DEAD_ARG; if (life) { - printf(" dead:"); + UCLOG(" dead:"); for (i = 0; life; ++i, life >>= 1) { if (life & 1) { - printf(" %d", i); + UCLOG(" %d", i); } } } @@ -1809,28 +1809,28 @@ void tcg_dump_op(TCGContext *s, bool have_prefs, TCGOp* op) TCGRegSet set = op->output_pref[i]; if (i == 0) { - printf(" pref="); + UCLOG(" pref="); } else { - printf(","); + UCLOG(","); } if (set == 0) { - printf("none"); + UCLOG("none"); } else if (set == MAKE_64BIT_MASK(0, TCG_TARGET_NB_REGS)) { - printf("all"); + UCLOG("all"); #ifdef CONFIG_DEBUG_TCG } else if (tcg_regset_single(set)) { TCGReg reg = tcg_regset_first(set); printf("%s", tcg_target_reg_names[reg]); #endif } else if (TCG_TARGET_NB_REGS <= 32) { - printf("%#x", (uint32_t)set); + UCLOG("%#x", (uint32_t)set); } else { - printf("%#" PRIx64, (uint64_t)set); + UCLOG("%#" PRIx64, (uint64_t)set); } } } - printf("\n"); + UCLOG("\n"); } #if 0 @@ -1863,16 +1863,16 @@ void tcg_dump_ops(TCGContext *s, bool have_prefs, const char *headline) int insn_idx = 0; int op_idx = 0; - printf("\n*** %s\n", headline); + UCLOG("\n*** %s\n", headline); // tcg_dump_tbs(s, tcg_dump_tb, NULL); QTAILQ_FOREACH(op, &s->ops, link) { if (op->opc == INDEX_op_insn_start) { - printf("\n insn_idx=%d", insn_idx); + UCLOG("\n insn_idx=%d", insn_idx); insn_idx++; op_idx = 0; } else { - printf(" %d: ", op_idx); + UCLOG(" %d: ", op_idx); } op_idx++; tcg_dump_op(s, have_prefs, op); diff --git a/qemu/unicorn_common.h b/qemu/unicorn_common.h index 84bbb9f1..02b10ea8 100644 --- a/qemu/unicorn_common.h +++ b/qemu/unicorn_common.h @@ -11,6 +11,7 @@ void vm_start(struct uc_struct*); void tcg_exec_init(struct uc_struct *uc, unsigned long tb_size); +int afl_forkserver_start(struct uc_struct*); // return true on success, false on failure static inline bool cpu_physical_mem_read(AddressSpace *as, hwaddr addr, @@ -106,7 +107,9 @@ static inline void uc_common_init(struct uc_struct* uc) uc->softfloat_initialize = softfloat_init; uc->tcg_flush_tlb = tcg_flush_softmmu_tlb; uc->memory_map_io = memory_map_io; - +#ifdef UNICORN_HAS_AFL + uc->afl_forkserver_start = afl_forkserver_start; +#endif if (!uc->release) uc->release = release_common; } diff --git a/uc.c b/uc.c index c5024447..2ad8edc7 100644 --- a/uc.c +++ b/uc.c @@ -934,24 +934,27 @@ uc_err uc_afl_fuzz( return UC_ERR_MODE; #else if (!uc) { - fprintf(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] Unicorn Engine passed to uc_afl_fuzz is NULL!\n"); + return UC_ERR_AFL_RET_ERROR; + } + if (!(uc->mode & UC_MODE_AFL)) { + return UC_ERR_MODE; } if (!input_file || input_file[0] == 0) { - fprintf(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] No input file provided to uc_afl_fuzz.\n"); + return UC_ERR_AFL_RET_ERROR; } if (!place_input_callback) { - fprintf(stderr, "[!] no place_input_callback set.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] no place_input_callback set.\n"); + return UC_ERR_AFL_RET_ERROR; } if (always_validate && !validate_crash_callback) { - fprintf(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] always_validate set but validate_crash_callback is missing.\n"); + return UC_ERR_AFL_RET_ERROR; } if (!exit_count) { - fprintf(stderr, "[!] Nullptr provided for exits.\n"); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] Nullptr provided for exits.\n"); + return UC_ERR_AFL_RET_ERROR; } uint32_t mmap_in_len = 0; @@ -977,15 +980,16 @@ uc_err uc_afl_fuzz( break; case UC_AFL_RET_FINISHED: // Nothing more to do - return afl_ret; + return UC_ERR_AFL_RET_FINISHED; case UC_AFL_RET_ERROR: + return UC_ERR_AFL_RET_ERROR; case UC_AFL_RET_CALLED_TWICE: // Nothing more we can do - return afl_ret; + return UC_ERR_AFL_RET_CALLED_TWICE; default: // What have we done - fprintf(stderr, "[!] Unexpected forkserver return: %d", afl_ret); - return UC_AFL_RET_ERROR; + UCLOG(stderr, "[!] Unexpected forkserver return: %d", afl_ret); + return UC_ERR_AFL_RET_ERROR; } bool first_round = true; @@ -993,7 +997,7 @@ uc_err uc_afl_fuzz( #if defined(AFL_DEBUG) if (uc->afl_testcase_ptr) { - printf("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); + UCLOG("[d] uc->afl_testcase_ptr = %p, len = %d\n", uc->afl_testcase_ptr, *uc->afl_testcase_size_p); } #endif @@ -1018,7 +1022,7 @@ uc_err uc_afl_fuzz( No shmap fuzzing involved - Let's read a "normal" file. */ off_t in_len = uc_afl_mmap_file(input_file, &in_buf); if (unlikely(in_len < 0)) { - fprintf(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); + UCLOG(stderr, "[!] Unable to mmap file: %s (return was %ld)\n", input_file, (long int) in_len); perror("mmap"); fflush(stderr); return UC_AFL_RET_ERROR; @@ -1047,7 +1051,7 @@ uc_err uc_afl_fuzz( goto next_iter; } - fprintf(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); + UCLOG(stderr, "[!] UC returned Error: '%s' - let's abort().\n", uc_strerror(uc_emu_ret)); fflush(stderr); abort();