Ejemplo n.º 1
0
static dr_emit_flags_t
bb_event(void *drcontext, void *tag, instrlist_t *bb,
         bool for_trace, bool translating)
{
    fuzz_pass_context_t *fp;
    pass_target_t *live;

    if (for_trace || translating)
        return DR_EMIT_DEFAULT;

    /* It is ok to be racy, so hold no locks for updating. */
    /* update global num_bbs */
    num_total_bbs++;
    /* update num_bbs for each live target */
    fp = (fuzz_pass_context_t *) drmgr_get_tls_field(drcontext, tls_idx_fuzzer);
    live = fp->live_targets;
    if (live != NULL) {
        /* XXX: the function entry basic block is not counted because the live target
         * is only added on its first execution after bb_event.
         */
        live->target->num_bbs++;
        DRFUZZ_LOG(3, "basic block "UINT64_FORMAT_STRING" @"PFX" during fuzzing "PFX"\n",
                   live->target->num_bbs, tag, live->target->func_pc);
    }
    return DR_EMIT_DEFAULT;
}
Ejemplo n.º 2
0
static void
post_fuzz_handler(void *wrapcxt, void *user_data)
{
    fuzz_pass_context_t *fp = (fuzz_pass_context_t *) user_data;
    pass_target_t *live = fp->live_targets;
    bool repeat = live->target->post_fuzz_cb(fp, (generic_func_t) live->target->func_pc);

    DRFUZZ_LOG(3, "post_fuzz() for target "PFX" (%s)\n", live->target->func_pc,
               repeat ? "repeat" : "stop");

    if (repeat) {
        dr_mcontext_t *mc = drwrap_get_mcontext(wrapcxt);
        IF_DEBUG(drext_status_t redirect_status;);
        /* restore the original xsp before repeating */
        DRFUZZ_LOG(4, "fuzz target "PFX": restoring xsp to "PFX"\n",
                   live->target->func_pc, live->xsp);
        mc->xsp = live->xsp;
        mc->pc = live->target->func_pc;
        IF_DEBUG(redirect_status =) drwrap_redirect_execution(wrapcxt);
        DRFUZZ_LOG(4, "fuzz target "PFX" requesting redirect to self entry; result: %d\n",
                   live->target->func_pc, live->target->func_pc, redirect_status);
    } else { /* the current target is finished, so pop from live stack and cache it */
Ejemplo n.º 3
0
static void
pre_fuzz_handler(void *wrapcxt, INOUT void **user_data)
{
    void *dcontext = drwrap_get_drcontext(wrapcxt);
    app_pc target_to_fuzz = drwrap_get_func(wrapcxt);
    fuzz_target_t *target = hashtable_lookup(&fuzz_target_htable, target_to_fuzz);
    fuzz_pass_context_t *fp = (fuzz_pass_context_t *) drmgr_get_tls_field(dcontext,
                                                                          tls_idx_fuzzer);
    bool is_target_entry = false;
    pass_target_t *live = NULL;
    dr_mcontext_t *mc;
    uint i;

    ASSERT(target != NULL, "pre_fuzz must be associated with a fuzz target");

    DRFUZZ_LOG(3, "pre_fuzz() for target "PFX" with %d args\n",
               target_to_fuzz, target->arg_count);

    /* XXX i#1734: this heuristic may be incorrect when a handled fault occurs during
     * the very last iteration of the last fuzz pass on any thread.
     */
    clear_thread_state(fp);

    /* Stop the target iterator that was captured at the last critical fault, because
     * the fact that we are in pre-fuzz implies the fault was handled and doesn't matter.
     */
    if (fp->thread_state->targets != NULL)
        drfuzz_target_iterator_stop(fp->thread_state->targets);

    /* XXX: assumes the fuzz target is never called recursively */
    if (fp->live_targets != NULL && fp->live_targets->target->func_pc == target_to_fuzz) {
        live = fp->live_targets; /* this is a repetition of the last live target */
    } else {
        is_target_entry = true; /* this is a new invocation of a target */
        live = activate_cached_target(fp, target_to_fuzz); /* check the cache */
        if (live == NULL)
            live = create_pass_target(dcontext, wrapcxt);
        live->next = fp->live_targets; /* push to live stack */
        fp->live_targets = live;
    }

    /* required by dr_redirect_execution() (avoids having to merge the mcontext) */
    mc = drwrap_get_mcontext_ex(wrapcxt, DR_MC_ALL); /* XXX: can we relax this? */

    if (is_target_entry) {
        live->xsp = mc->xsp;
#ifdef X86
        live->unclobber.retaddr_loc = (reg_t *) mc->xsp; /* see retaddr_unclobber_t */
#endif
        live->unclobber.retaddr = (reg_t) drwrap_get_retaddr(wrapcxt);
        DRFUZZ_LOG(4, "fuzz target "PFX": saving stack pointer "PFX"\n",
                   target_to_fuzz, mc->xsp);
        for (i = 0; i < target->arg_count; i++) { /* store the original arg values */
            live->original_args[i] = (reg_t) drwrap_get_arg(wrapcxt, i);
            /* copy original args to current args for the first iteration of the fuzz */
            live->current_args[i] = live->original_args[i];
            DRFUZZ_LOG(4, "fuzz target "PFX": saving original arg #%d: "PFX"\n",
                       target_to_fuzz, i, live->original_args[i]);
        }
    }

    /* restore the original arg values before calling the client */
    for (i = 0; i < target->arg_count; i++) {
        DRFUZZ_LOG(4, "fuzz target "PFX": restoring original arg #%d: "PFX"\n",
                   target_to_fuzz, i, live->original_args[i]);
        drwrap_set_arg(wrapcxt, i, (void *) live->original_args[i]);
    }

#ifdef ARM
    mc->lr = live->unclobber.retaddr; /* restore retaddr to link register */
#else /* X86 */
    *live->unclobber.retaddr_loc = live->unclobber.retaddr; /* restore retaddr to stack */
#endif

    target->pre_fuzz_cb(fp, (generic_func_t) target_to_fuzz, mc);
    drwrap_set_mcontext(wrapcxt);
    for (i = 0; i < target->arg_count; i++)
        live->current_args[i] = (reg_t) drwrap_get_arg(wrapcxt, i);

    *user_data = fp;
}