manual code cleanups (reviewed)
Tried to minimize actual code modifcations but we got - several comments/printf messages edited to meet line limits - occasionally switch some lines to put declarations or printfs in blocks - couple more places marked TODO or FIXME to avoid non-trivial changes - fixed PAGE_SIZE define in helpers.h to avoid redeclaration warning - remove several chunks of dead or commented code Co-authored-by: Steffen Schulz <steffen.schulz@intel.com>
This commit is contained in:
parent
949ab6c9f9
commit
e4269fc973
@ -19,10 +19,11 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "nyx/auxiliary_buffer.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "nyx/auxiliary_buffer.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/trace_dump.h"
|
||||
@ -234,7 +235,7 @@ void reset_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer){
|
||||
}
|
||||
|
||||
void set_success_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t success){
|
||||
//should refactor to let caller directly set the result codes
|
||||
//TODO refactor to let caller directly set the result codes
|
||||
if (success == 2) {
|
||||
VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_starved);
|
||||
} else {
|
||||
|
@ -20,6 +20,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
@ -49,7 +50,7 @@ enum nyx_result_codes {
|
||||
};
|
||||
|
||||
typedef struct auxilary_buffer_header_s{
|
||||
uint64_t magic; /* 0x54502d554d4551 */
|
||||
uint64_t magic;
|
||||
uint16_t version;
|
||||
uint16_t hash;
|
||||
/* more to come */
|
||||
|
26
nyx/debug.c
26
nyx/debug.c
@ -1,7 +1,10 @@
|
||||
#include <execinfo.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "signal.h"
|
||||
|
||||
@ -19,7 +22,6 @@ void qemu_backtrace(void){
|
||||
|
||||
char **strings = backtrace_symbols(buffer, nptrs);
|
||||
if (strings == NULL) {
|
||||
//perror("backtrace_symbols");
|
||||
fprintf(stderr, "backtrace_symbols failed!\n");
|
||||
return;
|
||||
//exit(EXIT_FAILURE);
|
||||
@ -54,21 +56,7 @@ static void sigint_handler(int signo, siginfo_t *info, void *extra) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
/*
|
||||
static void aexit_handler(void) {
|
||||
fprintf(stderr, "ATTEMPT TO CALL EXIT (PID: %d)\n", getpid());
|
||||
qemu_backtrace();
|
||||
fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
|
||||
while(1){
|
||||
sleep(1);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void init_crash_handler(void){
|
||||
|
||||
//qemu_backtrace();
|
||||
|
||||
struct sigaction action;
|
||||
action.sa_flags = SA_SIGINFO;
|
||||
action.sa_sigaction = sigsegfault_handler;
|
||||
@ -95,12 +83,6 @@ void init_crash_handler(void){
|
||||
_exit(1);
|
||||
}
|
||||
}
|
||||
//atexit(aexit_handler);
|
||||
|
||||
/* test */
|
||||
//int i = 0;
|
||||
//((char*)i)[3] = 0;
|
||||
|
||||
}
|
||||
|
||||
void hexdump_kafl(const void* data, size_t size) {
|
||||
|
@ -5,7 +5,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/error-report.h"
|
||||
|
@ -19,55 +19,49 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include"qemu/osdep.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
#include "qemu/rcu_queue.h"
|
||||
#include "migration/migration.h"
|
||||
#include "migration/register.h"
|
||||
#include "migration/savevm.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/global_state.h"
|
||||
#include<stdint.h>
|
||||
#include<sys/mman.h>
|
||||
#include<sys/stat.h>
|
||||
#include<sys/types.h>
|
||||
|
||||
#include<immintrin.h>
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <immintrin.h>
|
||||
#include <stdint.h>
|
||||
#include"block/qapi.h"
|
||||
#include"exec/ram_addr.h"
|
||||
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include"migration/global_state.h"
|
||||
#include"migration/migration.h"
|
||||
#include"migration/qemu-file.h"
|
||||
#include"migration/register.h"
|
||||
#include"migration/savevm.h"
|
||||
#include"migration/vmstate.h"
|
||||
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/state/snapshot_state.h"
|
||||
#include"qemu/main-loop.h"
|
||||
#include"qemu/rcu_queue.h"
|
||||
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/qapi.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include"sysemu/block-backend.h"
|
||||
#include"sysemu/cpus.h"
|
||||
#include"sysemu/kvm_int.h"
|
||||
#include"sysemu/reset.h"
|
||||
#include"sysemu/runstate.h"
|
||||
#include"sysemu/sysemu.h"
|
||||
|
||||
#include "nyx/memory_access.h"
|
||||
#include"nyx/debug.h"
|
||||
#include"nyx/fast_vm_reload.h"
|
||||
#include"nyx/state/snapshot_state.h"
|
||||
#include"nyx/state/state.h"
|
||||
|
||||
#include "nyx/helpers.h"
|
||||
#include"nyx/helpers.h"
|
||||
#include"nyx/memory_access.h"
|
||||
|
||||
#include "nyx/snapshot/helper.h"
|
||||
#include "nyx/snapshot/memory/block_list.h"
|
||||
#include "nyx/snapshot/memory/shadow_memory.h"
|
||||
|
||||
#include "nyx/snapshot/memory/backend/nyx_debug.h"
|
||||
#include "nyx/snapshot/memory/backend/nyx_fdl.h"
|
||||
#include "nyx/snapshot/memory/nyx_fdl_user.h"
|
||||
#include "nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include "nyx/snapshot/block/nyx_block_snapshot.h"
|
||||
#include"nyx/snapshot/helper.h"
|
||||
#include"nyx/snapshot/memory/block_list.h"
|
||||
#include"nyx/snapshot/memory/shadow_memory.h"
|
||||
#include"nyx/snapshot/block/nyx_block_snapshot.h"
|
||||
#include"nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include"nyx/snapshot/memory/backend/nyx_debug.h"
|
||||
|
||||
FastReloadMemoryMode mode = RELOAD_MEMORY_MODE_DEBUG;
|
||||
|
||||
@ -107,7 +101,6 @@ static void fast_snapshot_init_operation(fast_reload_t* self, const char* snapsh
|
||||
}
|
||||
|
||||
self->fdl_user_state = nyx_fdl_user_init(self->shadow_memory_state);
|
||||
|
||||
nyx_fdl_user_enable(self->fdl_user_state);
|
||||
}
|
||||
|
||||
@ -148,20 +141,16 @@ static void fast_snapshot_restore_operation(fast_reload_t* self){
|
||||
case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG:
|
||||
num_dirty_pages += nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state, self->shadow_memory_state, self->blocklist);
|
||||
num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true);
|
||||
//assert(false);
|
||||
//sleep(1);
|
||||
break;
|
||||
}
|
||||
|
||||
num_dirty_pages += nyx_snapshot_user_fdl_restore(self->fdl_user_state, self->shadow_memory_state, self->blocklist);
|
||||
//nyx_device_state_post_restore(self->device_state);
|
||||
GET_GLOBAL_STATE()->num_dirty_pages = num_dirty_pages;
|
||||
}
|
||||
|
||||
static inline void fast_snapshot_pre_create_incremental_operation(fast_reload_t* self){
|
||||
/* flush all pending block writes */
|
||||
bdrv_drain_all();
|
||||
|
||||
memory_global_dirty_log_sync();
|
||||
|
||||
nyx_device_state_switch_incremental(self->device_state);
|
||||
@ -231,7 +220,7 @@ void fast_reload_init(fast_reload_t* self){
|
||||
/* fix this */
|
||||
void fast_reload_destroy(fast_reload_t* self){
|
||||
|
||||
/* complete me */
|
||||
/* TODO: complete me */
|
||||
|
||||
//close(self->vmx_fdl_fd);
|
||||
//munmap(self->fdl_data, (self->guest_ram_size/0x1000)*8);
|
||||
@ -249,9 +238,8 @@ inline static void unlock_snapshot(const char* folder){
|
||||
char* info_file;
|
||||
char* lock_file;
|
||||
|
||||
assert(asprintf(&info_file, "%s/INFO.txt", folder) != -1);
|
||||
|
||||
/* info file */
|
||||
assert(asprintf(&info_file, "%s/INFO.txt", folder) != -1);
|
||||
FILE* f_info = fopen(info_file, "w+b");
|
||||
if(GET_GLOBAL_STATE()->fast_reload_pre_image){
|
||||
const char* msg = "THIS IS A NYX PRE IMAGE SNAPSHOT FOLDER!\n";
|
||||
@ -264,7 +252,6 @@ inline static void unlock_snapshot(const char* folder){
|
||||
fclose(f_info);
|
||||
|
||||
assert(asprintf(&lock_file, "%s/ready.lock", folder) != -1);
|
||||
|
||||
int fd = open(lock_file, O_WRONLY | O_CREAT, S_IRWXU);
|
||||
close(fd);
|
||||
|
||||
@ -275,7 +262,6 @@ inline static void wait_for_snapshot(const char* folder){
|
||||
char* lock_file;
|
||||
|
||||
assert(asprintf(&lock_file, "%s/ready.lock", folder) != -1);
|
||||
|
||||
while( access(lock_file, F_OK ) == -1 ) {
|
||||
sleep(1);
|
||||
|
||||
@ -284,8 +270,7 @@ inline static void wait_for_snapshot(const char* folder){
|
||||
}
|
||||
|
||||
void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool is_pre_snapshot){
|
||||
|
||||
//printf("================ %s => %s =============\n", __func__, folder);
|
||||
nyx_trace();
|
||||
|
||||
/* sanity check */
|
||||
if(!folder_exits(folder)){
|
||||
@ -312,7 +297,7 @@ void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool
|
||||
|
||||
|
||||
static void fast_reload_create_from_snapshot(fast_reload_t* self, const char* folder, bool lock_iothread, bool pre_snapshot){
|
||||
//printf("%s called\n", __func__);
|
||||
nyx_trace();
|
||||
|
||||
assert(self != NULL);
|
||||
wait_for_snapshot(folder);
|
||||
@ -345,26 +330,22 @@ static void fast_reload_create_from_snapshot(fast_reload_t* self, const char* fo
|
||||
if(!pre_snapshot){
|
||||
nyx_device_state_save_tsc(self->device_state);
|
||||
}
|
||||
|
||||
//fast_reload_restore(self);
|
||||
//vm_start();
|
||||
}
|
||||
|
||||
void fast_reload_create_from_file(fast_reload_t* self, const char* folder, bool lock_iothread){
|
||||
//printf("CALL: %s\n", __func__);
|
||||
nyx_trace();
|
||||
fast_reload_create_from_snapshot(self, folder, lock_iothread, false);
|
||||
}
|
||||
|
||||
void fast_reload_create_from_file_pre_image(fast_reload_t* self, const char* folder, bool lock_iothread){
|
||||
//printf("CALL: %s\n", __func__);
|
||||
nyx_trace();
|
||||
fast_reload_create_from_snapshot(self, folder, lock_iothread, true);
|
||||
}
|
||||
|
||||
void fast_reload_create_in_memory(fast_reload_t* self){
|
||||
|
||||
assert(self != NULL);
|
||||
nyx_trace();
|
||||
nyx_debug_p(RELOAD_PREFIX,"=> CREATING FAST RELOAD SNAPSHOT FROM CURRENT VM STATE");
|
||||
assert(self != NULL);
|
||||
|
||||
rcu_read_lock();
|
||||
|
||||
@ -380,62 +361,28 @@ void fast_reload_create_in_memory(fast_reload_t* self){
|
||||
|
||||
rcu_read_unlock();
|
||||
cpu_synchronize_all_post_init();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void fast_reload_restore(fast_reload_t* self){
|
||||
assert(self != NULL);
|
||||
self->dirty_pages = 0;
|
||||
|
||||
//rcu_read_lock();
|
||||
//cpu_synchronize_all_states();
|
||||
//bdrv_drain_all_begin();
|
||||
|
||||
/* flush all pending block writes */
|
||||
bdrv_drain_all();
|
||||
//bdrv_flush_all();
|
||||
|
||||
bdrv_drain_all();
|
||||
memory_global_dirty_log_sync();
|
||||
//unset_black_list_pages(self);
|
||||
|
||||
nyx_block_snapshot_reset(self->block_state);
|
||||
/*
|
||||
for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
|
||||
//if(!self->tmp_snapshot.enabled)
|
||||
cow_cache_reset(self->cow_cache_array[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
nyx_device_state_restore(self->device_state);
|
||||
//fdl_fast_reload(self->qemu_state);
|
||||
//fdl_fast_reload(self->device_state->qemu_state);
|
||||
|
||||
nyx_block_snapshot_flush(self->block_state);
|
||||
//GET_GLOBAL_STATE()->cow_cache_full = false;
|
||||
//call_fast_change_handlers();
|
||||
|
||||
|
||||
fast_snapshot_restore_operation(self);
|
||||
|
||||
//find_dirty_pages_fdl(self);
|
||||
//fast_reload_qemu_user_fdl_restore(self);
|
||||
|
||||
|
||||
//set_tsc_value(self, self->tmp_snapshot.enabled);
|
||||
nyx_device_state_post_restore(self->device_state);
|
||||
kvm_arch_put_registers(qemu_get_cpu(0), KVM_PUT_FULL_STATE_FAST);
|
||||
qemu_get_cpu(0)->vcpu_dirty = false;
|
||||
|
||||
//bdrv_drain_all_end();
|
||||
//rcu_read_unlock();
|
||||
|
||||
|
||||
//printf("========================= NEXT\n\n");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -447,7 +394,7 @@ bool read_snapshot_memory(fast_reload_t* self, uint64_t address, void* ptr, size
|
||||
/* fix this */
|
||||
void* fast_reload_get_physmem_shadow_ptr(fast_reload_t* self, uint64_t physaddr){
|
||||
|
||||
abort(); /* fix this function first -> pc_piix memory split issue */
|
||||
abort(); /* TODO: fix this function first -> pc_piix memory split issue */
|
||||
|
||||
/*
|
||||
assert(self != NULL);
|
||||
@ -470,17 +417,16 @@ void fast_reload_blacklist_page(fast_reload_t* self, uint64_t physaddr){
|
||||
}
|
||||
|
||||
bool fast_reload_snapshot_exists(fast_reload_t* self){
|
||||
if(!self){ // || !self->qemu_state){
|
||||
if(!self){
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void fast_reload_create_tmp_snapshot(fast_reload_t* self){
|
||||
assert(self); // && self->qemu_state);
|
||||
assert(self);
|
||||
|
||||
self->dirty_pages = 0;
|
||||
|
||||
fast_snapshot_pre_create_incremental_operation(self);
|
||||
|
||||
if(!self->bitmap_copy){
|
||||
@ -488,11 +434,6 @@ void fast_reload_create_tmp_snapshot(fast_reload_t* self){
|
||||
}
|
||||
coverage_bitmap_copy_to_buffer(self->bitmap_copy);
|
||||
|
||||
//GET_GLOBAL_STATE()->cow_cache_full = false;
|
||||
|
||||
//self->tmp_snapshot.root_dirty_pages_num = 0;
|
||||
|
||||
|
||||
fast_snapshot_create_incremental_operation(self);
|
||||
self->incremental_snapshot_enabled = true;
|
||||
}
|
||||
@ -504,34 +445,18 @@ void fast_reload_discard_tmp_snapshot(fast_reload_t* self){
|
||||
|
||||
/* flush all pending block writes */
|
||||
bdrv_drain_all();
|
||||
|
||||
memory_global_dirty_log_sync();
|
||||
//unset_black_list_pages(self);
|
||||
|
||||
fast_snapshot_restore_operation(self);
|
||||
|
||||
//find_dirty_pages_fdl(self);
|
||||
//fast_reload_qemu_user_fdl_restore(self);
|
||||
|
||||
shadow_memory_restore_memory(self->shadow_memory_state);
|
||||
shadow_memory_switch_snapshot(self->shadow_memory_state, false);
|
||||
//restore_root_memory(self);
|
||||
|
||||
|
||||
|
||||
nyx_device_state_disable_incremental(self->device_state);
|
||||
//fdl_fast_disable_tmp(self->qemu_state);
|
||||
//fdl_fast_disable_tmp(self->device_state->qemu_state);
|
||||
|
||||
nyx_block_snapshot_disable_incremental(self->block_state);
|
||||
|
||||
/*
|
||||
for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
|
||||
cow_cache_disable_tmp_mode(self->cow_cache_array[i]);
|
||||
}
|
||||
*/
|
||||
self->incremental_snapshot_enabled = false;
|
||||
|
||||
}
|
||||
|
||||
bool fast_reload_root_created(fast_reload_t* self){
|
||||
|
@ -21,21 +21,19 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "monitor/monitor.h"
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include"monitor/monitor.h"
|
||||
#include"sysemu/runstate.h"
|
||||
#include"qemu-common.h"
|
||||
|
||||
#include "nyx/snapshot/memory/block_list.h"
|
||||
#include "nyx/snapshot/memory/shadow_memory.h"
|
||||
#include "nyx/snapshot/memory/backend/nyx_fdl.h"
|
||||
#include "nyx/snapshot/memory/nyx_fdl_user.h"
|
||||
#include "nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include"nyx/snapshot/block/nyx_block_snapshot.h"
|
||||
#include"nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include"nyx/snapshot/memory/backend/nyx_dirty_ring.h"
|
||||
#include"nyx/snapshot/memory/backend/nyx_fdl.h"
|
||||
#include"nyx/snapshot/memory/block_list.h"
|
||||
#include"nyx/snapshot/memory/nyx_fdl_user.h"
|
||||
#include"nyx/snapshot/memory/shadow_memory.h"
|
||||
|
||||
#include "nyx/snapshot/block/nyx_block_snapshot.h"
|
||||
|
||||
#include "nyx/snapshot/memory/backend/nyx_dirty_ring.h"
|
||||
#include "nyx/helpers.h"
|
||||
#include"nyx/helpers.h"
|
||||
|
||||
|
||||
typedef enum FastReloadMemoryMode {
|
||||
@ -95,7 +93,7 @@ typedef struct fast_reload_s{
|
||||
fast_reload_t* fast_reload_new(void);
|
||||
|
||||
|
||||
/* get rid of this */
|
||||
/* TODO: get rid of this */
|
||||
void fast_reload_create_to_file(fast_reload_t* self, const char* folder, bool lock_iothread);
|
||||
void fast_reload_create_from_file(fast_reload_t* self, const char* folder, bool lock_iothread);
|
||||
void fast_reload_create_from_file_pre_image(fast_reload_t* self, const char* folder, bool lock_iothread);
|
||||
|
@ -1,20 +1,24 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "qapi/error.h"
|
||||
#include "fast_vm_reload_sync.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "qapi/qapi-types-run-state.h"
|
||||
#include "qemu-common.h"
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/kvm_nested.h"
|
||||
#include"qemu/osdep.h"
|
||||
|
||||
#include<assert.h>
|
||||
#include<stdint.h>
|
||||
#include<stdio.h>
|
||||
|
||||
#include"exec/memory.h"
|
||||
#include"qapi/error.h"
|
||||
#include"qapi/qapi-types-run-state.h"
|
||||
#include"qemu/main-loop.h"
|
||||
#include"qemu-common.h"
|
||||
|
||||
#include"sysemu/kvm.h"
|
||||
#include"sysemu/kvm_int.h"
|
||||
#include"sysemu/runstate.h"
|
||||
|
||||
#include"fast_vm_reload_sync.h"
|
||||
#include"nyx/debug.h"
|
||||
#include"nyx/fast_vm_reload.h"
|
||||
#include"nyx/kvm_nested.h"
|
||||
#include"nyx/state/state.h"
|
||||
|
||||
extern int save_snapshot(const char *name, Error **errp);
|
||||
extern int load_snapshot(const char *name, Error **errp);
|
||||
@ -147,7 +151,6 @@ static inline void perform_task_no_block_mode(fast_vm_reload_sync_t* self, FastR
|
||||
switch(request){
|
||||
case REQUEST_SAVE_SNAPSHOT_PRE:
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
//fast_reload_create_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true);
|
||||
fast_reload_create_in_memory(get_fast_reload_snapshot());
|
||||
fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true);
|
||||
|
||||
@ -158,34 +161,26 @@ static inline void perform_task_no_block_mode(fast_vm_reload_sync_t* self, FastR
|
||||
adjust_rip(env, get_fast_reload_snapshot());
|
||||
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
|
||||
case REQUEST_SAVE_SNAPSHOT_ROOT:
|
||||
|
||||
kvm_arch_get_registers(cpu);
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
create_root_snapshot();
|
||||
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
//call_fast_change_handlers();
|
||||
break;
|
||||
|
||||
case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
|
||||
adjust_rip(env, get_fast_reload_snapshot());
|
||||
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
|
||||
case REQUEST_SAVE_SNAPSHOT_TMP:
|
||||
fast_reload_create_tmp_snapshot(get_fast_reload_snapshot());
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
|
||||
break;
|
||||
case REQUEST_LOAD_SNAPSHOT_PRE:
|
||||
abort();
|
||||
break;
|
||||
case REQUEST_LOAD_SNAPSHOT_ROOT:
|
||||
case REQUEST_LOAD_SNAPSHOT_TMP:
|
||||
|
||||
//vm_stop(RUN_STATE_RESTORE_VM);
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
//call_fast_change_handlers();
|
||||
break;
|
||||
|
||||
case REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP:
|
||||
kvm_arch_get_registers(cpu);
|
||||
|
||||
@ -193,20 +188,17 @@ static inline void perform_task_no_block_mode(fast_vm_reload_sync_t* self, FastR
|
||||
set_nested_rip(cpu, env->eip);
|
||||
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
|
||||
|
||||
//case REQUEST_SAVE_SNAPSHOT_ROOT_NESTED:
|
||||
kvm_arch_get_registers(cpu);
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
create_root_snapshot();
|
||||
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
|
||||
vm_start();
|
||||
//call_fast_change_handlers();
|
||||
cpu_resume(cpu);
|
||||
qemu_mutex_unlock_iothread();
|
||||
}
|
||||
@ -216,7 +208,6 @@ static inline void perform_task_block_mode(fast_vm_reload_sync_t* self, FastRelo
|
||||
case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
|
||||
case REQUEST_SAVE_SNAPSHOT_PRE:
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
//fast_reload_create_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true);
|
||||
fast_reload_create_in_memory(get_fast_reload_snapshot());
|
||||
fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_pre_path, true);
|
||||
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
|
||||
@ -225,8 +216,7 @@ static inline void perform_task_block_mode(fast_vm_reload_sync_t* self, FastRelo
|
||||
case REQUEST_SAVE_SNAPSHOT_ROOT:
|
||||
/* TODO: fix this */
|
||||
vm_stop(RUN_STATE_SAVE_VM);
|
||||
create_root_snapshot(); /* TODO: Fix this -> fucky in ahci mode */
|
||||
//fast_reload_create_in_memory(get_fast_reload_snapshot());
|
||||
create_root_snapshot(); /* TODO: fix this -> broken in ahci mode */
|
||||
break;
|
||||
case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
|
||||
case REQUEST_SAVE_SNAPSHOT_TMP:
|
||||
@ -241,7 +231,6 @@ static inline void perform_task_block_mode(fast_vm_reload_sync_t* self, FastRelo
|
||||
vm_stop(RUN_STATE_RESTORE_VM);
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
break;
|
||||
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
@ -289,18 +278,12 @@ void reload_request_discard_tmp(fast_vm_reload_sync_t* self){
|
||||
}
|
||||
|
||||
bool check_if_relood_request_exists_pre(fast_vm_reload_sync_t* self){
|
||||
|
||||
/* TODO: always returns false or abort() ? */
|
||||
if(self->request_exists_pre){
|
||||
self->request_exists_pre = false;
|
||||
abort();
|
||||
|
||||
/*
|
||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, false);
|
||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL_RT, false);
|
||||
qemu_clock_enable(QEMU_CLOCK_HOST, false);
|
||||
*/
|
||||
|
||||
//printf("%s: task found: %d\n", __func__, self->current_request);
|
||||
|
||||
CPUState* cpu = qemu_get_cpu(0);
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
CPUX86State *env = &x86_cpu->env;
|
||||
@ -357,12 +340,6 @@ bool check_if_relood_request_exists_post(fast_vm_reload_sync_t* self){
|
||||
self->current_request = REQUEST_VOID;
|
||||
perform_task(self, request);
|
||||
|
||||
/*
|
||||
qemu_clock_enable(QEMU_CLOCK_HOST, true);
|
||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL_RT, true);
|
||||
qemu_clock_enable(QEMU_CLOCK_VIRTUAL, true);
|
||||
*/
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -44,12 +44,9 @@ typedef struct fast_vm_reload_sync_s{
|
||||
|
||||
bool request_exists;
|
||||
bool request_exists_pre;
|
||||
FastReloadRequest current_request;
|
||||
|
||||
bool debug_mode;
|
||||
|
||||
FastReloadMode mode;
|
||||
|
||||
FastReloadRequest current_request;
|
||||
} fast_vm_reload_sync_t;
|
||||
|
||||
|
||||
|
@ -11,17 +11,17 @@
|
||||
#include "file_helper.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Helper Functions Declarations
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Private Helper Functions Declarations
|
||||
*/
|
||||
|
||||
size_t _count_lines_in_file(FILE* fp);
|
||||
|
||||
void _parse_addresses_in_file(FILE* fp, size_t num_addrs, uint64_t* addrs);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Functions
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Public Functions
|
||||
*/
|
||||
|
||||
void write_debug_result(char* buf){
|
||||
int unused __attribute__((unused));
|
||||
@ -92,9 +92,9 @@ void delete_redqueen_files(void){
|
||||
unused = ftruncate(se_fd, 0);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Helper Functions Definitions
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Private Helper Functions Definitions
|
||||
*/
|
||||
|
||||
size_t _count_lines_in_file(FILE* fp){
|
||||
size_t val = 0;
|
||||
|
@ -1,19 +1,22 @@
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "nyx/helpers.h"
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "qemu-common.h"
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "nyx/state/state.h"
|
||||
|
||||
void nyx_abort(char* msg){
|
||||
set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, msg, strlen(msg));
|
||||
@ -112,8 +115,6 @@ static void resize_coverage_bitmap(uint32_t new_bitmap_size){
|
||||
}
|
||||
|
||||
bool apply_capabilities(CPUState *cpu){
|
||||
//X86CPU *cpux86 = X86_CPU(cpu);
|
||||
//CPUX86State *env = &cpux86->env;
|
||||
|
||||
nyx_debug("%s: agent supports timeout detection: %d\n", __func__, GET_GLOBAL_STATE()->cap_timeout_detection);
|
||||
nyx_debug("%s: agent supports only-reload mode: %d\n", __func__, GET_GLOBAL_STATE()->cap_only_reload_mode);
|
||||
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
uint64_t get_rip(CPUState *cpu);
|
||||
|
||||
typedef struct nyx_coverage_bitmap_copy_s{
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/hypercall/configuration.h"
|
||||
#include "nyx/memory_access.h"
|
||||
@ -54,7 +55,11 @@ void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu,
|
||||
}
|
||||
|
||||
if (config.agent_version != NYX_AGENT_VERSION){
|
||||
fprintf(stderr, "[QEMU-Nyx] Error: NYX_AGENT_VERSION does not match in agent configuration (%d != %d) - You are probably using an outdated agent...\n", config.agent_version, NYX_AGENT_VERSION);
|
||||
fprintf(stderr,
|
||||
"[QEMU-Nyx] Error: NYX_AGENT_VERSION does not match in agent "
|
||||
"configuration (%d != %d) - "
|
||||
"You are probably using an outdated agent...\n",
|
||||
config.agent_version, NYX_AGENT_VERSION);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@ -78,9 +83,7 @@ void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu,
|
||||
}
|
||||
|
||||
GET_GLOBAL_STATE()->cap_cr3 = env->cr[3];
|
||||
|
||||
GET_GLOBAL_STATE()->cap_coverage_bitmap_size = config.coverage_bitmap_size;
|
||||
|
||||
GET_GLOBAL_STATE()->input_buffer_size = GET_GLOBAL_STATE()->shared_payload_buffer_size;
|
||||
|
||||
if (config.input_buffer_size){
|
||||
|
@ -3,7 +3,10 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
void handle_hypercall_kafl_get_host_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
|
||||
|
||||
void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
|
||||
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
#include "nyx/synchronization.h"
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/hypercall/debug.h"
|
||||
|
||||
//#define NYX_ENABLE_DEBUG_HYPERCALLS
|
||||
|
||||
#ifdef NYX_ENABLE_DEBUG_HYPERCALLS
|
||||
|
||||
static double get_time(void){
|
||||
@ -39,18 +41,14 @@ static void print_time_diff(int iterations){
|
||||
static void meassure_performance(void){
|
||||
static int perf_counter = 0;
|
||||
if ((perf_counter%1000) == 0){
|
||||
//printf("perf_counter -> %d \n", perf_counter);
|
||||
print_time_diff(1000);
|
||||
}
|
||||
perf_counter++;
|
||||
}
|
||||
|
||||
void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
//CPUX86State *env = &x86_cpu->env;
|
||||
static bool first = true;
|
||||
|
||||
//printf("CALLED %s: %lx\n", __func__, hypercall_arg);
|
||||
switch(hypercall_arg&0xFFF){
|
||||
case 0: /* create root snapshot */
|
||||
if(!fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_ROOT_EXISTS)){
|
||||
@ -58,13 +56,11 @@ void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu
|
||||
}
|
||||
break;
|
||||
case 1: /* create tmp snapshot */
|
||||
//printf("%s: create tmp...(RIP: %lx)\n", __func__, get_rip(cpu));
|
||||
if(!fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_TMP_EXISTS)){
|
||||
request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_TMP);
|
||||
}
|
||||
break;
|
||||
case 2: /* load root snapshot (+ discard tmp snapshot) */
|
||||
//printf("%s: load root...(RIP: %lx)\n", __func__, get_rip(cpu));
|
||||
if(fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_TMP_EXISTS)){
|
||||
reload_request_discard_tmp(GET_GLOBAL_STATE()->reload_state);
|
||||
}
|
||||
@ -89,24 +85,19 @@ void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu
|
||||
request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_LOAD_SNAPSHOT_ROOT);
|
||||
break;
|
||||
}
|
||||
/*
|
||||
case 6:
|
||||
printf("%s: -> request to add 0x%lx to block-list\n", __func__, hypercall_arg&(~0xFFF));
|
||||
CPUX86State *env = &(X86_CPU(cpu))->env;
|
||||
kvm_arch_get_registers_fast(cpu);
|
||||
hwaddr phys_addr = (hwaddr) get_paging_phys_addr(cpu, env->cr[3], hypercall_arg&(~0xFFF));
|
||||
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
|
||||
|
||||
break;
|
||||
*/
|
||||
default:
|
||||
abort();
|
||||
}
|
||||
}
|
||||
#else
|
||||
#else /* NYX_ENABLE_DEBUG_HYPERCALLS */
|
||||
|
||||
void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
fprintf(stderr, "[QEMU-Nyx] Error: This hypercall (HYPERCALL_KAFL_DEBUG_TMP) is not enabled!\n");
|
||||
set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)"Disabled debug hypercall called...", strlen("Disabled debug hypercall called..."));
|
||||
|
||||
fprintf(stderr, "[QEMU-Nyx] Error: HYPERCALL_KAFL_DEBUG_TMP not enabled!\n");
|
||||
set_abort_reason_auxiliary_buffer(
|
||||
GET_GLOBAL_STATE()->auxilary_buffer,
|
||||
(char *)"HYPERCALL_KAFL_DEBUG_TMP is not enabled.",
|
||||
strlen("HYPERCALL_KAFL_DEBUG_TMP is not enabled."));
|
||||
synchronization_lock();
|
||||
}
|
||||
#endif
|
@ -1,3 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
|
@ -20,21 +20,21 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include "qemu-common.h"
|
||||
#include "exec/memory.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu-common.h"
|
||||
|
||||
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/cpus.h"
|
||||
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/runstate.h"
|
||||
|
||||
|
||||
#include "nyx/pt.h"
|
||||
@ -50,13 +50,12 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/nested_hypercalls.h"
|
||||
#include "nyx/fast_vm_reload_sync.h"
|
||||
|
||||
#include "nyx/redqueen.h"
|
||||
#include "nyx/hypercall/configuration.h"
|
||||
#include "nyx/hypercall/debug.h"
|
||||
|
||||
//#define DEBUG_HPRINTF
|
||||
#define HPRINTF_SIZE 0x1000
|
||||
#define HPRINTF_SIZE 0x1000 /* FIXME: take from nyx.h */
|
||||
|
||||
bool hypercall_enabled = false;
|
||||
char hprintf_buffer[HPRINTF_SIZE];
|
||||
@ -93,18 +92,11 @@ bool setup_snapshot_once = false;
|
||||
|
||||
|
||||
bool handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//nyx_trace();
|
||||
/*
|
||||
kvm_arch_get_registers(cpu);
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
CPUX86State *env = &x86_cpu->env;
|
||||
nyx_trace();
|
||||
|
||||
printf("%s: exception_injected: %d\n", __func__, env->exception_injected);
|
||||
*/
|
||||
if(hypercall_enabled){
|
||||
if (init_state){
|
||||
set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 2);
|
||||
//fprintf(stderr, "--------------------\n");
|
||||
synchronization_lock();
|
||||
|
||||
} else {
|
||||
@ -115,46 +107,26 @@ bool handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu, uint
|
||||
}
|
||||
|
||||
if(!setup_snapshot_once){
|
||||
//pt_reset_bitmap();
|
||||
|
||||
|
||||
coverage_bitmap_reset();
|
||||
request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP);
|
||||
setup_snapshot_once = true;
|
||||
|
||||
for(int i = 0; i < INTEL_PT_MAX_RANGES; i++){
|
||||
//printf("=> %d\n", i);
|
||||
//if(filter_enabled[i]){
|
||||
if(GET_GLOBAL_STATE()->pt_ip_filter_configured[i]){
|
||||
pt_enable_ip_filtering(cpu, i, true, false);
|
||||
}
|
||||
}
|
||||
pt_init_decoder(cpu);
|
||||
|
||||
request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_LOAD_SNAPSHOT_ROOT);
|
||||
|
||||
//printf("DONE!\n");
|
||||
/*
|
||||
qemu_mutex_lock_iothread();
|
||||
nyx_debug_p(CORE_PREFIX, "...GOOOOOO!!!!");
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
nyx_debug_p(CORE_PREFIX, "...DONE!!!!");
|
||||
qemu_mutex_unlock_iothread();
|
||||
*/
|
||||
GET_GLOBAL_STATE()->in_fuzzing_mode = true;
|
||||
set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 3);
|
||||
|
||||
//sigprof_enabled = true;
|
||||
//reset_timeout_detector(&GET_GLOBAL_STATE()->timeout_detector);
|
||||
}
|
||||
else{
|
||||
//set_illegal_payload();
|
||||
synchronization_lock();
|
||||
reset_timeout_detector(&GET_GLOBAL_STATE()->timeout_detector);
|
||||
GET_GLOBAL_STATE()->in_fuzzing_mode = true;
|
||||
|
||||
|
||||
//printf("RIP => %lx\n", get_rip(cpu));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -169,25 +141,15 @@ static void acquire_print_once(CPUState *cpu){
|
||||
if(acquire_print_once_bool){
|
||||
acquire_print_once_bool = false;
|
||||
kvm_arch_get_registers(cpu);
|
||||
//X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
//CPUX86State *env = &x86_cpu->env;
|
||||
nyx_debug("handle_hypercall_kafl_acquire at:%lx\n", get_rip(cpu));
|
||||
//disassemble_at_rip(STDERR_FILENO, get_rip(cpu), cpu, env->cr[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_hypercall_kafl_acquire(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//return;
|
||||
if(hypercall_enabled){
|
||||
if (!init_state){
|
||||
acquire_print_once(cpu);
|
||||
//init_det_filter();
|
||||
synchronization_enter_fuzzing_loop(cpu);
|
||||
/*
|
||||
if (pt_enable(cpu, false) == 0){
|
||||
cpu->pt_enabled = true;
|
||||
}
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -231,7 +193,6 @@ static void set_return_value(CPUState *cpu, uint64_t return_value){
|
||||
|
||||
static void handle_hypercall_kafl_req_stream_data(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
static uint8_t req_stream_buffer[0x1000];
|
||||
|
||||
if(is_called_in_fuzzing_mode("HYPERCALL_KAFL_REQ_STREAM_DATA")){
|
||||
return;
|
||||
}
|
||||
@ -294,7 +255,6 @@ static void handle_hypercall_kafl_req_stream_data_bulk(struct kvm_run *run, CPUS
|
||||
|
||||
}
|
||||
|
||||
//fprintf(stderr, "%s -> %d\n", __func__, bytes);
|
||||
set_return_value(cpu, bytes);
|
||||
}
|
||||
}
|
||||
@ -336,20 +296,15 @@ static void release_print_once(CPUState *cpu){
|
||||
if(release_print_once_bool){
|
||||
release_print_once_bool = false;
|
||||
kvm_arch_get_registers(cpu);
|
||||
//X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
//CPUX86State *env = &x86_cpu->env;
|
||||
nyx_debug("handle_hypercall_kafl_release at:%lx\n", get_rip(cpu));
|
||||
//disassemble_at_rip(STDERR_FILENO, get_rip(cpu), cpu, env->cr[3]);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_hypercall_kafl_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//fprintf(stderr, "%s\n", __func__);
|
||||
if(hypercall_enabled){
|
||||
if (init_state){
|
||||
init_state = false;
|
||||
} else {
|
||||
//printf(CORE_PREFIX, "Got STARVED notification (num=%llu)\n", hypercall_arg);
|
||||
if (hypercall_arg > 0) {
|
||||
GET_GLOBAL_STATE()->starved = 1;
|
||||
} else {
|
||||
@ -386,9 +341,7 @@ void handle_hypercall_kafl_mtf(struct kvm_run *run, CPUState *cpu, uint64_t hype
|
||||
void handle_hypercall_kafl_page_dump_bp(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg, uint64_t page){
|
||||
//nyx_trace();
|
||||
kvm_arch_get_registers_fast(cpu);
|
||||
|
||||
nyx_debug("%s --> %lx\n", __func__, get_rip(cpu));
|
||||
|
||||
kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_MTF);
|
||||
|
||||
bool success = false;
|
||||
@ -403,10 +356,8 @@ void handle_hypercall_kafl_page_dump_bp(struct kvm_run *run, CPUState *cpu, uint
|
||||
}
|
||||
else{
|
||||
nyx_debug("%s: FAIL: %d\n", __func__, success);
|
||||
//assert(false);
|
||||
|
||||
kvm_remove_all_breakpoints(cpu);
|
||||
|
||||
kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
|
||||
kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_MTF);
|
||||
}
|
||||
@ -415,7 +366,7 @@ void handle_hypercall_kafl_page_dump_bp(struct kvm_run *run, CPUState *cpu, uint
|
||||
|
||||
static inline void set_page_dump_bp(CPUState *cpu, uint64_t cr3, uint64_t addr){
|
||||
|
||||
nyx_debug("\n\n%s %lx %lx\n\n", __func__, cr3, addr);
|
||||
nyx_debug("%s --> %lx %lx\n", __func__, cr3, addr);
|
||||
kvm_remove_all_breakpoints(cpu);
|
||||
kvm_insert_breakpoint(cpu, addr, 1, 1);
|
||||
kvm_update_guest_debug(cpu, 0);
|
||||
@ -481,23 +432,11 @@ static void handle_hypercall_kafl_submit_kasan(struct kvm_run *run, CPUState *cp
|
||||
}
|
||||
}
|
||||
|
||||
//#define PANIC_DEBUG
|
||||
|
||||
void handle_hypercall_kafl_panic(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
static char reason[1024];
|
||||
if(hypercall_enabled){
|
||||
#ifdef PANIC_DEBUG
|
||||
if(hypercall_arg){
|
||||
//fprintf(stderr, "Panic in user mode!\n");
|
||||
//nyx_debug_p(CORE_PREFIX, "Panic in user mode!");
|
||||
} else{
|
||||
nyx_debug("Panic in kernel mode!\n");
|
||||
nyx_debug_p(CORE_PREFIX, "Panic in kernel mode!");
|
||||
//assert(0);
|
||||
}
|
||||
#endif
|
||||
if(fast_reload_snapshot_exists(get_fast_reload_snapshot()) && GET_GLOBAL_STATE()->in_fuzzing_mode){
|
||||
|
||||
// TODO: either remove or document + and apply for kasan/timeout as well
|
||||
if(hypercall_arg & 0x8000000000000000ULL){
|
||||
|
||||
reason[0] = '\x00';
|
||||
@ -530,52 +469,16 @@ void handle_hypercall_kafl_panic(struct kvm_run *run, CPUState *cpu, uint64_t hy
|
||||
}
|
||||
|
||||
static void handle_hypercall_kafl_create_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
//CPUX86State *env = &x86_cpu->env;
|
||||
if(!fast_reload_tmp_created(get_fast_reload_snapshot())){
|
||||
|
||||
/* decode PT data */
|
||||
pt_disable(qemu_get_cpu(0), false);
|
||||
|
||||
/*
|
||||
kvm_arch_get_registers(cpu);
|
||||
kvm_cpu_synchronize_state(cpu);
|
||||
//fprintf(stderr, "%s: CREATE at %lx\n", __func__, get_rip(cpu));
|
||||
|
||||
//env->eip -= 3; // vmcall size
|
||||
//kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
|
||||
fast_reload_create_tmp_snapshot(get_fast_reload_snapshot());
|
||||
//kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_TMP); //_TMP_FIX_RIP);
|
||||
|
||||
request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_TMP);
|
||||
set_tmp_snapshot_created(GET_GLOBAL_STATE()->auxilary_buffer, 1);
|
||||
//handle_hypercall_kafl_acquire(run, cpu);
|
||||
//fprintf(stderr, "%s: CREATE DONE at %lx\n", __func__, get_rip(cpu));
|
||||
|
||||
handle_hypercall_kafl_release(run, cpu, hypercall_arg);
|
||||
}
|
||||
else{
|
||||
//fprintf(stderr, "%s: LOAD Continue at %lx\n", __func__, get_rip(cpu));
|
||||
//fprintf(stderr, "%s: LOAD at %lx\n", __func__, get_rip(cpu));
|
||||
|
||||
/*
|
||||
qemu_mutex_lock_iothread();
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
fprintf(stderr, "%s: LOAD Continue at %lx\n", __func__, get_rip(cpu));
|
||||
*/
|
||||
|
||||
//handle_hypercall_kafl_acquire(run, cpu);
|
||||
// TODO: raise an error?
|
||||
}
|
||||
}
|
||||
|
||||
@ -594,21 +497,10 @@ static void handle_hypercall_kafl_panic_extended(struct kvm_run *run, CPUState *
|
||||
|
||||
static void handle_hypercall_kafl_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
if(hypercall_enabled){
|
||||
#ifdef PANIC_DEBUG
|
||||
if(hypercall_arg){
|
||||
nyx_debug_p(CORE_PREFIX, "ASan notification in user mode!");
|
||||
} else{
|
||||
nyx_debug_p(CORE_PREFIX, "ASan notification in kernel mode!");
|
||||
}
|
||||
#endif
|
||||
if(fast_reload_snapshot_exists(get_fast_reload_snapshot())){
|
||||
synchronization_lock_asan_found();
|
||||
//synchronization_stop_vm_kasan(cpu);
|
||||
} else{
|
||||
nyx_debug_p(CORE_PREFIX, "KASAN detected during initialization of stage 1 or stage 2 loader");
|
||||
//hypercall_snd_char(KAFL_PROTO_KASAN);
|
||||
nyx_debug_p(CORE_PREFIX, "Protocol - SEND: KAFL_PROTO_KASAN");
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -658,7 +550,7 @@ static void handle_hypercall_kafl_user_range_advise(struct kvm_run *run, CPUStat
|
||||
}
|
||||
|
||||
static void handle_hypercall_kafl_user_submit_mode(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//printf("%s\n", __func__);
|
||||
nyx_trace();
|
||||
|
||||
if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_USER_SUBMIT_MODE")){
|
||||
return;
|
||||
@ -843,16 +735,14 @@ static void handle_hypercall_kafl_persist_page_past_snapshot(struct kvm_run *run
|
||||
int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall, uint64_t arg){
|
||||
int ret = -1;
|
||||
//fprintf(stderr, "%s -> %ld\n", __func__, hypercall);
|
||||
|
||||
// FIXME: ret is always 0. no default case.
|
||||
switch(hypercall){
|
||||
case KVM_EXIT_KAFL_ACQUIRE:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_ACQUIRE\n");
|
||||
handle_hypercall_kafl_acquire(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_GET_PAYLOAD:
|
||||
// = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_GET_PAYLOAD\n");
|
||||
handle_hypercall_get_payload(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
@ -865,44 +755,30 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_RELEASE:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_RELEASE\n");
|
||||
handle_hypercall_kafl_release(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_SUBMIT_CR3:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_SUBMIT_CR3\n");
|
||||
handle_hypercall_kafl_cr3(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_SUBMIT_PANIC:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_SUBMIT_PANIC\n");
|
||||
handle_hypercall_kafl_submit_panic(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_SUBMIT_KASAN:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_SUBMIT_KASAN\n");
|
||||
handle_hypercall_kafl_submit_kasan(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_PANIC:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_PANIC\n");
|
||||
handle_hypercall_kafl_panic(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_KASAN:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_KASAN\n");
|
||||
handle_hypercall_kafl_kasan(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_LOCK:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_LOCK\n");
|
||||
handle_hypercall_kafl_lock(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
@ -910,15 +786,11 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall
|
||||
nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_INFO)...");
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_NEXT_PAYLOAD:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_NEXT_PAYLOAD\n");
|
||||
case KVM_EXIT_KAFL_NEXT_PAYLOAD:
|
||||
handle_hypercall_kafl_next_payload(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_PRINTF:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "KVM_EXIT_KAFL_PRINTF\n");
|
||||
case KVM_EXIT_KAFL_PRINTF:
|
||||
handle_hypercall_kafl_printf(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
@ -930,20 +802,15 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall
|
||||
nyx_abort((char*)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK)...");
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
/* user space only exit reasons */
|
||||
case KVM_EXIT_KAFL_USER_RANGE_ADVISE:
|
||||
//timeout_reload_pending = false;
|
||||
handle_hypercall_kafl_user_range_advise(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_USER_SUBMIT_MODE:
|
||||
//timeout_reload_pending = false;
|
||||
handle_hypercall_kafl_user_submit_mode(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_USER_FAST_ACQUIRE:
|
||||
//timeout_reload_pending = false;
|
||||
if(handle_hypercall_kafl_next_payload(run, cpu, arg)){
|
||||
handle_hypercall_kafl_cr3(run, cpu, arg);
|
||||
handle_hypercall_kafl_acquire(run, cpu, arg);
|
||||
@ -951,46 +818,34 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_TOPA_MAIN_FULL:
|
||||
//timeout_reload_pending = false;
|
||||
//fprintf(stderr, "pt_handle_overflow\n");
|
||||
pt_handle_overflow(cpu);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_USER_ABORT:
|
||||
//timeout_reload_pending = false;
|
||||
handle_hypercall_kafl_user_abort(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_NESTED_CONFIG:
|
||||
//timeout_reload_pending = false;
|
||||
handle_hypercall_kafl_nested_config(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
case KVM_EXIT_KAFL_NESTED_PREPARE:
|
||||
//timeout_reload_pending = false;
|
||||
handle_hypercall_kafl_nested_prepare(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case KVM_EXIT_KAFL_NESTED_ACQUIRE:
|
||||
//timeout_reload_pending = false;
|
||||
handle_hypercall_kafl_nested_acquire(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case KVM_EXIT_KAFL_NESTED_RELEASE:
|
||||
//timeout_reload_pending = false;
|
||||
//KVM_EXIT_KAFL_NESTED_RELEASE_GOTO:
|
||||
handle_hypercall_kafl_nested_release(run, cpu, arg);
|
||||
//unlock_reload_pending(cpu);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case KVM_EXIT_KAFL_NESTED_HPRINTF:
|
||||
handle_hypercall_kafl_nested_hprintf(run, cpu, arg);
|
||||
ret = 0;
|
||||
break;
|
||||
|
||||
case KVM_EXIT_KAFL_PAGE_DUMP_BP:
|
||||
handle_hypercall_kafl_page_dump_bp(run, cpu, arg, run->debug.arch.pc);
|
||||
ret = 0;
|
||||
|
@ -21,9 +21,12 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#define PAYLOAD_BUFFER_SIZE_64 26
|
||||
#define PAYLOAD_BUFFER_SIZE_32 20
|
||||
|
||||
// FIXME: move to common nyx.h
|
||||
#define KAFL_MODE_64 0
|
||||
#define KAFL_MODE_32 1
|
||||
#define KAFL_MODE_16 2
|
||||
@ -82,13 +85,6 @@ bool check_bitmap_byte(uint32_t value);
|
||||
*/
|
||||
#define KASAN_PAYLOAD_32 "\xFA\xB8\x1F\x00\x00\x00\xBB\x09\x00\x00\x00\xB9\x00\x00\x00\x00\x0F\x01\xC1\xF4"
|
||||
|
||||
/*
|
||||
* printk Notifier Payload (x86-64)
|
||||
* 0f 01 c1 vmcall
|
||||
* c3 retn
|
||||
*/
|
||||
#define PRINTK_PAYLOAD "\x0F\x01\xC1\xC3"
|
||||
|
||||
void pt_setup_program(void* ptr);
|
||||
void pt_setup_snd_handler(void (*tmp)(char, void*), void* tmp_s);
|
||||
void pt_setup_ip_filters(uint8_t filter_id, uint64_t start, uint64_t end);
|
||||
@ -98,8 +94,6 @@ void pt_disable_wrapper(CPUState *cpu);
|
||||
|
||||
void hypercall_submit_address(uint64_t address);
|
||||
bool hypercall_check_tuple(uint64_t current_addr, uint64_t prev_addr);
|
||||
//void hypercall_check_in_range(uint64_t* addr);
|
||||
|
||||
|
||||
bool hypercall_check_transition(uint64_t value);
|
||||
void hypercall_submit_transition(uint32_t value);
|
||||
|
@ -20,6 +20,12 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/cutils.h"
|
||||
#include "hw/qdev-properties.h"
|
||||
@ -38,8 +44,6 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "sysemu/qtest.h"
|
||||
#include "qapi/visitor.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include "pt.h"
|
||||
#include "nyx/hypercall/hypercall.h"
|
||||
#include "nyx/interface.h"
|
||||
@ -47,14 +51,11 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "nyx/synchronization.h"
|
||||
#include "nyx/snapshot/devices/state_reallocation.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/sharedir.h"
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/trace_dump.h"
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "redqueen.h"
|
||||
|
||||
#define CONVERT_UINT64(x) (uint64_t)(strtoull(x, NULL, 16))
|
||||
@ -314,16 +315,6 @@ static bool verify_workdir_state(nyx_interface_state *s, Error **errp){
|
||||
|
||||
|
||||
assert(asprintf(&tmp, "%s/aux_buffer_%d", workdir, id) != -1);
|
||||
/*
|
||||
if (file_exits(tmp)){
|
||||
nyx_debug_p(INTERFACE_PREFIX, "%s does not already exists...", tmp);
|
||||
free(tmp);
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
init_aux_buffer(tmp);
|
||||
}
|
||||
*/
|
||||
init_aux_buffer(tmp);
|
||||
free(tmp);
|
||||
|
||||
@ -406,13 +397,12 @@ static void nyx_realize(DeviceState *dev, Error **errp){
|
||||
GET_GLOBAL_STATE()->worker_id = s->worker_id;
|
||||
|
||||
if (!s->workdir || !verify_workdir_state(s, errp)){
|
||||
nyx_error("Error: work dir...\n");
|
||||
nyx_error("Error: Invalid work dir...\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (!s->sharedir || !verify_sharedir_state(s, errp)){
|
||||
nyx_error("Warning: Invalid sharedir...\n");
|
||||
//abort();
|
||||
}
|
||||
else{
|
||||
sharedir_set_dir(GET_GLOBAL_STATE()->sharedir, s->sharedir);
|
||||
@ -432,11 +422,8 @@ static Property nyx_interface_properties[] = {
|
||||
DEFINE_PROP_CHR("chardev", nyx_interface_state, chr),
|
||||
|
||||
DEFINE_PROP_STRING("sharedir", nyx_interface_state, sharedir),
|
||||
|
||||
|
||||
DEFINE_PROP_STRING("workdir", nyx_interface_state, workdir),
|
||||
DEFINE_PROP_UINT32("worker_id", nyx_interface_state, worker_id, 0xFFFF),
|
||||
|
||||
DEFINE_PROP_UINT64("cow_primary_size", nyx_interface_state, cow_primary_size, 0),
|
||||
/*
|
||||
* Since DEFINE_PROP_UINT64 is somehow broken (signed/unsigned madness),
|
||||
@ -463,9 +450,7 @@ static Property nyx_interface_properties[] = {
|
||||
|
||||
static void nyx_interface_class_init(ObjectClass *klass, void *data){
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
//PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
|
||||
dc->realize = nyx_realize;
|
||||
//k->class_id = PCI_CLASS_MEMORY_RAM;
|
||||
dc->props = nyx_interface_properties;
|
||||
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
|
||||
dc->desc = "Nyx Interface";
|
||||
|
@ -1,11 +1,14 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include <linux/kvm.h>
|
||||
#include "sysemu/kvm.h"
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "nyx/kvm_nested.h"
|
||||
#include "cpu.h"
|
||||
#include <linux/kvm.h>
|
||||
#include "nyx/debug.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "qemu/rcu_queue.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "pt.h"
|
||||
|
||||
#define PPAGE_SIZE 0x1000
|
||||
@ -284,30 +287,12 @@ void print_48_paging(uint64_t cr3){
|
||||
write_address(0, 0x1000, 0);
|
||||
}
|
||||
|
||||
/*
|
||||
static bool change_page_permissions(uint64_t phys_addr, CPUState *cpu){
|
||||
RAMBlock *block;
|
||||
|
||||
//MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
|
||||
|
||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
||||
if(!memcmp(block->idstr, "pc.ram", 6)){
|
||||
printf("FOUND AND MODIFIED! %lx\n", mprotect((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_NONE));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
uint64_t get_nested_guest_rip(CPUState *cpu){
|
||||
|
||||
X86CPU *cpux86 = X86_CPU(cpu);
|
||||
CPUX86State *env = &cpux86->env;
|
||||
|
||||
kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
|
||||
|
||||
struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
|
||||
|
||||
return saved_vmcs->guest_rip;
|
||||
@ -319,7 +304,6 @@ uint64_t get_nested_host_rip(CPUState *cpu){
|
||||
CPUX86State *env = &cpux86->env;
|
||||
|
||||
kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
|
||||
|
||||
struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
|
||||
|
||||
return saved_vmcs->host_rip;
|
||||
@ -331,7 +315,6 @@ uint64_t get_nested_host_cr3(CPUState *cpu){
|
||||
CPUX86State *env = &cpux86->env;
|
||||
|
||||
kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
|
||||
|
||||
struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
|
||||
|
||||
return saved_vmcs->host_cr3;
|
||||
@ -342,13 +325,9 @@ void set_nested_rip(CPUState *cpu, uint64_t rip){
|
||||
X86CPU *cpux86 = X86_CPU(cpu);
|
||||
CPUX86State *env = &cpux86->env;
|
||||
|
||||
//kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
|
||||
|
||||
struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
|
||||
|
||||
saved_vmcs->guest_rip = rip;
|
||||
|
||||
//return saved_vmcs->guest_rip;
|
||||
}
|
||||
|
||||
void kvm_nested_get_info(CPUState *cpu){
|
||||
@ -358,57 +337,13 @@ void kvm_nested_get_info(CPUState *cpu){
|
||||
|
||||
kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
|
||||
|
||||
struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
|
||||
__attribute__((unused)) struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "VMCS host_cr3:\t%lx", saved_vmcs->host_cr3);
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "VMCS host_cr4:\t%lx", saved_vmcs->host_cr4);
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "VMCS host_ia32_efer:\t%lx", saved_vmcs->host_ia32_efer);
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "VMCS host_cr0:\t%lx", saved_vmcs->host_cr0);
|
||||
|
||||
return;
|
||||
|
||||
//cpu->parent_cr3 = saved_vmcs->host_cr3+0x1000;
|
||||
GET_GLOBAL_STATE()->parent_cr3 = saved_vmcs->host_cr3+0x1000;
|
||||
fprintf(stderr, "saved_vmcs->guest_cr3: %lx %lx %lx\n", saved_vmcs->guest_cr3, saved_vmcs->host_cr3, env->cr[3]);
|
||||
pt_set_cr3(cpu, saved_vmcs->host_cr3+0x1000, false); /* USERSPACE */
|
||||
//pt_set_cr3(cpu, saved_vmcs->host_cr3+0x1000, false); /* KERNELSPACE QEMU fuzzing fix...fucking kpti (https://gruss.cc/files/kaiser.pdf)!!! */
|
||||
|
||||
/* let's modify page permissions of our CR3 referencing PTs */
|
||||
//change_page_permissions(cpu->parent_cr3, cpu);
|
||||
|
||||
|
||||
if (!(saved_vmcs->host_cr0 & CR0_PG_MASK)) {
|
||||
printf("PG disabled\n");
|
||||
}
|
||||
else{
|
||||
if (saved_vmcs->host_cr4 & CR4_PAE_MASK) {
|
||||
if (saved_vmcs->host_ia32_efer & (1 << 10)) {
|
||||
if (saved_vmcs->host_cr0 & CR4_LA57_MASK) {
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "mem_info_la57");
|
||||
abort();
|
||||
//mem_info_la57(mon, env);
|
||||
} else {
|
||||
nyx_debug_p(NESTED_VM_PREFIX, " ==== L1 Page Tables ====");
|
||||
print_48_paging(saved_vmcs->host_cr3);
|
||||
|
||||
if(saved_vmcs->ept_pointer){
|
||||
nyx_debug_p(NESTED_VM_PREFIX, " ==== L2 Page Tables ====");
|
||||
print_48_paging(saved_vmcs->ept_pointer);
|
||||
}
|
||||
//mem_info_la48(mon, env);
|
||||
}
|
||||
}
|
||||
else{
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "mem_info_pae32");
|
||||
abort();
|
||||
//mem_info_pae32(mon, env);
|
||||
}
|
||||
}
|
||||
else {
|
||||
nyx_debug_p(NESTED_VM_PREFIX, "mem_info_32");
|
||||
abort();
|
||||
//mem_info_32(mon, env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#define AREA_DESC_LEN 256
|
||||
@ -430,8 +365,6 @@ typedef struct {
|
||||
}config_t;
|
||||
|
||||
void print_configuration(FILE *stream, void* configuration, size_t size){
|
||||
//void print_configuration(void* configuration, size_t size){
|
||||
|
||||
fprintf(stream, "%s: size: %lx\n", __func__, size);
|
||||
assert((size-sizeof(config_t))%sizeof(area_t_export_t) == 0);
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
#pragma once
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdint.h>
|
||||
|
||||
void print_48_paging(uint64_t cr3);
|
||||
void kvm_nested_get_info(CPUState *cpu);
|
||||
|
@ -18,8 +18,11 @@ You should have received a copy of the GNU General Public License
|
||||
along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include <errno.h>
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include "exec/gdbstub.h"
|
||||
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "exec/ram_addr.h"
|
||||
@ -29,9 +32,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#include "nyx/hypercall/hypercall.h"
|
||||
#include "debug.h"
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
#include "exec/gdbstub.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "nyx/helpers.h"
|
||||
|
||||
#define INVALID_ADDRESS 0xFFFFFFFFFFFFFFFFULL
|
||||
@ -141,31 +142,23 @@ bool write_physical_memory(uint64_t address, uint8_t* data, uint32_t size, CPUSt
|
||||
}
|
||||
|
||||
static void refresh_kvm(CPUState *cpu){
|
||||
//int ret = 0;
|
||||
if (!cpu->vcpu_dirty) {
|
||||
//kvm_arch_get_registers_fast(cpu);
|
||||
kvm_arch_get_registers(cpu);
|
||||
|
||||
//cpu->vcpu_dirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void refresh_kvm_non_dirty(CPUState *cpu){
|
||||
if (!cpu->vcpu_dirty) {
|
||||
kvm_arch_get_registers_fast(cpu);
|
||||
//kvm_arch_get_registers(cpu);
|
||||
}
|
||||
}
|
||||
|
||||
bool remap_payload_slot(uint64_t phys_addr, uint32_t slot, CPUState *cpu){
|
||||
//assert(0); /* nested code -> test me later */
|
||||
|
||||
assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size);
|
||||
RAMBlock *block;
|
||||
refresh_kvm_non_dirty(cpu);
|
||||
|
||||
uint32_t i = slot;
|
||||
|
||||
uint64_t phys_addr_ram_offset = address_to_ram_offset(phys_addr);
|
||||
|
||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
||||
@ -174,9 +167,6 @@ bool remap_payload_slot(uint64_t phys_addr, uint32_t slot, CPUState *cpu){
|
||||
munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE);
|
||||
mmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, GET_GLOBAL_STATE()->shared_payload_buffer_fd, (i*x86_64_PAGE_SIZE));
|
||||
|
||||
//printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE));
|
||||
//printf("MMAP: %p\n", mmap((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, GET_GLOBAL_STATE()->shared_payload_buffer_fd, (i*x86_64_PAGE_SIZE)));
|
||||
|
||||
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
|
||||
break;
|
||||
}
|
||||
@ -186,7 +176,6 @@ bool remap_payload_slot(uint64_t phys_addr, uint32_t slot, CPUState *cpu){
|
||||
}
|
||||
|
||||
bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t shm_size, bool virtual, uint64_t cr3){
|
||||
//printf("%s ---> \n", __func__);
|
||||
assert(fd && shm_size);
|
||||
assert((slot*x86_64_PAGE_SIZE) < shm_size);
|
||||
|
||||
@ -206,8 +195,6 @@ bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t sh
|
||||
}
|
||||
}
|
||||
uint64_t phys_addr_ram_offset = address_to_ram_offset(phys_addr);
|
||||
|
||||
//printf("phys_addr -> %lx\n", phys_addr);
|
||||
|
||||
nyx_debug("%s: addr => %lx phys_addr => %lx\n", __func__, addr, phys_addr);
|
||||
|
||||
@ -223,9 +210,6 @@ bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t sh
|
||||
assert(false);
|
||||
}
|
||||
|
||||
//printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE));
|
||||
//printf("MMAP: %p\n", mmap((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, (i*x86_64_PAGE_SIZE)));
|
||||
|
||||
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
|
||||
break;
|
||||
}
|
||||
@ -235,8 +219,6 @@ bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t sh
|
||||
}
|
||||
|
||||
bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *cpu){
|
||||
//assert(0); /* nested code -> test me later */
|
||||
|
||||
assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size);
|
||||
RAMBlock *block;
|
||||
refresh_kvm_non_dirty(cpu);
|
||||
@ -252,9 +234,6 @@ bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *c
|
||||
munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE);
|
||||
mmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), 0x1000, PROT_READ , MAP_SHARED | MAP_FIXED, GET_GLOBAL_STATE()->shared_payload_buffer_fd, (i*x86_64_PAGE_SIZE));
|
||||
|
||||
//printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE));
|
||||
//printf("MMAP: %p\n", mmap((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_READ , MAP_SHARED | MAP_FIXED, GET_GLOBAL_STATE()->shared_payload_buffer_fd, (i*x86_64_PAGE_SIZE)));
|
||||
|
||||
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
|
||||
break;
|
||||
}
|
||||
@ -295,8 +274,6 @@ bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){
|
||||
refresh_kvm_non_dirty(cpu);
|
||||
|
||||
for(uint32_t i = 0; i < (GET_GLOBAL_STATE()->shared_payload_buffer_size/x86_64_PAGE_SIZE); i++){
|
||||
//MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
|
||||
//hwaddr phys_addr = cpu_get_phys_page_attrs_debug(cpu, ((virt_guest_addr+(i*x86_64_PAGE_SIZE)) & x86_64_PAGE_MASK), &attrs);
|
||||
uint64_t phys_addr = get_paging_phys_addr(cpu, GET_GLOBAL_STATE()->parent_cr3, ((virt_guest_addr+(i*x86_64_PAGE_SIZE)) & x86_64_PAGE_MASK));
|
||||
|
||||
assert(phys_addr != INVALID_ADDRESS);
|
||||
@ -305,17 +282,12 @@ bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){
|
||||
|
||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
||||
if(!memcmp(block->idstr, "pc.ram", 6)){
|
||||
//printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE));
|
||||
if(munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE) == -1){
|
||||
nyx_error("munmap failed!\n");
|
||||
//exit(1);
|
||||
assert(false);
|
||||
}
|
||||
//printf("MMAP: %lx\n", mmap((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, shared_payload_buffer_fd, (i*x86_64_PAGE_SIZE)));
|
||||
|
||||
if(mmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, GET_GLOBAL_STATE()->shared_payload_buffer_fd, (i*x86_64_PAGE_SIZE)) == MAP_FAILED){
|
||||
nyx_error("mmap failed!\n");
|
||||
//exit(1);
|
||||
assert(false);
|
||||
}
|
||||
|
||||
@ -335,7 +307,7 @@ bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){
|
||||
|
||||
bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu)
|
||||
{
|
||||
/* Todo: later &address_space_memory + phys_addr -> mmap SHARED */
|
||||
/* TODO: later &address_space_memory + phys_addr -> mmap SHARED */
|
||||
int asidx;
|
||||
MemTxAttrs attrs;
|
||||
hwaddr phys_addr;
|
||||
@ -350,7 +322,6 @@ bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUSta
|
||||
l = counter;
|
||||
|
||||
refresh_kvm(cpu);
|
||||
//cpu_synchronize_state(cpu);
|
||||
asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
|
||||
attrs = MEMTXATTRS_UNSPECIFIED;
|
||||
phys_addr = cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs);
|
||||
@ -474,8 +445,6 @@ static int redqueen_update_guest_debug(CPUState *cpu) {
|
||||
}
|
||||
|
||||
return kvm_vcpu_ioctl(cpu, KVM_SET_GUEST_DEBUG, &data.dbg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void redqueen_remove_all_breakpoints(CPUState *cpu) {
|
||||
@ -558,7 +527,6 @@ int insert_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len){
|
||||
|
||||
|
||||
int remove_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len){
|
||||
//fprintf(stderr, "%s %lx\n", __func__, addr);
|
||||
redqueen_remove_breakpoint(cpu, addr, len);
|
||||
redqueen_update_guest_debug(cpu);
|
||||
return 0;
|
||||
@ -809,7 +777,6 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f
|
||||
|
||||
bool read_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu){
|
||||
uint8_t tmp_buf[x86_64_PAGE_SIZE];
|
||||
//MemTxAttrs attrs;
|
||||
hwaddr phys_addr;
|
||||
int asidx;
|
||||
|
||||
@ -825,12 +792,10 @@ bool read_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUStat
|
||||
len_to_copy = x86_64_PAGE_SIZE;
|
||||
|
||||
asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
|
||||
//MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
|
||||
#ifdef DEBUG_48BIT_WALK
|
||||
phys_addr_2 = cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs);
|
||||
#endif
|
||||
phys_addr = (hwaddr)get_paging_phys_addr(cpu, env->cr[3], address) & 0xFFFFFFFFFFFFF000ULL;// != 0xFFFFFFFFFFFFFFFFULL)
|
||||
//nyx_debug_p(MEM_PREFIX, "TRANSLATE: %lx -> %lx == %lx", address, phys_addr, phys_addr_2);
|
||||
|
||||
#ifdef DEBUG_48BIT_WALK
|
||||
assert(phys_addr == phys_addr_2);
|
||||
|
@ -22,7 +22,6 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
#ifndef MEMORY_ACCESS_H
|
||||
#define MEMORY_ACCESS_H
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <linux/kvm.h>
|
||||
#include "qemu-common.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "kvm_nested.h"
|
||||
@ -16,14 +17,11 @@
|
||||
|
||||
|
||||
bool hypercalls_enabled = false;
|
||||
|
||||
bool create_snapshot = false;
|
||||
|
||||
uint64_t htos_cr3 = 0;
|
||||
uint64_t htos_config = 0;
|
||||
|
||||
static bool init_state = true;
|
||||
|
||||
int nested_once = 0;
|
||||
|
||||
bool nested_setup_snapshot_once = false;
|
||||
@ -32,23 +30,13 @@ bool nested_setup_snapshot_once = false;
|
||||
|
||||
void handle_hypercall_kafl_nested_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
/* magic */
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
nyx_trace();
|
||||
uint32_t size = 0;
|
||||
read_physical_memory(htos_config, (uint8_t*) &size, sizeof(uint32_t), cpu);
|
||||
fprintf(stderr, "--> %x\n", size);
|
||||
|
||||
void* buffer = malloc(size);
|
||||
|
||||
read_physical_memory(htos_config+sizeof(uint32_t), buffer, size, cpu);
|
||||
/*
|
||||
hexdump_kafl(buffer, size);
|
||||
|
||||
FILE *f = fopen("/tmp/htos_configuration", "w");
|
||||
fwrite(buffer, size, 1, f);
|
||||
fclose(f);
|
||||
|
||||
*/
|
||||
print_configuration(stderr, buffer, size);
|
||||
|
||||
FILE* f = fopen("/tmp/hypertrash_configration", "w");
|
||||
@ -56,34 +44,19 @@ void handle_hypercall_kafl_nested_config(struct kvm_run *run, CPUState *cpu, uin
|
||||
fclose(f);
|
||||
|
||||
free(buffer);
|
||||
/*
|
||||
hexdump_virtual_memory()
|
||||
_memory(0x38d31000, 0x2000, cpu);
|
||||
*/
|
||||
}
|
||||
|
||||
#define ANSI_COLOR_YELLOW "\x1b[33m"
|
||||
#define ANSI_COLOR_RESET "\x1b[0m"
|
||||
|
||||
void handle_hypercall_kafl_nested_hprintf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
char hprintf_buffer[0x1000];
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
nyx_trace();
|
||||
char hprintf_buffer[0x1000];
|
||||
read_physical_memory((uint64_t)run->hypercall.args[0], (uint8_t*)hprintf_buffer, 0x1000, cpu);
|
||||
|
||||
//fprintf(stderr, ANSI_COLOR_YELLOW "%s" ANSI_COLOR_RESET, hprintf_buffer);
|
||||
|
||||
set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strnlen(hprintf_buffer, 0x1000)+1);
|
||||
synchronization_lock_hprintf();
|
||||
//hexdump_kafl(hprintf_buffer, 0x200);
|
||||
}
|
||||
|
||||
void handle_hypercall_kafl_nested_prepare(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
//cpu->fast_reload_snapshot = (void*)fast_reload_new();
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
nyx_trace();
|
||||
kvm_arch_get_registers(cpu);
|
||||
|
||||
if((uint64_t)run->hypercall.args[0]){
|
||||
@ -92,6 +65,7 @@ void handle_hypercall_kafl_nested_prepare(struct kvm_run *run, CPUState *cpu, ui
|
||||
else{
|
||||
abort();
|
||||
}
|
||||
|
||||
size_t buffer_size = (size_t)((uint64_t)run->hypercall.args[0] * sizeof(uint64_t));
|
||||
uint64_t* buffer = malloc(buffer_size);
|
||||
memset(buffer, 0x0, buffer_size);
|
||||
@ -119,12 +93,12 @@ void handle_hypercall_kafl_nested_prepare(struct kvm_run *run, CPUState *cpu, ui
|
||||
bool acquired = false;
|
||||
|
||||
void handle_hypercall_kafl_nested_early_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
nyx_trace();
|
||||
|
||||
if(!hypercalls_enabled){
|
||||
return;
|
||||
}
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
|
||||
bool state = GET_GLOBAL_STATE()->in_reload_mode;
|
||||
if(!state){
|
||||
GET_GLOBAL_STATE()->in_reload_mode = true;
|
||||
@ -137,99 +111,15 @@ void handle_hypercall_kafl_nested_early_release(struct kvm_run *run, CPUState *c
|
||||
}
|
||||
|
||||
void handle_hypercall_kafl_nested_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
hypercalls_enabled = true;
|
||||
static int rcount = 0;
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
|
||||
if((rcount%100) == 0){
|
||||
|
||||
kvm_arch_get_registers(cpu);
|
||||
//printf("TRY %s %lx %lx %lx (%d)\n", __func__, get_rip(cpu), get_nested_guest_rip(cpu), get_nested_host_rip(cpu), rcount);
|
||||
|
||||
// sleep(rand()%4);
|
||||
}
|
||||
rcount++;
|
||||
synchronization_disable_pt(cpu);
|
||||
/*
|
||||
//vm_stop(RUN_STATE_RESTORE_VM);
|
||||
qemu_mutex_lock_iothread();
|
||||
//load_snapshot("kafl", NULL);
|
||||
//vm_start();
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
qemu_mutex_unlock_iothread();
|
||||
*/
|
||||
//kvm_vm_ioctl(kvm_state, KVM_SET_CLOCK, &data);
|
||||
|
||||
// printf("DONE %s\n", __func__);
|
||||
|
||||
/*
|
||||
kvm_arch_get_registers(cpu);
|
||||
fprintf(stderr, "RELOADING DUDE %d!\n", rcount);
|
||||
qemu_mutex_lock_iothread();
|
||||
fast_reload_restore(get_fast_reload_snapshot());
|
||||
qemu_mutex_unlock_iothread();
|
||||
*/
|
||||
//}
|
||||
//sleep(1);
|
||||
|
||||
|
||||
|
||||
return;
|
||||
//assert(false);
|
||||
nyx_debug_p(CORE_PREFIX, "%s %d", __func__, init_state);
|
||||
//sleep(10);
|
||||
|
||||
/* magic */
|
||||
|
||||
//X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
//CPUX86State *env = &x86_cpu->env;
|
||||
|
||||
|
||||
if (init_state){
|
||||
printf("INIT STATE\n");
|
||||
init_state = false;
|
||||
|
||||
//synchronization_disable_pt(cpu);
|
||||
|
||||
nyx_debug_p(CORE_PREFIX, "Protocol - SEND: KAFL_PROTO_RELEASE");
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
|
||||
//if(reload_mode || reload_mode_temp){
|
||||
|
||||
//}
|
||||
|
||||
//synchronization_disable_pt(cpu);
|
||||
|
||||
|
||||
nyx_debug_p(CORE_PREFIX, "%s UNLOCKED", __func__);
|
||||
|
||||
// printf("INTEL PT is disabled!\n");
|
||||
|
||||
}
|
||||
|
||||
|
||||
qemu_mutex_lock_iothread();
|
||||
//fast_reload_restore(get_fast_reload_snapshot());
|
||||
qemu_mutex_unlock_iothread();
|
||||
|
||||
nyx_debug_p(CORE_PREFIX, "%s UNLOCKED 2", __func__);
|
||||
|
||||
|
||||
//kvm_cpu_synchronize_state(cpu);
|
||||
|
||||
acquired = false;
|
||||
|
||||
nyx_trace();
|
||||
// TODO not implemented - see git history for scraps
|
||||
nyx_error("Not implemented.\n");
|
||||
abort();
|
||||
}
|
||||
|
||||
static inline void set_page_dump_bp_nested(CPUState *cpu, uint64_t cr3, uint64_t addr){
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
nyx_trace();
|
||||
|
||||
kvm_remove_all_breakpoints(cpu);
|
||||
kvm_insert_breakpoint(cpu, addr, 1, 1);
|
||||
kvm_update_guest_debug(cpu, 0);
|
||||
@ -239,15 +129,9 @@ static inline void set_page_dump_bp_nested(CPUState *cpu, uint64_t cr3, uint64_t
|
||||
}
|
||||
|
||||
void handle_hypercall_kafl_nested_acquire(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
|
||||
#ifdef DEBUG_NESTED_HYPERCALLS
|
||||
printf("============> %s\n", __func__);
|
||||
#endif
|
||||
nyx_trace();
|
||||
|
||||
if (!acquired){
|
||||
printf("TRY %s\n", __func__);
|
||||
|
||||
|
||||
printf("DONE %s\n", __func__);
|
||||
|
||||
acquired = true;
|
||||
|
||||
//create_fast_snapshot(cpu, true);
|
||||
@ -267,30 +151,15 @@ void handle_hypercall_kafl_nested_acquire(struct kvm_run *run, CPUState *cpu, ui
|
||||
|
||||
kvm_arch_get_registers(cpu);
|
||||
|
||||
X86CPU *x86_cpu = X86_CPU(cpu);
|
||||
CPUX86State *env = &x86_cpu->env;
|
||||
|
||||
printf("IN FUZZING LOOP! %lx\n", env->eip);
|
||||
GET_GLOBAL_STATE()->in_fuzzing_mode = true;
|
||||
set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 3);
|
||||
|
||||
/*
|
||||
if(GET_GLOBAL_STATE()->protect_payload_buffer){
|
||||
for(int i = 0; i < GET_GLOBAL_STATE()->nested_payload_pages_num; i++){
|
||||
remap_payload_slot_protected(GET_GLOBAL_STATE()->nested_payload_pages[i], i, cpu);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
synchronization_lock();
|
||||
|
||||
|
||||
kvm_arch_get_registers(cpu);
|
||||
kvm_arch_get_registers(cpu);
|
||||
|
||||
uint64_t cr3 = get_nested_host_cr3(cpu) & 0xFFFFFFFFFFFFF000ULL;
|
||||
//fprintf(stderr, "CR3 -> 0x%lx\n", cr3);
|
||||
pt_set_cr3(cpu, cr3, false);
|
||||
GET_GLOBAL_STATE()->parent_cr3 = cr3;
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* HyperTrash! */
|
||||
void handle_hypercall_kafl_nested_hprintf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
|
||||
void handle_hypercall_kafl_nested_prepare(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
|
||||
|
245
nyx/page_cache.c
245
nyx/page_cache.c
@ -1,6 +1,4 @@
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include "qemu/osdep.h"
|
||||
#include <errno.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/x86.h>
|
||||
@ -10,26 +8,19 @@
|
||||
#include <stdio.h>
|
||||
#include <sys/mman.h>
|
||||
#include <assert.h>
|
||||
#include "page_cache.h"
|
||||
#include "debug.h"
|
||||
#ifndef STANDALONE_DECODER
|
||||
#include "cpu.h"
|
||||
#include "memory_access.h"
|
||||
#include "fast_vm_reload.h"
|
||||
#include "kvm_nested.h"
|
||||
#include "nyx/page_cache.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/state/state.h"
|
||||
#endif
|
||||
|
||||
|
||||
#define PAGE_CACHE_ADDR_LINE_SIZE sizeof(uint64_t)
|
||||
|
||||
#define UNMAPPED_PAGE 0xFFFFFFFFFFFFFFFFULL
|
||||
|
||||
#ifndef STANDALONE_DECODER
|
||||
static bool reload_addresses(page_cache_t* self){
|
||||
#else
|
||||
bool reload_addresses(page_cache_t* self){
|
||||
#endif
|
||||
khiter_t k;
|
||||
int ret;
|
||||
uint64_t addr, offset;
|
||||
@ -38,8 +29,7 @@ bool reload_addresses(page_cache_t* self){
|
||||
size_t self_offset = lseek(self->fd_address_file, 0, SEEK_END);
|
||||
|
||||
if(self_offset != self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE){
|
||||
//fprintf(stderr, "Reloading files ...\n");
|
||||
|
||||
/* reload page cache from disk */
|
||||
lseek(self->fd_address_file, self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE, SEEK_SET);
|
||||
offset = self->num_pages;
|
||||
while(read(self->fd_address_file, &value, PAGE_CACHE_ADDR_LINE_SIZE)){
|
||||
@ -51,30 +41,20 @@ bool reload_addresses(page_cache_t* self){
|
||||
if(k == kh_end(self->lookup)){
|
||||
|
||||
if(value & 0xFFF){
|
||||
fprintf(stderr, "Load page: %lx (UMAPPED)\n", addr);
|
||||
//k = kh_put(PC_CACHE, self->lookup, addr, &ret);
|
||||
//kh_value(self->lookup, k) = UNMAPPED_PAGE;
|
||||
fprintf(stderr, "Load page: %lx (UNMAPPED)\n", addr);
|
||||
}
|
||||
else{
|
||||
//fprintf(stderr, "Load page: %lx\n", addr);
|
||||
k = kh_put(PC_CACHE, self->lookup, addr, &ret);
|
||||
kh_value(self->lookup, k) = (offset-1)*PAGE_SIZE;
|
||||
}
|
||||
|
||||
/*
|
||||
k = kh_put(PC_CACHE, self->lookup, addr, &ret);
|
||||
kh_value(self->lookup, k) = (offset-1)*PAGE_SIZE;
|
||||
*/
|
||||
}
|
||||
else{
|
||||
/* likely a bug / race condition in page_cache itself! */
|
||||
fprintf(stderr, "----------> Page duplicate found ...skipping! %lx\n", addr);
|
||||
/* should not be possible ... */
|
||||
//abort();
|
||||
}
|
||||
}
|
||||
|
||||
//fprintf(stderr, "Old Value: %d - New Value: %ld\n", self->num_pages, (uint32_t)self_offset/PAGE_CACHE_ADDR_LINE_SIZE);
|
||||
|
||||
/* reload page dump file */
|
||||
munmap(self->page_data, self->num_pages*PAGE_SIZE);
|
||||
self->num_pages = self_offset/PAGE_CACHE_ADDR_LINE_SIZE;
|
||||
@ -86,7 +66,6 @@ bool reload_addresses(page_cache_t* self){
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifndef STANDALONE_DECODER
|
||||
static bool append_page(page_cache_t* self, uint64_t page, uint64_t cr3){
|
||||
bool success = true;
|
||||
if(!self->num_pages){
|
||||
@ -99,87 +78,25 @@ static bool append_page(page_cache_t* self, uint64_t page, uint64_t cr3){
|
||||
self->page_data = mmap(NULL, (self->num_pages+1)*PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd_page_file, 0);
|
||||
}
|
||||
|
||||
|
||||
//if(!dump_page_cr3_snapshot(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->pt_c3_filter)){
|
||||
// if(!dump_page_cr3_snapshot(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)){
|
||||
if(!dump_page_cr3_ht(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->pt_c3_filter)){
|
||||
if(!dump_page_cr3_ht(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)){
|
||||
if(!dump_page_cr3_snapshot(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)){
|
||||
|
||||
//fprintf(stderr, "FAILED DUMP PROCESS of PAGE %lx\n", page);
|
||||
//memset(self->page_data+(PAGE_SIZE*self->num_pages), 0xff, PAGE_SIZE);
|
||||
|
||||
munmap(self->page_data, (self->num_pages+1)*PAGE_SIZE);
|
||||
assert(!ftruncate(self->fd_page_file, (self->num_pages)*PAGE_SIZE));
|
||||
self->page_data = mmap(NULL, (self->num_pages)*PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd_page_file, 0);
|
||||
|
||||
//qemu_backtrace();
|
||||
success = false;
|
||||
return success;
|
||||
//assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
//}
|
||||
|
||||
/*
|
||||
if(!dump_page_cr3_ht(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)){
|
||||
fprintf(stderr, "FAILED DUMP PROCESS of PAGE %lx\n", page);
|
||||
assert(false);
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
//fast_loadvm();
|
||||
if(cr3){
|
||||
dump_page_cr3_ht(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3); //self->cpu->parent_cr3);
|
||||
//assert(dump_page_cr3_snapshot(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu, GET_GLOBAL_STATE()->parent_cr3)); //self->cpu->parent_cr3);
|
||||
|
||||
//read_virtual_memory_cr3(page, self->page_data+(PAGE_SIZE*self->num_pages), PAGE_SIZE, self->cpu, self->cpu->parent_cr3);
|
||||
}
|
||||
else{
|
||||
dump_page_ht(page, self->page_data+(PAGE_SIZE*self->num_pages), self->cpu);
|
||||
//read_virtual_memory(page, self->page_data+(PAGE_SIZE*self->num_pages), PAGE_SIZE, self->cpu);
|
||||
}
|
||||
*/
|
||||
fsync(self->fd_page_file);
|
||||
self->num_pages++;
|
||||
return success;
|
||||
}
|
||||
#else
|
||||
bool append_page(page_cache_t* self, uint64_t page, uint8_t* ptr){
|
||||
self->last_page = 0xFFFFFFFFFFFFFFFF;
|
||||
self->last_addr = 0xFFFFFFFFFFFFFFFF;
|
||||
page &= 0xFFFFFFFFFFFFF000ULL;
|
||||
bool success = true;
|
||||
if(!self->num_pages){
|
||||
assert(!ftruncate(self->fd_page_file, (self->num_pages+1)*PAGE_SIZE));
|
||||
self->page_data = mmap(NULL, (self->num_pages+1)*PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd_page_file, 0);
|
||||
}
|
||||
else{
|
||||
munmap(self->page_data, self->num_pages*PAGE_SIZE);
|
||||
assert(!ftruncate(self->fd_page_file, (self->num_pages+1)*PAGE_SIZE));
|
||||
self->page_data = mmap(NULL, (self->num_pages+1)*PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd_page_file, 0);
|
||||
}
|
||||
|
||||
memcpy(self->page_data+(PAGE_SIZE*self->num_pages), ptr, PAGE_SIZE);
|
||||
|
||||
fsync(self->fd_page_file);
|
||||
|
||||
int ret;
|
||||
khiter_t k;
|
||||
k = kh_put(PC_CACHE, self->lookup, page, &ret);
|
||||
kh_value(self->lookup, k) = self->num_pages*PAGE_SIZE;
|
||||
assert(write(self->fd_address_file, &page, PAGE_CACHE_ADDR_LINE_SIZE) == PAGE_CACHE_ADDR_LINE_SIZE);
|
||||
|
||||
self->num_pages++;
|
||||
|
||||
return success;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void page_cache_lock(page_cache_t* self){
|
||||
#ifndef STANDALONE_DECODER
|
||||
int ret = 0;
|
||||
while (true){
|
||||
ret = flock(self->fd_lock, LOCK_EX);
|
||||
@ -194,11 +111,9 @@ static void page_cache_lock(page_cache_t* self){
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void page_cache_unlock(page_cache_t* self){
|
||||
#ifndef STANDALONE_DECODER
|
||||
int ret = 0;
|
||||
while (true){
|
||||
ret = flock(self->fd_lock, LOCK_UN);
|
||||
@ -213,35 +128,24 @@ static void page_cache_unlock(page_cache_t* self){
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool update_page_cache(page_cache_t* self, uint64_t page, khiter_t* k){
|
||||
|
||||
//#define DEBUG_PAGE_CACHE_LOCK
|
||||
|
||||
page_cache_lock(self);
|
||||
#ifdef DEBUG_PAGE_CACHE_LOCK
|
||||
fprintf(stderr, "%d: LOCKING PAGE CACHE\n", getpid());
|
||||
#endif
|
||||
|
||||
if(reload_addresses(self)){
|
||||
*k = kh_get(PC_CACHE, self->lookup, page);
|
||||
}
|
||||
|
||||
|
||||
if(*k == kh_end(self->lookup)){
|
||||
#ifndef STANDALONE_DECODER
|
||||
int ret;
|
||||
|
||||
uint64_t cr3 = GET_GLOBAL_STATE()->parent_cr3; //self->cpu->parent_cr3;
|
||||
if(!is_addr_mapped_cr3_snapshot(page, self->cpu, GET_GLOBAL_STATE()->parent_cr3) && !is_addr_mapped_cr3_snapshot(page, self->cpu, GET_GLOBAL_STATE()->pt_c3_filter)){ //self->cpu->parent_cr3)){
|
||||
//fprintf(stderr, "PAGE NOT FOUND in SNAPSHOT %lx\n", page);
|
||||
//assert(false);
|
||||
uint64_t cr3 = GET_GLOBAL_STATE()->parent_cr3;
|
||||
if(!is_addr_mapped_cr3_snapshot(page, self->cpu, GET_GLOBAL_STATE()->parent_cr3) && !is_addr_mapped_cr3_snapshot(page, self->cpu, GET_GLOBAL_STATE()->pt_c3_filter)){
|
||||
/* TODO! */
|
||||
}
|
||||
|
||||
*k = kh_get(PC_CACHE, self->lookup, page);
|
||||
|
||||
if(*k == kh_end(self->lookup) && reload_addresses(self)){
|
||||
/* reload sucessful */
|
||||
*k = kh_get(PC_CACHE, self->lookup, page);
|
||||
@ -255,31 +159,13 @@ static bool update_page_cache(page_cache_t* self, uint64_t page, khiter_t* k){
|
||||
kh_value(self->lookup, *k) = (self->num_pages-1)*PAGE_SIZE;
|
||||
}
|
||||
else{
|
||||
//fprintf(stderr, "Fail!!!!\n");
|
||||
page_cache_unlock(self);
|
||||
return false;
|
||||
/*
|
||||
uint64_t new_page = page | 0xFFF;
|
||||
assert(write(self->fd_address_file, &new_page, PAGE_CACHE_ADDR_LINE_SIZE) == PAGE_CACHE_ADDR_LINE_SIZE);
|
||||
kh_value(self->lookup, *k) = UNMAPPED_PAGE;
|
||||
fprintf(stderr, "APPEND UNMAPPED PAGE %lx!\n", page);
|
||||
*/
|
||||
}
|
||||
|
||||
*k = kh_get(PC_CACHE, self->lookup, page);
|
||||
}
|
||||
#else
|
||||
//printf("PAGE NOT FOUND: %lx! ABORTING\n", page);
|
||||
page_cache_unlock(self);
|
||||
return false;
|
||||
abort();
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG_PAGE_CACHE_LOCK
|
||||
fprintf(stderr, "%d: UNLOCKING PAGE CACHE\n", getpid());
|
||||
#endif
|
||||
|
||||
page_cache_unlock(self);
|
||||
return true;
|
||||
}
|
||||
@ -287,40 +173,21 @@ static bool update_page_cache(page_cache_t* self, uint64_t page, khiter_t* k){
|
||||
uint64_t page_cache_fetch(page_cache_t* self, uint64_t page, bool* success, bool test_mode){
|
||||
page &= 0xFFFFFFFFFFFFF000ULL;
|
||||
|
||||
/*
|
||||
if(test_mode){
|
||||
*success = false;
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
||||
//if(page == 0x7ffca45b5000)
|
||||
// return UNMAPPED_PAGE;
|
||||
//printf("%s %lx\n", __func__, page);
|
||||
|
||||
//if (page == 0x0434000)
|
||||
// return 0;
|
||||
|
||||
if (self->last_page == page){
|
||||
*success = true;
|
||||
return self->last_addr;
|
||||
}
|
||||
|
||||
//nyx_debug_p(PAGE_CACHE_PREFIX, "page_cache_fetch %lx", page);
|
||||
|
||||
khiter_t k;
|
||||
k = kh_get(PC_CACHE, self->lookup, page);
|
||||
if(k == kh_end(self->lookup)){
|
||||
if(test_mode || update_page_cache(self, page, &k) == false){
|
||||
//fprintf(stderr, "%s: fail!\n", __func__);
|
||||
*success = false;
|
||||
//abort();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
self->last_page = page;
|
||||
//fprintf(stderr, "[%d]\tkh_n_buckets: %d %d\n", getpid(), kh_n_buckets(self->lookup), k);
|
||||
|
||||
if(kh_value(self->lookup, k) == UNMAPPED_PAGE){
|
||||
self->last_addr = UNMAPPED_PAGE;
|
||||
@ -329,25 +196,16 @@ uint64_t page_cache_fetch(page_cache_t* self, uint64_t page, bool* success, bool
|
||||
self->last_addr = (uint64_t)self->page_data+kh_value(self->lookup, k);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//fprintf(stderr, "try to unlock flock!\n");
|
||||
//fprintf(stderr, "flock unlocked!\n");
|
||||
|
||||
*success = true;
|
||||
return self->last_addr;
|
||||
}
|
||||
|
||||
/* fix this */
|
||||
/* FIXME */
|
||||
uint64_t page_cache_fetch2(page_cache_t* self, uint64_t page, bool* success){
|
||||
return page_cache_fetch(self, page, success, false);
|
||||
}
|
||||
|
||||
#ifndef STANDALONE_DECODER
|
||||
page_cache_t* page_cache_new(CPUState *cpu, const char* cache_file){
|
||||
#else
|
||||
page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_width){
|
||||
#endif
|
||||
page_cache_t* self = malloc(sizeof(page_cache_t));
|
||||
|
||||
char* tmp1;
|
||||
@ -357,21 +215,13 @@ page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_w
|
||||
assert(asprintf(&tmp2, "%s.addr", cache_file) != -1);
|
||||
assert(asprintf(&tmp3, "%s.lock", cache_file) != -1);
|
||||
|
||||
|
||||
self->lookup = kh_init(PC_CACHE);
|
||||
self->fd_page_file = open(tmp1, O_CLOEXEC | O_RDWR, S_IRWXU);
|
||||
self->fd_address_file = open(tmp2, O_CLOEXEC | O_RDWR, S_IRWXU);
|
||||
|
||||
#ifndef STANDALONE_DECODER
|
||||
self->cpu = cpu;
|
||||
self->fd_lock = open(tmp3, O_CLOEXEC);
|
||||
assert(self->fd_lock > 0);
|
||||
#else
|
||||
if(self->fd_page_file == -1 || self->fd_address_file == -1){
|
||||
printf("[ ] Page cache files not found...\n");
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(self->disassemble_cache, 0x0, 16);
|
||||
|
||||
@ -381,11 +231,7 @@ page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_w
|
||||
self->last_page = 0xFFFFFFFFFFFFFFFF;
|
||||
self->last_addr = 0xFFFFFFFFFFFFFFFF;
|
||||
|
||||
#ifndef STANDALONE_DECODER
|
||||
nyx_debug_p(PAGE_CACHE_PREFIX, "%s (%s - %s)", __func__, tmp1, tmp2);
|
||||
#else
|
||||
nyx_debug_p(PAGE_CACHE_PREFIX, "%s (%s - %s) WORD_WIDTH: %d", __func__, tmp1, tmp2, disassembler_word_width);
|
||||
#endif
|
||||
|
||||
free(tmp3);
|
||||
free(tmp2);
|
||||
@ -407,35 +253,6 @@ page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_w
|
||||
return self;
|
||||
}
|
||||
|
||||
#ifdef STANDALONE_DECODER
|
||||
void page_cache_destroy(page_cache_t* self){
|
||||
munmap(self->page_data, self->num_pages * 0x1000);
|
||||
kh_destroy(PC_CACHE, self->lookup);
|
||||
|
||||
cs_close(&self->handle_16);
|
||||
cs_close(&self->handle_32);
|
||||
cs_close(&self->handle_64);
|
||||
free(self);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
static bool page_cache_load(uint64_t virtual_addr){
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
|
||||
static bool page_cache_load_cr3(uint64_t virtual_addr, uint64_t cr3){
|
||||
return true;
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
bool page_cache_disassemble(page_cache_t* self, uint64_t address, cs_insn **insn){
|
||||
return true;
|
||||
}
|
||||
@ -454,26 +271,16 @@ cs_insn* page_cache_cs_malloc(page_cache_t* self, disassembler_mode_t mode){
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//#define EXPERIMENTAL_PAGE_FETCH
|
||||
|
||||
bool page_cache_disassemble_iter(page_cache_t* self, uint64_t* address, cs_insn *insn, uint64_t* failed_page, disassembler_mode_t mode){
|
||||
|
||||
//printf("%s %lx\n", __func__, *address);
|
||||
|
||||
*failed_page = 0xFFFFFFFFFFFFFFFFULL;
|
||||
|
||||
bool success = true;
|
||||
size_t code_size = 16;
|
||||
|
||||
#if defined(STANDALONE_DECODER) || !defined(EXPERIMENTAL_PAGE_FETCH)
|
||||
uint8_t* code = (uint8_t*)page_cache_fetch(self, *address, &success, false);
|
||||
#else
|
||||
uint8_t* code = (uint8_t*)page_cache_fetch(self, *address, &success, true);
|
||||
#endif
|
||||
uint8_t* code_ptr = 0;
|
||||
|
||||
|
||||
//disassembler_mode_t mode = mode_16;
|
||||
csh* current_handle = NULL;
|
||||
|
||||
switch(mode){
|
||||
@ -491,54 +298,30 @@ bool page_cache_disassemble_iter(page_cache_t* self, uint64_t* address, cs_insn
|
||||
}
|
||||
|
||||
if (code == (void*)UNMAPPED_PAGE || success == false){
|
||||
*failed_page = *address;// & 0xFFFFFFFFFFFFF000ULL;
|
||||
//printf("FAIL???? (0x%lx) %lx %d\n", *address, code, success);
|
||||
*failed_page = *address;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((*address & 0xFFF) >= (0x1000-16)){
|
||||
//printf("-------------> Disassemble between pages...%lx (%lx %lx %lx)\n", *address, (*address&0xFFF), (0x1000-16), 0xf-(0xfff-(*address&0xfff)));
|
||||
memcpy((void*)self->disassemble_cache, (void*)((uint64_t)code+(0x1000-16)), 16);
|
||||
code_ptr = self->disassemble_cache + 0xf-(0xfff-(*address&0xfff));
|
||||
|
||||
#if defined(STANDALONE_DECODER) || !defined(EXPERIMENTAL_PAGE_FETCH)
|
||||
code = (uint8_t*)page_cache_fetch(self, *address+0x1000, &success, false);
|
||||
#else
|
||||
code = (uint8_t*)page_cache_fetch(self, *address+0x1000, &success, true);
|
||||
#endif
|
||||
|
||||
/* broken AF */
|
||||
if(success == true){
|
||||
//printf("=> A\n");
|
||||
//*failed_page = (*address+0x1000) & 0xFFFFFFFFFFFFF000ULL;
|
||||
//return false;
|
||||
//printf("=> %lx %lx\n", (0xfff-(*address&0xfff)), *address);
|
||||
memcpy((void*)(self->disassemble_cache+16), (void*)code, 16);
|
||||
//code_size = 16;
|
||||
return cs_disasm_iter(*current_handle, (const uint8_t**) &code_ptr, &code_size, address, insn);
|
||||
}
|
||||
else{
|
||||
//printf("=> B\n");
|
||||
code_size = (0xfff-(*address&0xfff));
|
||||
//printf("%lx\n", code_size);
|
||||
//abort();
|
||||
//*failed_page = *address;
|
||||
if(!cs_disasm_iter(*current_handle, (const uint8_t**) &code_ptr, &code_size, address, insn)){
|
||||
*failed_page = (*address+0x1000) & 0xFFFFFFFFFFFFF000ULL;
|
||||
//fprintf(stderr, "%s FAIL: %lx %lx\n", __func__, *address, *failed_page);
|
||||
//if(*address != 0x555555554ffe && *address != 0x7ffff7478ffc && *address != 0x7ffff7820ff6 && *address != 0x7ffff7822ffa)
|
||||
// abort();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
//return cs_disasm_iter(self->handle, (const uint8_t**) &code_ptr, &code_size, address, insn);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//printf("=> C\n");
|
||||
code_ptr = code + (*address&0xFFF);
|
||||
|
||||
//printf("Disassemble...(%lx %x)\n", code_ptr, *code_ptr);
|
||||
return cs_disasm_iter(*current_handle, (const uint8_t**) &code_ptr, &code_size, address, insn);
|
||||
}
|
||||
}
|
||||
|
@ -2,18 +2,16 @@
|
||||
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/x86.h>
|
||||
#ifndef STANDALONE_DECODER
|
||||
#include "qemu/osdep.h"
|
||||
#endif
|
||||
#include "khash.h"
|
||||
#include <libxdc.h>
|
||||
|
||||
#include "qemu-common.h"
|
||||
#include "khash.h"
|
||||
|
||||
KHASH_MAP_INIT_INT64(PC_CACHE, uint64_t)
|
||||
|
||||
typedef struct page_cache_s{
|
||||
#ifndef STANDALONE_DECODER
|
||||
CPUState *cpu;
|
||||
#endif
|
||||
khash_t(PC_CACHE) *lookup;
|
||||
int fd_page_file;
|
||||
int fd_address_file;
|
||||
@ -30,14 +28,7 @@ typedef struct page_cache_s{
|
||||
uint64_t last_addr;
|
||||
} page_cache_t;
|
||||
|
||||
#ifndef STANDALONE_DECODER
|
||||
page_cache_t* page_cache_new(CPUState *cpu, const char* cache_file);
|
||||
#else
|
||||
page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_width);
|
||||
void page_cache_destroy(page_cache_t* self);
|
||||
bool append_page(page_cache_t* self, uint64_t page, uint8_t* ptr);
|
||||
#endif
|
||||
|
||||
uint64_t page_cache_fetch(page_cache_t* self, uint64_t page, bool* success, bool test_mode);
|
||||
|
||||
bool page_cache_disassemble(page_cache_t* self, uint64_t address, cs_insn **insn);
|
||||
@ -45,5 +36,4 @@ bool page_cache_disassemble_iter(page_cache_t* self, uint64_t* address, cs_insn
|
||||
|
||||
cs_insn* page_cache_cs_malloc(page_cache_t* self, disassembler_mode_t mode);
|
||||
|
||||
|
||||
uint64_t page_cache_fetch2(page_cache_t* self, uint64_t page, bool* success);
|
@ -7,10 +7,9 @@
|
||||
uint8_t cmp_patch_data[] = { 0x38, 0xC0, [2 ... MAX_INSTRUCTION_SIZE]=0x90 }; // CMP AL,AL; NOP, NOP ...
|
||||
const uint8_t *cmp_patch = &cmp_patch_data[0];
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Helper Functions Declarations
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
/*
|
||||
* Private Helper Functions Declarations
|
||||
*/
|
||||
static void _patcher_apply_patch(patcher_t *self, size_t index);
|
||||
|
||||
static void _patcher_restore_patch(patcher_t *self, size_t index);
|
||||
@ -26,9 +25,9 @@ static void _patcher_free_patch_infos(patcher_t *self);
|
||||
static redqueen_t* _redq_ptr(patcher_t *self);
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Functions
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Public Functions
|
||||
*/
|
||||
|
||||
patcher_t* patcher_new(CPUState *cpu){
|
||||
patcher_t *res = malloc(sizeof(patcher_t));
|
||||
@ -118,10 +117,9 @@ bool patcher_validate_patches(patcher_t *self){
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Helper Functions Definitions
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/*
|
||||
* Private Helper Functions Definitions
|
||||
*/
|
||||
|
||||
static void _patcher_apply_patch(patcher_t *self, size_t index) {
|
||||
abort(); // deprecated function -> remove this code later
|
||||
|
@ -10,8 +10,11 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#define MAX_INSTRUCTION_SIZE 64
|
||||
//Patch used to replace cmp instructions. It encodes CMP AL, AL a comparision which always evaluates to true. This can
|
||||
//be used to remove hash checks that we suspsect can later on be patched.
|
||||
/*
|
||||
* Patch used to replace cmp instructions. It encodes CMP AL, AL a comparison
|
||||
* which always evaluates to true. This can be used to remove hash checks that
|
||||
* we suspsect can later on be patched.
|
||||
*/
|
||||
extern const uint8_t* cmp_patch;
|
||||
|
||||
typedef struct patch_info_s{
|
||||
|
112
nyx/pt.c
112
nyx/pt.c
@ -20,32 +20,36 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <libxdc.h>
|
||||
#include <linux/kvm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "exec/memory.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "qemu-common.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "nyx/pt.h"
|
||||
#include "exec/memory.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "nyx/hypercall/hypercall.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "nyx/interface.h"
|
||||
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/file_helper.h"
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/hypercall/hypercall.h"
|
||||
#include "nyx/interface.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "nyx/page_cache.h"
|
||||
#include "nyx/pt.h"
|
||||
#include "nyx/redqueen_trace.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/trace_dump.h"
|
||||
|
||||
#ifdef CONFIG_REDQUEEN
|
||||
#include "nyx/patcher.h"
|
||||
#include "nyx/redqueen.h"
|
||||
#include "nyx/redqueen_patch.h"
|
||||
#include "nyx/patcher.h"
|
||||
#endif
|
||||
#include "nyx/page_cache.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include <libxdc.h>
|
||||
#include "nyx/helpers.h"
|
||||
#include "nyx/trace_dump.h"
|
||||
#include "nyx/redqueen_trace.h"
|
||||
|
||||
#define PT_BUFFER_MMAP_ADDR 0x3ffff0000000
|
||||
|
||||
@ -83,39 +87,10 @@ static inline int pt_ioctl(int fd, unsigned long request, unsigned long arg){
|
||||
return ioctl(fd, request, arg);
|
||||
}
|
||||
|
||||
#ifdef DUMP_AND_DEBUG_PT
|
||||
void dump_pt_trace(void* buffer, int bytes){
|
||||
static FILE* f = NULL;
|
||||
static int fcounter = 0;
|
||||
static size_t size = 0;
|
||||
char filename[256];
|
||||
|
||||
|
||||
|
||||
if(!f){
|
||||
snprintf(filename, 256, "/tmp/trace_data/data_%d", fcounter);
|
||||
f = fopen(filename, "wb");
|
||||
}
|
||||
|
||||
size += fwrite(buffer, bytes , 1, f) * bytes;
|
||||
|
||||
if(size >= 0x80000000){ // 2GB
|
||||
fclose(f);
|
||||
fcounter++;
|
||||
size = 0;
|
||||
snprintf(filename, 256, "/tmp/trace_data/data_%d", fcounter);
|
||||
f = fopen(filename, "wb");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void pt_dump(CPUState *cpu, int bytes){
|
||||
//pt_write_pt_dump_file(cpu->pt_mmap, bytes);
|
||||
|
||||
if(!(GET_GLOBAL_STATE()->redqueen_state && GET_GLOBAL_STATE()->redqueen_state->intercept_mode)){
|
||||
if (GET_GLOBAL_STATE()->in_fuzzing_mode && GET_GLOBAL_STATE()->decoder_page_fault == false && GET_GLOBAL_STATE()->decoder && !GET_GLOBAL_STATE()->dump_page){
|
||||
GET_GLOBAL_STATE()->pt_trace_size += bytes;
|
||||
//dump_pt_trace(cpu->pt_mmap, bytes);
|
||||
pt_write_pt_dump_file(cpu->pt_mmap, bytes);
|
||||
decoder_result_t result = libxdc_decode(GET_GLOBAL_STATE()->decoder, cpu->pt_mmap, bytes);
|
||||
switch(result){
|
||||
@ -154,17 +129,16 @@ int pt_enable(CPUState *cpu, bool hmp_mode){
|
||||
}
|
||||
|
||||
int pt_disable(CPUState *cpu, bool hmp_mode){
|
||||
//printf("%s\n", __func__);
|
||||
int r = pt_cmd(cpu, KVM_VMX_PT_DISABLE, hmp_mode);
|
||||
return r;
|
||||
}
|
||||
|
||||
int pt_set_cr3(CPUState *cpu, uint64_t val, bool hmp_mode){
|
||||
int r = 0;
|
||||
|
||||
if (val == GET_GLOBAL_STATE()->pt_c3_filter){
|
||||
return 0; // nothing changed
|
||||
}
|
||||
//fprintf(stderr, "=========== %s %lx ============\n", __func__, val);
|
||||
int r = 0;
|
||||
|
||||
if (cpu->pt_enabled){
|
||||
return -EINVAL;
|
||||
@ -215,7 +189,7 @@ int pt_enable_ip_filtering(CPUState *cpu, uint8_t addrn, bool redqueen, bool hmp
|
||||
void pt_init_decoder(CPUState *cpu){
|
||||
uint64_t filters[4][2] = {0};
|
||||
|
||||
/* it's time to clean up this code -.- */
|
||||
/* TODO time to clean up this code -.- */
|
||||
filters[0][0] = GET_GLOBAL_STATE()->pt_ip_filter_a[0];
|
||||
filters[0][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[0];
|
||||
filters[1][0] = GET_GLOBAL_STATE()->pt_ip_filter_a[1];
|
||||
@ -261,10 +235,6 @@ void pt_kvm_init(CPUState *cpu){
|
||||
cpu->pt_fd = 0;
|
||||
|
||||
cpu->pt_decoder_state = NULL;
|
||||
//cpu->redqueen_state=NULL;
|
||||
//cpu->redqueen_patch_state = patcher_new(cpu);
|
||||
|
||||
//init_redqueen_patch_state();
|
||||
|
||||
cpu->reload_pending = false;
|
||||
cpu->intel_pt_run_trashed = false;
|
||||
@ -295,27 +265,22 @@ void pt_pre_kvm_run(CPUState *cpu){
|
||||
}
|
||||
|
||||
|
||||
//if(cpu->redqueen_enable_pending){
|
||||
if(GET_GLOBAL_STATE()->redqueen_enable_pending){
|
||||
//nyx_debug_p(REDQUEEN_PREFIX, "rq enable");
|
||||
if (GET_GLOBAL_STATE()->redqueen_state){
|
||||
enable_rq_intercept_mode(GET_GLOBAL_STATE()->redqueen_state);
|
||||
}
|
||||
//cpu->redqueen_enable_pending = false;
|
||||
GET_GLOBAL_STATE()->redqueen_enable_pending = false;
|
||||
//qemu_cpu_kick_self();
|
||||
}
|
||||
|
||||
//if(cpu->redqueen_disable_pending){
|
||||
if(GET_GLOBAL_STATE()->redqueen_disable_pending){
|
||||
//nyx_debug_p(REDQUEEN_PREFIX, "rq disable");
|
||||
if (GET_GLOBAL_STATE()->redqueen_state){
|
||||
disable_rq_intercept_mode(GET_GLOBAL_STATE()->redqueen_state);
|
||||
}
|
||||
//cpu->redqueen_disable_pending = false;
|
||||
GET_GLOBAL_STATE()->redqueen_disable_pending = false;
|
||||
//qemu_cpu_kick_self();
|
||||
}
|
||||
|
||||
if(GET_GLOBAL_STATE()->pt_trace_mode || GET_GLOBAL_STATE()->pt_trace_mode_force){
|
||||
if (!cpu->pt_fd) {
|
||||
cpu->pt_fd = kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SETUP_FD, (unsigned long)0);
|
||||
@ -324,9 +289,12 @@ void pt_pre_kvm_run(CPUState *cpu){
|
||||
|
||||
cpu->pt_mmap = mmap((void*)PT_BUFFER_MMAP_ADDR, ret, PROT_READ|PROT_WRITE, MAP_SHARED, cpu->pt_fd, 0);
|
||||
assert(cpu->pt_mmap != (void*)0xFFFFFFFFFFFFFFFF);
|
||||
assert(mmap(cpu->pt_mmap+ret, 0x1000, PROT_READ|PROT_WRITE, MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1, 0) == (void*)(cpu->pt_mmap+ret)); //;!= (void*)0xFFFFFFFFFFFFFFFF); // add an extra page to have enough space for an additional PT_TRACE_END byte
|
||||
|
||||
nyx_debug("\t\t============> pt_mmap:%p - %p\n", cpu->pt_mmap, cpu->pt_mmap+ret);
|
||||
// add an extra page to have enough space for an additional PT_TRACE_END byte
|
||||
assert(mmap(cpu->pt_mmap + ret, 0x1000, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_FIXED | MAP_PRIVATE, -1,
|
||||
0) == (void *)(cpu->pt_mmap + ret));
|
||||
|
||||
nyx_debug("=> pt_mmap: %p - %p\n", cpu->pt_mmap, cpu->pt_mmap + ret);
|
||||
|
||||
memset(cpu->pt_mmap+ret, 0x55, 0x1000);
|
||||
}
|
||||
@ -334,8 +302,6 @@ void pt_pre_kvm_run(CPUState *cpu){
|
||||
if (cpu->pt_cmd){
|
||||
switch(cpu->pt_cmd){
|
||||
case KVM_VMX_PT_ENABLE:
|
||||
//fprintf(stderr, "=========== KVM_VMX_PT_ENABLE ============\n");
|
||||
|
||||
if (cpu->pt_fd){
|
||||
/* dump for the very last time before enabling VMX_PT ... just in case */
|
||||
ioctl(cpu->pt_fd, KVM_VMX_PT_CHECK_TOPA_OVERFLOW, (unsigned long)0);
|
||||
@ -346,8 +312,6 @@ void pt_pre_kvm_run(CPUState *cpu){
|
||||
}
|
||||
break;
|
||||
case KVM_VMX_PT_DISABLE:
|
||||
//fprintf(stderr, "=========== KVM_VMX_PT_DISABLE ============\n");
|
||||
|
||||
if (cpu->pt_fd){
|
||||
ret = ioctl(cpu->pt_fd, cpu->pt_cmd, 0);
|
||||
if (ret > 0){
|
||||
@ -374,13 +338,9 @@ void pt_pre_kvm_run(CPUState *cpu){
|
||||
ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)0);
|
||||
break;
|
||||
case KVM_VMX_PT_CONFIGURE_CR3:
|
||||
//fprintf(stderr, "=========== KVM_VMX_PT_CONFIGURE_CR3 ============\n");
|
||||
|
||||
ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, GET_GLOBAL_STATE()->pt_c3_filter);
|
||||
break;
|
||||
case KVM_VMX_PT_ENABLE_CR3:
|
||||
//fprintf(stderr, "=========== KVM_VMX_PT_ENABLE_CR3 ============\n");
|
||||
|
||||
ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)0);
|
||||
break;
|
||||
default:
|
||||
@ -391,7 +351,6 @@ void pt_pre_kvm_run(CPUState *cpu){
|
||||
}
|
||||
cpu->pt_cmd = 0;
|
||||
cpu->pt_ret = 0;
|
||||
//kvm_cpu_synchronize_state(cpu);
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&pt_dump_mutex);
|
||||
@ -401,26 +360,13 @@ void pt_handle_overflow(CPUState *cpu){
|
||||
pthread_mutex_lock(&pt_dump_mutex);
|
||||
int overflow = ioctl(cpu->pt_fd, KVM_VMX_PT_CHECK_TOPA_OVERFLOW, (unsigned long)0);
|
||||
if (overflow > 0){
|
||||
//cpu->overflow_counter++;
|
||||
pt_dump(cpu, overflow);
|
||||
}
|
||||
|
||||
/*else{
|
||||
printf("CPU NOT ENABLED?!\n");
|
||||
assert(false);
|
||||
}
|
||||
*/
|
||||
pthread_mutex_unlock(&pt_dump_mutex);
|
||||
}
|
||||
|
||||
void pt_post_kvm_run(CPUState *cpu){
|
||||
if(GET_GLOBAL_STATE()->pt_trace_mode || GET_GLOBAL_STATE()->pt_trace_mode_force){
|
||||
|
||||
//printf("%s\n", __func__);
|
||||
//int overflow;
|
||||
//if (cpu->pt_enabled){
|
||||
pt_handle_overflow(cpu);
|
||||
//unlock_reload_pending(cpu);
|
||||
//}
|
||||
}
|
||||
}
|
||||
|
185
nyx/redqueen.c
185
nyx/redqueen.c
@ -19,18 +19,21 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "nyx/redqueen.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "nyx/interface.h"
|
||||
#include <inttypes.h>
|
||||
#include "file_helper.h"
|
||||
#include "patcher.h"
|
||||
#include "debug.h"
|
||||
#include "redqueen_trace.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/x86.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "nyx/redqueen.h"
|
||||
#include "debug.h"
|
||||
#include "file_helper.h"
|
||||
#include "nyx/interface.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "patcher.h"
|
||||
#include "redqueen_trace.h"
|
||||
|
||||
redqueen_workdir_t redqueen_workdir = {0};
|
||||
|
||||
@ -61,11 +64,6 @@ redqueen_t* new_rq_state(CPUState *cpu, page_cache_t* page_cache){
|
||||
|
||||
res->trace_state=redqueen_trace_new();
|
||||
|
||||
//FILE* pt_file = fopen("/tmp/redqueen_vm.img", "wb");
|
||||
//delete_redqueen_files();
|
||||
//fwrite(&start_range, sizeof(uint64_t), 1, pt_file);
|
||||
//fwrite(code, sizeof(uint8_t), end_range-start_range, pt_file);
|
||||
//fclose(pt_file);
|
||||
return res;
|
||||
}
|
||||
|
||||
@ -232,7 +230,7 @@ void destroy_rq_state(redqueen_t* self){
|
||||
|
||||
static void redqueen_set_addr_flags(redqueen_t* self, uint64_t addr, uint32_t flags){
|
||||
int unused = 0;
|
||||
//fprintf(stderr, "%s\n", __func__);
|
||||
|
||||
khiter_t k = kh_get(RQ, self->lookup, addr);
|
||||
if(k == kh_end(self->lookup)){
|
||||
k = kh_put(RQ, self->lookup, addr, &unused);
|
||||
@ -276,17 +274,8 @@ static uint32_t redqueen_update_addr_count(redqueen_t* self, uint64_t addr){
|
||||
return value & 0xFF000000UL;
|
||||
}
|
||||
|
||||
/*
|
||||
static void set_rq_trace_enabled_bp(redqueen_t* self, uint64_t addr){
|
||||
redqueen_set_addr_flags(self, addr, CMP_BITMAP_TRACE_ENABLED);
|
||||
}
|
||||
*/
|
||||
|
||||
void set_rq_instruction(redqueen_t* self, uint64_t addr){
|
||||
//fprintf(stderr, "%s\n", __func__);
|
||||
if( !redqueen_check_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED)){
|
||||
//fprintf(stderr, "%s +2\n", __func__);
|
||||
|
||||
redqueen_set_addr_flags(self, addr, CMP_BITMAP_RQ_INSTRUCTION);
|
||||
}
|
||||
}
|
||||
@ -296,7 +285,6 @@ void set_rq_blacklist(redqueen_t* self, uint64_t addr){
|
||||
}
|
||||
|
||||
static void insert_hooks_whitelist(redqueen_t* self){
|
||||
fprintf(stderr, "%s\n", __func__);
|
||||
for(size_t i = 0; i < self->num_breakpoint_whitelist; i++){
|
||||
insert_breakpoint(self->cpu, self->breakpoint_whitelist[i], 1);
|
||||
}
|
||||
@ -304,17 +292,13 @@ static void insert_hooks_whitelist(redqueen_t* self){
|
||||
|
||||
static void insert_hooks_bitmap(redqueen_t* self){
|
||||
uint64_t c = 0;
|
||||
//fprintf(stderr, "%s\n", __func__);
|
||||
|
||||
uint64_t addr;
|
||||
uint32_t value __attribute__((unused));
|
||||
uint32_t mode = GET_GLOBAL_STATE()->redqueen_instrumentation_mode;
|
||||
//uint32_t mode = self->cpu->redqueen_instrumentation_mode;
|
||||
|
||||
kh_foreach(self->lookup, addr, value, {
|
||||
//fprintf(stderr, "%s %lx %x\n", __func__, addr, value);
|
||||
if(redqueen_check_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED)){ continue; }
|
||||
|
||||
//bool should_hook_se = (mode == REDQUEEN_SE_INSTRUMENTATION) && redqueen_check_addr_flags(self, addr, CMP_BITMAP_SHOULD_HOOK_SE);
|
||||
bool should_hook_rq = (mode == REDQUEEN_LIGHT_INSTRUMENTATION ) && redqueen_check_addr_flags(self, addr, CMP_BITMAP_SHOULD_HOOK_RQ);
|
||||
|
||||
if( should_hook_rq ){
|
||||
@ -325,11 +309,9 @@ static void insert_hooks_bitmap(redqueen_t* self){
|
||||
}
|
||||
|
||||
void redqueen_insert_hooks(redqueen_t* self){
|
||||
// fprintf(stderr, "%s %x\n", __func__, self->cpu->redqueen_instrumentation_mode);
|
||||
|
||||
nyx_debug_p(REDQUEEN_PREFIX, "insert hooks");
|
||||
assert(!self->hooks_applied);
|
||||
//switch(self->cpu->redqueen_instrumentation_mode){
|
||||
switch(GET_GLOBAL_STATE()->redqueen_instrumentation_mode){
|
||||
case(REDQUEEN_LIGHT_INSTRUMENTATION):
|
||||
insert_hooks_bitmap(self);
|
||||
@ -347,7 +329,6 @@ void redqueen_insert_hooks(redqueen_t* self){
|
||||
|
||||
void redqueen_remove_hooks(redqueen_t* self){
|
||||
nyx_debug_p(REDQUEEN_PREFIX, "remove hooks");
|
||||
// fprintf(stderr, "remove hooks\n");
|
||||
assert(self->hooks_applied);
|
||||
remove_all_breakpoints(self->cpu);
|
||||
|
||||
@ -361,6 +342,7 @@ void redqueen_remove_hooks(redqueen_t* self){
|
||||
static uint64_t get_segment_register(x86_reg reg) {
|
||||
X86CPU *cpu = X86_CPU(qemu_get_cpu(0));
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
switch(reg){
|
||||
case X86_REG_GS: return env->segs[R_GS].base;
|
||||
case X86_REG_FS: return env->segs[R_FS].base;
|
||||
@ -524,6 +506,7 @@ static void print_comp_result(uint64_t addr, const char* type, uint64_t val1, ui
|
||||
|
||||
char result_buf[256];
|
||||
const char *format = NULL;
|
||||
|
||||
uint8_t pos = 0;
|
||||
pos += snprintf(result_buf+pos, 256-pos, "%lx\t\t %s", addr, type);
|
||||
//nyx_debug_p(REDQUEEN_PREFIX, "got size: %ld", size);
|
||||
@ -650,7 +633,7 @@ static uint64_t read_stack(uint64_t word_index){
|
||||
rsp = limit_to_word_width(rsp);
|
||||
uint64_t res = 0;
|
||||
uint64_t stack_ptr = rsp + word_index * word_width_to_bytes();
|
||||
/* todo @ sergej */
|
||||
/* TODO @ sergej */
|
||||
assert(read_virtual_memory(stack_ptr, (uint8_t*)(&res), 8, qemu_get_cpu(0)));
|
||||
return limit_to_word_width(res);
|
||||
}
|
||||
@ -676,14 +659,14 @@ static void format_strcmp(uint8_t* buf1, uint8_t* buf2){
|
||||
static bool test_strchr(uint64_t arg1, uint64_t arg2){
|
||||
CPUState *cpu = qemu_get_cpu(0);
|
||||
|
||||
/* todo @ sergej */
|
||||
/* TODO @ sergej */
|
||||
if(!is_addr_mapped(arg1, cpu) || arg2 & (~0xff)){
|
||||
return false;
|
||||
}
|
||||
uint8_t buf1[REDQUEEN_MAX_STRCMP_LEN];
|
||||
uint8_t buf2[REDQUEEN_MAX_STRCMP_LEN];
|
||||
|
||||
/* todo @ sergej */
|
||||
/* TODO @ sergej */
|
||||
assert(read_virtual_memory(arg1, &buf1[0], REDQUEEN_MAX_STRCMP_LEN, cpu));
|
||||
if(!memchr(buf1,'\0',REDQUEEN_MAX_STRCMP_LEN) ){return false;}
|
||||
memset(buf2,'\0',REDQUEEN_MAX_STRCMP_LEN);
|
||||
@ -700,7 +683,7 @@ static bool test_strcmp(uint64_t arg1, uint64_t arg2){
|
||||
//nyx_debug_p(REDQUEEN_PREFIX,"valid ptrs");
|
||||
uint8_t buf1[REDQUEEN_MAX_STRCMP_LEN];
|
||||
uint8_t buf2[REDQUEEN_MAX_STRCMP_LEN];
|
||||
/* todo @ sergej */
|
||||
/* TODO @ sergej */
|
||||
assert(read_virtual_memory(arg1, &buf1[0], REDQUEEN_MAX_STRCMP_LEN, cpu));
|
||||
assert(read_virtual_memory(arg2, &buf2[0], REDQUEEN_MAX_STRCMP_LEN, cpu));
|
||||
format_strcmp(buf1,buf2);
|
||||
@ -742,19 +725,6 @@ static void extract_call_params(void){
|
||||
test_strcmp_sys_v();
|
||||
}
|
||||
|
||||
/*
|
||||
static bool is_memory_access(redqueen_t* self, cs_insn* insn){
|
||||
return insn->id != X86_INS_LEA && strstr(insn->op_str,"[");
|
||||
}
|
||||
|
||||
static bool is_trace_entry_point(redqueen_t* self, uint64_t addr){
|
||||
//if(addr >= self->address_range_start && addr <= self->address_range_end){
|
||||
return redqueen_check_addr_flags(self, addr, CMP_BITMAP_TRACE_ENABLED);
|
||||
//}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
static void handle_hook_redqueen_light(redqueen_t* self, uint64_t ip, cs_insn *insn){
|
||||
if(insn->id == X86_INS_CMP || insn->id == X86_INS_XOR){ //handle original redqueen case
|
||||
get_cmp_value(insn, "CMP");
|
||||
@ -770,9 +740,6 @@ static void handle_hook_redqueen_light(redqueen_t* self, uint64_t ip, cs_insn *i
|
||||
}
|
||||
|
||||
static uint8_t handle_hook_breakpoint(redqueen_t* self, bool write_data){
|
||||
//fprintf(stderr, "%s\n", __func__);
|
||||
//printf("%s\n", __func__);
|
||||
|
||||
X86CPU *cpu = X86_CPU(self->cpu);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
@ -821,112 +788,12 @@ static uint8_t handle_hook_breakpoint(redqueen_t* self, bool write_data){
|
||||
return ins_size;
|
||||
}
|
||||
|
||||
/*
|
||||
static void debug_print_disasm(char* desc, uint64_t ip, CPUState* cpu_state){
|
||||
//uint64_t cs_address = ip;
|
||||
uint8_t code[64];
|
||||
csh handle;
|
||||
cs_insn *insn;
|
||||
read_virtual_memory(ip, &code[0], 64, cpu_state);
|
||||
if (cs_open(CS_ARCH_X86, get_capstone_mode(cpu_state->disassembler_word_width), &handle) == CS_ERR_OK){
|
||||
cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
|
||||
size_t count = cs_disasm(handle, &code[0], 64, ip, 1, &insn);
|
||||
if(count > 0){
|
||||
nyx_debug_p(REDQUEEN_PREFIX,"%s\t %lx: %s %s",desc, ip, insn->mnemonic, insn->op_str);
|
||||
} else {
|
||||
nyx_debug_p(REDQUEEN_PREFIX,"%s\t Failed to disassemble at: %lx",desc, ip);
|
||||
}
|
||||
cs_close(&handle);
|
||||
cs_free(insn, count);
|
||||
} else {
|
||||
nyx_debug_p(REDQUEEN_PREFIX,"%s\t Failed to create capstone instance at: %lx",desc, ip);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
static void debug_print_state(char* desc, CPUState* cpu_state){
|
||||
X86CPU *cpu = X86_CPU(cpu_state);
|
||||
CPUX86State *env = &cpu->env;
|
||||
debug_print_disasm(desc, env->eip, cpu_state);
|
||||
nyx_debug_p(REDQUEEN_PREFIX,"ECX: %lx", get_reg_cpu(cpu_state, (char*)"rcx"));
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
int trace_debug = false;
|
||||
|
||||
void handle_hook(redqueen_t* self){
|
||||
X86CPU *cpu = X86_CPU(self->cpu);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
uint8_t ins;
|
||||
|
||||
read_virtual_memory(env->eip, (uint8_t*)&ins, 1, self->cpu);
|
||||
|
||||
if(ins == 0xcc && self->cpu->singlestep_enabled){
|
||||
fprintf(stderr, "fix... %lx\n", env->eip);
|
||||
self->cpu->singlestep_enabled = false;
|
||||
self->singlestep_enabled = false;
|
||||
//kvm_insert_breakpoint(self->cpu, self->last_rip, 1, 0);
|
||||
kvm_update_guest_debug(self->cpu, 0);
|
||||
self->last_rip = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if(!self->cpu->singlestep_enabled){
|
||||
fprintf(stderr, "HOOK %lx\n", env->eip);
|
||||
|
||||
if(self->last_rip != 0) abort();
|
||||
self->last_rip = env->eip;
|
||||
|
||||
read_virtual_memory(env->eip, (uint8_t*)&ins, 1, self->cpu);
|
||||
if(ins != 0xcc) abort();
|
||||
kvm_remove_breakpoint(self->cpu, env->eip, 1, 0);
|
||||
self->cpu->singlestep_enabled = true;
|
||||
self->singlestep_enabled = true;
|
||||
if(self->cpu->pt_enabled && self->cpu->pt_c3_filter == env->cr[3]){
|
||||
handle_hook_breakpoint(self);
|
||||
}
|
||||
kvm_update_guest_debug(self->cpu, 0);
|
||||
|
||||
} else{
|
||||
fprintf(stderr, "HOOK %lx SINGLETEP\n", env->eip);
|
||||
|
||||
|
||||
if(self->last_rip == 0) abort();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
self->cpu->singlestep_enabled = false;
|
||||
self->singlestep_enabled = false;
|
||||
if(self->counter_bitmap[self->last_rip-self->address_range_start]++ < REDQUEEN_TRAP_LIMIT){
|
||||
fprintf(stderr, "TRAP INSTALLED\n");
|
||||
read_virtual_memory(env->eip, (uint8_t*)&ins, 1, self->cpu);
|
||||
if(ins == 0xcc) abort();
|
||||
|
||||
if(ins != 0xcc)
|
||||
kvm_insert_breakpoint(self->cpu, self->last_rip, 1, 0);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "TRAP INSTALLED nOPE %lx %lx\n", self->counter_bitmap[self->last_rip-self->address_range_start], self->counter_bitmap);
|
||||
}
|
||||
kvm_update_guest_debug(self->cpu, 0);
|
||||
self->last_rip = 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void handle_hook(redqueen_t* self){
|
||||
X86CPU *cpu = X86_CPU(self->cpu);
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
if (self->next_rip){
|
||||
|
||||
//fprintf(stderr, "REMOVE %lx at %lx\n", self->next_rip, env->eip);
|
||||
remove_breakpoint(self->cpu, self->next_rip, 1);
|
||||
|
||||
if(self->last_rip && redqueen_update_addr_count(self, self->last_rip) < REDQUEEN_TRAP_LIMIT){
|
||||
@ -941,11 +808,9 @@ void handle_hook(redqueen_t* self){
|
||||
|
||||
if(redqueen_check_addr(self, env->eip)){
|
||||
|
||||
//fprintf(stderr, "INSERT %lx\n", env->eip);
|
||||
self->last_rip = env->eip;
|
||||
remove_breakpoint(self->cpu, env->eip, 1);
|
||||
|
||||
//if(self->cpu->pt_enabled && self->cpu->pt_c3_filter == env->cr[3]){
|
||||
if(self->cpu->pt_enabled && GET_GLOBAL_STATE()->pt_c3_filter == env->cr[3]){
|
||||
self->next_rip = handle_hook_breakpoint(self, true);
|
||||
}
|
||||
@ -953,25 +818,18 @@ void handle_hook(redqueen_t* self){
|
||||
self->next_rip = handle_hook_breakpoint(self, true);
|
||||
}
|
||||
}
|
||||
else {
|
||||
//fprintf(stderr, "NOPE %lx\n", env->eip);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
static void _redqueen_update_whitelist(redqueen_t* self){
|
||||
//if(self->cpu->redqueen_instrumentation_mode == REDQUEEN_WHITELIST_INSTRUMENTATION){
|
||||
if(GET_GLOBAL_STATE()->redqueen_instrumentation_mode == REDQUEEN_WHITELIST_INSTRUMENTATION){
|
||||
//size_t num_addrs = 0;
|
||||
//uint64_t *addrs;
|
||||
if(GET_GLOBAL_STATE()->redqueen_instrumentation_mode == REDQUEEN_WHITELIST_INSTRUMENTATION){
|
||||
free(self->breakpoint_whitelist);
|
||||
parse_address_file(redqueen_workdir.breakpoint_white, &self->num_breakpoint_whitelist, &self->breakpoint_whitelist);
|
||||
}
|
||||
}
|
||||
|
||||
static void _redqueen_update_blacklist(redqueen_t* self){
|
||||
//if(self->cpu->redqueen_update_blacklist){
|
||||
if(GET_GLOBAL_STATE()->redqueen_update_blacklist){
|
||||
size_t num_addrs = 0;
|
||||
uint64_t *addrs;
|
||||
@ -986,7 +844,6 @@ static void _redqueen_update_blacklist(redqueen_t* self){
|
||||
void enable_rq_intercept_mode(redqueen_t* self){
|
||||
if(!self->intercept_mode){
|
||||
delete_redqueen_files();
|
||||
//unlink("/tmp/redqueen_result.txt");
|
||||
_redqueen_update_whitelist(self);
|
||||
_redqueen_update_blacklist(self);
|
||||
redqueen_insert_hooks(self);
|
||||
|
@ -19,21 +19,20 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef REDQUEEN_H
|
||||
#define REDQUEEN_H
|
||||
#pragma once
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include <linux/kvm.h>
|
||||
#include <capstone/capstone.h>
|
||||
#include <capstone/x86.h>
|
||||
#include "redqueen_trace.h"
|
||||
#include "khash.h"
|
||||
#include "page_cache.h"
|
||||
#include "nyx/redqueen_trace.h"
|
||||
#include "nyx/khash.h"
|
||||
#include "nyx/page_cache.h"
|
||||
|
||||
//#define RQ_DEBUG
|
||||
|
||||
@ -120,4 +119,3 @@ void redqueen_remove_hooks(redqueen_t* self);
|
||||
|
||||
void redqueen_callback(void* opaque, disassembler_mode_t mode, uint64_t start_addr, uint64_t end_addr);
|
||||
|
||||
#endif
|
||||
|
@ -1,18 +1,19 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "redqueen_patch.h"
|
||||
#include "redqueen.h"
|
||||
#include "patcher.h"
|
||||
#include "file_helper.h"
|
||||
#include "debug.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Helper Functions Declarations
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Private Helper Functions Declarations
|
||||
*/
|
||||
|
||||
void _load_and_set_patches(patcher_t* self);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Public Functions
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Public Functions
|
||||
*/
|
||||
|
||||
void pt_enable_patches(patcher_t *self){
|
||||
_load_and_set_patches(self);
|
||||
@ -24,9 +25,9 @@ void pt_disable_patches(patcher_t *self){
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
// Private Helper Functions Definitions
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
/*
|
||||
* Private Helper Functions Definitions
|
||||
*/
|
||||
|
||||
|
||||
void _load_and_set_patches(patcher_t* self){
|
||||
|
@ -1,11 +1,8 @@
|
||||
#ifndef __GUARD_REDQUEEN_PATCH__
|
||||
#define __GUARD_REDQUEEN_PATCH__
|
||||
#pragma once
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <linux/kvm.h>
|
||||
#include "sysemu/kvm.h"
|
||||
#include "nyx/patcher.h"
|
||||
|
||||
void pt_enable_patches(patcher_t *self);
|
||||
|
||||
void pt_disable_patches(patcher_t *self);
|
||||
#endif
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
|
@ -1,3 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdint.h>
|
||||
@ -5,8 +7,7 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#pragma once
|
||||
#include "khash.h"
|
||||
#include "nyx/khash.h"
|
||||
#include <libxdc.h>
|
||||
|
||||
typedef unsigned __int128 uint128_t;
|
||||
@ -19,11 +20,13 @@ typedef uint128_t khint128_t;
|
||||
@param key The integer [khint64_t]
|
||||
@return The hash value [khint_t]
|
||||
*/
|
||||
#define kh_int128_hash_func(key) (khint32_t)((key)>>33^(key)^(key)<<11) ^ (((key>>64))>>33^((key>>64))^((key>>64))<<11)
|
||||
#define kh_int128_hash_func(key) \
|
||||
(khint32_t)((key) >> 33 ^ (key) ^ (key) << 11) ^ (((key >> 64)) >> 33 ^ ((key >> 64)) ^ ((key >> 64)) << 11)
|
||||
/*! @function
|
||||
@abstract 64-bit integer comparison function
|
||||
*/
|
||||
#define kh_int128_hash_equal(a, b) ((a) == (b))
|
||||
|
||||
/*! @function
|
||||
@abstract Instantiate a hash map containing 64-bit integer keys
|
||||
@param name Name of the hash table [symbol]
|
||||
|
@ -1,12 +1,15 @@
|
||||
#include "sharedir.h"
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <dirent.h>
|
||||
#include <stdbool.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "nyx/debug.h"
|
||||
#include "sharedir.h"
|
||||
|
||||
//#define SHAREDIR_DEBUG
|
||||
|
||||
@ -98,7 +101,6 @@ static sharedir_file_t* sharedir_get_object(sharedir_t* self, const char* file){
|
||||
obj->mod_time = get_file_mod_time(obj->path);
|
||||
|
||||
/* put into hash_list */
|
||||
|
||||
char* new_file = NULL;
|
||||
assert(asprintf(&new_file, "%s", file) != -1);
|
||||
k = kh_put(SHAREDIR_LOOKUP, self->lookup, new_file, &ret);
|
||||
|
@ -1,8 +1,8 @@
|
||||
#pragma once
|
||||
#include <stdio.h>
|
||||
#include "khash.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "khash.h"
|
||||
|
||||
typedef struct sharedir_file_s{
|
||||
char* file;
|
||||
|
@ -1,6 +1,9 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "nyx/snapshot/block/block_cow.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "nyx/state/state.h"
|
||||
@ -8,7 +11,6 @@
|
||||
|
||||
|
||||
//#define COW_CACHE_DEBUG
|
||||
|
||||
//#define COW_CACHE_VERBOSE
|
||||
|
||||
#define CHUNK_SIZE 0x1000
|
||||
@ -31,8 +33,6 @@ static inline uint64_t get_global_cow_cache_primary_size(void){
|
||||
|
||||
cow_cache_t* cow_cache_new(const char* filename){
|
||||
|
||||
//printf("%s: \"%s\"\n", __func__, filename);
|
||||
|
||||
cow_cache_t* self = malloc(sizeof(cow_cache_t));
|
||||
self->lookup_primary = kh_init(COW_CACHE);
|
||||
self->lookup_secondary = kh_init(COW_CACHE);
|
||||
@ -41,7 +41,6 @@ cow_cache_t* cow_cache_new(const char* filename){
|
||||
self->cow_primary_size = COW_CACHE_PRIMARY_MINIMUM_SIZE;
|
||||
self->data_primary = mmap(NULL, self->cow_primary_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
assert(self->data_primary != MAP_FAILED);
|
||||
//memset(self->data_primary, COW_CACHE_PRIMARY_MINIMUM_SIZE/CHUNK_SIZE, CHUNK_SIZE);
|
||||
|
||||
self->data_secondary = mmap(NULL, COW_CACHE_SECONDARY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
|
||||
assert(self->data_secondary != MAP_FAILED);
|
||||
@ -88,7 +87,6 @@ static char* gen_file_name(cow_cache_t* self, const char* filename_prefix, const
|
||||
}
|
||||
|
||||
assert(asprintf(&tmp1, "%s_%s.%s", filename_prefix, tmp2, filename_postfix) != -1);
|
||||
|
||||
free(tmp2);
|
||||
|
||||
return tmp1;
|
||||
@ -98,18 +96,12 @@ void read_primary_buffer(cow_cache_t* self, const char* filename_prefix, bool sw
|
||||
assert(!self->enabled_fuzz);
|
||||
global_cow_primary_size_adjustable = false;
|
||||
|
||||
//printf("%s: %s\n", __func__, self->filename);
|
||||
|
||||
char* tmp1;
|
||||
char* tmp2;
|
||||
|
||||
//assert(asprintf(&tmp1, "%s_%s.khash", filename_prefix, self->filename) != -1);
|
||||
//assert(asprintf(&tmp2, "%s_%s.pcow", filename_prefix, self->filename) != -1);
|
||||
|
||||
tmp1 = gen_file_name(self, filename_prefix, "khash");
|
||||
tmp2 = gen_file_name(self, filename_prefix, "pcow");
|
||||
|
||||
//printf("%s\n", tmp1);
|
||||
kh_destroy(COW_CACHE, self->lookup_primary);
|
||||
|
||||
struct stat buffer;
|
||||
@ -129,7 +121,6 @@ void read_primary_buffer(cow_cache_t* self, const char* filename_prefix, bool sw
|
||||
|
||||
int fd = open(tmp2, O_RDONLY);
|
||||
|
||||
//printf("TRY TO MMAP : %lx\n", buffer.st_size);
|
||||
if(switch_mode){
|
||||
munmap(self->data_primary, self->cow_primary_size);
|
||||
self->cow_primary_size = get_global_cow_cache_primary_size();
|
||||
@ -150,11 +141,9 @@ void read_primary_buffer(cow_cache_t* self, const char* filename_prefix, bool sw
|
||||
memcpy(self->data_primary, ptr, buffer.st_size);
|
||||
munmap(ptr, COW_CACHE_PRIMARY_MINIMUM_SIZE);
|
||||
}
|
||||
//printf("self->data_primary -> %p\n", self->data_primary );
|
||||
close(fd);
|
||||
|
||||
self->offset_primary = buffer.st_size;
|
||||
//fprintf(stderr, "self->offset_primary: %lx\n", self->offset_primary);
|
||||
|
||||
if(switch_mode){
|
||||
switch_to_fuzz_mode(self);
|
||||
@ -162,27 +151,17 @@ void read_primary_buffer(cow_cache_t* self, const char* filename_prefix, bool sw
|
||||
|
||||
free(tmp1);
|
||||
free(tmp2);
|
||||
|
||||
//printf("DONE!\n");
|
||||
|
||||
}
|
||||
|
||||
void dump_primary_buffer(cow_cache_t* self, const char* filename_prefix){
|
||||
assert(self->enabled_fuzz);
|
||||
|
||||
//printf("%s: %s\n", __func__, self->filename);
|
||||
|
||||
|
||||
char* tmp1;
|
||||
char* tmp2;
|
||||
|
||||
//assert(asprintf(&tmp1, "%s_%s.khash", filename_prefix, self->filename) != -1);
|
||||
//assert(asprintf(&tmp2, "%s_%s.pcow", filename_prefix, self->filename) != -1);
|
||||
|
||||
tmp1 = gen_file_name(self, filename_prefix, "khash");
|
||||
tmp2 = gen_file_name(self, filename_prefix, "pcow");
|
||||
|
||||
//printf("%s\n", tmp1);
|
||||
if(self->offset_primary){
|
||||
kh_write(COW_CACHE, self->lookup_primary, tmp1);
|
||||
}
|
||||
@ -194,33 +173,16 @@ void dump_primary_buffer(cow_cache_t* self, const char* filename_prefix){
|
||||
if(fp == NULL) {
|
||||
fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp2);
|
||||
assert(false);
|
||||
//exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(self->offset_primary){
|
||||
fwrite(self->data_primary, CHUNK_SIZE, self->offset_primary/CHUNK_SIZE, fp);
|
||||
}
|
||||
//fprintf(stderr, "self->offset_primary: %lx\n", self->offset_primary);
|
||||
|
||||
|
||||
fclose(fp);
|
||||
|
||||
free(tmp1);
|
||||
free(tmp2);
|
||||
|
||||
//printf("DONE!\n");
|
||||
|
||||
|
||||
/*
|
||||
|
||||
qemu_mutex_unlock_iothread();
|
||||
fast_reload_t* snapshot = fast_reload_new();
|
||||
fast_reload_create(snapshot);
|
||||
qemu_mutex_lock_iothread();
|
||||
|
||||
printf("CREATED!\n");
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
void cow_cache_reset(cow_cache_t* self){
|
||||
@ -229,9 +191,6 @@ void cow_cache_reset(cow_cache_t* self){
|
||||
/* TODO */
|
||||
assert(self->enabled_fuzz);
|
||||
|
||||
//fprintf(stderr, "RESETING COW STUFF YO %s (%lx)\n", self->filename, self->offset_secondary);
|
||||
|
||||
|
||||
if(self->enabled_fuzz){
|
||||
|
||||
#ifdef DEBUG_COW_LAYER
|
||||
@ -315,7 +274,6 @@ static inline void read_from_primary_buffer(cow_cache_t* self, BlockBackend *blk
|
||||
#ifdef COW_CACHE_DEBUG
|
||||
printf("[PRE ] READ DIRTY COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx\n", offset_addr, iov_offset, self->offset_primary);
|
||||
#endif
|
||||
//iov_from_buf_full_register(qiov->iov, qiov->niov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
|
||||
qemu_iovec_from_buf(qiov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
|
||||
}
|
||||
return;
|
||||
@ -332,7 +290,6 @@ static inline void read_from_secondary_buffer(cow_cache_t* self, BlockBackend *b
|
||||
#ifdef COW_CACHE_DEBUG
|
||||
printf("[FTMP] READ DIRTY COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx\n", offset_addr, iov_offset, self->offset_secondary);
|
||||
#endif
|
||||
//iov_from_buf_full_register(qiov->iov, qiov->niov, iov_offset, self->data_secondary_tmp + kh_value(self->lookup_secondary_tmp, k), CHUNK_SIZE);
|
||||
qemu_iovec_from_buf(qiov, iov_offset, self->data_secondary_tmp + kh_value(self->lookup_secondary_tmp, k), CHUNK_SIZE);
|
||||
return;
|
||||
}
|
||||
@ -344,7 +301,6 @@ static inline void read_from_secondary_buffer(cow_cache_t* self, BlockBackend *b
|
||||
#ifdef COW_CACHE_DEBUG
|
||||
printf("[FUZZ] READ DIRTY COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx\n", offset_addr, iov_offset, self->offset_secondary);
|
||||
#endif
|
||||
//iov_from_buf_full_register(qiov->iov, qiov->niov, iov_offset, self->data_secondary + kh_value(self->lookup_secondary, k), CHUNK_SIZE);
|
||||
qemu_iovec_from_buf(qiov, iov_offset, self->data_secondary + kh_value(self->lookup_secondary, k), CHUNK_SIZE);
|
||||
return;
|
||||
}
|
||||
@ -355,7 +311,6 @@ static inline void read_from_secondary_buffer(cow_cache_t* self, BlockBackend *b
|
||||
#ifdef COW_CACHE_DEBUG
|
||||
printf("[PRE ] READ DIRTY COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx\n", offset_addr, iov_offset, self->offset_primary);
|
||||
#endif
|
||||
//iov_from_buf_full_register(qiov->iov, qiov->niov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
|
||||
qemu_iovec_from_buf(qiov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
|
||||
}
|
||||
}
|
||||
@ -373,9 +328,6 @@ static int cow_cache_read(cow_cache_t* self, BlockBackend *blk, int64_t offset,
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
//iov_from_buf_full_register(qiov->iov, qiov->niov, offset, NULL, bytes);
|
||||
|
||||
blk_co_preadv(blk, offset, bytes, qiov, flags);
|
||||
|
||||
if ((qiov->size%CHUNK_SIZE)){
|
||||
@ -411,7 +363,6 @@ static inline void write_to_primary_buffer(cow_cache_t* self, BlockBackend *blk,
|
||||
k = kh_get(COW_CACHE, self->lookup_primary, offset_addr);
|
||||
if(unlikely(k == kh_end(self->lookup_primary))){
|
||||
/* create page */
|
||||
|
||||
k = kh_put(COW_CACHE, self->lookup_primary, offset_addr, &ret);
|
||||
#ifdef COW_CACHE_DEBUG
|
||||
printf("ADD NEW COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx\n", offset_addr, iov_offset, self->offset_primary);
|
||||
@ -436,23 +387,11 @@ static inline void write_to_primary_buffer(cow_cache_t* self, BlockBackend *blk,
|
||||
|
||||
/* write to cached page */
|
||||
qemu_iovec_to_buf(qiov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
|
||||
|
||||
|
||||
/*
|
||||
if(self->offset_primary >= 0xA00000){
|
||||
printf("SWITCH TO SECONDARY\n");
|
||||
switch_to_fuzz_mode(self);
|
||||
dump_primary_buffer(self, "/tmp/cow_dump");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static inline void write_to_secondary_buffer(cow_cache_t* self, BlockBackend *blk, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags, uint64_t offset_addr, uint64_t iov_offset){
|
||||
int ret;
|
||||
|
||||
//assert((offset_addr&(CHUNK_SIZE-1)) == 0);
|
||||
|
||||
if(!self->enabled_fuzz_tmp){
|
||||
/* L2 mode */
|
||||
|
||||
@ -471,7 +410,6 @@ static inline void write_to_secondary_buffer(cow_cache_t* self, BlockBackend *bl
|
||||
self->offset_secondary += CHUNK_SIZE;
|
||||
|
||||
}
|
||||
//printf("WRITE -> %lx\n", kh_value(self->lookup_secondary, k_secondary));
|
||||
/* write to cache */
|
||||
qemu_iovec_to_buf(qiov, iov_offset, self->data_secondary + kh_value(self->lookup_secondary, k_secondary), CHUNK_SIZE);
|
||||
}
|
||||
@ -494,14 +432,12 @@ static inline void write_to_secondary_buffer(cow_cache_t* self, BlockBackend *bl
|
||||
}
|
||||
|
||||
/* write to cache */
|
||||
//printf("WRITE TO L2 TMP -> %lx\n", self->data_secondary_tmp + kh_value(self->lookup_secondary_tmp, k_secondary_tmp));
|
||||
qemu_iovec_to_buf(qiov, iov_offset, self->data_secondary_tmp + kh_value(self->lookup_secondary_tmp, k_secondary_tmp), CHUNK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
/* write data to cow cache */
|
||||
static int cow_cache_write(cow_cache_t* self, BlockBackend *blk, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags){
|
||||
//khiter_t k;
|
||||
|
||||
#ifdef DEBUG_COW_LAYER
|
||||
if(self->enabled_fuzz){
|
||||
@ -520,7 +456,6 @@ static int cow_cache_write(cow_cache_t* self, BlockBackend *blk, int64_t offset,
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
//printf("qiov->size: %lx %lx\n", qiov->size, CHUNK_SIZE);
|
||||
if((qiov->size%CHUNK_SIZE) && GET_GLOBAL_STATE()->in_fuzzing_mode){
|
||||
GET_GLOBAL_STATE()->cow_cache_full = true;
|
||||
fprintf(stderr, "WARNING: %s write in %lx CHUNKSIZE\n", __func__, qiov->size);
|
||||
@ -560,12 +495,8 @@ void cow_cache_read_entry(void* opaque){
|
||||
printf("%s %lx %lx\n", __func__, rwco->offset, acb->bytes);
|
||||
#endif
|
||||
|
||||
|
||||
//printf("rwco->ret: %lx %lx\n", rwco->ret, acb->bytes);
|
||||
rwco->ret = cow_cache_read( *((cow_cache_t**)(rwco->blk)), rwco->blk, rwco->offset, acb->bytes, rwco->qiov, rwco->flags);
|
||||
|
||||
//last_read = PAGE_MASK;
|
||||
|
||||
blk_aio_complete(acb);
|
||||
}
|
||||
|
||||
|
@ -3,11 +3,11 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
#include "nyx/khash.h"
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "block/block.h"
|
||||
|
||||
#include "nyx/khash.h"
|
||||
#include "nyx/redqueen_trace.h"
|
||||
|
||||
//#define DEBUG_COW_LAYER
|
||||
@ -57,9 +57,6 @@ typedef struct cow_cache_s{
|
||||
|
||||
cow_cache_t* cow_cache_new(const char* filename);
|
||||
void cow_cache_reset(cow_cache_t* self);
|
||||
//int coroutine_fn cow_cache_read(cow_cache_t* self, BlockBackend *blk, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags);
|
||||
//int coroutine_fn cow_cache_write(cow_cache_t* self, BlockBackend *blk, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags);
|
||||
|
||||
|
||||
void switch_to_fuzz_mode(cow_cache_t* self);
|
||||
|
||||
|
@ -1,16 +1,14 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/qapi.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#include "nyx/snapshot/block/nyx_block_snapshot.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/snapshot/block/nyx_block_snapshot.h"
|
||||
#include "nyx/state/state.h"
|
||||
|
||||
typedef struct fast_reload_cow_entry_s{
|
||||
@ -109,39 +107,6 @@ nyx_block_t* nyx_block_snapshot_init(void){
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
|
||||
static void fast_reload_serialize_cow(fast_reload_t* self, const char* folder){
|
||||
fast_reload_cow_entry_t entry;
|
||||
|
||||
char* tmp1;
|
||||
char* tmp2;
|
||||
|
||||
assert(asprintf(&tmp1, "%s/fs_cache.meta", folder) != -1);
|
||||
assert(asprintf(&tmp2, "%s/fs_drv", folder) != -1);
|
||||
|
||||
|
||||
FILE* f = fopen (tmp1, "w");
|
||||
|
||||
fwrite(&(self->cow_cache_array_size), sizeof(uint32_t), 1, f);
|
||||
|
||||
for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
|
||||
entry.id = i;
|
||||
printf("%d -> %s\n", i, (const char*)self->cow_cache_array[i]->filename);
|
||||
strncpy((char*)&entry.idstr, (const char*)self->cow_cache_array[i]->filename, 256);
|
||||
fwrite(&entry, sizeof(fast_reload_cow_entry_t), 1, f);
|
||||
|
||||
dump_primary_buffer(self->cow_cache_array[i], tmp2);
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
free(tmp1);
|
||||
free(tmp2);
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
void nyx_block_snapshot_flush(nyx_block_t* self){
|
||||
GET_GLOBAL_STATE()->cow_cache_full = false;
|
||||
}
|
||||
@ -181,7 +146,6 @@ void nyx_block_snapshot_serialize(nyx_block_t* self, const char* snapshot_folder
|
||||
|
||||
for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
|
||||
entry.id = i;
|
||||
//printf("%d -> %s\n", i, (const char*)self->cow_cache_array[i]->filename);
|
||||
strncpy((char*)&entry.idstr, (const char*)self->cow_cache_array[i]->filename, 255);
|
||||
fwrite(&entry, sizeof(fast_reload_cow_entry_t), 1, f);
|
||||
|
||||
|
@ -1,44 +1,34 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
#include "qemu/rcu_queue.h"
|
||||
#include "migration/migration.h"
|
||||
#include "migration/register.h"
|
||||
#include "migration/savevm.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/qjson.h"
|
||||
#include "migration/global_state.h"
|
||||
|
||||
#include "nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include "nyx/debug.h"
|
||||
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "block/qapi.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "migration/vmstate.h"
|
||||
|
||||
#include "nyx/snapshot/devices/state_reallocation.h"
|
||||
|
||||
#include <linux/kvm.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <immintrin.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "qemu/rcu_queue.h"
|
||||
|
||||
#include "block/qapi.h"
|
||||
#include "exec/ram_addr.h"
|
||||
#include "migration/global_state.h"
|
||||
#include "migration/migration.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/qjson.h"
|
||||
#include "migration/register.h"
|
||||
#include "migration/savevm.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "sysemu/block-backend.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/reset.h"
|
||||
#include "sysemu/runstate.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include "nyx/snapshot/devices/state_reallocation.h"
|
||||
#include "nyx/snapshot/devices/vm_change_state_handlers.h"
|
||||
|
||||
|
||||
|
||||
#define STATE_BUFFER 0x8000000 /* up to 128MB */
|
||||
|
||||
extern void enable_fast_snapshot_rtc(void);
|
||||
@ -67,7 +57,7 @@ static void save_tsc_value(nyx_device_state_t* self, bool incremental_mode){
|
||||
CPUX86State *env = &cpu->env;
|
||||
|
||||
if(incremental_mode){
|
||||
self->tsc_value_incremental = env->tsc; // - 0x200000; /* fml */
|
||||
self->tsc_value_incremental = env->tsc;
|
||||
}
|
||||
else{
|
||||
self->tsc_value = env->tsc;
|
||||
@ -342,7 +332,6 @@ nyx_device_state_t* nyx_device_state_init_from_snapshot(const char* snapshot_fol
|
||||
uint8_t ret = global_state_store();
|
||||
assert(!ret);
|
||||
|
||||
/* Testing Stuff */
|
||||
struct stat buffer;
|
||||
assert(stat (qemu_state_file, &buffer) == 0);
|
||||
|
||||
@ -353,7 +342,7 @@ nyx_device_state_t* nyx_device_state_init_from_snapshot(const char* snapshot_fol
|
||||
fclose(f);
|
||||
|
||||
fast_savevm_opaque.buf = state_buf2;
|
||||
fast_savevm_opaque.f = NULL;//fopen("/tmp/qemu_state", "w");
|
||||
fast_savevm_opaque.f = NULL;
|
||||
fast_savevm_opaque.pos = 0;
|
||||
QEMUFile* file_dump = qemu_fopen_ops(&fast_savevm_opaque, &fast_loadvm_ops);
|
||||
|
||||
@ -390,16 +379,14 @@ nyx_device_state_t* nyx_device_state_init(void){
|
||||
|
||||
Error *local_err = NULL;
|
||||
struct fast_savevm_opaque_t fast_savevm_opaque, fast_loadvm_opaque;
|
||||
//state_reallocation_t* qemu_state;
|
||||
|
||||
void* tmp_buf = malloc(1024*1024*16);
|
||||
//memset(self->state_buf, 0, STATE_BUFFER);
|
||||
|
||||
fast_savevm_opaque.output_buffer = self->state_buf;
|
||||
fast_savevm_opaque.output_buffer_size = &self->state_buf_size;
|
||||
|
||||
fast_savevm_opaque.buf = tmp_buf;//self->state_buf;
|
||||
fast_savevm_opaque.f = NULL; //fopen("/tmp/delta", "w");
|
||||
fast_savevm_opaque.buf = tmp_buf;
|
||||
fast_savevm_opaque.f = NULL;
|
||||
fast_savevm_opaque.pos = 0;
|
||||
|
||||
uint8_t ret = global_state_store();
|
||||
@ -407,31 +394,21 @@ nyx_device_state_t* nyx_device_state_init(void){
|
||||
|
||||
QEMUFile* f = qemu_fopen_ops(&fast_savevm_opaque, &fast_savevm_ops_to_buffer);
|
||||
ret = fast_qemu_savevm_state(f, &local_err);
|
||||
//qemu_fflush(f);
|
||||
|
||||
|
||||
fast_loadvm_opaque.buf = tmp_buf; //self->state_buf;
|
||||
fast_loadvm_opaque.buf = tmp_buf;
|
||||
fast_loadvm_opaque.f = NULL;
|
||||
fast_loadvm_opaque.pos = 0;
|
||||
QEMUFile* file_dump = qemu_fopen_ops(&fast_loadvm_opaque, &fast_loadvm_ops);
|
||||
|
||||
//qemu_mutex_lock_iothread();
|
||||
//qemu_devices_reset();
|
||||
self->qemu_state = state_reallocation_new(file_dump);
|
||||
//qemu_mutex_unlock_iothread();
|
||||
qemu_fclose(file_dump);
|
||||
|
||||
|
||||
//sleep(1);
|
||||
qemu_fclose(f);
|
||||
free(tmp_buf);
|
||||
|
||||
|
||||
enable_fast_snapshot_mode();
|
||||
save_tsc_value(self, false);
|
||||
return self;
|
||||
|
||||
//return qemu_state;
|
||||
}
|
||||
|
||||
void nyx_device_state_switch_incremental(nyx_device_state_t* self){
|
||||
|
@ -19,21 +19,22 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "sysemu/kvm_int.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/register.h"
|
||||
#include "migration/savevm.h"
|
||||
#include "migration/qemu-file.h"
|
||||
#include "migration/vmstate.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/snapshot/devices/state_reallocation.h"
|
||||
#include "nyx/snapshot/devices/nyx_device_state.h"
|
||||
#include "nyx/snapshot/devices/state_reallocation.h"
|
||||
|
||||
//#define VERBOSE_DEBUG
|
||||
|
||||
//uint32_t fpos = 0;
|
||||
#define QEMU_VM_SUBSECTION 0x05
|
||||
|
||||
typedef struct CompatEntry {
|
||||
@ -85,20 +86,13 @@ static void fast_timer_get(void* data, size_t size, void* opaque)
|
||||
{
|
||||
QEMUTimer *ts = (QEMUTimer*) opaque;
|
||||
uint64_t expire_time = *((uint64_t*)data);
|
||||
//fprintf(stderr, "%s: VALUE IS: %lx\n", __func__, expire_time);
|
||||
|
||||
if (expire_time != -1) {
|
||||
timer_mod_ns(ts, expire_time);
|
||||
} else {
|
||||
timer_del(ts);
|
||||
}
|
||||
//fprintf(stderr, "%s: DONE!\n", __func__);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
static SaveStateEntry *fdl_find_se(const char *idstr, int instance_id)
|
||||
{
|
||||
SaveStateEntry *se;
|
||||
@ -107,7 +101,6 @@ static SaveStateEntry *fdl_find_se(const char *idstr, int instance_id)
|
||||
if (!strcmp(se->idstr, idstr) &&
|
||||
(instance_id == se->instance_id ||
|
||||
instance_id == se->alias_id)){
|
||||
//printf("FOUND 1\n");
|
||||
return se;
|
||||
}
|
||||
/* Migrating from an older version? */
|
||||
@ -115,12 +108,10 @@ static SaveStateEntry *fdl_find_se(const char *idstr, int instance_id)
|
||||
if (!strcmp(se->compat->idstr, idstr) &&
|
||||
(instance_id == se->compat->instance_id ||
|
||||
instance_id == se->alias_id)){
|
||||
//printf("FOUND 2\n");
|
||||
return se;
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("NOPE\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -131,9 +122,7 @@ static inline VMStateDescription* fdl_vmstate_get_subsection(VMStateDescription
|
||||
{
|
||||
while (sub && *sub && (*sub)->needed) {
|
||||
if (strcmp(idstr, (*sub)->name) == 0) {
|
||||
//printf("SUB %p\n", &sub);
|
||||
//sub_vmsd_ptr = ⊂
|
||||
return *sub; /* don't dereference...return ptr */
|
||||
return *sub;
|
||||
}
|
||||
sub++;
|
||||
}
|
||||
@ -150,9 +139,7 @@ static int fdl_vmstate_subsection_load(state_reallocation_t* self, QEMUFile *f,
|
||||
|
||||
len = qemu_peek_byte(f, 1);
|
||||
if (len < strlen(vmsd->name) + 1) {
|
||||
/* subsection name has be be "section_name/a" */
|
||||
//fprintf(stderr, "%s: exit\n", __func__);
|
||||
|
||||
/* subsection name has to be "section_name/a" */
|
||||
return 0;
|
||||
}
|
||||
size = qemu_peek_buffer(f, (uint8_t **)&idstr_ret, len, 2);
|
||||
@ -164,7 +151,6 @@ static int fdl_vmstate_subsection_load(state_reallocation_t* self, QEMUFile *f,
|
||||
|
||||
if (strncmp(vmsd->name, idstr, strlen(vmsd->name)) != 0) {
|
||||
/* it doesn't have a valid subsection name */
|
||||
//fprintf(stderr, "%s: exit\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
sub_vmsd = fdl_vmstate_get_subsection((VMStateDescription **)vmsd->subsections, idstr);
|
||||
@ -199,8 +185,6 @@ static void add_post_fptr(state_reallocation_t* self, void* fptr, uint32_t versi
|
||||
if(!self){
|
||||
return;
|
||||
}
|
||||
//printf("%s: %s\n", __func__, name);
|
||||
|
||||
|
||||
if(!strcmp("I440FX", name)){
|
||||
return;
|
||||
@ -271,7 +255,7 @@ static void add_post_fptr(state_reallocation_t* self, void* fptr, uint32_t versi
|
||||
self->fast_state_fptr_pos++;
|
||||
|
||||
if(self->fast_state_fptr_pos >= self->fast_state_fptr_size){
|
||||
printf("RESIZE %s\n", __func__);
|
||||
nyx_debug("RESIZE %s\n", __func__);
|
||||
self->fast_state_fptr_size += REALLOC_SIZE;
|
||||
self->fptr = realloc(self->fptr, self->fast_state_fptr_size * sizeof(void*));
|
||||
self->opaque = realloc(self->opaque, self->fast_state_fptr_size * sizeof(void*));
|
||||
@ -482,36 +466,26 @@ static inline int get_handler(state_reallocation_t* self, QEMUFile* f, void* cur
|
||||
add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "CPU_Double_U")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
assert(0);
|
||||
add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "buffer")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, size);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "unused_buffer")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
/* save nothing */
|
||||
}
|
||||
else if(!strcmp(field->info->name, "tmp")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, size);
|
||||
|
||||
/* save nothing */
|
||||
}
|
||||
else if(!strcmp(field->info->name, "bitmap")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
assert(0);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "qtailq")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
assert(0);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "timer")){
|
||||
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size);
|
||||
//printf("%s time\n", vmsd_name);
|
||||
//add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, sizeof(QEMUTimer));
|
||||
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "fpreg")){
|
||||
@ -520,56 +494,32 @@ static inline int get_handler(state_reallocation_t* self, QEMUFile* f, void* cur
|
||||
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "pci config")){
|
||||
//fprintf(stderr, "type: %s (size: %lx)\n", field->info->name, size);
|
||||
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "pci irq state")){
|
||||
//fprintf(stderr, "type: %s (size: %lx)\n", field->info->name, size);
|
||||
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
|
||||
}
|
||||
else if(!strcmp(field->info->name, "virtio")){
|
||||
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
|
||||
//fprintf(stderr, "[QEMU-PT] %s: WARNING no handler for %s, type %s, size %lx!\n",
|
||||
// __func__, vmsd_name, field->info->name, size);
|
||||
}
|
||||
else{
|
||||
fprintf(stderr, "[QEMU-PT] %s: WARNING no handler for %s, type %s, size %lx!\n",
|
||||
__func__, vmsd_name, field->info->name, size);
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//migration_obj_t* obj;
|
||||
//void* base_opaque;
|
||||
|
||||
//#define VERBOSE_DEBUG
|
||||
|
||||
/* todo: modify opaque_ptr */
|
||||
/* TODO: modify opaque_ptr */
|
||||
static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id, uintptr_t* opaque_ptr)
|
||||
{
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf("---------------------------------\nVMSD: %p\t%s\n", opaque, vmsd->name);
|
||||
#endif
|
||||
|
||||
//fprintf(stderr, "---------------------------------\nVMSD: %p\t%s\n", opaque, vmsd->name);
|
||||
|
||||
VMStateField *field = (VMStateField *)vmsd->fields;
|
||||
int ret = 0;
|
||||
|
||||
/*
|
||||
bool alloc_later = false;
|
||||
if(alloc_block){
|
||||
base_opaque = opaque;
|
||||
alloc_block = false;
|
||||
alloc_later = true;
|
||||
obj = alloc_migration_obj();
|
||||
}
|
||||
*/
|
||||
|
||||
uint64_t total_size = 0;
|
||||
|
||||
if (version_id > vmsd->version_id) {
|
||||
@ -594,31 +544,14 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
printf("\tPRELOAD Function\n");
|
||||
#endif
|
||||
/* TODO ADD PRE FPTR FOR SERIAL */
|
||||
//add_pre_fptr(self, vmsd->pre_load, opaque, vmsd->name);
|
||||
//fprintf(stderr, "PRELOAD RUN: %s\n", vmsd->name);
|
||||
//add_pre_fptr(self, vmsd->pre_load, opaque, vmsd->name);
|
||||
add_post_fptr(self, vmsd->pre_load, 1337, opaque, vmsd->name);
|
||||
//int ret = 0;
|
||||
//return;
|
||||
|
||||
|
||||
|
||||
/*
|
||||
int ret = vmsd->pre_load(opaque);
|
||||
if (ret) {
|
||||
return ret;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
while (field->name) {
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf("Field: %s %s %s\n", __func__, vmsd->name, field->name);
|
||||
#endif
|
||||
//fprintf(stderr, "Field: %s %s %s\n", __func__, vmsd->name, field->name);
|
||||
|
||||
//printf("Field: %s %s %s\n", __func__, vmsd->name, field->name);
|
||||
if ((field->field_exists &&
|
||||
field->field_exists(opaque, version_id)) ||
|
||||
(!field->field_exists &&
|
||||
@ -627,8 +560,6 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
int i, n_elems = vmstate_n_elems(opaque, field);
|
||||
int size = vmstate_size(opaque, field);
|
||||
|
||||
//printf("\t\t%s %d\n", field->name, size);
|
||||
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf("-----------------> vmstate_handle_alloc\n");
|
||||
#endif
|
||||
@ -640,33 +571,16 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
#endif
|
||||
// printf("Field-Offset 0x%lx-0x%lx\n", opaque+field->offset, opaque+field->offset+(size*n_elems));
|
||||
|
||||
/* fix me */
|
||||
/* broken af */
|
||||
//printf("add_translatable_block: %lx %lx %ld\n", *(void **)first_elem, first_elem, n_elems*size);
|
||||
/*
|
||||
if((n_elems*size)){
|
||||
add_translatable_block((void*)(*(void **)first_elem), (void*)first_elem, (uint64_t)(n_elems*size), field->name, 0, (void*) NULL, (void*) NULL);
|
||||
}
|
||||
*/
|
||||
|
||||
//fprintf(stderr, "FIX ME VMS_POINTER\n");
|
||||
first_elem = *(void **)first_elem;
|
||||
assert(first_elem || !n_elems || !size);
|
||||
}
|
||||
|
||||
for (i = 0; i < n_elems; i++) {
|
||||
uint64_t* tmp_opaque_ptr = 0;
|
||||
total_size += size;
|
||||
void *curr_elem = first_elem + size * i;
|
||||
|
||||
//if (!(field->flags & VMS_POINTER)) {
|
||||
// tmp_opaque_ptr = 0;
|
||||
//}
|
||||
//assert(!(field->flags & VMS_POINTER) || n_elems == 1);
|
||||
|
||||
if (field->flags & VMS_ARRAY_OF_POINTER) {
|
||||
//printf("VMS_ARRAY_OF_POINTER\n");
|
||||
//add_mblock((uint64_t)(curr_elem), (uint64_t)(size));
|
||||
//add_mblock((uint64_t)(field->offset + (opaque)), (uint64_t)(size*n_elems));
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf("Field-Offset 1 0x%lx-0x%lx\n", (uint64_t)(field->offset + (opaque)), (uint64_t)(field->offset+(size*n_elems) + (opaque)));
|
||||
printf("=VMS_ARRAY_OF_POINTER 1= %lx %x\n", *((uint64_t*)curr_elem), size);
|
||||
@ -684,9 +598,6 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
if (!curr_elem && size) {
|
||||
// if null pointer check placeholder and do not follow
|
||||
assert(field->flags & VMS_ARRAY_OF_POINTER);
|
||||
//printf("=================vmstate_info_nullptr\n");#
|
||||
//add_mblock((uint64_t)(curr_elem), (uint64_t)(size));
|
||||
//add_mblock((uint64_t)(field->offset + (opaque)), (uint64_t)(size*n_elems));
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf("Field-Offset 2 0x%lx-0x%lx\n", (uint64_t)(field->offset + (opaque)), (uint64_t)(field->offset+(size*n_elems) + (opaque)));
|
||||
printf("=VMS_ARRAY_OF_POINTER 2= %lx %x\n", *((uint64_t*)curr_elem), size);
|
||||
@ -706,8 +617,7 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
printf("=VMS_STRUCT= %lx %x\n", *((uint64_t*)curr_elem), size);
|
||||
//hexDump((void*)field->name, curr_elem, size);
|
||||
#endif
|
||||
/* fix me */
|
||||
//ret = vmstate_load_state(f, field->vmsd, curr_elem, field->vmsd->version_id);
|
||||
/* FIXME */
|
||||
ret = fdl_vmstate_load_state(self, f, field->vmsd, curr_elem, field->vmsd->version_id, tmp_opaque_ptr);
|
||||
#ifdef VERBOSE_DEBUG
|
||||
//hexDump((void*)field->name, curr_elem, size);
|
||||
@ -719,9 +629,6 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
ret = get_handler(self, f, curr_elem, size, field, (char*)vmsd->name);
|
||||
}
|
||||
if (ret >= 0) {
|
||||
//printf("FILE ERROR\n");
|
||||
//fprintf(stderr, "FILE ERROR\n");
|
||||
//assert(0);
|
||||
ret = qemu_file_get_error(f);
|
||||
}
|
||||
if (ret < 0) {
|
||||
@ -739,28 +646,18 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
field++;
|
||||
}
|
||||
|
||||
/* fix me */
|
||||
/* FIXME */
|
||||
ret = fdl_vmstate_subsection_load(self, f, vmsd, opaque);
|
||||
//ret = fdl_vmstate_subsection_load(f, vmsd, opaque, opaque_ptr);
|
||||
|
||||
if (ret != 0) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
if(alloc_later){
|
||||
add_opaque_block(obj, opaque, total_size);
|
||||
}
|
||||
*/
|
||||
|
||||
//printf("------\n");
|
||||
|
||||
if (vmsd->post_load) {
|
||||
#ifdef VERBOSE_DEBUG
|
||||
printf("\tPOSTLOAD Function\n");
|
||||
#endif
|
||||
add_post_fptr(self, vmsd->post_load, version_id, opaque, vmsd->name);
|
||||
//ret = 0;
|
||||
ret = vmsd->post_load(opaque, version_id);
|
||||
}
|
||||
#ifdef VERBOSE_DEBUG
|
||||
@ -772,24 +669,17 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
|
||||
|
||||
static int fdl_vmstate_load(state_reallocation_t* self, QEMUFile *f, SaveStateEntry *se, int version_id)
|
||||
{
|
||||
//trace_vmstate_load(se->idstr, se->vmsd ? se->vmsd->name : "(old)");
|
||||
if (!se->vmsd) { /* Old style */
|
||||
//fprintf(stderr, "\t<<<OLD Style>>>\n");
|
||||
return se->ops->load_state(f, se->opaque, version_id);
|
||||
}
|
||||
//fprintf(stderr, "NEW Style\n");
|
||||
uintptr_t* t = (uintptr_t*)&(se->opaque);
|
||||
//printf("------>\n");
|
||||
//printf("VMSD1: %s\n", (VMStateDescription *)(se->vmsd)->name);
|
||||
|
||||
//printf("SE:\t%p %p %p %p\n", se, se->opaque, &(se->opaque) ,t);
|
||||
return fdl_vmstate_load_state(self, f, se->vmsd, se->opaque, version_id, (uintptr_t*)t);
|
||||
|
||||
uintptr_t *t = (uintptr_t *)&(se->opaque);
|
||||
return fdl_vmstate_load_state(self, f, se->vmsd, se->opaque, version_id, (uintptr_t *)t);
|
||||
}
|
||||
|
||||
static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, MigrationIncomingState *mis){
|
||||
uint32_t instance_id, version_id, section_id;
|
||||
SaveStateEntry *se;
|
||||
//LoadStateEntry *le = NULL;
|
||||
|
||||
char idstr[256];
|
||||
int ret;
|
||||
@ -803,11 +693,8 @@ static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, Migrat
|
||||
instance_id = qemu_get_be32(f);
|
||||
version_id = qemu_get_be32(f);
|
||||
|
||||
//printf("%s %s %d\n", __func__, idstr, instance_id);
|
||||
|
||||
/* Find savevm section */
|
||||
se = fdl_find_se(idstr, instance_id);
|
||||
//printf("se %p\n", se);
|
||||
if (se == NULL) {
|
||||
printf("Unknown savevm section or instance '%s' %d", idstr, instance_id);
|
||||
return -EINVAL;
|
||||
@ -818,15 +705,6 @@ static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, Migrat
|
||||
printf("savevm: unsupported version %d for '%s' v%d", version_id, idstr, se->version_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
/* Add entry */
|
||||
/*
|
||||
le = g_malloc0(sizeof(*le));
|
||||
le->se = se;
|
||||
//printf("\tSE:%s\n", se);
|
||||
le->section_id = section_id;
|
||||
le->version_id = version_id;
|
||||
QLIST_INSERT_HEAD(&mis->loadvm_handlers, le, entry);
|
||||
*/
|
||||
|
||||
se->load_version_id = version_id;
|
||||
se->load_section_id = section_id;
|
||||
@ -878,12 +756,9 @@ static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, Migrat
|
||||
}
|
||||
else{
|
||||
nyx_debug("---------------------------------\nVMSD2: %p\n", (void*)se->vmsd);
|
||||
//abort();
|
||||
//fprintf(stderr, "---------------------------------\nVMSD2: %s\n", (VMStateDescription *)(se->vmsd)->name);
|
||||
ret = vmstate_load(f, se);
|
||||
}
|
||||
|
||||
//ret = vmstate_load(f, se);
|
||||
if (ret < 0) {
|
||||
printf("error while loading state for instance 0x%x of device '%s'", instance_id, idstr);
|
||||
return ret;
|
||||
@ -915,9 +790,6 @@ static void fdl_enumerate_global_states(state_reallocation_t* self, QEMUFile *f)
|
||||
switch (section_type) {
|
||||
case QEMU_VM_SECTION_START:
|
||||
case QEMU_VM_SECTION_FULL:
|
||||
//if(!fpos){
|
||||
// fpos = qemu_ftell(f);
|
||||
//}
|
||||
fdl_enumerate_section(self, f, mis);
|
||||
break;
|
||||
default:
|
||||
@ -971,15 +843,7 @@ state_reallocation_t* state_reallocation_new(QEMUFile *f){
|
||||
return self;
|
||||
}
|
||||
|
||||
/*
|
||||
void state_reallocation_new_no_fdl(QEMUFile *f){
|
||||
fdl_enumerate_global_states(NULL, f);
|
||||
}
|
||||
*/
|
||||
|
||||
void fdl_fast_reload(state_reallocation_t* self){
|
||||
//uint64_t count = 0;
|
||||
|
||||
|
||||
for(uint32_t i = 0; i < self->fast_state_fptr_pos; i++){
|
||||
if((self->version[i]) == 1337){
|
||||
@ -989,14 +853,11 @@ void fdl_fast_reload(state_reallocation_t* self){
|
||||
|
||||
if(!self->tmp_snapshot.enabled){
|
||||
for(uint32_t i = 0; i < self->fast_state_pos; i++){
|
||||
//count += self->size[i];
|
||||
memcpy(self->ptr[i], self->copy[i], self->size[i]);
|
||||
}
|
||||
}
|
||||
else{
|
||||
//fprintf(stderr, "====== %s TMP MODE ====== \n", __func__);
|
||||
for(uint32_t i = 0; i < self->fast_state_pos; i++){
|
||||
//count += self->size[i];
|
||||
memcpy(self->ptr[i], self->tmp_snapshot.copy[i], self->size[i]);
|
||||
}
|
||||
}
|
||||
|
@ -19,17 +19,12 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STATE_REALLOCATION
|
||||
#define STATE_REALLOCATION
|
||||
|
||||
#pragma once
|
||||
#include "qemu/osdep.h"
|
||||
#include "monitor/monitor.h"
|
||||
//#include "qemu-common.h"
|
||||
#include "migration/migration.h"
|
||||
#include "nyx/khash.h"
|
||||
|
||||
|
||||
|
||||
#define IO_BUF_SIZE 32768
|
||||
|
||||
struct QEMUFile_tmp {
|
||||
@ -40,10 +35,9 @@ struct QEMUFile_tmp {
|
||||
int64_t bytes_xfer;
|
||||
int64_t xfer_limit;
|
||||
|
||||
int64_t pos; /* start of buffer when writing, end of buffer
|
||||
when reading */
|
||||
int64_t pos; // buffer start on write, end on read
|
||||
volatile int buf_index;
|
||||
int buf_size; /* 0 when writing */
|
||||
int buf_size; // 0 when writing
|
||||
uint8_t buf[IO_BUF_SIZE];
|
||||
};
|
||||
|
||||
@ -88,8 +82,6 @@ typedef struct state_reallocation_s{
|
||||
size_t *get_size;
|
||||
void **get_data;
|
||||
|
||||
//QEMUFile** file;
|
||||
|
||||
uint32_t fast_state_get_fptr_size;
|
||||
uint32_t fast_state_get_fptr_pos;
|
||||
|
||||
@ -103,11 +95,8 @@ typedef struct state_reallocation_s{
|
||||
|
||||
state_reallocation_t* state_reallocation_new(QEMUFile *f);
|
||||
|
||||
//void fdl_enumerate_global_states(QEMUFile *f);
|
||||
void fdl_fast_reload(state_reallocation_t* self);
|
||||
|
||||
void fdl_fast_create_tmp(state_reallocation_t* self);
|
||||
void fdl_fast_enable_tmp(state_reallocation_t* self);
|
||||
void fdl_fast_disable_tmp(state_reallocation_t* self);
|
||||
|
||||
#endif
|
@ -2,7 +2,6 @@
|
||||
#include <assert.h>
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "nyx/snapshot/devices/vm_change_state_handlers.h"
|
||||
|
||||
@ -26,7 +25,8 @@ void call_fast_change_handlers(void){
|
||||
change_cpu_handler(change_cpu_opaque, 1, RUN_STATE_RUNNING);
|
||||
|
||||
return;
|
||||
/* check if necessary */
|
||||
|
||||
/* TODO: check if necessary */
|
||||
if(change_ide_core_handler){
|
||||
for(uint8_t i = 0; i < change_ide_core_opaque_num; i++){
|
||||
change_ide_core_handler(change_ide_core_opaque[i], 1, RUN_STATE_RUNNING);
|
||||
|
@ -2,11 +2,8 @@
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
/* don't! */
|
||||
#define MAX_REGIONS 8
|
||||
|
||||
#ifndef PAGE_SIZE
|
||||
#define PAGE_SIZE 0x1000
|
||||
#define PAGE_SIZE qemu_real_host_page_size
|
||||
#endif
|
||||
|
||||
#define BITMAP_SIZE(x) ((x/PAGE_SIZE)/8)
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
|
||||
void nyx_snapshot_debug_pre_init(void);
|
||||
|
@ -1,10 +1,13 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include "nyx/snapshot/memory/backend/nyx_dirty_ring.h"
|
||||
#include "nyx/snapshot/helper.h"
|
||||
|
||||
#include "sysemu/kvm.h"
|
||||
#include "sysemu/kvm_int.h"
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/kvm.h>
|
||||
|
||||
#define FAST_IN_RANGE(address, start, end) (address < end && address >= start)
|
||||
@ -221,7 +224,7 @@ nyx_dirty_ring_t* nyx_dirty_ring_init(shadow_memory_t* shadow_memory){
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
#ifdef DEBUG__PRINT_DIRTY_RING
|
||||
for(int i = 0; i < self->kvm_region_slots_num; i++){
|
||||
printf("[%d].enabled = %d\n", i, self->kvm_region_slots[i].enabled);
|
||||
printf("[%d].bitmap = %p\n", i, self->kvm_region_slots[i].bitmap);
|
||||
@ -236,7 +239,7 @@ nyx_dirty_ring_t* nyx_dirty_ring_init(shadow_memory_t* shadow_memory){
|
||||
printf("[%d].region_offset = -\n", i);
|
||||
}
|
||||
}
|
||||
*/
|
||||
#endif
|
||||
|
||||
dirty_ring_flush(kvm_get_vm_fd(kvm_state));
|
||||
return self;
|
||||
@ -318,20 +321,7 @@ static void save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memo
|
||||
}
|
||||
}
|
||||
|
||||
//entry = &ring->dirty_gfns[ring->reset_index & (ring->size - 1)];
|
||||
|
||||
|
||||
uint32_t nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
/*
|
||||
static int perf_counter = 0;
|
||||
|
||||
if((perf_counter%1000) == 0){
|
||||
fprintf(stderr, "perf_counter -> %d\n", perf_counter); //, self->test_total, self->test);
|
||||
}
|
||||
|
||||
perf_counter++;
|
||||
*/
|
||||
|
||||
dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist, kvm_get_vm_fd(kvm_state));
|
||||
return restore_memory(self, shadow_memory_state, blocklist);
|
||||
}
|
||||
@ -342,11 +332,6 @@ void nyx_snapshot_nyx_dirty_ring_save_root_pages(nyx_dirty_ring_t* self, shadow_
|
||||
save_root_pages(self, shadow_memory_state, blocklist);
|
||||
}
|
||||
|
||||
/* enable operation */
|
||||
|
||||
/* restore operation */
|
||||
|
||||
|
||||
void nyx_snapshot_nyx_dirty_ring_flush(void){
|
||||
dirty_ring_flush(kvm_get_vm_fd(kvm_state));
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nyx/snapshot/memory/block_list.h"
|
||||
#include "nyx/snapshot/memory/shadow_memory.h"
|
||||
|
||||
@ -37,7 +38,9 @@ void nyx_dirty_ring_pre_init(int kvm_fd, int vm_fd);
|
||||
nyx_dirty_ring_t* nyx_dirty_ring_init(shadow_memory_t* shadow_memory);
|
||||
|
||||
uint32_t nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
|
||||
|
||||
void nyx_snapshot_nyx_dirty_ring_save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
|
||||
|
||||
void nyx_snapshot_nyx_dirty_ring_flush(void);
|
||||
|
||||
void nyx_snapshot_nyx_dirty_ring_flush_and_collect(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
@ -29,7 +28,8 @@
|
||||
nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
|
||||
|
||||
static bool fdl_created = false;
|
||||
assert(fdl_created == false); /* not sure if we're able to create another FDL instance -> probably not */
|
||||
/* not sure if we're able to create another FDL instance -> probably not */
|
||||
assert(fdl_created == false);
|
||||
fdl_created = true;
|
||||
|
||||
nyx_fdl_t* self = malloc(sizeof(nyx_fdl_t));
|
||||
@ -45,11 +45,10 @@ nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
|
||||
self->vmx_fdl_fd = kvm_vm_ioctl(kvm_state, KVM_VMX_FDL_SETUP_FD, (unsigned long)0);
|
||||
|
||||
configuration.num = 0;
|
||||
//memset(&self->fdl_data2, 0, sizeof(struct fdl_data_t2));
|
||||
|
||||
for(uint8_t i = 0; i < shadow_memory->ram_regions_num; i++){
|
||||
configuration.areas[configuration.num].base_address = shadow_memory->ram_regions[i].base; // block->mr->addr;
|
||||
configuration.areas[configuration.num].size = shadow_memory->ram_regions[i].size; //MEM_SPLIT_START; //block->used_length;
|
||||
configuration.areas[configuration.num].base_address = shadow_memory->ram_regions[i].base;
|
||||
configuration.areas[configuration.num].size = shadow_memory->ram_regions[i].size;
|
||||
configuration.num++;
|
||||
}
|
||||
|
||||
@ -95,10 +94,8 @@ nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
|
||||
return self;
|
||||
}
|
||||
|
||||
#define MEMSET_BITMAP
|
||||
|
||||
#ifdef MEMSET_BITMAP
|
||||
static uint32_t nyx_snapshot_nyx_fdl_restore_new(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
/* restore operation */
|
||||
uint32_t nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
|
||||
uint32_t num_dirty_pages = 0;
|
||||
void* current_region = NULL;
|
||||
@ -153,135 +150,12 @@ static uint32_t nyx_snapshot_nyx_fdl_restore_new(nyx_fdl_t* self, shadow_memory_
|
||||
return num_dirty_pages;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* restore operation */
|
||||
uint32_t nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
|
||||
/* not sure which one is faster -> benchmark ASAP */
|
||||
#ifdef MEMSET_BITMAP
|
||||
return nyx_snapshot_nyx_fdl_restore_new(self, shadow_memory_state, blocklist);
|
||||
#else
|
||||
return nyx_snapshot_nyx_fdl_restore_old(self, shadow_memory_state, blocklist);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
void nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
|
||||
void* current_region = NULL;
|
||||
|
||||
struct fdl_result result;
|
||||
memset(&result, 0, sizeof(struct fdl_result));
|
||||
int res = ioctl(self->vmx_fdl_fd, KVM_VMX_FDL_GET_INDEX, &result);
|
||||
assert(!res);
|
||||
|
||||
//nyx_snapshot_nyx_fdl_unset_blocklisted_pages(self, shadow_memory_state, blocklist);
|
||||
|
||||
|
||||
for(uint8_t i = 0; i < result.num; i++){
|
||||
#ifdef SHOW_NUM_DIRTY_PAGES
|
||||
printf("Kernel -> [%d] %ld \t%ldKB\n", i, result.values[i], (0x1000*result.values[i])>>0x10);
|
||||
#endif
|
||||
|
||||
if(shadow_memory_state->tmp_snapshot.enabled){
|
||||
current_region = shadow_memory_state->ram_regions[i].incremental_region_ptr;
|
||||
}
|
||||
else{
|
||||
current_region = shadow_memory_state->ram_regions[i].snapshot_region_ptr;
|
||||
}
|
||||
|
||||
for(uint64_t j = 0; j < result.values[i]; j++){
|
||||
|
||||
uint64_t physical_addr = self->fdl_data2.entry[i].fdl_stack[j];
|
||||
uint64_t entry_offset_addr = physical_addr - shadow_memory_state->ram_regions[i].base;
|
||||
|
||||
void* host_addr = shadow_memory_state->ram_regions[i].host_region_ptr + entry_offset_addr;
|
||||
void* snapshot_addr = current_region + entry_offset_addr;
|
||||
|
||||
|
||||
// optimize this
|
||||
if(test_and_clear_bit((long)(entry_offset_addr>>12), (unsigned long*)self->fdl_data2.entry[i].fdl_bitmap) == 0 && snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
|
||||
#ifdef DEBUG_VERFIY_BITMAP
|
||||
if(!is_black_listed_addr(self, entry_offset_addr)){
|
||||
printf("WARNING: %s: -> %lx is not blacklisted\n", __func__, entry_offset_addr);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
printf("SKIP\n");
|
||||
continue; // blacklisted page
|
||||
}
|
||||
|
||||
memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
#ifdef RESET_VRAM
|
||||
//nyx_snapshot_nyx_fdl_restore_vram(self, shadow_memory_state);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
void nyx_snapshot_nyx_fdl_restore2(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
nyx_snapshot_nyx_fdl_unset_blocklisted_pages(self, shadow_memory_state, blocklist);
|
||||
|
||||
struct fdl_result result;
|
||||
memset(&result, 0, sizeof(struct fdl_result));
|
||||
int res = ioctl(self->vmx_fdl_fd, KVM_VMX_FDL_GET_INDEX, &result);
|
||||
assert(!res);
|
||||
|
||||
|
||||
for(uint8_t i = 0; i < result.num; i++){
|
||||
#ifdef SHOW_NUM_DIRTY_PAGES
|
||||
printf("Kernel -> [%d] %ld \t%ldKB\n", i, result.values[i], (0x1000*result.values[i])>>0x10);
|
||||
#endif
|
||||
for(uint64_t j = 0; j < result.values[i]; j++){
|
||||
uint64_t addr = self->fdl_data2.entry[i].fdl_stack[j];
|
||||
uint64_t offset_addr = addr - self->shadow_memory_state[i].base;
|
||||
|
||||
|
||||
if(test_and_clear_bit((long)(offset_addr>>12), (unsigned long*)self->fdl_data2.entry[i].fdl_bitmap) == 0){
|
||||
#ifdef DEBUG_VERFIY_BITMAP
|
||||
if(!is_black_listed_addr(self, offset_addr)){
|
||||
printf("WARNING: %s: -> %lx is not blacklisted\n", __func__, offset_addr);
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
continue; // blacklisted page
|
||||
}
|
||||
|
||||
//assert(test_and_clear_bit(offset_addr>>12, fdl_data2.entry[i].fdl_bitmap));
|
||||
//fdl_data2.entry[i].fdl_bitmap[(offset_addr/0x1000)/8] = 0;
|
||||
|
||||
//printf("DIRTY -> 0x%lx [BITMAP: %d] [%d]\n", addr, fdl_data2.entry[i].fdl_bitmap[(offset_addr/0x1000)/8], test_bit(offset_addr>>12, fdl_data2.entry[i].fdl_bitmap));
|
||||
|
||||
|
||||
if(shadow_memory_state->incremental_enabled){
|
||||
//memcpy((void*)(fdl_data2.entry[i].host_ptr+offset_addr), (void*)(self->tmp_snapshot.shadow_memory[i]+offset_addr), TARGET_PAGE_SIZE);
|
||||
memcpy((void*)(self->fdl_data2.entry[i].host_ptr+offset_addr), (void*)(self->fdl_data2.entry[i].tmp_shadow_ptr+offset_addr), TARGET_PAGE_SIZE);
|
||||
}
|
||||
else{
|
||||
memcpy((void*)(self->fdl_data2.entry[i].host_ptr+offset_addr), (void*)(self->fdl_data2.entry[i].shadow_ptr+offset_addr), TARGET_PAGE_SIZE);
|
||||
}
|
||||
}
|
||||
}
|
||||
#ifdef RESET_VRAM
|
||||
//nyx_snapshot_nyx_fdl_restore_vram(self, shadow_memory_state);
|
||||
#endif
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
|
||||
void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
|
||||
struct fdl_result result;
|
||||
memset(&result, 0, sizeof(struct fdl_result));
|
||||
int res = ioctl(self->vmx_fdl_fd, KVM_VMX_FDL_GET_INDEX, &result);
|
||||
assert(!res);
|
||||
|
||||
//nyx_snapshot_nyx_fdl_unset_blocklisted_pages(self, shadow_memory_state, blocklist);
|
||||
|
||||
for(uint8_t i = 0; i < result.num; i++){
|
||||
#ifdef SHOW_NUM_DIRTY_PAGES
|
||||
printf("Kernel -> [%d] %ld \t%ldKB\n", i, result.values[i], (0x1000*result.values[i])>>0x10);
|
||||
@ -294,7 +168,6 @@ void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t* self, shadow_memory_t* shad
|
||||
|
||||
void* host_addr = shadow_memory_state->ram_regions[i].host_region_ptr + entry_offset_addr;
|
||||
void* incremental_addr = shadow_memory_state->ram_regions[i].incremental_region_ptr + entry_offset_addr;
|
||||
//void* snapshot_addr = shadow_memory_state->ram_regions[i].snapshot_region_ptr + entry_offset_addr;
|
||||
|
||||
if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
|
||||
#ifdef DEBUG_VERFIY_BITMAP
|
||||
@ -303,10 +176,8 @@ void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t* self, shadow_memory_t* shad
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
//printf("SKIP\n");
|
||||
continue; // blacklisted page
|
||||
continue; // skip blacklisted page
|
||||
}
|
||||
//printf("%s -> %p <-- %p\n", __func__, incremental_addr, host_addr);
|
||||
|
||||
clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap);
|
||||
shadow_memory_track_dirty_root_pages(shadow_memory_state, entry_offset_addr, i);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nyx/snapshot/memory/block_list.h"
|
||||
#include "nyx/snapshot/memory/shadow_memory.h"
|
||||
|
||||
|
@ -1,6 +1,5 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
@ -23,12 +22,8 @@ snapshot_page_blocklist_t* snapshot_page_blocklist_init(void){
|
||||
snapshot_page_blocklist_t* self = malloc(sizeof(snapshot_page_blocklist_t));
|
||||
|
||||
uint64_t ram_size = get_ram_size();
|
||||
//printf("%s: ram_size: 0x%lx\n", __func__, ram_size);
|
||||
|
||||
self->phys_area_size = ram_size <= MEM_SPLIT_START ? ram_size : ram_size + (MEM_SPLIT_END-MEM_SPLIT_START);
|
||||
|
||||
//printf("%s: phys_area_size: 0x%lx\n", __func__, self->phys_area_size);
|
||||
|
||||
self->phys_bitmap = malloc(BITMAP_SIZE(self->phys_area_size));
|
||||
memset(self->phys_bitmap, 0x0, BITMAP_SIZE(self->phys_area_size));
|
||||
|
||||
|
@ -22,9 +22,6 @@ typedef struct snapshot_page_blocklist_s{
|
||||
uint64_t phys_area_size;
|
||||
}snapshot_page_blocklist_t;
|
||||
|
||||
|
||||
//snapshot_page_blocklist_t* snapshot_page_blocklist_init(shadow_memory_t* snapshot);
|
||||
|
||||
void snapshot_page_blocklist_add(snapshot_page_blocklist_t* self, uint64_t phys_addr);
|
||||
|
||||
/* returns true if phys_addr is on the blocklis */
|
||||
|
@ -1,10 +1,8 @@
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
#include "qemu/rcu_queue.h"
|
||||
#include "migration/migration.h"
|
||||
|
||||
#include "nyx/memory_access.h"
|
||||
@ -32,7 +30,6 @@ nyx_fdl_user_t* nyx_fdl_user_init(shadow_memory_t* shadow_memory_state){
|
||||
self->entry[i].stack = malloc(DIRTY_STACK_SIZE(shadow_memory_state->ram_regions[i].size));
|
||||
self->entry[i].bitmap = malloc(BITMAP_SIZE(shadow_memory_state->ram_regions[i].size));
|
||||
}
|
||||
//printf("%s -> %p\n", __func__, self);
|
||||
return self;
|
||||
}
|
||||
|
||||
@ -132,8 +129,6 @@ void nyx_fdl_user_set(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state
|
||||
break;
|
||||
}
|
||||
|
||||
//ram_area = FAST_IN_RANGE(addr, fdl_data2.entry[0].base, fdl_data2.entry[0].base+(fdl_data2.entry[0].size-1)) ? 0 : ram_area;
|
||||
|
||||
if(ram_area == 0xff){
|
||||
printf("ERROR: %s %lx [%d]\n", __func__, addr, ram_area);
|
||||
abort();
|
||||
@ -149,7 +144,7 @@ void nyx_fdl_user_set(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state
|
||||
|
||||
assert(self->entry[ram_area].bitmap);
|
||||
|
||||
/* todo -> better handling of nyx_fdl_state */
|
||||
/* TODO -> better handling of nyx_fdl_state */
|
||||
if(!test_bit(pfn, (const unsigned long*)self->entry[ram_area].bitmap)){
|
||||
set_bit(pfn, (unsigned long*)self->entry[ram_area].bitmap);
|
||||
|
||||
@ -185,7 +180,6 @@ void nyx_snapshot_nyx_fdl_user_save_root_pages(nyx_fdl_user_t* self, shadow_memo
|
||||
#ifdef DEBUG_USER_FDL
|
||||
printf("%s -> %p <-- %p\n", __func__, incremental_addr, host_addr);
|
||||
#endif
|
||||
//printf("%s -> %p <-- %p\n", __func__, incremental_addr, host_addr);
|
||||
|
||||
clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap);
|
||||
shadow_memory_track_dirty_root_pages(shadow_memory_state, entry_offset_addr, i);
|
||||
|
@ -6,6 +6,8 @@
|
||||
#include "nyx/snapshot/memory/shadow_memory.h"
|
||||
#include "nyx/snapshot/memory/backend/nyx_fdl.h"
|
||||
|
||||
#define MAX_REGIONS 8 /* don't */
|
||||
|
||||
typedef struct nyx_fdl_user_s{
|
||||
struct {
|
||||
uint64_t* stack;
|
||||
@ -18,8 +20,11 @@ typedef struct nyx_fdl_user_s{
|
||||
}nyx_fdl_user_t;
|
||||
|
||||
nyx_fdl_user_t* nyx_fdl_user_init(shadow_memory_t* shadow_memory_state);
|
||||
|
||||
void nyx_fdl_user_enable(nyx_fdl_user_t* self);
|
||||
|
||||
void nyx_fdl_user_set(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, nyx_fdl_t* nyx_fdl_state, uint64_t addr, uint64_t length);
|
||||
|
||||
uint32_t nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
|
||||
|
||||
void nyx_snapshot_nyx_fdl_user_save_root_pages(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
|
||||
|
@ -1,7 +1,6 @@
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
|
||||
#include "exec/ram_addr.h"
|
||||
@ -62,8 +61,6 @@ shadow_memory_t* shadow_memory_init(void){
|
||||
assert(!ftruncate(self->snapshot_ptr_fd, self->memory_size));
|
||||
fcntl(self->snapshot_ptr_fd, F_ADD_SEALS, F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);
|
||||
|
||||
//printf("MMAP -> 0x%lx\n", self->memory_size);
|
||||
|
||||
self->snapshot_ptr = mmap(NULL, self->memory_size, PROT_READ | PROT_WRITE , MAP_SHARED , self->snapshot_ptr_fd, 0);
|
||||
madvise(self->snapshot_ptr, self->memory_size, MADV_RANDOM | MADV_MERGEABLE);
|
||||
|
||||
@ -76,8 +73,6 @@ shadow_memory_t* shadow_memory_init(void){
|
||||
uint8_t regions_num = 0;
|
||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
||||
nyx_debug_p(RELOAD_PREFIX, "%lx %lx %lx\t%s\t%p", block->offset, block->used_length, block->max_length, block->idstr, block->host);
|
||||
//printf("%lx %lx %lx\t%s\t%p\n", block->offset, block->used_length, block->max_length, block->idstr, block->host);
|
||||
|
||||
block_array[i] = block;
|
||||
|
||||
memcpy(self->snapshot_ptr+offset, block->host, block->used_length);
|
||||
@ -108,7 +103,6 @@ shadow_memory_t* shadow_memory_init(void){
|
||||
self->ram_regions[self->ram_regions_num].size = block->used_length-MEM_SPLIT_START;
|
||||
self->ram_regions[self->ram_regions_num].offset = (snapshot_ptr_offset_array[i] + MEM_SPLIT_START) - snapshot_ptr_offset_array[0];
|
||||
self->ram_regions[self->ram_regions_num].host_region_ptr = block->host+MEM_SPLIT_START;
|
||||
//self->ram_regions[self->ram_regions_num].snapshot_region_ptr = self->ptr+self->ram_regions[self->ram_regions_num].offset;
|
||||
self->ram_regions[self->ram_regions_num].snapshot_region_ptr = snapshot_ptr_offset_array[i]+MEM_SPLIT_START;
|
||||
self->ram_regions[self->ram_regions_num].idstr = malloc(strlen(block->idstr) + 1);
|
||||
memset(self->ram_regions[self->ram_regions_num].idstr, 0, strlen(block->idstr) + 1);
|
||||
@ -169,9 +163,7 @@ shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, b
|
||||
|
||||
FILE* file_mem_meta = fopen (path_meta, "r");
|
||||
assert(file_mem_meta != NULL);
|
||||
|
||||
assert(fread(&head, sizeof(fast_reload_dump_head_t), 1, file_mem_meta) == 1);
|
||||
|
||||
fclose(file_mem_meta);
|
||||
|
||||
if(self->ram_regions_num != head.shadow_memory_regions){
|
||||
@ -202,13 +194,10 @@ shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, b
|
||||
}
|
||||
assert(self->memory_size == ftell(file_mem_dump));
|
||||
fseek(file_mem_dump, 0L, SEEK_SET);
|
||||
|
||||
fclose(file_mem_dump);
|
||||
|
||||
self->snapshot_ptr_fd = open(path_dump, O_RDONLY);
|
||||
//printf("self->snapshot_ptr_fd: %d\n", self->snapshot_ptr_fd);
|
||||
self->snapshot_ptr = mmap(0, self->memory_size, PROT_READ, MAP_SHARED, self->snapshot_ptr_fd, 0);
|
||||
//printf("TRY TO MMAP : %p\n", self->snapshot_ptr);
|
||||
|
||||
assert(self->snapshot_ptr != (void*)-1);
|
||||
madvise(self->snapshot_ptr, self->memory_size, MADV_MERGEABLE);
|
||||
@ -219,7 +208,6 @@ shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, b
|
||||
uint8_t regions_num = 0;
|
||||
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
|
||||
nyx_debug_p(RELOAD_PREFIX, "%lx %lx %lx\t%s\t%p", block->offset, block->used_length, block->max_length, block->idstr, block->host);
|
||||
//printf("%lx %lx %lx\t%s\t%p\n", block->offset, block->used_length, block->max_length, block->idstr, block->host);
|
||||
|
||||
block_array[i] = block;
|
||||
snapshot_ptr_offset_array[i++] = self->snapshot_ptr+offset;
|
||||
@ -250,7 +238,6 @@ shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, b
|
||||
self->ram_regions[self->ram_regions_num].size = block->used_length-MEM_SPLIT_START;
|
||||
self->ram_regions[self->ram_regions_num].offset = (snapshot_ptr_offset_array[i] + MEM_SPLIT_START) - snapshot_ptr_offset_array[0];
|
||||
self->ram_regions[self->ram_regions_num].host_region_ptr = block->host+MEM_SPLIT_START;
|
||||
//self->ram_regions[self->ram_regions_num].snapshot_region_ptr = self->ptr+self->ram_regions[self->ram_regions_num].offset;
|
||||
self->ram_regions[self->ram_regions_num].snapshot_region_ptr = snapshot_ptr_offset_array[i]+MEM_SPLIT_START;
|
||||
self->ram_regions[self->ram_regions_num].idstr = malloc(strlen(block->idstr) + 1);
|
||||
memset(self->ram_regions[self->ram_regions_num].idstr, 0, strlen(block->idstr) + 1);
|
||||
@ -272,21 +259,21 @@ shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, b
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SHADOW_MEMCPY_VERSION
|
||||
/* memcpy version */
|
||||
/*
|
||||
for(uint8_t i = 0; i < self->ram_regions_num; i++){
|
||||
void* host_addr = self->ram_regions[i].host_region_ptr + 0;
|
||||
void* snapshot_addr = self->ram_regions[i].snapshot_region_ptr + 0;
|
||||
memcpy(host_addr, snapshot_addr, self->ram_regions[i].size);
|
||||
}
|
||||
*/
|
||||
|
||||
#else
|
||||
/* munmap + mmap version */
|
||||
for(uint8_t i = 0; i < self->ram_regions_num; i++){
|
||||
void* host_addr = self->ram_regions[i].host_region_ptr + 0;
|
||||
assert(munmap(host_addr, self->ram_regions[i].size) != EINVAL);
|
||||
assert(mmap(host_addr, self->ram_regions[i].size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_FIXED, self->snapshot_ptr_fd, self->ram_regions[i].offset) != MAP_FAILED);
|
||||
}
|
||||
#endif
|
||||
|
||||
shadow_memory_init_generic(self);
|
||||
return self;
|
||||
@ -348,31 +335,6 @@ void shadow_memory_serialize(shadow_memory_t* self, const char* snapshot_folder)
|
||||
FILE* file_mem_meta = fopen(tmp1, "w+b");
|
||||
FILE* file_mem_data = fopen(tmp2, "w+b");
|
||||
|
||||
//} FILE* file_ptr_meta, FILE* file_ptr_data){
|
||||
|
||||
//assert(self);
|
||||
//assert(file_ptr_meta);
|
||||
//assert(file_ptr_data);
|
||||
/*
|
||||
nyx_debug("black_list_pages_num: %lx\n", self->black_list_pages_num);
|
||||
nyx_debug("black_list_pages_size: %lx\n", self->black_list_pages_size);
|
||||
nyx_debug("black_list_pages ...\n");
|
||||
for (uint64_t i = 0; i < self->black_list_pages_num; i++ ){
|
||||
nyx_debug("self->black_list_pages[%ld] = %lx\n", i, self->black_list_pages[i]);
|
||||
}
|
||||
*/
|
||||
|
||||
//printf("shadow_memory_regions: %d\n", self->ram_regions_num);
|
||||
//nyx_debug("ram_region_index: %d\n", self->ram_region_index);
|
||||
|
||||
/*
|
||||
for (uint32_t i = 0; i < self->ram_regions_num; i++){
|
||||
printf("self->shadow_memory[%d] = %lx %s\n", i, self->ram_regions[i].base, self->ram_regions[i].idstr);
|
||||
}
|
||||
|
||||
printf("ram_size: %lx\n", self->memory_size);
|
||||
*/
|
||||
|
||||
fast_reload_dump_head_t head;
|
||||
fast_reload_dump_entry_t entry;
|
||||
|
||||
|
@ -73,8 +73,6 @@ void shadow_memory_switch_snapshot(shadow_memory_t* self, bool incremental);
|
||||
|
||||
void shadow_memory_restore_memory(shadow_memory_t* self);
|
||||
|
||||
//void shadow_memory_prepare_incremental_snapshot(shadow_memory_t* self);
|
||||
|
||||
static inline void shadow_memory_track_dirty_root_pages(shadow_memory_t* self, uint64_t address, uint8_t slot){
|
||||
if(unlikely(self->root_track_pages_num >= self->root_track_pages_size)){
|
||||
self->root_track_pages_size <<= 2;
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/memory_access.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void serialize_state(const char* filename_prefix, bool is_pre_snapshot){
|
||||
nyx_trace();
|
||||
@ -80,7 +81,6 @@ void deserialize_state(const char* filename_prefix){
|
||||
if(fp == NULL) {
|
||||
nyx_debug("[%s] Could not open file %s.\n", __func__, tmp);
|
||||
assert(false);
|
||||
//exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
|
||||
|
@ -19,6 +19,11 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/memory_access.h"
|
||||
@ -177,9 +182,6 @@ void enable_fast_reloads(void){
|
||||
void init_page_cache(char* path){
|
||||
assert(global_state.page_cache == NULL);
|
||||
global_state.page_cache = page_cache_new((CPUState *)qemu_get_cpu(0), path);
|
||||
#ifdef STATE_VERBOSE
|
||||
nyx_debug("\n\nINIT PAGE_CACHE => %s\n", path);
|
||||
#endif
|
||||
}
|
||||
|
||||
page_cache_t* get_page_cache(void){
|
||||
@ -201,8 +203,10 @@ static void* alloc_auxiliary_buffer(const char* file){
|
||||
void* ptr;
|
||||
struct stat st;
|
||||
int fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
|
||||
|
||||
assert(ftruncate(fd, AUX_BUFFER_SIZE) == 0);
|
||||
stat(file, &st);
|
||||
|
||||
nyx_debug_p(INTERFACE_PREFIX, "new aux buffer file: (max size: %x) %lx", AUX_BUFFER_SIZE, st.st_size);
|
||||
|
||||
assert(AUX_BUFFER_SIZE == st.st_size);
|
||||
|
@ -4,7 +4,6 @@
|
||||
#include "nyx/fast_vm_reload.h"
|
||||
#include "qemu-common.h"
|
||||
#include "qemu/osdep.h"
|
||||
#include "target/i386/cpu.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "nyx/debug.h"
|
||||
@ -28,6 +27,7 @@ volatile bool synchronization_kvm_loop_waiting = false;
|
||||
|
||||
/* SIGALRM based timeout detection */
|
||||
//#define DEBUG_TIMEOUT_DETECTOR
|
||||
|
||||
void init_timeout_detector(timeout_detector_t* timer){
|
||||
timer->kvm_tid = 0;
|
||||
timer->detection_enabled = false;
|
||||
@ -100,7 +100,6 @@ void arm_sigprof_timer(timeout_detector_t* timer){
|
||||
fprintf(stderr, "Attempting to re-arm an expired timer! => reset(%ld.%ld)\n",
|
||||
timer->config.tv_sec, timer->config.tv_usec);
|
||||
reset_timeout_detector(timer);
|
||||
//return true;
|
||||
}
|
||||
assert(setitimer(ITIMER_REAL, &timer->alarm, NULL) == 0);
|
||||
}
|
||||
@ -145,7 +144,6 @@ void unblock_signals(void){
|
||||
sigaddset(&set, SIGSEGV);
|
||||
sigaddset(&set, SIGALRM);
|
||||
sigprocmask(SIG_UNBLOCK, &set, NULL);
|
||||
//fprintf(stderr, "%s!\n", __func__);
|
||||
}
|
||||
|
||||
/* -------------------- */
|
||||
@ -191,7 +189,6 @@ void synchronization_unlock(void){
|
||||
|
||||
pthread_mutex_lock(&synchronization_lock_mutex);
|
||||
pthread_cond_signal(&synchronization_lock_condition);
|
||||
//hypercall_reset_hprintf_counter();
|
||||
pthread_mutex_unlock(&synchronization_lock_mutex);
|
||||
}
|
||||
|
||||
@ -199,8 +196,6 @@ void synchronization_unlock(void){
|
||||
uint64_t run_counter = 0;
|
||||
bool in_fuzzing_loop = false;
|
||||
|
||||
//bool last_timeout = false;
|
||||
|
||||
void synchronization_lock_hprintf(void){
|
||||
pthread_mutex_lock(&synchronization_lock_mutex);
|
||||
interface_send_char(NYX_INTERFACE_PING);
|
||||
@ -243,8 +238,6 @@ void synchronization_lock(void){
|
||||
kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
|
||||
}
|
||||
|
||||
//last_timeout = false;
|
||||
|
||||
if(unlikely(GET_GLOBAL_STATE()->in_redqueen_reload_mode)) {
|
||||
fsync_redqueen_files();
|
||||
}
|
||||
@ -260,20 +253,12 @@ void synchronization_lock(void){
|
||||
|
||||
check_auxiliary_config_buffer(GET_GLOBAL_STATE()->auxilary_buffer, &GET_GLOBAL_STATE()->shadow_config);
|
||||
|
||||
//set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 1);
|
||||
if (GET_GLOBAL_STATE()->starved == true)
|
||||
set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 2);
|
||||
else
|
||||
set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 1);
|
||||
|
||||
GET_GLOBAL_STATE()->pt_trace_size = 0;
|
||||
/*
|
||||
if(GET_GLOBAL_STATE()->dump_page){
|
||||
fprintf(stderr, "DISABLING TIMEOUT DETECTION\n");
|
||||
disable_timeout_detector(&(GET_GLOBAL_STATE()->timeout_detector));
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
static void perform_reload(void){
|
||||
@ -303,8 +288,6 @@ void synchronization_lock_crash_found(void){
|
||||
|
||||
perform_reload();
|
||||
|
||||
//synchronization_lock();
|
||||
|
||||
in_fuzzing_loop = false;
|
||||
}
|
||||
|
||||
@ -322,8 +305,6 @@ void synchronization_lock_asan_found(void){
|
||||
|
||||
perform_reload();
|
||||
|
||||
//synchronization_lock();
|
||||
|
||||
in_fuzzing_loop = false;
|
||||
}
|
||||
|
||||
@ -360,7 +341,6 @@ void synchronization_lock_shutdown_detected(void){
|
||||
perform_reload();
|
||||
|
||||
in_fuzzing_loop = false;
|
||||
//synchronization_lock();
|
||||
}
|
||||
|
||||
void synchronization_payload_buffer_write_detected(void){
|
||||
@ -381,7 +361,6 @@ void synchronization_payload_buffer_write_detected(void){
|
||||
perform_reload();
|
||||
|
||||
in_fuzzing_loop = false;
|
||||
//synchronization_lock();
|
||||
}
|
||||
|
||||
void synchronization_cow_full_detected(void){
|
||||
@ -396,20 +375,13 @@ void synchronization_cow_full_detected(void){
|
||||
perform_reload();
|
||||
|
||||
in_fuzzing_loop = false;
|
||||
//synchronization_lock();
|
||||
}
|
||||
|
||||
void synchronization_disable_pt(CPUState *cpu){
|
||||
//fprintf(stderr, "==============> %s\n", __func__);
|
||||
// nyx_trace();
|
||||
if(!in_fuzzing_loop){
|
||||
//fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP]\n", getpid(), run_counter, __func__);
|
||||
set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 0);
|
||||
/*
|
||||
qemu_backtrace();
|
||||
while(1){
|
||||
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
pt_disable(qemu_get_cpu(0), false);
|
||||
@ -423,9 +395,6 @@ void synchronization_disable_pt(CPUState *cpu){
|
||||
set_result_pt_trace_size(GET_GLOBAL_STATE()->auxilary_buffer, GET_GLOBAL_STATE()->pt_trace_size);
|
||||
set_result_bb_coverage(GET_GLOBAL_STATE()->auxilary_buffer, GET_GLOBAL_STATE()->bb_coverage);
|
||||
|
||||
|
||||
|
||||
|
||||
in_fuzzing_loop = false;
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include <linux/kvm.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
typedef struct timeout_detector_s {
|
||||
int kvm_tid;
|
||||
|
@ -1,10 +1,13 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "state/state.h"
|
||||
#include "trace_dump.h"
|
||||
#include "nyx/debug.h"
|
||||
#include "nyx/state/state.h"
|
||||
#include "nyx/trace_dump.h"
|
||||
|
||||
/* dump PT trace as returned from HW */
|
||||
|
||||
@ -21,7 +24,7 @@ void pt_trace_dump_init(char* filename)
|
||||
{
|
||||
int test_fd;
|
||||
|
||||
//fprintf(stderr, "Enable pt trace dump at %s", filename);
|
||||
nyx_debug("Enable pt trace dump at %s", filename);
|
||||
pt_dump_initialized = true;
|
||||
|
||||
test_fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
|
||||
@ -55,7 +58,6 @@ void pt_write_pt_dump_file(uint8_t *data, size_t bytes)
|
||||
return;
|
||||
|
||||
fd = open(pt_trace_dump_filename, O_APPEND|O_WRONLY, 0644);
|
||||
//fd = open(pt_trace_dump_filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Error writing pt_trace_dump to %s: %s\n", pt_trace_dump_filename, strerror(errno));
|
||||
assert(0);
|
||||
|
@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void pt_trace_dump_init(char* filename);
|
||||
void pt_trace_dump_enable(bool enable);
|
||||
void pt_write_pt_dump_file(uint8_t *data, size_t bytes);
|
||||
|
Loading…
x
Reference in New Issue
Block a user