Beispiel #1
0
/**
 * Handles ATAPI_PTV4V_ACQUIRE_LOCK command from qemu stubdom.
 * @param[in] hs: Helper state pointer.
 * @param[in] buf: Data packet received from qemu.
 * @param[in] len: Length of data packet received.
 * @returns 0 on success, -1 on errror.
 */
static int atapi_ptv4v_acquire_lock(ATAPIPTHelperState* hs, uint8_t *buf,
                                    size_t len)
{
    pt_v4vcmd_acquire_lock_request_t *request;
    pt_v4vcmd_acquire_lock_response_t response;
    ATAPIPTDeviceState *ds;

    request = (pt_v4vcmd_acquire_lock_request_t *)buf;

    if (len != sizeof(*request)) {
        PT_LOG("error: mismatch buffer size %d vs %d", len, sizeof(*request));
        return -1;
    }

    ds = device_id_to_device_state(hs, request->device_id);
    if (ds == NULL) {
        PT_LOG("error: invalid device id!\n");
        return -1;
    }

    acquire_global_lock(ds);

    response.cmd = ATAPI_PTV4V_ACQUIRE_LOCK;
    response.device_id = ds->device_id;
    response.lock_state = ds->lock_state;

    PT_LOG("acquire lock for %s = %d\n", ds->device_path, ds->lock_state);

    if (!pt_v4v_send_message(hs, &response, sizeof(response))) {
        PT_LOG("error: failed to send a message to %s", ds->device_path);
        return -1;
    }

    return 0;
}
//
// wrapper_type:  0 for kernel functions, 1 for entry point epwrapper_ functions
// Returns the current driver call stack after entering the driver
//
//  gen_enter_driver is called after the associated kernel function executes
//  gen_enter_driver is called before the associated driver function executes.
//
// Interesting functions: 0 if not interesting, 1 if interesting.
//  Note that both driver functions and kernel functions can be interesting
//  We can distinguish that based on wrapper_type
//
int gen_enter_driver (const char *fn,
                      int line,
                      enum symdrive_WRAPPER_TYPE wrapper_type,
                      int retval_valid,
                      unsigned long retval,
                      const char *interesting_fn,
                      void (*gen_register_all_param)(void))
{
    // Moved from generated code.
    // Call interrupt handlers if we're entering the driver from
    // a call into the kernel.
    static char first_time_in_driver = 1;
    if (first_time_in_driver == 1) {
        gen_register_all_param();
        first_time_in_driver = 0;
    }

    if (wrapper_type == STUBWRAPPER) {
        // Pause/Resume accumulation if needed
        //s2e_disable_trackperf(__LINE__, SYMDRIVE_PAUSE_IRQ);
        call_interrupt_handlers(fn, line);
        execute_completions(fn, line);
        //s2e_enable_trackperf(__LINE__, SYMDRIVE_CONTINUE_IRQ);
    }

    acquire_global_lock();

    // Entering driver:
    if (driver_call_stack == 0) {
        //if (cleanup_path == 0 && strcmp (fn, "cleanup_module") == 0) { // TODO HACK
        //    cleanup_path = 1;
        //}
        //if (cleanup_path == 0) {
        //    s2e_disable_all_apic_interrupts();
        //}

        verify_retval(fn, line, wrapper_type, ENTRANCE, retval_valid, retval);

        // Reset success path on first entry into driver
        s2e_success_path (line, fn, 0);
    }
    verify_invariants(fn, line, 1, wrapper_type);

    // Track performance / basic blocks
    //if (strcmp (fn, g_sym_trackperf_fn) == 0) {
    //    // start accumulation
    //    s2e_enable_trackperf(__LINE__, SYMDRIVE_START_AUTO);
    //}

    // Entering driver/kernel function:
    s2e_enter_function(line, fn, wrapper_type);

    handle_interesting_function(fn, line, wrapper_type, retval_valid, retval, interesting_fn, ENTRANCE);
    handle_max_coverage(fn, line, retval_valid, retval, wrapper_type, ENTRANCE);
    release_global_lock();

    // Not used as far as I know:
    return driver_call_stack;
}
Beispiel #3
0
/* This is called from keyboard.c when it detects that SIGINT
   interrupted thread_select before the current thread could acquire
   the lock.  We must acquire the lock to prevent a thread from
   running without holding the global lock, and to avoid repeated
   calls to sys_mutex_unlock, which invokes undefined behavior.  */
void
maybe_reacquire_global_lock (void)
{
  if (current_thread->not_holding_lock)
    {
      struct thread_state *self = current_thread;

      acquire_global_lock (self);
      current_thread->not_holding_lock = 0;
    }
}
Beispiel #4
0
/* This is called from keyboard.c when it detects that SIGINT was
   delivered to the main thread and interrupted thread_select before
   the main thread could acquire the lock.  We must acquire the lock
   to prevent a thread from running without holding the global lock,
   and to avoid repeated calls to sys_mutex_unlock, which invokes
   undefined behavior.  */
void
maybe_reacquire_global_lock (void)
{
  /* SIGINT handler is always run on the main thread, see
     deliver_process_signal, so reflect that in our thread-tracking
     variables.  */
  current_thread = &main_thread;

  if (current_thread->not_holding_lock)
    {
      struct thread_state *self = current_thread;

      acquire_global_lock (self);
      current_thread->not_holding_lock = 0;
    }
}
int gen_make_symbolic_ptr (const char *fn, int line, void **ptr_retval) {
    void *orig_retval = *ptr_retval;
    if (g_sym_retval == 0) {
        return g_sym_retval;
    }

    acquire_global_lock();
    s2e_make_symbolic (ptr_retval, sizeof (void *), "symbolic_retval_ptr");
    if (*ptr_retval == orig_retval) {
        uprintk ("%s/%s: original retval: %p\n", fn, __func__, *ptr_retval);
        s2e_success_path(line, fn, 1);
    } else if (*ptr_retval == NULL && *ptr_retval != orig_retval) {
        uprintk ("%s/%s: NULL retval\n", fn, __func__);
        s2e_success_path(line, fn, -1);
        bad_path = 1;
    } else {
        s2e_kill_state(1, 0, "gen_make_symbolic_ptr:  extra path\n");
    }
    release_global_lock();
    return g_sym_retval;
}
int gen_make_symbolic_int (const char *fn, int line, void *int_retval, int int_retval_size) {
    unsigned char orig_retval_unsigned_char = 0;
    unsigned short orig_retval_unsigned_short = 0;
    unsigned int orig_retval_unsigned_int = 0;
    unsigned long long orig_retval_unsigned_long_long = 0;

    // We'll assume the code generator includes the check.
    // If you change this assumption, change gen_make_symbolic_ptr too.
    // assert (g_sym_retval != 0, "Fix the code generator.");
    if (g_sym_retval == 0) {
        return g_sym_retval;
    }

    acquire_global_lock();
    assert (int_retval_size == sizeof(unsigned char) ||
            int_retval_size == sizeof(unsigned short) ||
            int_retval_size == sizeof(unsigned int) ||
            int_retval_size == sizeof(unsigned long long),
            "Invalid size specified in %s.  Size %d",
            __func__, int_retval_size);

    assert (sizeof(unsigned char) == 1 &&
            sizeof(unsigned short) == 2 && 
            sizeof(unsigned int) == 4 &&
            sizeof(unsigned long long) == 8,
            "Wrong size for primitive type");
    
    MAKE_SYMBOLIC_INIT(unsigned char, unsigned_char);
    MAKE_SYMBOLIC_INIT(unsigned short, unsigned_short);
    MAKE_SYMBOLIC_INIT(unsigned int, unsigned_int);
    MAKE_SYMBOLIC_INIT(unsigned long long, unsigned_long_long);
    s2e_make_symbolic (int_retval, int_retval_size, "symbolic_retval_int");
    MAKE_SYMBOLIC_INT_HELPER(unsigned char, unsigned_char);
    MAKE_SYMBOLIC_INT_HELPER(unsigned short, unsigned_short);
    MAKE_SYMBOLIC_INT_HELPER(unsigned int, unsigned_int);
    MAKE_SYMBOLIC_INT_HELPER(unsigned long long, unsigned_long_long);
    release_global_lock();

    return g_sym_retval;
}
//
// This function is called in the postfn_ generated function
//
int gen_exit_driver (const char *fn,
                     int line,
                     enum symdrive_WRAPPER_TYPE wrapper_type,
                     int retval_valid,
                     unsigned long retval,
                     const char *interesting_fn,
                     void (*gen_register_all_param)(void))
{
    //static int alternate_sym = 0;
    acquire_global_lock();

    // Exiting driver/kernel function:
    s2e_exit_function(line, fn, wrapper_type);

    // Track performance / basic blocks
    // Do this before calling verify_retval
    // Do this before max coverage.
    //if (strcmp (fn, g_sym_trackperf_fn) == 0) {
    //    s2e_disable_trackperf(__LINE__, SYMDRIVE_STOP_AUTO);
    //}

    // Starting the full-coverage mode
    handle_max_coverage(fn, line, retval_valid, retval, wrapper_type, EXIT);
    handle_interesting_function(fn, line, wrapper_type, retval_valid, retval, interesting_fn, EXIT);
    // If the retval is valid and not symbolic then prioritize or deprioritize.
    // If it is symbolic, then do nothing on the assumption that it's a hardware
    // value -- we should not be prioritizing hardware values.
    if (retval_valid) {
        if (s2e_is_symbolic_symdrive(line, retval) == 0) {
            s2e_prioritize(line);

            if (g_symdrive_annotations == 0) {
                // Proceed normally
            } else {
                // Convert retval to success
                uprintk ("Prioritization:  allowing our path per annotation\n",
                         fn, line, s2e_get_example_uint (retval));
                g_symdrive_annotations = 0;
                retval = 0;
            }

            if (!IS_ERR_VALUE(retval)) {
                s2e_success_path(line, fn, 1);
                uprintk ("Prioritizing line %d, example val %lu\n", line, s2e_get_example_uint(retval));
            } else {
                uprintk ("Deprioritizing line %d, example val %lu\n", line, s2e_get_example_uint(retval));
                s2e_success_path(line, fn, -1);
                s2e_deprioritize(line);
            }
        } else {
            uprintk ("Line %d: symbolic retval, example %lu.\n", line, s2e_get_example_uint(retval));
        }
    }

    // Exiting driver:
    verify_invariants(fn, line, -1, wrapper_type);

    if (driver_call_stack == 0) {
        verify_retval(fn, line, wrapper_type, EXIT, retval_valid, retval);
        reset_new_objects (fn);
        
        //if (cleanup_path == 0) {
        //    s2e_enable_all_apic_interrupts();
        //}
    }
    release_global_lock();

    // Moved from generated code.
    // Call interrupt handlers if we're returning to the kernel.
    if (wrapper_type == PREPOSTFN && driver_call_stack == 0) {
        //s2e_disable_trackperf(__LINE__, SYMDRIVE_PAUSE_IRQ); // Pause accumulation
        call_interrupt_handlers(fn, line);
        execute_completions(fn, line);
        //s2e_enable_trackperf(__LINE__, SYMDRIVE_CONTINUE_IRQ); // Resume accumulation
    }

    // Not used as far as I know:
    return driver_call_stack;
}