Beispiel #1
0
/* Initializes a dcontext with the supplied state and calls dispatch */
void
dynamo_start(priv_mcontext_t *mc)
{
    priv_mcontext_t *mcontext;
    dcontext_t *dcontext = get_thread_private_dcontext();
    ASSERT(dcontext != NULL);
    thread_starting(dcontext);

    /* Signal other threads for take over. */
    dynamorio_take_over_threads(dcontext);

    /* Set return address */
    mc->pc = canonicalize_pc_target(dcontext, mc->pc);
    dcontext->next_tag = mc->pc;
    ASSERT(dcontext->next_tag != NULL);

    /* transfer exec state to mcontext */
    mcontext = get_mcontext(dcontext);
    *mcontext = *mc;

    /* clear pc */
    mcontext->pc = 0;

    DOLOG(2, LOG_TOP, {
        byte *cur_esp;
        GET_STACK_PTR(cur_esp);
        LOG(THREAD, LOG_TOP, 2, "%s: next_tag="PFX", cur xsp="PFX", mc->xsp="PFX"\n",
            __FUNCTION__, dcontext->next_tag, cur_esp, mc->xsp);
    });
Beispiel #2
0
bool
instr_is_cti_short_rewrite(instr_t *instr, byte *pc)
{
    /* We assume all app's cbz/cbnz have been mangled.
     * See comments in x86/'s version of this routine.
     */
    dcontext_t *dcontext;
    dr_isa_mode_t old_mode;
    if (pc == NULL) {
        if (instr == NULL || !instr_has_allocated_bits(instr) ||
            instr->length != CTI_SHORT_REWRITE_LENGTH)
            return false;
        pc = instr_get_raw_bits(instr);
    }
    if (instr != NULL && instr_opcode_valid(instr)) {
        int opc = instr_get_opcode(instr);
        if (opc != OP_cbz && opc != OP_cbnz)
            return false;
    }
    if ((*(pc+1) != CBNZ_BYTE_A && *(pc+1) != CBZ_BYTE_A) ||
        /* Further verify by checking for a disp of 1 */
        (*pc & 0xf8) != 0x08)
        return false;
    /* XXX: this would be easier if decode_raw_is_jmp took in isa_mode */
    dcontext = get_thread_private_dcontext();
    if (instr != NULL)
        dr_set_isa_mode(dcontext, instr_get_isa_mode(instr), &old_mode);
    if (!decode_raw_is_jmp(dcontext, pc + CTI_SHORT_REWRITE_B_OFFS))
        return false;
    if (instr != NULL)
        dr_set_isa_mode(dcontext, old_mode, NULL);
    return true;
}
Beispiel #3
0
static void
nudge_terminate_on_dstack(dcontext_t *dcontext)
{
    ASSERT(dcontext == get_thread_private_dcontext());
    if (dcontext->nudge_terminate_process) {
        os_terminate_with_code(dcontext, TERMINATE_PROCESS|TERMINATE_CLEANUP,
                               dcontext->nudge_exit_code);
    } else
        os_terminate(dcontext, TERMINATE_THREAD|TERMINATE_CLEANUP);
    ASSERT_NOT_REACHED();
}
Beispiel #4
0
bool
redirect_heap_call(HANDLE heap)
{
    ASSERT(!dynamo_initialized || dynamo_exited || standalone_library ||
           get_thread_private_dcontext() == NULL /*thread exiting*/ ||
           !os_using_app_state(get_thread_private_dcontext()));
#ifdef CLIENT_INTERFACE
    if (!INTERNAL_OPTION(privlib_privheap))
        return false;
#endif
    /* either default heap, or one whose creation we intercepted */
    return (
#ifdef CLIENT_INTERFACE
            /* check both current and private: should be same, but
             * handle case where didn't swap
             */
            heap == get_private_peb()->ProcessHeap ||
#endif
            heap == get_peb(NT_CURRENT_PROCESS)->ProcessHeap ||
            is_dynamo_address((byte*)heap));
}
Beispiel #5
0
static void
annotation_unmanage_code_area(void *start, size_t size)
{
    dcontext_t *dcontext = get_thread_private_dcontext();

    if (!is_jit_managed_area(start))
        return;

    LOG(GLOBAL, LOG_ANNOTATIONS, 2,
        "Remove code area "PFX"-"PFX" from JIT managed regions\n",
        start, (app_pc) start + size);

    mutex_lock(&thread_initexit_lock);
    flush_fragments_and_remove_region(dcontext, start, size,
                                      true/*own initexit_lock*/, false/*keep futures*/);
    mutex_unlock(&thread_initexit_lock);

    jitopt_clear_span(start, (app_pc) start + size);
}
Beispiel #6
0
/* Initializes a dcontext with the supplied state and calls dispatch */
void
dynamo_start(priv_mcontext_t *mc)
{
    priv_mcontext_t *mcontext;
    dcontext_t *dcontext = get_thread_private_dcontext();
    ASSERT(dcontext != NULL);
    thread_starting(dcontext);

    /* Signal other threads for take over. */
    dynamorio_take_over_threads(dcontext);

    /* Set return address */
    dcontext->next_tag = mc->pc;
    ASSERT(dcontext->next_tag != NULL);

    /* transfer exec state to mcontext */
    mcontext = get_mcontext(dcontext);
    *mcontext = *mc;

    /* clear pc */
    mcontext->pc = 0;

    /* Swap stacks so dispatch is invoked outside the application.
     * We begin interpretation at the application return point,
     * and thus we need to look like DR returned -- adjust the app
     * stack to account for the return address.
     */
    mcontext->xsp += XSP_SZ;
    call_switch_stack(dcontext, dcontext->dstack, dispatch,
                      false/*not on initstack*/, true/*return on error*/);
    /* In release builds, this will simply return and continue native
     * execution.  That's better than calling unexpected_return() which
     * goes into an infinite loop.
     */
    ASSERT_NOT_REACHED();
}
Beispiel #7
0
/* This is the actual nudge handler
 * Notes: This function returns a boolean mainly to fix case 5130; it is not
 *        really necessary.
 */
bool
generic_nudge_handler(nudge_arg_t *arg_dont_use)
{
    dcontext_t *dcontext = get_thread_private_dcontext();
    nudge_arg_t safe_arg = {0};
    uint nudge_action_mask = 0;

#ifdef WINDOWS
    /* this routine is run natively via leave_call_native() so there's no
     * cxt switch that swapped for us
     */
    if (dcontext != NULL)
        swap_peb_pointer(dcontext, true/*to priv*/);
#endif

    /* To be extra safe we use safe_read() to access the nudge argument, though once
     * we get past the checks below we are trusting its content. */
    ASSERT(arg_dont_use != NULL && "invalid nudge argument");
    if (!safe_read(arg_dont_use, sizeof(nudge_arg_t), &safe_arg)) {
        ASSERT(false && "invalid nudge argument");
        goto nudge_finished;
    }
    nudge_action_mask = safe_arg.nudge_action_mask;

    /* if needed tell thread exit to free the application stack */
    if (!TEST(NUDGE_NUDGER_FREE_STACK, safe_arg.flags)) {
        dcontext->free_app_stack = true;
    } else {
        ASSERT_NOT_TESTED();
    }

    /* FIXME - would be nice to inform nudge creator if we need to nop the nudge. */

    /* Fix for case 5702.  If a nudge thread comes in during process exit,
     * don't process it, i.e., nop it. FIXME - this leaks the app stack and nudge arg
     * if the nudge was supposed to free them. */
    if (dynamo_exited)
        goto nudge_finished;

    /* Node manager will not be able to nudge before reading the drmarker and
     * the dr_marker isn't available before callback_interception_init().
     * Since after callback_interception_init() new threads won't be allowed
     * to progress till dynamo_initialized is set, by the time a nudge thread
     * reaches here dynamo_initialized should be set. */
    ASSERT(dynamo_initialized);
    if (!dynamo_initialized)
        goto nudge_finished;

    /* We should always have a dcontext. */
    ASSERT(dcontext != NULL);
    if (dcontext == NULL)
        goto nudge_finished;

    ENTERING_DR();

    /* Xref case 552, the nudge_target value provides a reasonable measure
     * of security against an attacker leveraging this routine. */
    if (dcontext->nudge_target != (void *)generic_nudge_target) {
        /* FIXME - should we report this likely attempt to attack us? need
         * a unit test for this (though will then have to tone this down). */
        ASSERT(false && "unauthorized thread tried to nudge");
        /* If we really are under attack we should terminate immediately and
         * proceed no further. Note we are leaking the app stack and nudge arg if we
         * were supposed to free them. */
        os_terminate(dcontext, TERMINATE_THREAD);
        ASSERT_NOT_REACHED();
    }

    /* Free the arg if requested. */
    if (TEST(NUDGE_FREE_ARG, safe_arg.flags)) {
        ASSERT_NOT_TESTED();
        nt_free_virtual_memory(arg_dont_use);
    }

    handle_nudge(dcontext, &safe_arg);

 nudge_finished:
    return nudge_thread_cleanup(dcontext, false/*just thread*/, 0/*unused*/);
}