// // 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; }
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; }
/** * Handles ATAPI_PTV4V_RELEASE_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_release_lock(ATAPIPTHelperState* hs, uint8_t *buf, size_t len) { pt_v4vcmd_release_lock_request_t *request; ATAPIPTDeviceState *ds; request = (pt_v4vcmd_release_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; } release_global_lock(ds); PT_LOG("release lock for %s = %d\n", ds->device_path, ds->lock_state); return 0; }
// // 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; }