diff --git a/accel/kvm/kvm-all.c b/accel/kvm/kvm-all.c
index b39c4cd5b9..a02c540959 100644
--- a/accel/kvm/kvm-all.c
+++ b/accel/kvm/kvm-all.c
@@ -48,15 +48,15 @@
#ifdef QEMU_NYX
// clang-format on
-#include "nyx/pt.h"
-#include "nyx/hypercall/hypercall.h"
-#include "nyx/synchronization.h"
#include "nyx/debug.h"
-#include "nyx/state/state.h"
-#include "nyx/interface.h"
#include "nyx/fast_vm_reload_sync.h"
-#include "nyx/snapshot/memory/backend/nyx_dirty_ring.h"
#include "nyx/helpers.h"
+#include "nyx/hypercall/hypercall.h"
+#include "nyx/interface.h"
+#include "nyx/pt.h"
+#include "nyx/snapshot/memory/backend/nyx_dirty_ring.h"
+#include "nyx/state/state.h"
+#include "nyx/synchronization.h"
// clang-format off
#endif
@@ -93,7 +93,7 @@ struct KVMState
AccelState parent_obj;
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
bool nyx_no_pt_mode;
// clang-format off
#endif
@@ -387,12 +387,14 @@ static int kvm_get_vcpu(KVMState *s, unsigned long vcpu_id)
#ifdef QEMU_NYX
// clang-format on
-int kvm_get_vm_fd(KVMState *s){
+int kvm_get_vm_fd(KVMState *s)
+{
return s->vmfd;
}
-KVMMemoryListener* kvm_get_kml(int as_id){
- return kvm_state->as[as_id].ml;
+KVMMemoryListener *kvm_get_kml(int as_id)
+{
+ return kvm_state->as[as_id].ml;
}
// clang-format off
#endif
@@ -416,9 +418,9 @@ int kvm_init_vcpu(CPUState *cpu)
cpu->vcpu_dirty = true;
#ifdef QEMU_NYX
-// clang-format on
- if(s->nyx_no_pt_mode){
- if(!getenv("NYX_DISABLE_DIRTY_RING")){
+ // clang-format on
+ if (s->nyx_no_pt_mode) {
+ if (!getenv("NYX_DISABLE_DIRTY_RING")) {
nyx_dirty_ring_pre_init(cpu->kvm_fd, s->vmfd);
}
}
@@ -450,7 +452,7 @@ int kvm_init_vcpu(CPUState *cpu)
ret = kvm_arch_init_vcpu(cpu);
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
unblock_signals();
// clang-format off
#endif
@@ -1928,28 +1930,34 @@ static int kvm_init(MachineState *ms)
goto err;
}
#ifdef QEMU_NYX
-// clang-format on
- if (ioctl(s->fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_PT) != 1 && ioctl(s->fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_FDL) != 1) {
-
+ // clang-format on
+ if (ioctl(s->fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_PT) != 1 &&
+ ioctl(s->fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_FDL) != 1)
+ {
/* fallback -> use vanilla KVM module instead (no Intel-PT tracing or nested hypercalls at this point) */
- fprintf(stderr, "[QEMU-Nyx] Could not access KVM-PT kernel module!\n[QEMU-Nyx] Trying vanilla KVM...\n");
+ fprintf(stderr, "[QEMU-Nyx] Could not access KVM-PT kernel "
+ "module!\n[QEMU-Nyx] Trying vanilla KVM...\n");
if (s->fd == -1) {
- fprintf(stderr, "[QEMU-Nyx] Error: NYX fallback failed: Could not access vanilla KVM module!\n");
+ fprintf(stderr, "[QEMU-Nyx] Error: NYX fallback failed: Could not "
+ "access vanilla KVM module!\n");
ret = -errno;
goto err;
}
int ret_val = ioctl(s->fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
- if(ret_val == -1 || ret_val == 0){
- fprintf(stderr, "[QEMU-Nyx] Error: NYX requires support for KVM_CAP_DIRTY_LOG_RING in fallback mode!\n");
+ if (ret_val == -1 || ret_val == 0) {
+ fprintf(stderr, "[QEMU-Nyx] Error: NYX requires support for "
+ "KVM_CAP_DIRTY_LOG_RING in fallback mode!\n");
ret = -errno;
goto err;
}
/* check for vmware_backdoor support */
int fd = open("/sys/module/kvm/parameters/enable_vmware_backdoor", O_RDONLY);
- if(fd == -1){
- fprintf(stderr, "ERROR: /sys/module/kvm/parameters/enable_vmware_backdoor file not found...\n");
+ if (fd == -1) {
+ fprintf(stderr,
+ "ERROR: /sys/module/kvm/parameters/enable_vmware_backdoor file "
+ "not found...\n");
ret = -errno;
goto err;
}
@@ -1958,28 +1966,32 @@ static int kvm_init(MachineState *ms)
assert(read(fd, &vmware_backdoor_option, 1) == 1);
close(fd);
- if(vmware_backdoor_option == 'N'){
- fprintf(stderr, "\n[QEMU-Nyx] ERROR: vmware backdoor is not enabled...\n");
+ if (vmware_backdoor_option == 'N') {
+ fprintf(stderr,
+ "\n[QEMU-Nyx] ERROR: vmware backdoor is not enabled...\n");
fprintf(stderr, "\n\tRun the following commands to fix the issue:\n");
fprintf(stderr, "\t-----------------------------------------\n");
fprintf(stderr, "\tsudo modprobe -r kvm-intel\n");
fprintf(stderr, "\tsudo modprobe -r kvm\n");
fprintf(stderr, "\tsudo modprobe kvm enable_vmware_backdoor=y\n");
fprintf(stderr, "\tsudo modprobe kvm-intel\n");
- fprintf(stderr, "\tcat /sys/module/kvm/parameters/enable_vmware_backdoor\n");
+ fprintf(stderr,
+ "\tcat /sys/module/kvm/parameters/enable_vmware_backdoor\n");
fprintf(stderr, "\t-----------------------------------------\n\n");
ret = -errno;
goto err;
}
- fprintf(stderr, "[QEMU-Nyx] NYX runs in fallback mode (no Intel-PT tracing or nested hypercall support)!\n");
- s->nyx_no_pt_mode = true;
+ fprintf(stderr, "[QEMU-Nyx] NYX runs in fallback mode (no Intel-PT tracing "
+ "or nested hypercall support)!\n");
+ s->nyx_no_pt_mode = true;
GET_GLOBAL_STATE()->nyx_fdl = false;
- GET_GLOBAL_STATE()->pt_trace_mode = false; // Intel PT is not available in this mode
- fast_reload_set_mode(get_fast_reload_snapshot(), RELOAD_MEMORY_MODE_DIRTY_RING);
- }
- else{
- s->nyx_no_pt_mode = false;
+ GET_GLOBAL_STATE()->pt_trace_mode =
+ false; // Intel PT is not available in this mode
+ fast_reload_set_mode(get_fast_reload_snapshot(),
+ RELOAD_MEMORY_MODE_DIRTY_RING);
+ } else {
+ s->nyx_no_pt_mode = false;
GET_GLOBAL_STATE()->nyx_fdl = true;
fast_reload_set_mode(get_fast_reload_snapshot(), RELOAD_MEMORY_MODE_FDL);
}
@@ -2050,13 +2062,16 @@ static int kvm_init(MachineState *ms)
s->vmfd = ret;
#ifdef QEMU_NYX
-// clang-format on
- if(s->nyx_no_pt_mode){
- if(getenv("NYX_DISABLE_DIRTY_RING")){
- fprintf(stderr, "WARNING: Nyx has disabled KVM's dirty-ring (required to enable full VGA support during pre-snapshot creation procedure)\n");
- fast_reload_set_mode(get_fast_reload_snapshot(), RELOAD_MEMORY_MODE_DEBUG_QUIET); /* required to create snapshot */
- }
- else{
+ // clang-format on
+ if (s->nyx_no_pt_mode) {
+ if (getenv("NYX_DISABLE_DIRTY_RING")) {
+ fprintf(stderr,
+ "WARNING: Nyx has disabled KVM's dirty-ring (required to enable "
+ "full VGA support during pre-snapshot creation procedure)\n");
+ fast_reload_set_mode(
+ get_fast_reload_snapshot(),
+ RELOAD_MEMORY_MODE_DEBUG_QUIET); /* required to create snapshot */
+ } else {
nyx_dirty_ring_early_init(s->fd, s->vmfd);
}
}
@@ -2105,11 +2120,10 @@ static int kvm_init(MachineState *ms)
#ifndef QEMU_NYX
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, 1);
#else
-// clang-format on
- if(s->nyx_no_pt_mode){
+ // clang-format on
+ if (s->nyx_no_pt_mode) {
ret = kvm_vm_enable_cap(s, KVM_CAP_MANUAL_DIRTY_LOG_PROTECT2, 0, 1);
- }
- else{
+ } else {
ret = 0;
}
// clang-format off
@@ -2405,13 +2419,14 @@ static void kvm_eat_signals(CPUState *cpu)
#ifdef QEMU_NYX
// clang-format on
-static int handle_vmware_hypercall(struct kvm_run *run, CPUState *cpu){
- kvm_arch_get_registers_fast(cpu);
+static int handle_vmware_hypercall(struct kvm_run *run, CPUState *cpu)
+{
+ kvm_arch_get_registers_fast(cpu);
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
- return handle_kafl_hypercall(run, cpu, env->regs[R_EBX]+100, env->regs[R_ECX]);
+ return handle_kafl_hypercall(run, cpu, env->regs[R_EBX] + 100, env->regs[R_ECX]);
}
// clang-format off
#endif
@@ -2432,10 +2447,10 @@ int kvm_cpu_exec(CPUState *cpu)
cpu_exec_start(cpu);
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
static bool timeout_reload_pending = false;
- if(timeout_reload_pending){
- synchronization_lock_timeout_found();
+ if (timeout_reload_pending) {
+ synchronization_lock_timeout_found();
}
timeout_reload_pending = false;
// clang-format off
@@ -2462,8 +2477,8 @@ int kvm_cpu_exec(CPUState *cpu)
}
#ifdef QEMU_NYX
-// clang-format on
- if(!kvm_state->nyx_no_pt_mode){
+ // clang-format on
+ if (!kvm_state->nyx_no_pt_mode) {
pt_pre_kvm_run(cpu);
}
// clang-format off
@@ -2475,7 +2490,7 @@ int kvm_cpu_exec(CPUState *cpu)
smp_rmb();
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
arm_sigprof_timer(&GET_GLOBAL_STATE()->timeout_detector);
// clang-format off
#endif
@@ -2483,8 +2498,8 @@ int kvm_cpu_exec(CPUState *cpu)
run_ret = kvm_vcpu_ioctl(cpu, KVM_RUN, 0);
#ifdef QEMU_NYX
-// clang-format on
- if (disarm_sigprof_timer(&GET_GLOBAL_STATE()->timeout_detector)){
+ // clang-format on
+ if (disarm_sigprof_timer(&GET_GLOBAL_STATE()->timeout_detector)) {
timeout_reload_pending = true;
}
// clang-format off
@@ -2493,10 +2508,10 @@ int kvm_cpu_exec(CPUState *cpu)
attrs = kvm_arch_post_run(cpu, run);
#ifdef QEMU_NYX
-// clang-format on
- if(!kvm_state->nyx_no_pt_mode){
- pt_post_kvm_run(cpu);
- }
+ // clang-format on
+ if (!kvm_state->nyx_no_pt_mode) {
+ pt_post_kvm_run(cpu);
+ }
// clang-format off
#endif
@@ -2522,24 +2537,25 @@ int kvm_cpu_exec(CPUState *cpu)
fprintf(stderr, "error: kvm run failed %s\n",
strerror(-run_ret));
#else
-// clang-format on
- if(run_ret == -EFAULT){
- if(GET_GLOBAL_STATE()->protect_payload_buffer){
- if (GET_GLOBAL_STATE()->in_fuzzing_mode){
+ // clang-format on
+ if (run_ret == -EFAULT) {
+ if (GET_GLOBAL_STATE()->protect_payload_buffer) {
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
/* Fuzzing is enabled at this point -> don't exit */
synchronization_payload_buffer_write_detected();
ret = 0;
break;
- }
- else{
- fprintf(stderr, "ERROR: invalid write to input buffer detected before harness was ready (write protection is enabled)!\n");
+ } else {
+ fprintf(
+ stderr,
+ "ERROR: invalid write to input buffer detected before "
+ "harness was ready (write protection is enabled)!\n");
exit(1);
}
}
}
- fprintf(stderr, "QEMU-PT: error: kvm run failed %s\n",
- strerror(-run_ret));
+ fprintf(stderr, "QEMU-PT: error: kvm run failed %s\n", strerror(-run_ret));
qemu_backtrace();
// clang-format off
#endif
@@ -2562,8 +2578,10 @@ int kvm_cpu_exec(CPUState *cpu)
DPRINTF("handle_io\n");
#ifdef QEMU_NYX
-// clang-format on
- if(run->io.port == 0x5658 && run->io.size == 4 && *((uint32_t*)((uint8_t *)run + run->io.data_offset)) == 0x8080801f) {
+ // clang-format on
+ if (run->io.port == 0x5658 && run->io.size == 4 &&
+ *((uint32_t *)((uint8_t *)run + run->io.data_offset)) == 0x8080801f)
+ {
assert(kvm_state->nyx_no_pt_mode);
ret = handle_vmware_hypercall(run, cpu);
break;
@@ -2598,20 +2616,23 @@ int kvm_cpu_exec(CPUState *cpu)
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
ret = EXCP_INTERRUPT;
#else
-// clang-format on
- if(GET_GLOBAL_STATE()->in_fuzzing_mode){
+ // clang-format on
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
#define CONFIG_KVM_EXIT_SHUTODWN_IS_PANIC // consider triple-fault etc as crash?
#ifndef CONFIG_KVM_EXIT_SHUTODWN_IS_PANIC
/* Fuzzing is enabled at this point -> don't exit */
- fprintf(stderr, "Got KVM_EXIT_SHUTDOWN while in fuzzing mode => reload\n",);
- handle_hypercall_kafl_release(run, cpu, (uint64_t)run->hypercall.args[0]);
- ret = 0;
+ fprintf(stderr,
+ "Got KVM_EXIT_SHUTDOWN while in fuzzing mode => reload\n", );
+ handle_hypercall_kafl_release(run, cpu,
+ (uint64_t)run->hypercall.args[0]);
+ ret = 0;
#else
- nyx_debug("Got KVM_EXIT_SHUTDOWN while in fuzzing mode => panic\n");
- handle_hypercall_kafl_panic(run, cpu, (uint64_t)run->hypercall.args[0]);
- ret = 0;
+ nyx_debug("Got KVM_EXIT_SHUTDOWN while in fuzzing mode => panic\n");
+ handle_hypercall_kafl_panic(run, cpu,
+ (uint64_t)run->hypercall.args[0]);
+ ret = 0;
#endif
- } else{
+ } else {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
ret = EXCP_INTERRUPT;
}
@@ -2623,7 +2644,7 @@ int kvm_cpu_exec(CPUState *cpu)
(uint64_t)run->hw.hardware_exit_reason);
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
assert(false);
// clang-format off
#endif
@@ -2635,27 +2656,28 @@ int kvm_cpu_exec(CPUState *cpu)
break;
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
case KVM_EXIT_DIRTY_RING_FULL:
- //printf("[*] WARNING: KVM_EXIT_DIRTY_RING_FULL\n");
+ // printf("[*] WARNING: KVM_EXIT_DIRTY_RING_FULL\n");
fast_reload_handle_dirty_ring_full(get_fast_reload_snapshot());
ret = 0;
break;
- case KVM_EXIT_KAFL_ACQUIRE ... (KVM_EXIT_KAFL_ACQUIRE+100):
- ret = handle_kafl_hypercall(run, cpu, (uint64_t)run->exit_reason, (uint64_t)run->hypercall.args[0]);
+ case KVM_EXIT_KAFL_ACQUIRE ...(KVM_EXIT_KAFL_ACQUIRE + 100):
+ ret = handle_kafl_hypercall(run, cpu, (uint64_t)run->exit_reason,
+ (uint64_t)run->hypercall.args[0]);
break;
-
+
case KVM_EXIT_DEBUG:
- kvm_arch_get_registers(cpu);
- if(!handle_hypercall_kafl_hook(run, cpu, (uint64_t)run->hypercall.args[0])){
- ret = kvm_arch_handle_exit(cpu, run);
- }
- else {
- ret = 0;
- }
- break;
-// clang-format off
+ kvm_arch_get_registers(cpu);
+ if (!handle_hypercall_kafl_hook(run, cpu, (uint64_t)run->hypercall.args[0]))
+ {
+ ret = kvm_arch_handle_exit(cpu, run);
+ } else {
+ ret = 0;
+ }
+ break;
+// clang-format off
#endif
case KVM_EXIT_SYSTEM_EVENT:
@@ -2665,14 +2687,16 @@ int kvm_cpu_exec(CPUState *cpu)
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
ret = EXCP_INTERRUPT;
#else
-// clang-format on
- fprintf(stderr, "ATTEMPT TO SHUTDOWN MACHINE (KVM_SYSTEM_EVENT_SHUTDOWN)!\n");
- if(GET_GLOBAL_STATE()->in_fuzzing_mode){
+ // clang-format on
+ fprintf(
+ stderr,
+ "ATTEMPT TO SHUTDOWN MACHINE (KVM_SYSTEM_EVENT_SHUTDOWN)!\n");
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
/* Fuzzing is enabled at this point -> don't exit */
- handle_hypercall_kafl_release(run, cpu, (uint64_t)run->hypercall.args[0]);
+ handle_hypercall_kafl_release(run, cpu,
+ (uint64_t)run->hypercall.args[0]);
ret = 0;
- }
- else{
+ } else {
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
ret = EXCP_INTERRUPT;
}
@@ -2684,14 +2708,15 @@ int kvm_cpu_exec(CPUState *cpu)
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
ret = EXCP_INTERRUPT;
#else
-// clang-format on
- fprintf(stderr, "ATTEMPT TO SHUTDOWN MACHINE (KVM_SYSTEM_EVENT_RESET)!\n");
- if(GET_GLOBAL_STATE()->in_fuzzing_mode){
+ // clang-format on
+ fprintf(stderr,
+ "ATTEMPT TO SHUTDOWN MACHINE (KVM_SYSTEM_EVENT_RESET)!\n");
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
/* Fuzzing is enabled at this point -> don't exit */
- handle_hypercall_kafl_release(run, cpu, (uint64_t)run->hypercall.args[0]);
+ handle_hypercall_kafl_release(run, cpu,
+ (uint64_t)run->hypercall.args[0]);
ret = 0;
- }
- else{
+ } else {
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
ret = EXCP_INTERRUPT;
}
@@ -2706,14 +2731,15 @@ int kvm_cpu_exec(CPUState *cpu)
qemu_mutex_unlock_iothread();
ret = 0;
#else
-// clang-format on
- fprintf(stderr, "ATTEMPT TO SHUTDOWN MACHINE (KVM_SYSTEM_EVENT_CRASH)!\n");
- if(GET_GLOBAL_STATE()->in_fuzzing_mode){
+ // clang-format on
+ fprintf(stderr,
+ "ATTEMPT TO SHUTDOWN MACHINE (KVM_SYSTEM_EVENT_CRASH)!\n");
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
/* Fuzzing is enabled at this point -> don't exit */
- handle_hypercall_kafl_release(run, cpu, (uint64_t)run->hypercall.args[0]);
+ handle_hypercall_kafl_release(run, cpu,
+ (uint64_t)run->hypercall.args[0]);
ret = 0;
- }
- else{
+ } else {
kvm_cpu_synchronize_state(cpu);
qemu_mutex_lock_iothread();
qemu_system_guest_panicked(cpu_get_crash_info(cpu));
@@ -2736,14 +2762,15 @@ int kvm_cpu_exec(CPUState *cpu)
// clang-format on
#define CONFIG_UNKNOWN_ERROR_IS_PANIC
#ifndef CONFIG_UNKNOWN_ERROR_IS_PANIC
- fprintf(stderr, "Unknown exit code (%d) => ABORT\n", run->exit_reason);
- ret = kvm_arch_handle_exit(cpu, run);
+ fprintf(stderr, "Unknown exit code (%d) => ABORT\n", run->exit_reason);
+ ret = kvm_arch_handle_exit(cpu, run);
assert(ret == 0);
#else
nyx_debug("kvm_arch_handle_exit(%d) => panic\n", run->exit_reason);
- ret = kvm_arch_handle_exit(cpu, run);
- if (ret != 0)
- handle_hypercall_kafl_panic(run, cpu, (uint64_t)run->hypercall.args[0]);
+ ret = kvm_arch_handle_exit(cpu, run);
+ if (ret != 0)
+ handle_hypercall_kafl_panic(run, cpu,
+ (uint64_t)run->hypercall.args[0]);
#endif
// clang-format off
#endif
@@ -2751,31 +2778,35 @@ int kvm_cpu_exec(CPUState *cpu)
break;
}
-#ifdef QEMU_NYX
-// clang-format on
- if(GET_GLOBAL_STATE()->in_fuzzing_mode && GET_GLOBAL_STATE()->cow_cache_full){
+#ifdef QEMU_NYX
+ // clang-format on
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode && GET_GLOBAL_STATE()->cow_cache_full)
+ {
synchronization_cow_full_detected();
GET_GLOBAL_STATE()->cow_cache_full = false;
- ret = 0;
- }
- else{
- if(GET_GLOBAL_STATE()->in_fuzzing_mode && cpu->halted){
+ ret = 0;
+ } else {
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode && cpu->halted) {
fprintf(stderr, "%s: Attempt to halt CPU -> FUCK OFF!\n", __func__);
- cpu->halted = 0;
+ cpu->halted = 0;
GET_GLOBAL_STATE()->shutdown_requested = true;
}
- if(GET_GLOBAL_STATE()->in_fuzzing_mode && GET_GLOBAL_STATE()->shutdown_requested){
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode &&
+ GET_GLOBAL_STATE()->shutdown_requested)
+ {
/* Fuzzing is enabled at this point -> don't exit */
- fprintf(stderr, "shutdown_requested -> calling handle_hypercall_kafl_release\n");
+ fprintf(
+ stderr,
+ "shutdown_requested -> calling handle_hypercall_kafl_release\n");
- //synchronization_lock_shutdown_detected();
+ // synchronization_lock_shutdown_detected();
synchronization_lock_crash_found();
GET_GLOBAL_STATE()->shutdown_requested = false;
- ret = 0;
+ ret = 0;
}
}
- if(reload_request_exists(GET_GLOBAL_STATE()->reload_state)){
+ if (reload_request_exists(GET_GLOBAL_STATE()->reload_state)) {
break;
}
// clang-format off
@@ -2788,7 +2819,7 @@ int kvm_cpu_exec(CPUState *cpu)
if (ret < 0) {
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
fprintf(stderr, "ATTEMPT TO SHUTDOWN MACHINE (ret < 0)!\n");
// clang-format off
#endif
@@ -2799,8 +2830,8 @@ int kvm_cpu_exec(CPUState *cpu)
atomic_set(&cpu->exit_request, 0);
#ifdef QEMU_NYX
-// clang-format on
- if(check_if_relood_request_exists_pre(GET_GLOBAL_STATE()->reload_state)){
+ // clang-format on
+ if (check_if_relood_request_exists_pre(GET_GLOBAL_STATE()->reload_state)) {
pause_all_vcpus(); /* performance boost ??? */
}
// clang-format off
@@ -3203,7 +3234,7 @@ void kvm_init_cpu_signals(CPUState *cpu)
#endif
sigdelset(&set, SIG_IPI);
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
sigdelset(&set, SIGALRM);
// clang-format off
#endif
diff --git a/nyx/auxiliary_buffer.c b/nyx/auxiliary_buffer.c
index 877e7ddf4f..5da12bf451 100644
--- a/nyx/auxiliary_buffer.c
+++ b/nyx/auxiliary_buffer.c
@@ -19,259 +19,309 @@ along with QEMU-PT. If not, see .
*/
-#include
-#include
-#include
#include "qemu/osdep.h"
#include "nyx/auxiliary_buffer.h"
-#include "nyx/state/state.h"
#include "nyx/debug.h"
+#include "nyx/state/state.h"
#include "nyx/trace_dump.h"
+#include
+#include
+#include
/* experimental feature (currently broken)
* enabled via trace mode
*/
-//#define SUPPORT_COMPILE_TIME_REDQUEEN
+// #define SUPPORT_COMPILE_TIME_REDQUEEN
-#define VOLATILE_WRITE_64(dst, src) *((volatile uint64_t*)&dst) = (uint64_t)src
-#define VOLATILE_WRITE_32(dst, src) *((volatile uint32_t*)&dst) = (uint32_t)src
-#define VOLATILE_WRITE_16(dst, src) *((volatile uint16_t*)&dst) = (uint16_t)src
-#define VOLATILE_WRITE_8(dst, src) *((volatile uint8_t*)&dst) = (uint8_t)src
+#define VOLATILE_WRITE_64(dst, src) *((volatile uint64_t *)&dst) = (uint64_t)src
+#define VOLATILE_WRITE_32(dst, src) *((volatile uint32_t *)&dst) = (uint32_t)src
+#define VOLATILE_WRITE_16(dst, src) *((volatile uint16_t *)&dst) = (uint16_t)src
+#define VOLATILE_WRITE_8(dst, src) *((volatile uint8_t *)&dst) = (uint8_t)src
-#define VOLATILE_READ_64(dst, src) dst = *((volatile uint64_t*)(&src))
-#define VOLATILE_READ_32(dst, src) dst = *((volatile uint32_t*)(&src))
-#define VOLATILE_READ_16(dst, src) dst = *((volatile uint16_t*)(&src))
-#define VOLATILE_READ_8(dst, src) dst = *((volatile uint8_t*)(&src))
+#define VOLATILE_READ_64(dst, src) dst = *((volatile uint64_t *)(&src))
+#define VOLATILE_READ_32(dst, src) dst = *((volatile uint32_t *)(&src))
+#define VOLATILE_READ_16(dst, src) dst = *((volatile uint16_t *)(&src))
+#define VOLATILE_READ_8(dst, src) dst = *((volatile uint8_t *)(&src))
-static void volatile_memset(void* dst, uint8_t ch, size_t count){
- for (size_t i = 0; i < count; i++){
- VOLATILE_WRITE_8(((uint8_t*)dst)[i], ch);
- }
-}
-
-static void volatile_memcpy(void* dst, void* src, size_t size){
- for (size_t i = 0; i < size; i++){
- VOLATILE_WRITE_8(((uint8_t*)dst)[i], ((uint8_t*)src)[i]);
- }
-}
-
-void init_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer){
- nyx_trace();
- volatile_memset((void*) auxilary_buffer, 0, sizeof(auxilary_buffer_t));
-
- VOLATILE_WRITE_16(auxilary_buffer->header.version, QEMU_PT_VERSION);
-
- uint16_t hash = (sizeof(auxilary_buffer_header_t) +
- sizeof(auxilary_buffer_cap_t) +
- sizeof(auxilary_buffer_config_t) +
- sizeof(auxilary_buffer_result_t) +
- sizeof(auxilary_buffer_misc_t)) % 0xFFFF;
-
- VOLATILE_WRITE_16(auxilary_buffer->header.hash, hash);
-
- VOLATILE_WRITE_64(auxilary_buffer->header.magic, AUX_MAGIC);
-}
-
-void check_auxiliary_config_buffer(auxilary_buffer_t* auxilary_buffer, auxilary_buffer_config_t* shadow_config){
- uint8_t changed = 0;
- VOLATILE_READ_8(changed, auxilary_buffer->configuration.changed);
- if (changed){
-
-
- uint8_t aux_byte;
-
- VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.redqueen_mode);
- if(aux_byte){
- /* enable redqueen mode */
- if(aux_byte != shadow_config->redqueen_mode){
- GET_GLOBAL_STATE()->in_redqueen_reload_mode = true;
- GET_GLOBAL_STATE()->redqueen_enable_pending = true;
- GET_GLOBAL_STATE()->redqueen_instrumentation_mode = REDQUEEN_LIGHT_INSTRUMENTATION;
- }
- }
- else{
- /* disable redqueen mode */
- if(aux_byte != shadow_config->redqueen_mode){
- GET_GLOBAL_STATE()->in_redqueen_reload_mode = false;
- GET_GLOBAL_STATE()->redqueen_disable_pending = true;
- GET_GLOBAL_STATE()->redqueen_instrumentation_mode = REDQUEEN_NO_INSTRUMENTATION;
- }
+static void volatile_memset(void *dst, uint8_t ch, size_t count)
+{
+ for (size_t i = 0; i < count; i++) {
+ VOLATILE_WRITE_8(((uint8_t *)dst)[i], ch);
}
+}
- VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.trace_mode);
- if(aux_byte){
- /* enable trace mode */
- if(aux_byte != shadow_config->trace_mode && GET_GLOBAL_STATE()->redqueen_state){
+static void volatile_memcpy(void *dst, void *src, size_t size)
+{
+ for (size_t i = 0; i < size; i++) {
+ VOLATILE_WRITE_8(((uint8_t *)dst)[i], ((uint8_t *)src)[i]);
+ }
+}
+
+void init_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ nyx_trace();
+ volatile_memset((void *)auxilary_buffer, 0, sizeof(auxilary_buffer_t));
+
+ VOLATILE_WRITE_16(auxilary_buffer->header.version, QEMU_PT_VERSION);
+
+ uint16_t hash =
+ (sizeof(auxilary_buffer_header_t) + sizeof(auxilary_buffer_cap_t) +
+ sizeof(auxilary_buffer_config_t) + sizeof(auxilary_buffer_result_t) +
+ sizeof(auxilary_buffer_misc_t)) %
+ 0xFFFF;
+
+ VOLATILE_WRITE_16(auxilary_buffer->header.hash, hash);
+
+ VOLATILE_WRITE_64(auxilary_buffer->header.magic, AUX_MAGIC);
+}
+
+void check_auxiliary_config_buffer(auxilary_buffer_t *auxilary_buffer,
+ auxilary_buffer_config_t *shadow_config)
+{
+ uint8_t changed = 0;
+ VOLATILE_READ_8(changed, auxilary_buffer->configuration.changed);
+ if (changed) {
+ uint8_t aux_byte;
+
+ VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.redqueen_mode);
+ if (aux_byte) {
+ /* enable redqueen mode */
+ if (aux_byte != shadow_config->redqueen_mode) {
+ GET_GLOBAL_STATE()->in_redqueen_reload_mode = true;
+ GET_GLOBAL_STATE()->redqueen_enable_pending = true;
+ GET_GLOBAL_STATE()->redqueen_instrumentation_mode =
+ REDQUEEN_LIGHT_INSTRUMENTATION;
+ }
+ } else {
+ /* disable redqueen mode */
+ if (aux_byte != shadow_config->redqueen_mode) {
+ GET_GLOBAL_STATE()->in_redqueen_reload_mode = false;
+ GET_GLOBAL_STATE()->redqueen_disable_pending = true;
+ GET_GLOBAL_STATE()->redqueen_instrumentation_mode =
+ REDQUEEN_NO_INSTRUMENTATION;
+ }
+ }
+
+ VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.trace_mode);
+ if (aux_byte) {
+ /* enable trace mode */
+ if (aux_byte != shadow_config->trace_mode &&
+ GET_GLOBAL_STATE()->redqueen_state)
+ {
#ifdef SUPPORT_COMPILE_TIME_REDQUEEN
- GET_GLOBAL_STATE()->pt_trace_mode_force = true;
+ GET_GLOBAL_STATE()->pt_trace_mode_force = true;
#endif
- GET_GLOBAL_STATE()->trace_mode = true;
- redqueen_set_trace_mode();
- pt_trace_dump_enable(true);
- }
- }
- else {
- /* disable trace mode */
- if(aux_byte != shadow_config->trace_mode && GET_GLOBAL_STATE()->redqueen_state){
+ GET_GLOBAL_STATE()->trace_mode = true;
+ redqueen_set_trace_mode();
+ pt_trace_dump_enable(true);
+ }
+ } else {
+ /* disable trace mode */
+ if (aux_byte != shadow_config->trace_mode &&
+ GET_GLOBAL_STATE()->redqueen_state)
+ {
#ifdef SUPPORT_COMPILE_TIME_REDQUEEN
- GET_GLOBAL_STATE()->pt_trace_mode_force = false;
+ GET_GLOBAL_STATE()->pt_trace_mode_force = false;
#endif
- GET_GLOBAL_STATE()->trace_mode = false;
- redqueen_unset_trace_mode();
- pt_trace_dump_enable(false);
- }
+ GET_GLOBAL_STATE()->trace_mode = false;
+ redqueen_unset_trace_mode();
+ pt_trace_dump_enable(false);
+ }
+ }
+
+ VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.page_dump_mode);
+ if (aux_byte) {
+ GET_GLOBAL_STATE()->dump_page = true;
+ uint64_t data;
+ VOLATILE_READ_64(data, auxilary_buffer->configuration.page_addr);
+ GET_GLOBAL_STATE()->dump_page_addr = data;
+ // fprintf(stderr, "%s dump_page_addr => 0x%lx\n", __func__, GET_GLOBAL_STATE()->dump_page_addr);
+ VOLATILE_WRITE_8(auxilary_buffer->configuration.page_dump_mode, 0);
+ VOLATILE_WRITE_64(auxilary_buffer->configuration.page_addr, 0);
+ }
+
+ /* modify reload mode */
+ VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.reload_mode);
+ GET_GLOBAL_STATE()->in_reload_mode = aux_byte;
+
+ /* modify protect_payload_buffer */
+ VOLATILE_READ_8(aux_byte,
+ auxilary_buffer->configuration.protect_payload_buffer);
+ if (GET_GLOBAL_STATE()->protect_payload_buffer == 0 && aux_byte == 1) {
+ GET_GLOBAL_STATE()->protect_payload_buffer = aux_byte;
+ }
+
+ /* modify protect_payload_buffer */
+ VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.discard_tmp_snapshot);
+ GET_GLOBAL_STATE()->discard_tmp_snapshot = aux_byte;
+ VOLATILE_WRITE_8(auxilary_buffer->configuration.discard_tmp_snapshot, 0);
+
+ /* copy to shodow */
+ VOLATILE_READ_8(shadow_config->timeout_sec,
+ auxilary_buffer->configuration.timeout_sec);
+ VOLATILE_READ_32(shadow_config->timeout_usec,
+ auxilary_buffer->configuration.timeout_usec);
+
+ // if(shadow_config->timeout_sec || shadow_config->timeout_usec){
+ /* apply only non-zero values */
+ update_itimer(&(GET_GLOBAL_STATE()->timeout_detector),
+ shadow_config->timeout_sec, shadow_config->timeout_usec);
+ //}
+
+ VOLATILE_READ_8(shadow_config->redqueen_mode,
+ auxilary_buffer->configuration.redqueen_mode);
+ VOLATILE_READ_8(shadow_config->trace_mode,
+ auxilary_buffer->configuration.trace_mode);
+ VOLATILE_READ_8(shadow_config->reload_mode,
+ auxilary_buffer->configuration.reload_mode);
+
+ VOLATILE_READ_8(shadow_config->verbose_level,
+ auxilary_buffer->configuration.verbose_level);
+
+ /* reset the 'changed' byte */
+ VOLATILE_WRITE_8(auxilary_buffer->configuration.changed, 0);
}
+}
- VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.page_dump_mode);
- if(aux_byte){
- GET_GLOBAL_STATE()->dump_page = true;
- uint64_t data;
- VOLATILE_READ_64(data, auxilary_buffer->configuration.page_addr);
- GET_GLOBAL_STATE()->dump_page_addr = data;
- //fprintf(stderr, "%s dump_page_addr => 0x%lx\n", __func__, GET_GLOBAL_STATE()->dump_page_addr);
- VOLATILE_WRITE_8(auxilary_buffer->configuration.page_dump_mode, 0);
- VOLATILE_WRITE_64(auxilary_buffer->configuration.page_addr, 0);
+void set_crash_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash);
+}
+
+void set_asan_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_sanitizer);
+}
+
+void set_timeout_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_timeout);
+}
+
+void set_reload_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.reloaded, 1);
+}
+
+void set_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.pt_overflow, 1);
+}
+
+void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint32_t sec,
+ uint32_t usec,
+ uint32_t num_dirty_pages)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_done, 1);
+
+ VOLATILE_WRITE_32(auxilary_buffer->result.runtime_sec, sec);
+ VOLATILE_WRITE_32(auxilary_buffer->result.runtime_usec, usec);
+ VOLATILE_WRITE_32(auxilary_buffer->result.dirty_pages, num_dirty_pages);
+}
+
+
+void set_hprintf_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer,
+ char *msg,
+ uint32_t len)
+{
+ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE - 2));
+ volatile_memcpy((void *)&auxilary_buffer->misc.data, (void *)msg,
+ (size_t)MIN(len, MISC_SIZE - 2));
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_hprintf);
+}
+
+void set_crash_reason_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer,
+ char *msg,
+ uint32_t len)
+{
+ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE - 2));
+ volatile_memcpy((void *)&auxilary_buffer->misc.data, (void *)msg,
+ (size_t)MIN(len, MISC_SIZE - 2));
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash);
+}
+
+void set_abort_reason_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer,
+ char *msg,
+ uint32_t len)
+{
+ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE - 2));
+ volatile_memcpy((void *)&auxilary_buffer->misc.data, (void *)msg,
+ (size_t)MIN(len, MISC_SIZE - 2));
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_aborted);
+}
+
+void set_state_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint8_t state)
+{
+ if (auxilary_buffer) {
+ VOLATILE_WRITE_8(auxilary_buffer->result.state, state);
+ } else {
+ nyx_error("WARNING: auxilary_buffer pointer is zero\n");
}
+}
- /* modify reload mode */
- VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.reload_mode);
- GET_GLOBAL_STATE()->in_reload_mode = aux_byte;
+void set_page_not_found_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint64_t page_addr)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.page_not_found, 1);
+ VOLATILE_WRITE_64(auxilary_buffer->result.page_addr, page_addr);
+}
- /* modify protect_payload_buffer */
- VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.protect_payload_buffer);
- if (GET_GLOBAL_STATE()->protect_payload_buffer == 0 && aux_byte == 1){
- GET_GLOBAL_STATE()->protect_payload_buffer = aux_byte;
+void reset_page_not_found_result_buffer(auxilary_buffer_t *auxilary_buffer)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.page_not_found, 0);
+}
+
+void set_success_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint8_t success)
+{
+ // 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 {
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_success);
}
-
- /* modify protect_payload_buffer */
- VOLATILE_READ_8(aux_byte, auxilary_buffer->configuration.discard_tmp_snapshot);
- GET_GLOBAL_STATE()->discard_tmp_snapshot = aux_byte;
- VOLATILE_WRITE_8(auxilary_buffer->configuration.discard_tmp_snapshot, 0);
-
- /* copy to shodow */
- VOLATILE_READ_8(shadow_config->timeout_sec, auxilary_buffer->configuration.timeout_sec);
- VOLATILE_READ_32(shadow_config->timeout_usec, auxilary_buffer->configuration.timeout_usec);
-
- //if(shadow_config->timeout_sec || shadow_config->timeout_usec){
- /* apply only non-zero values */
- update_itimer(&(GET_GLOBAL_STATE()->timeout_detector), shadow_config->timeout_sec, shadow_config->timeout_usec);
- //}
-
- VOLATILE_READ_8(shadow_config->redqueen_mode, auxilary_buffer->configuration.redqueen_mode);
- VOLATILE_READ_8(shadow_config->trace_mode, auxilary_buffer->configuration.trace_mode);
- VOLATILE_READ_8(shadow_config->reload_mode, auxilary_buffer->configuration.reload_mode);
-
- VOLATILE_READ_8(shadow_config->verbose_level, auxilary_buffer->configuration.verbose_level);
-
- /* reset the 'changed' byte */
- VOLATILE_WRITE_8(auxilary_buffer->configuration.changed, 0);
- }
}
-void set_crash_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash);
-}
-
-void set_asan_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_sanitizer);
-}
-
-void set_timeout_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_timeout);
-}
-
-void set_reload_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.reloaded, 1);
-}
-
-void set_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.pt_overflow, 1);
-}
-
-void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint32_t sec, uint32_t usec, uint32_t num_dirty_pages){
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_done, 1);
-
- VOLATILE_WRITE_32(auxilary_buffer->result.runtime_sec, sec);
- VOLATILE_WRITE_32(auxilary_buffer->result.runtime_usec, usec);
- VOLATILE_WRITE_32(auxilary_buffer->result.dirty_pages, num_dirty_pages);
+void set_payload_buffer_write_reason_auxiliary_buffer(
+ auxilary_buffer_t *auxilary_buffer, char *msg, uint32_t len)
+{
+ VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE - 2));
+ volatile_memcpy((void *)&auxilary_buffer->misc.data, (void *)msg,
+ (size_t)MIN(len, MISC_SIZE - 2));
+ VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_input_buffer_write);
}
-
-void set_hprintf_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){
- VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2));
- volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t)MIN(len, MISC_SIZE-2));
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_hprintf);
+void set_tmp_snapshot_created(auxilary_buffer_t *auxilary_buffer, uint8_t value)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->result.tmp_snapshot_created, value);
}
-void set_crash_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){
- VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2));
- volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t) MIN(len, MISC_SIZE-2));
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash);
+void set_cap_agent_trace_bitmap(auxilary_buffer_t *auxilary_buffer, bool value)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->capabilites.agent_trace_bitmap, value);
}
-void set_abort_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){
- VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2));
- volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t) MIN(len, MISC_SIZE-2));
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_aborted);
+void set_cap_agent_ijon_trace_bitmap(auxilary_buffer_t *auxilary_buffer, bool value)
+{
+ VOLATILE_WRITE_8(auxilary_buffer->capabilites.agent_ijon_trace_bitmap, value);
}
-void set_state_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t state){
- if(auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.state, state);
- }
- else{
- nyx_error("WARNING: auxilary_buffer pointer is zero\n");
- }
+void set_result_dirty_pages(auxilary_buffer_t *auxilary_buffer, uint32_t value)
+{
+ VOLATILE_WRITE_32(auxilary_buffer->result.dirty_pages, value);
}
-void set_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer, uint64_t page_addr){
- VOLATILE_WRITE_8(auxilary_buffer->result.page_not_found, 1);
- VOLATILE_WRITE_64(auxilary_buffer->result.page_addr, page_addr);
+void set_result_pt_trace_size(auxilary_buffer_t *auxilary_buffer, uint32_t value)
+{
+ VOLATILE_WRITE_32(auxilary_buffer->result.pt_trace_size, value);
}
-void reset_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer){
- VOLATILE_WRITE_8(auxilary_buffer->result.page_not_found, 0);
-}
-
-void set_success_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t success){
- //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 {
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_success);
- }
-}
-
-void set_payload_buffer_write_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){
- VOLATILE_WRITE_16(auxilary_buffer->misc.len, MIN(len, MISC_SIZE-2));
- volatile_memcpy((void*)&auxilary_buffer->misc.data, (void*)msg, (size_t) MIN(len, MISC_SIZE-2));
- VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_input_buffer_write);
-}
-
-
-void set_tmp_snapshot_created(auxilary_buffer_t* auxilary_buffer, uint8_t value){
- VOLATILE_WRITE_8(auxilary_buffer->result.tmp_snapshot_created, value);
-}
-
-void set_cap_agent_trace_bitmap(auxilary_buffer_t* auxilary_buffer, bool value){
- VOLATILE_WRITE_8(auxilary_buffer->capabilites.agent_trace_bitmap, value);
-}
-
-void set_cap_agent_ijon_trace_bitmap(auxilary_buffer_t* auxilary_buffer, bool value){
- VOLATILE_WRITE_8(auxilary_buffer->capabilites.agent_ijon_trace_bitmap, value);
-}
-
-void set_result_dirty_pages(auxilary_buffer_t* auxilary_buffer, uint32_t value){
- VOLATILE_WRITE_32(auxilary_buffer->result.dirty_pages, value);
-}
-
-void set_result_pt_trace_size(auxilary_buffer_t* auxilary_buffer, uint32_t value){
- VOLATILE_WRITE_32(auxilary_buffer->result.pt_trace_size, value);
-}
-
-void set_result_bb_coverage(auxilary_buffer_t* auxilary_buffer, uint32_t value){
- if (value != auxilary_buffer->result.bb_coverage){
- VOLATILE_WRITE_32(auxilary_buffer->result.bb_coverage, value);
- }
+void set_result_bb_coverage(auxilary_buffer_t *auxilary_buffer, uint32_t value)
+{
+ if (value != auxilary_buffer->result.bb_coverage) {
+ VOLATILE_WRITE_32(auxilary_buffer->result.bb_coverage, value);
+ }
}
diff --git a/nyx/auxiliary_buffer.h b/nyx/auxiliary_buffer.h
index ba64ba4b7c..8423e60068 100644
--- a/nyx/auxiliary_buffer.h
+++ b/nyx/auxiliary_buffer.h
@@ -21,160 +21,178 @@ along with QEMU-PT. If not, see .
#pragma once
-#include
#include
+#include
#define AUX_BUFFER_SIZE 4096
#define AUX_MAGIC 0x54502d554d4551
-#define QEMU_PT_VERSION 3 /* let's start at 1 for the initial version using the aux buffer */
+#define QEMU_PT_VERSION \
+ 3 /* let's start at 1 for the initial version using the aux buffer */
#define HEADER_SIZE 128
-#define CAP_SIZE 256
+#define CAP_SIZE 256
#define CONFIG_SIZE 512
-#define STATE_SIZE 512
-#define MISC_SIZE 4096-(HEADER_SIZE+CAP_SIZE+CONFIG_SIZE+STATE_SIZE)
+#define STATE_SIZE 512
+#define MISC_SIZE 4096 - (HEADER_SIZE + CAP_SIZE + CONFIG_SIZE + STATE_SIZE)
-#define ADD_PADDING(max, type) uint8_t type ## _padding [max - sizeof(type)]
+#define ADD_PADDING(max, type) uint8_t type##_padding[max - sizeof(type)]
enum nyx_result_codes {
- rc_success = 0,
- rc_crash = 1,
- rc_hprintf = 2,
- rc_timeout = 3,
- rc_input_buffer_write = 4,
- rc_aborted = 5,
- rc_sanitizer = 6,
- rc_starved = 7,
+ rc_success = 0,
+ rc_crash = 1,
+ rc_hprintf = 2,
+ rc_timeout = 3,
+ rc_input_buffer_write = 4,
+ rc_aborted = 5,
+ rc_sanitizer = 6,
+ rc_starved = 7,
};
-typedef struct auxilary_buffer_header_s{
- uint64_t magic;
- uint16_t version;
- uint16_t hash;
- /* more to come */
+typedef struct auxilary_buffer_header_s {
+ uint64_t magic;
+ uint16_t version;
+ uint16_t hash;
+ /* more to come */
} __attribute__((packed)) auxilary_buffer_header_t;
-typedef struct auxilary_buffer_cap_s{
- uint8_t redqueen;
- uint8_t agent_timeout_detection; /* agent implements its own timeout detection; host timeout detection is still in used, but treshold is increased by x2; */
- uint8_t agent_trace_bitmap; /* agent implements its own tracing mechanism; PT tracing is disabled */
- uint8_t agent_ijon_trace_bitmap; /* agent uses the ijon shm buffer */
+typedef struct auxilary_buffer_cap_s {
+ uint8_t redqueen;
+ uint8_t agent_timeout_detection; /* agent implements its own timeout detection;
+ host timeout detection is still in used, but treshold is increased by x2; */
+ uint8_t agent_trace_bitmap; /* agent implements its own tracing mechanism; PT tracing is disabled */
+ uint8_t agent_ijon_trace_bitmap; /* agent uses the ijon shm buffer */
- uint32_t agent_input_buffer_size; /* agent requests a custom input buffer size (if the size is 0, the minimum buffer size is used) */
- uint32_t agent_coverage_bitmap_size; /* agent requests a custom coverage bitmap size (if the size is 0, the minimum buffer size is used) */
- /* more to come */
+ uint32_t agent_input_buffer_size; /* agent requests a custom input buffer size (if
+ the size is 0, the minimum buffer size is used) */
+ uint32_t agent_coverage_bitmap_size; /* agent requests a custom coverage bitmap
+ size (if the size is 0, the minimum buffer size is used) */
+ /* more to come */
} __attribute__((packed)) auxilary_buffer_cap_t;
-typedef struct auxilary_buffer_config_s{
- uint8_t changed; /* set this byte to kick in a rescan of this buffer */
+typedef struct auxilary_buffer_config_s {
+ uint8_t changed; /* set this byte to kick in a rescan of this buffer */
- uint8_t timeout_sec;
- uint32_t timeout_usec;
+ uint8_t timeout_sec;
+ uint32_t timeout_usec;
- /* trigger to enable / disable different QEMU-PT modes */
- uint8_t redqueen_mode;
- uint8_t trace_mode; /* dump decoded edge transitions to file */
- uint8_t reload_mode;
+ /* trigger to enable / disable different QEMU-PT modes */
+ uint8_t redqueen_mode;
+ uint8_t trace_mode; /* dump decoded edge transitions to file */
+ uint8_t reload_mode;
- uint8_t verbose_level;
+ uint8_t verbose_level;
- uint8_t page_dump_mode;
- uint64_t page_addr;
+ uint8_t page_dump_mode;
+ uint64_t page_addr;
- /* nested mode only */
- uint8_t protect_payload_buffer;
+ /* nested mode only */
+ uint8_t protect_payload_buffer;
- /* 0 -> disabled
- 1 -> decoding
- 2 -> decoding + full disassembling
- */
- //uint8_t pt_processing_mode;
+ /* 0 -> disabled
+ 1 -> decoding
+ 2 -> decoding + full disassembling
+ */
+ // uint8_t pt_processing_mode;
- /* snapshot extension */
- uint8_t discard_tmp_snapshot;
+ /* snapshot extension */
+ uint8_t discard_tmp_snapshot;
- /* more to come */
+ /* more to come */
} __attribute__((packed)) auxilary_buffer_config_t;
-typedef struct auxilary_buffer_result_s{
- /* 0 -> booting,
- 1 -> loader level 1,
- 2 -> loader level 2,
- 3 -> ready to fuzz
- */
- uint8_t state;
- uint8_t exec_done;
- uint8_t exec_result_code;
- uint8_t reloaded;
+typedef struct auxilary_buffer_result_s {
+ /* 0 -> booting,
+ 1 -> loader level 1,
+ 2 -> loader level 2,
+ 3 -> ready to fuzz
+ */
+ uint8_t state;
+ uint8_t exec_done;
+ uint8_t exec_result_code;
+ uint8_t reloaded;
- uint8_t pt_overflow;
- uint8_t page_not_found;
- uint8_t tmp_snapshot_created; /* incremental snapshot extension */
- uint8_t padding_3;
+ uint8_t pt_overflow;
+ uint8_t page_not_found;
+ uint8_t tmp_snapshot_created; /* incremental snapshot extension */
+ uint8_t padding_3;
- uint64_t page_addr;
- uint32_t dirty_pages;
- uint32_t pt_trace_size;
- uint32_t bb_coverage;
- uint32_t runtime_usec;
- uint32_t runtime_sec;
+ uint64_t page_addr;
+ uint32_t dirty_pages;
+ uint32_t pt_trace_size;
+ uint32_t bb_coverage;
+ uint32_t runtime_usec;
+ uint32_t runtime_sec;
- /* more to come */
+ /* more to come */
} __attribute__((packed)) auxilary_buffer_result_t;
-typedef struct auxilary_buffer_misc_s{
- uint16_t len;
- uint8_t data;
- /* non yet */
+typedef struct auxilary_buffer_misc_s {
+ uint16_t len;
+ uint8_t data;
+ /* non yet */
} __attribute__((packed)) auxilary_buffer_misc_t;
-typedef struct auxilary_buffer_s{
- auxilary_buffer_header_t header;
- ADD_PADDING(HEADER_SIZE, auxilary_buffer_header_t);
+typedef struct auxilary_buffer_s {
+ auxilary_buffer_header_t header;
+ ADD_PADDING(HEADER_SIZE, auxilary_buffer_header_t);
- auxilary_buffer_cap_t capabilites;
- ADD_PADDING(CAP_SIZE, auxilary_buffer_cap_t);
+ auxilary_buffer_cap_t capabilites;
+ ADD_PADDING(CAP_SIZE, auxilary_buffer_cap_t);
- auxilary_buffer_config_t configuration;
- ADD_PADDING(CONFIG_SIZE, auxilary_buffer_config_t);
+ auxilary_buffer_config_t configuration;
+ ADD_PADDING(CONFIG_SIZE, auxilary_buffer_config_t);
- auxilary_buffer_result_t result;
- ADD_PADDING(STATE_SIZE, auxilary_buffer_result_t);
+ auxilary_buffer_result_t result;
+ ADD_PADDING(STATE_SIZE, auxilary_buffer_result_t);
- auxilary_buffer_misc_t misc;
- ADD_PADDING(MISC_SIZE, auxilary_buffer_misc_t);
+ auxilary_buffer_misc_t misc;
+ ADD_PADDING(MISC_SIZE, auxilary_buffer_misc_t);
} __attribute__((packed)) auxilary_buffer_t;
-void init_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer);
-void check_auxiliary_config_buffer(auxilary_buffer_t* auxilary_buffer, auxilary_buffer_config_t* shadow_config);
+void init_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer);
+void check_auxiliary_config_buffer(auxilary_buffer_t *auxilary_buffer,
+ auxilary_buffer_config_t *shadow_config);
-void set_crash_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
-void set_asan_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
-void set_timeout_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
-void set_reload_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
-void set_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
-void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint32_t sec, uint32_t usec, uint32_t num_dirty_pages);
-void set_state_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t state);
-void set_hprintf_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len);
+void set_crash_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer);
+void set_asan_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer);
+void set_timeout_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer);
+void set_reload_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer);
+void set_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer);
+void set_exec_done_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint32_t sec,
+ uint32_t usec,
+ uint32_t num_dirty_pages);
+void set_state_auxiliary_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint8_t state);
+void set_hprintf_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer,
+ char *msg,
+ uint32_t len);
-void set_page_not_found_result_buffer(auxilary_buffer_t* auxilary_buffer, uint64_t page_addr);
-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);
-void set_crash_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len);
-void set_abort_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len);
+void set_page_not_found_result_buffer(auxilary_buffer_t *auxilary_buffer,
+ uint64_t page_addr);
+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);
+void set_crash_reason_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer,
+ char *msg,
+ uint32_t len);
+void set_abort_reason_auxiliary_buffer(auxilary_buffer_t *auxilary_buffer,
+ char *msg,
+ uint32_t len);
-void set_tmp_snapshot_created(auxilary_buffer_t* auxilary_buffer, uint8_t value);
+void set_tmp_snapshot_created(auxilary_buffer_t *auxilary_buffer, uint8_t value);
-void set_cap_agent_trace_bitmap(auxilary_buffer_t* auxilary_buffer, bool value);
-void set_cap_agent_ijon_trace_bitmap(auxilary_buffer_t* auxilary_buffer, bool value);
+void set_cap_agent_trace_bitmap(auxilary_buffer_t *auxilary_buffer, bool value);
+void set_cap_agent_ijon_trace_bitmap(auxilary_buffer_t *auxilary_buffer, bool value);
-void set_result_dirty_pages(auxilary_buffer_t* auxilary_buffer, uint32_t value);
-void set_result_pt_trace_size(auxilary_buffer_t* auxilary_buffer, uint32_t value);
+void set_result_dirty_pages(auxilary_buffer_t *auxilary_buffer, uint32_t value);
+void set_result_pt_trace_size(auxilary_buffer_t *auxilary_buffer, uint32_t value);
-void set_result_bb_coverage(auxilary_buffer_t* auxilary_buffer, uint32_t value);
+void set_result_bb_coverage(auxilary_buffer_t *auxilary_buffer, uint32_t value);
-void set_payload_buffer_write_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len);
+void set_payload_buffer_write_reason_auxiliary_buffer(
+ auxilary_buffer_t *auxilary_buffer, char *msg, uint32_t len);
diff --git a/nyx/debug.c b/nyx/debug.c
index dd2b5b6dd5..802bcf160e 100644
--- a/nyx/debug.c
+++ b/nyx/debug.c
@@ -1,8 +1,8 @@
+#include
#include
#include
#include
-#include
#include "qemu/osdep.h"
#include "nyx/debug.h"
@@ -11,54 +11,61 @@
#ifdef ENABLE_BACKTRACES
#define BT_BUF_SIZE 100
-void qemu_backtrace(void){
- void *buffer[BT_BUF_SIZE];
- int nptrs = 0;
- int j;
+void qemu_backtrace(void)
+{
+ void *buffer[BT_BUF_SIZE];
+ int nptrs = 0;
+ int j;
- nptrs = backtrace(buffer, BT_BUF_SIZE);
- fprintf(stderr, "backtrace() returned %d addresses\n", nptrs);
+ nptrs = backtrace(buffer, BT_BUF_SIZE);
+ fprintf(stderr, "backtrace() returned %d addresses\n", nptrs);
- char **strings = backtrace_symbols(buffer, nptrs);
- if (strings == NULL) {
- fprintf(stderr, "backtrace_symbols failed!\n");
- return;
- //exit(EXIT_FAILURE);
- }
+ char **strings = backtrace_symbols(buffer, nptrs);
+ if (strings == NULL) {
+ fprintf(stderr, "backtrace_symbols failed!\n");
+ return;
+ // exit(EXIT_FAILURE);
+ }
- for (j = 0; j < nptrs; j++)
- fprintf(stderr, "%s\n", strings[j]);
+ for (j = 0; j < nptrs; j++)
+ fprintf(stderr, "%s\n", strings[j]);
- free(strings);
+ free(strings);
}
-static void sigsegfault_handler(int signo, siginfo_t *info, void *extra) {
- fprintf(stderr, "[qemu-nyx] crash detected (pid: %d / signal: %d)\n", getpid(), signo);
- qemu_backtrace();
- fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
- while(1){
- sleep(1);
- }
+static void sigsegfault_handler(int signo, siginfo_t *info, void *extra)
+{
+ fprintf(stderr, "[qemu-nyx] crash detected (pid: %d / signal: %d)\n", getpid(),
+ signo);
+ qemu_backtrace();
+ fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
+ while (1) {
+ sleep(1);
+ }
}
-static void sigabrt_handler(int signo, siginfo_t *info, void *extra) {
- fprintf(stderr, "[qemu-nyx] crash detected (pid: %d / signal: %d)\n", getpid(), signo);
- qemu_backtrace();
- fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
- while(1){
- sleep(1);
- }
+static void sigabrt_handler(int signo, siginfo_t *info, void *extra)
+{
+ fprintf(stderr, "[qemu-nyx] crash detected (pid: %d / signal: %d)\n", getpid(),
+ signo);
+ qemu_backtrace();
+ fprintf(stderr, "WAITING FOR GDB ATTACH (PID: %d...\n", getpid());
+ while (1) {
+ sleep(1);
+ }
}
-static void sigint_handler(int signo, siginfo_t *info, void *extra) {
- fprintf(stderr, "[qemu-nyx] bye! (pid: %d / signal: %d)\n", getpid(), signo);
- exit(0);
+static void sigint_handler(int signo, siginfo_t *info, void *extra)
+{
+ fprintf(stderr, "[qemu-nyx] bye! (pid: %d / signal: %d)\n", getpid(), signo);
+ exit(0);
}
-void init_crash_handler(void){
+void init_crash_handler(void)
+{
struct sigaction action;
- action.sa_flags = SA_SIGINFO;
+ action.sa_flags = SA_SIGINFO;
action.sa_sigaction = sigsegfault_handler;
if (sigaction(SIGSEGV, &action, NULL) == -1) {
@@ -66,8 +73,7 @@ void init_crash_handler(void){
_exit(1);
}
-
-
+
action.sa_sigaction = sigabrt_handler;
if (sigaction(SIGABRT, &action, NULL) == -1) {
@@ -75,43 +81,44 @@ void init_crash_handler(void){
_exit(1);
}
- /* don't install a SIGINT handler if the nyx block cow cache layer is disabled */
- if(!getenv("NYX_DISABLE_BLOCK_COW")){
- action.sa_sigaction = sigint_handler;
- if (sigaction(SIGINT, &action, NULL) == -1) {
- fprintf(stderr, "SIGINT: sigaction failed");
- _exit(1);
+ /* don't install a SIGINT handler if the nyx block cow cache layer is disabled */
+ if (!getenv("NYX_DISABLE_BLOCK_COW")) {
+ action.sa_sigaction = sigint_handler;
+ if (sigaction(SIGINT, &action, NULL) == -1) {
+ fprintf(stderr, "SIGINT: sigaction failed");
+ _exit(1);
+ }
}
- }
}
-void hexdump_kafl(const void* data, size_t size) {
- char ascii[17];
- size_t i, j;
- ascii[16] = '\0';
- for (i = 0; i < size; ++i) {
- printf("%02X ", ((unsigned char*)data)[i]);
- if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
- ascii[i % 16] = ((unsigned char*)data)[i];
- } else {
- ascii[i % 16] = '.';
- }
- if ((i+1) % 8 == 0 || i+1 == size) {
- printf(" ");
- if ((i+1) % 16 == 0) {
- printf("| %s \n", ascii);
- } else if (i+1 == size) {
- ascii[(i+1) % 16] = '\0';
- if ((i+1) % 16 <= 8) {
- printf(" ");
- }
- for (j = (i+1) % 16; j < 16; ++j) {
- printf(" ");
- }
- printf("| %s \n", ascii);
- }
- }
- }
+void hexdump_kafl(const void *data, size_t size)
+{
+ char ascii[17];
+ size_t i, j;
+ ascii[16] = '\0';
+ for (i = 0; i < size; ++i) {
+ printf("%02X ", ((unsigned char *)data)[i]);
+ if (((unsigned char *)data)[i] >= ' ' && ((unsigned char *)data)[i] <= '~') {
+ ascii[i % 16] = ((unsigned char *)data)[i];
+ } else {
+ ascii[i % 16] = '.';
+ }
+ if ((i + 1) % 8 == 0 || i + 1 == size) {
+ printf(" ");
+ if ((i + 1) % 16 == 0) {
+ printf("| %s \n", ascii);
+ } else if (i + 1 == size) {
+ ascii[(i + 1) % 16] = '\0';
+ if ((i + 1) % 16 <= 8) {
+ printf(" ");
+ }
+ for (j = (i + 1) % 16; j < 16; ++j) {
+ printf(" ");
+ }
+ printf("| %s \n", ascii);
+ }
+ }
+ }
}
#endif
diff --git a/nyx/debug.h b/nyx/debug.h
index 3accf293f8..0aba444f57 100644
--- a/nyx/debug.h
+++ b/nyx/debug.h
@@ -5,43 +5,46 @@
#include
#include
-#include "qemu-common.h"
-#include "qemu/log.h"
#include "qemu/error-report.h"
+#include "qemu/log.h"
+#include "qemu-common.h"
#define ENABLE_BACKTRACES
-#define NYX_LOG_PREFIX "[QEMU-NYX] "
-#define CORE_PREFIX "Core: "
-#define MEM_PREFIX "Memory: "
-#define RELOAD_PREFIX "Reload: "
-#define PT_PREFIX "PT: "
-#define INTERFACE_PREFIX "Interface: "
-#define REDQUEEN_PREFIX "Redqueen: "
-#define DISASM_PREFIX "Disasm: "
-#define PAGE_CACHE_PREFIX "PageCache: "
-#define NESTED_VM_PREFIX "Nested: "
+#define NYX_LOG_PREFIX "[QEMU-NYX] "
+#define CORE_PREFIX "Core: "
+#define MEM_PREFIX "Memory: "
+#define RELOAD_PREFIX "Reload: "
+#define PT_PREFIX "PT: "
+#define INTERFACE_PREFIX "Interface: "
+#define REDQUEEN_PREFIX "Redqueen: "
+#define DISASM_PREFIX "Disasm: "
+#define PAGE_CACHE_PREFIX "PageCache: "
+#define NESTED_VM_PREFIX "Nested: "
#ifdef NYX_DEBUG
/*
* qemu_log() is the standard logging enabled with -D
* qemu_log_mask() is activated with additional -t nyx option
*/
-//#define nyx_debug(format, ...) qemu_log_mask(LOG_NYX, NYX_LOG_PREFIX "(%s#:%d)\t"format, __BASE_FILE__, __LINE__, ##__VA_ARGS__)
-#define nyx_debug(format, ...) qemu_log_mask(LOG_NYX, NYX_LOG_PREFIX format, ##__VA_ARGS__)
-#define nyx_debug_p(PREFIX, format, ...) qemu_log_mask(LOG_NYX, NYX_LOG_PREFIX PREFIX format, ##__VA_ARGS__)
+// #define nyx_debug(format, ...) qemu_log_mask(LOG_NYX, NYX_LOG_PREFIX
+// "(%s#:%d)\t"format, __BASE_FILE__, __LINE__, ##__VA_ARGS__)
+#define nyx_debug(format, ...) \
+ qemu_log_mask(LOG_NYX, NYX_LOG_PREFIX format, ##__VA_ARGS__)
+#define nyx_debug_p(PREFIX, format, ...) \
+ qemu_log_mask(LOG_NYX, NYX_LOG_PREFIX PREFIX format, ##__VA_ARGS__)
#else
#define nyx_debug(...)
#define nyx_debug_p(...)
#endif
-#define nyx_printf(format, ...) qemu_log(format, ##__VA_ARGS__)
-#define nyx_error(format, ...) error_printf(format, ##__VA_ARGS__)
-#define nyx_trace(format, ...) nyx_debug("=> %s\n", __func__)
+#define nyx_printf(format, ...) qemu_log(format, ##__VA_ARGS__)
+#define nyx_error(format, ...) error_printf(format, ##__VA_ARGS__)
+#define nyx_trace(format, ...) nyx_debug("=> %s\n", __func__)
#ifdef ENABLE_BACKTRACES
void qemu_backtrace(void);
void init_crash_handler(void);
-void hexdump_kafl(const void* data, size_t size);
+void hexdump_kafl(const void *data, size_t size);
#endif
diff --git a/nyx/fast_vm_reload.c b/nyx/fast_vm_reload.c
index 4fd0a38881..f58db8be34 100644
--- a/nyx/fast_vm_reload.c
+++ b/nyx/fast_vm_reload.c
@@ -19,136 +19,156 @@ along with QEMU-PT. If not, see .
*/
-#include"qemu/osdep.h"
+#include "qemu/osdep.h"
-#include
-#include
-#include
-#include
+#include
+#include
+#include
+#include
-#include
+#include
-#include"block/qapi.h"
-#include"exec/ram_addr.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/register.h"
-#include"migration/savevm.h"
-#include"migration/vmstate.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"qemu/main-loop.h"
-#include"qemu/rcu_queue.h"
+#include "qemu/main-loop.h"
+#include "qemu/rcu_queue.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 "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/debug.h"
-#include"nyx/fast_vm_reload.h"
-#include"nyx/state/snapshot_state.h"
-#include"nyx/state/state.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/memory_access.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/block/nyx_block_snapshot.h"
-#include"nyx/snapshot/devices/nyx_device_state.h"
-#include"nyx/snapshot/memory/backend/nyx_debug.h"
+#include "nyx/snapshot/block/nyx_block_snapshot.h"
+#include "nyx/snapshot/devices/nyx_device_state.h"
+#include "nyx/snapshot/helper.h"
+#include "nyx/snapshot/memory/backend/nyx_debug.h"
+#include "nyx/snapshot/memory/block_list.h"
+#include "nyx/snapshot/memory/shadow_memory.h"
FastReloadMemoryMode mode = RELOAD_MEMORY_MODE_DEBUG;
/* basic operations */
-static void fast_snapshot_init_operation(fast_reload_t* self, const char* snapshot_folder, bool pre_snapshot){
-
+static void fast_snapshot_init_operation(fast_reload_t *self,
+ const char *snapshot_folder,
+ bool pre_snapshot)
+{
assert((snapshot_folder == NULL && pre_snapshot == false) || snapshot_folder);
- if (snapshot_folder){
- self->device_state = nyx_device_state_init_from_snapshot(snapshot_folder, pre_snapshot);
- self->shadow_memory_state = shadow_memory_init_from_snapshot(snapshot_folder, pre_snapshot);
- }
- else{
- self->device_state = nyx_device_state_init();
+ if (snapshot_folder) {
+ self->device_state =
+ nyx_device_state_init_from_snapshot(snapshot_folder, pre_snapshot);
+ self->shadow_memory_state =
+ shadow_memory_init_from_snapshot(snapshot_folder, pre_snapshot);
+ } else {
+ self->device_state = nyx_device_state_init();
self->shadow_memory_state = shadow_memory_init();
}
-
- if(!pre_snapshot){
- switch(mode){
- case RELOAD_MEMORY_MODE_DEBUG:
- break;
- case RELOAD_MEMORY_MODE_DEBUG_QUIET:
- break;
- case RELOAD_MEMORY_MODE_FDL:
- self->fdl_state = nyx_fdl_init(self->shadow_memory_state);
- break;
- case RELOAD_MEMORY_MODE_FDL_DEBUG:
- self->fdl_state = nyx_fdl_init(self->shadow_memory_state);
- break;
- case RELOAD_MEMORY_MODE_DIRTY_RING:
- self->dirty_ring_state = nyx_dirty_ring_init(self->shadow_memory_state);
- break;
- case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG:
- self->dirty_ring_state = nyx_dirty_ring_init(self->shadow_memory_state);
- break;
+
+ if (!pre_snapshot) {
+ switch (mode) {
+ case RELOAD_MEMORY_MODE_DEBUG:
+ break;
+ case RELOAD_MEMORY_MODE_DEBUG_QUIET:
+ break;
+ case RELOAD_MEMORY_MODE_FDL:
+ self->fdl_state = nyx_fdl_init(self->shadow_memory_state);
+ break;
+ case RELOAD_MEMORY_MODE_FDL_DEBUG:
+ self->fdl_state = nyx_fdl_init(self->shadow_memory_state);
+ break;
+ case RELOAD_MEMORY_MODE_DIRTY_RING:
+ self->dirty_ring_state = nyx_dirty_ring_init(self->shadow_memory_state);
+ break;
+ case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG:
+ self->dirty_ring_state = nyx_dirty_ring_init(self->shadow_memory_state);
+ break;
}
self->fdl_user_state = nyx_fdl_user_init(self->shadow_memory_state);
nyx_fdl_user_enable(self->fdl_user_state);
}
- if (snapshot_folder){
- self->block_state = nyx_block_snapshot_init_from_file(snapshot_folder, pre_snapshot);
- }
- else{
+ if (snapshot_folder) {
+ self->block_state =
+ nyx_block_snapshot_init_from_file(snapshot_folder, pre_snapshot);
+ } else {
self->block_state = nyx_block_snapshot_init();
}
memory_global_dirty_log_start();
- if(!pre_snapshot){
+ if (!pre_snapshot) {
self->root_snapshot_created = true;
}
}
-static void fast_snapshot_restore_operation(fast_reload_t* self){
-
+static void fast_snapshot_restore_operation(fast_reload_t *self)
+{
uint32_t num_dirty_pages = 0;
- switch(mode){
- case RELOAD_MEMORY_MODE_DEBUG:
- num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true);
- break;
- case RELOAD_MEMORY_MODE_DEBUG_QUIET:
- num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, false);
- break;
- case RELOAD_MEMORY_MODE_FDL:
- num_dirty_pages += nyx_snapshot_nyx_fdl_restore(self->fdl_state, self->shadow_memory_state, self->blocklist);
- break;
- case RELOAD_MEMORY_MODE_FDL_DEBUG:
- num_dirty_pages += nyx_snapshot_nyx_fdl_restore(self->fdl_state, self->shadow_memory_state, self->blocklist);
- num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state, self->blocklist, true);
- break;
- case RELOAD_MEMORY_MODE_DIRTY_RING:
- num_dirty_pages += nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state, self->shadow_memory_state, self->blocklist);
- break;
- 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);
- break;
+ switch (mode) {
+ case RELOAD_MEMORY_MODE_DEBUG:
+ num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state,
+ self->blocklist, true);
+ break;
+ case RELOAD_MEMORY_MODE_DEBUG_QUIET:
+ num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state,
+ self->blocklist, false);
+ break;
+ case RELOAD_MEMORY_MODE_FDL:
+ num_dirty_pages += nyx_snapshot_nyx_fdl_restore(self->fdl_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ break;
+ case RELOAD_MEMORY_MODE_FDL_DEBUG:
+ num_dirty_pages += nyx_snapshot_nyx_fdl_restore(self->fdl_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ num_dirty_pages += nyx_snapshot_debug_restore(self->shadow_memory_state,
+ self->blocklist, true);
+ break;
+ case RELOAD_MEMORY_MODE_DIRTY_RING:
+ num_dirty_pages +=
+ nyx_snapshot_nyx_dirty_ring_restore(self->dirty_ring_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ break;
+ 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);
+ break;
}
- num_dirty_pages += nyx_snapshot_user_fdl_restore(self->fdl_user_state, self->shadow_memory_state, self->blocklist);
+ num_dirty_pages += nyx_snapshot_user_fdl_restore(self->fdl_user_state,
+ self->shadow_memory_state,
+ self->blocklist);
GET_GLOBAL_STATE()->num_dirty_pages = num_dirty_pages;
}
-static inline void fast_snapshot_pre_create_incremental_operation(fast_reload_t* self){
+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();
@@ -157,34 +177,49 @@ static inline void fast_snapshot_pre_create_incremental_operation(fast_reload_t*
nyx_block_snapshot_switch_incremental(self->block_state);
}
-static inline void fast_snapshot_create_incremental_operation(fast_reload_t* self){
+static inline void fast_snapshot_create_incremental_operation(fast_reload_t *self)
+{
shadow_memory_prepare_incremental(self->shadow_memory_state);
nyx_device_state_save_tsc_incremental(self->device_state);
- switch(mode){
- case RELOAD_MEMORY_MODE_DEBUG:
- nyx_snapshot_debug_save_root_pages(self->shadow_memory_state, self->blocklist, true);
- break;
- case RELOAD_MEMORY_MODE_DEBUG_QUIET:
- nyx_snapshot_debug_save_root_pages(self->shadow_memory_state, self->blocklist, false);
- break;
- case RELOAD_MEMORY_MODE_FDL:
- nyx_snapshot_nyx_fdl_save_root_pages(self->fdl_state, self->shadow_memory_state, self->blocklist);
- break;
- case RELOAD_MEMORY_MODE_FDL_DEBUG:
- nyx_snapshot_nyx_fdl_save_root_pages(self->fdl_state, self->shadow_memory_state, self->blocklist);
- nyx_snapshot_debug_save_root_pages(self->shadow_memory_state, self->blocklist, true);
- break;
- case RELOAD_MEMORY_MODE_DIRTY_RING:
- nyx_snapshot_nyx_dirty_ring_save_root_pages(self->dirty_ring_state, self->shadow_memory_state, self->blocklist);
- break;
- case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG:
- nyx_snapshot_nyx_dirty_ring_save_root_pages(self->dirty_ring_state, self->shadow_memory_state, self->blocklist);
- nyx_snapshot_debug_save_root_pages(self->shadow_memory_state, self->blocklist, true);
- break;
+ switch (mode) {
+ case RELOAD_MEMORY_MODE_DEBUG:
+ nyx_snapshot_debug_save_root_pages(self->shadow_memory_state,
+ self->blocklist, true);
+ break;
+ case RELOAD_MEMORY_MODE_DEBUG_QUIET:
+ nyx_snapshot_debug_save_root_pages(self->shadow_memory_state,
+ self->blocklist, false);
+ break;
+ case RELOAD_MEMORY_MODE_FDL:
+ nyx_snapshot_nyx_fdl_save_root_pages(self->fdl_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ break;
+ case RELOAD_MEMORY_MODE_FDL_DEBUG:
+ nyx_snapshot_nyx_fdl_save_root_pages(self->fdl_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ nyx_snapshot_debug_save_root_pages(self->shadow_memory_state,
+ self->blocklist, true);
+ break;
+ case RELOAD_MEMORY_MODE_DIRTY_RING:
+ nyx_snapshot_nyx_dirty_ring_save_root_pages(self->dirty_ring_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ break;
+ case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG:
+ nyx_snapshot_nyx_dirty_ring_save_root_pages(self->dirty_ring_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ nyx_snapshot_debug_save_root_pages(self->shadow_memory_state,
+ self->blocklist, true);
+ break;
}
- nyx_snapshot_nyx_fdl_user_save_root_pages(self->fdl_user_state, self->shadow_memory_state, self->blocklist);
+ nyx_snapshot_nyx_fdl_user_save_root_pages(self->fdl_user_state,
+ self->shadow_memory_state,
+ self->blocklist);
shadow_memory_switch_snapshot(self->shadow_memory_state, true);
kvm_arch_put_registers(qemu_get_cpu(0), KVM_PUT_FULL_STATE_FAST);
@@ -192,61 +227,65 @@ static inline void fast_snapshot_create_incremental_operation(fast_reload_t* sel
}
-fast_reload_t* fast_reload_new(void){
- fast_reload_t* self = malloc(sizeof(fast_reload_t));
+fast_reload_t *fast_reload_new(void)
+{
+ fast_reload_t *self = malloc(sizeof(fast_reload_t));
memset(self, 0x0, sizeof(fast_reload_t));
- self->root_snapshot_created = false;
+ self->root_snapshot_created = false;
self->incremental_snapshot_enabled = false;
self->bitmap_copy = NULL;
- return self;
+ return self;
}
-void fast_reload_set_mode(fast_reload_t* self, FastReloadMemoryMode m){
+void fast_reload_set_mode(fast_reload_t *self, FastReloadMemoryMode m)
+{
assert(!self->root_snapshot_created);
mode = m;
}
-FastReloadMemoryMode fast_reload_get_mode(fast_reload_t* self){
+FastReloadMemoryMode fast_reload_get_mode(fast_reload_t *self)
+{
return mode;
}
-void fast_reload_init(fast_reload_t* self){
+void fast_reload_init(fast_reload_t *self)
+{
self->blocklist = snapshot_page_blocklist_init();
}
/* fix this */
-void fast_reload_destroy(fast_reload_t* self){
-
+void fast_reload_destroy(fast_reload_t *self)
+{
/* TODO: complete me */
- //close(self->vmx_fdl_fd);
- //munmap(self->fdl_data, (self->guest_ram_size/0x1000)*8);
+ // close(self->vmx_fdl_fd);
+ // munmap(self->fdl_data, (self->guest_ram_size/0x1000)*8);
-/*
- munmap(self->ptr, self->guest_ram_size);
+ /*
+ munmap(self->ptr, self->guest_ram_size);
- free(self->black_list_pages);
+ free(self->black_list_pages);
- free(self);
-*/
+ free(self);
+ */
}
-inline static void unlock_snapshot(const char* folder){
- char* info_file;
- char* lock_file;
+inline static void unlock_snapshot(const char *folder)
+{
+ char *info_file;
+ char *lock_file;
/* 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";
+ 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";
fwrite(msg, strlen(msg), 1, f_info);
- }
- else{
- const char* msg = "THIS IS A NYX SNAPSHOT FOLDER!\n";
+ } else {
+ const char *msg = "THIS IS A NYX SNAPSHOT FOLDER!\n";
fwrite(msg, strlen(msg), 1, f_info);
}
fclose(f_info);
@@ -258,23 +297,26 @@ inline static void unlock_snapshot(const char* folder){
free(lock_file);
}
-inline static void wait_for_snapshot(const char* folder){
- char* lock_file;
+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 ) {
+ while (access(lock_file, F_OK) == -1) {
sleep(1);
-
}
free(lock_file);
}
-void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool is_pre_snapshot){
+void fast_reload_serialize_to_file(fast_reload_t *self,
+ const char *folder,
+ bool is_pre_snapshot)
+{
nyx_trace();
/* sanity check */
- if(!folder_exits(folder)){
- nyx_debug_p(RELOAD_PREFIX,"Folder %s does not exist...failed!", folder);
+ if (!folder_exits(folder)) {
+ nyx_debug_p(RELOAD_PREFIX, "Folder %s does not exist...failed!", folder);
assert(0);
}
@@ -286,7 +328,7 @@ void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool
/* block device state */
nyx_block_snapshot_serialize(self->block_state, folder);
-
+
/* NYX's state */
serialize_state(folder, is_pre_snapshot);
@@ -295,14 +337,18 @@ 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){
+static void fast_reload_create_from_snapshot(fast_reload_t *self,
+ const char *folder,
+ bool lock_iothread,
+ bool pre_snapshot)
+{
nyx_trace();
assert(self != NULL);
wait_for_snapshot(folder);
- nyx_debug_p(RELOAD_PREFIX,"=> CREATING FAST RELOAD SNAPSHOT FROM DUMP (located in: %s)", folder);
+ nyx_debug_p(RELOAD_PREFIX,
+ "=> CREATING FAST RELOAD SNAPSHOT FROM DUMP (located in: %s)", folder);
rcu_read_lock();
@@ -311,7 +357,7 @@ static void fast_reload_create_from_snapshot(fast_reload_t* self, const char* fo
cpu_synchronize_all_pre_loadvm();
- if(!pre_snapshot){
+ if (!pre_snapshot) {
memory_global_dirty_log_stop();
memory_global_dirty_log_sync();
}
@@ -320,30 +366,36 @@ static void fast_reload_create_from_snapshot(fast_reload_t* self, const char* fo
rcu_read_unlock();
- if(!pre_snapshot){
+ if (!pre_snapshot) {
deserialize_state(folder);
}
cpu_synchronize_all_post_init();
qemu_get_cpu(0)->vcpu_dirty = true;
kvm_arch_put_registers(qemu_get_cpu(0), KVM_PUT_FULL_STATE);
- if(!pre_snapshot){
+ if (!pre_snapshot) {
nyx_device_state_save_tsc(self->device_state);
}
}
-void fast_reload_create_from_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)
+{
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){
+void fast_reload_create_from_file_pre_image(fast_reload_t *self,
+ const char *folder,
+ bool lock_iothread)
+{
nyx_trace();
fast_reload_create_from_snapshot(self, folder, lock_iothread, true);
}
-void fast_reload_create_in_memory(fast_reload_t* self){
-
+void fast_reload_create_in_memory(fast_reload_t *self)
+{
nyx_trace();
assert(self != NULL);
@@ -358,17 +410,18 @@ void fast_reload_create_in_memory(fast_reload_t* self){
memory_global_dirty_log_sync();
fast_snapshot_init_operation(self, NULL, false);
-
+
rcu_read_unlock();
cpu_synchronize_all_post_init();
}
-void fast_reload_restore(fast_reload_t* self){
- assert(self != NULL);
+void fast_reload_restore(fast_reload_t *self)
+{
+ assert(self != NULL);
self->dirty_pages = 0;
/* flush all pending block writes */
- bdrv_drain_all();
+ bdrv_drain_all();
memory_global_dirty_log_sync();
nyx_block_snapshot_reset(self->block_state);
@@ -387,49 +440,54 @@ void fast_reload_restore(fast_reload_t* self){
}
-bool read_snapshot_memory(fast_reload_t* self, uint64_t address, void* ptr, size_t size){
- return shadow_memory_read_physical_memory(self->shadow_memory_state, address, ptr, size);
+bool read_snapshot_memory(fast_reload_t *self, uint64_t address, void *ptr, size_t size)
+{
+ return shadow_memory_read_physical_memory(self->shadow_memory_state, address,
+ ptr, size);
}
/* fix this */
-void* fast_reload_get_physmem_shadow_ptr(fast_reload_t* self, uint64_t physaddr){
-
- abort(); /* TODO: fix this function first -> pc_piix memory split issue */
+void *fast_reload_get_physmem_shadow_ptr(fast_reload_t *self, uint64_t physaddr)
+{
+ abort(); /* TODO: fix this function first -> pc_piix memory split issue */
/*
- assert(self != NULL);
- assert(!(physaddr&0xFFF)); // physaddr must be 4kb align !
+ assert(self != NULL);
+ assert(!(physaddr&0xFFF)); // physaddr must be 4kb align !
if (self->shadow_memory_regions){
for(uint64_t j = 0; j < self->shadow_memory_regions; j++){
- if(physaddr >= self->ram_block_array[j]->offset && physaddr < (self->ram_block_array[j]->offset+self->ram_block_array[j]->used_length)){
- return self->shadow_memory[j]+(physaddr-self->ram_block_array[j]->offset);
- }
+ if(physaddr >= self->ram_block_array[j]->offset && physaddr <
+ (self->ram_block_array[j]->offset+self->ram_block_array[j]->used_length)){ return
+ self->shadow_memory[j]+(physaddr-self->ram_block_array[j]->offset);
+ }
}
}
*/
- return NULL; // not found ... sorry :(
+ return NULL; // not found ... sorry :(
}
-void fast_reload_blacklist_page(fast_reload_t* self, uint64_t physaddr){
-
+void fast_reload_blacklist_page(fast_reload_t *self, uint64_t physaddr)
+{
assert(self->blocklist);
snapshot_page_blocklist_add(self->blocklist, physaddr);
}
-bool fast_reload_snapshot_exists(fast_reload_t* self){
- if(!self){
- return false;
- }
- return true;
+bool fast_reload_snapshot_exists(fast_reload_t *self)
+{
+ if (!self) {
+ return false;
+ }
+ return true;
}
-void fast_reload_create_tmp_snapshot(fast_reload_t* self){
- assert(self);
+void fast_reload_create_tmp_snapshot(fast_reload_t *self)
+{
+ assert(self);
self->dirty_pages = 0;
fast_snapshot_pre_create_incremental_operation(self);
- if(!self->bitmap_copy){
+ if (!self->bitmap_copy) {
self->bitmap_copy = new_coverage_bitmaps();
}
coverage_bitmap_copy_to_buffer(self->bitmap_copy);
@@ -438,7 +496,8 @@ void fast_reload_create_tmp_snapshot(fast_reload_t* self){
self->incremental_snapshot_enabled = true;
}
-void fast_reload_discard_tmp_snapshot(fast_reload_t* self){
+void fast_reload_discard_tmp_snapshot(fast_reload_t *self)
+{
assert(self && self->incremental_snapshot_enabled);
self->dirty_pages = 0;
@@ -459,45 +518,53 @@ void fast_reload_discard_tmp_snapshot(fast_reload_t* self){
self->incremental_snapshot_enabled = false;
}
-bool fast_reload_root_created(fast_reload_t* self){
+bool fast_reload_root_created(fast_reload_t *self)
+{
return self->root_snapshot_created;
}
-bool fast_reload_tmp_created(fast_reload_t* self){
+bool fast_reload_tmp_created(fast_reload_t *self)
+{
return self->incremental_snapshot_enabled;
}
-uint32_t get_dirty_page_num(fast_reload_t* self){
- if(self){
+uint32_t get_dirty_page_num(fast_reload_t *self)
+{
+ if (self) {
return self->dirty_pages;
- }
- else{
-
+ } else {
return 0;
}
}
-bool fast_reload_set_bitmap(fast_reload_t* self){
- if(self->incremental_snapshot_enabled){
+bool fast_reload_set_bitmap(fast_reload_t *self)
+{
+ if (self->incremental_snapshot_enabled) {
coverage_bitmap_copy_from_buffer(self->bitmap_copy);
return true;
}
return false;
}
-void fast_reload_qemu_user_fdl_set_dirty(fast_reload_t* self, MemoryRegion *mr, uint64_t addr, uint64_t length){
+void fast_reload_qemu_user_fdl_set_dirty(fast_reload_t *self,
+ MemoryRegion *mr,
+ uint64_t addr,
+ uint64_t length)
+{
/* works only with PC.RAM's memory region */
assert(mr->alias_offset == 0);
- nyx_fdl_user_set(self->fdl_user_state, self->shadow_memory_state, self->fdl_state, addr, length);
+ nyx_fdl_user_set(self->fdl_user_state, self->shadow_memory_state,
+ self->fdl_state, addr, length);
}
-void fast_reload_handle_dirty_ring_full(fast_reload_t* self){
- if(self->dirty_ring_state){
- nyx_snapshot_nyx_dirty_ring_flush_and_collect(self->dirty_ring_state, self->shadow_memory_state, self->blocklist);
- }
- else{
+void fast_reload_handle_dirty_ring_full(fast_reload_t *self)
+{
+ if (self->dirty_ring_state) {
+ nyx_snapshot_nyx_dirty_ring_flush_and_collect(self->dirty_ring_state,
+ self->shadow_memory_state,
+ self->blocklist);
+ } else {
nyx_snapshot_nyx_dirty_ring_flush();
}
-
}
diff --git a/nyx/fast_vm_reload.h b/nyx/fast_vm_reload.h
index 7edff2669e..eb80bb4d4e 100644
--- a/nyx/fast_vm_reload.h
+++ b/nyx/fast_vm_reload.h
@@ -21,115 +21,123 @@ along with QEMU-PT. If not, see .
#pragma once
-#include"monitor/monitor.h"
-#include"sysemu/runstate.h"
-#include"qemu-common.h"
+#include "monitor/monitor.h"
+#include "sysemu/runstate.h"
+#include "qemu-common.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/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/helpers.h"
+#include "nyx/helpers.h"
typedef enum FastReloadMemoryMode {
- RELOAD_MEMORY_MODE_DEBUG, /* memcmp-based dirty tracing - it's super slow - only for debug purposes */
- RELOAD_MEMORY_MODE_DEBUG_QUIET, /* debug mode in non-verbose mode */
- RELOAD_MEMORY_MODE_FDL, /* super fast page tracker build around KVM-PT's dirty tracker (FDL = fast dirty log) */
- RELOAD_MEMORY_MODE_FDL_DEBUG, /* FDL + debug mode */
- RELOAD_MEMORY_MODE_DIRTY_RING, /* fast page tracker build around KVM's dirty ring API */
- RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG, /* dirty ring + debug mode */
+ RELOAD_MEMORY_MODE_DEBUG, /* memcmp-based dirty tracing - it's super slow - only for debug purposes */
+ RELOAD_MEMORY_MODE_DEBUG_QUIET, /* debug mode in non-verbose mode */
+ RELOAD_MEMORY_MODE_FDL, /* super fast page tracker build around KVM-PT's dirty tracker (FDL = fast dirty log) */
+ RELOAD_MEMORY_MODE_FDL_DEBUG, /* FDL + debug mode */
+ RELOAD_MEMORY_MODE_DIRTY_RING, /* fast page tracker build around KVM's dirty ring API */
+ RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG, /* dirty ring + debug mode */
} FastReloadMemoryMode;
-
-typedef struct fast_reload_dump_head_s{
- uint32_t shadow_memory_regions;
- uint32_t ram_region_index;
-} fast_reload_dump_head_t;
+typedef struct fast_reload_dump_head_s {
+ uint32_t shadow_memory_regions;
+ uint32_t ram_region_index;
+} fast_reload_dump_head_t;
-typedef struct fast_reload_s{
+typedef struct fast_reload_s {
+ FastReloadMemoryMode mode;
- FastReloadMemoryMode mode;
+ /* memory snapshot */
+ shadow_memory_t *shadow_memory_state;
- /* memory snapshot */
- shadow_memory_t* shadow_memory_state;
+ /* state of page frame blocklist */
+ snapshot_page_blocklist_t *blocklist;
- /* state of page frame blocklist */
- snapshot_page_blocklist_t* blocklist;
+ /* state of FDL */
+ nyx_fdl_t *fdl_state;
- /* state of FDL */
- nyx_fdl_t* fdl_state;
+ /* dirty ring state */
+ nyx_dirty_ring_t *dirty_ring_state;
- /* dirty ring state */
- nyx_dirty_ring_t* dirty_ring_state;
+ /* state of user-level FDL */
+ nyx_fdl_user_t *fdl_user_state;
- /* state of user-level FDL */
- nyx_fdl_user_t* fdl_user_state;
+ /* nyx's serialized device state */
+ nyx_device_state_t *device_state;
- /* nyx's serialized device state */
- nyx_device_state_t* device_state;
+ nyx_block_t *block_state;
- nyx_block_t* block_state;
+ bool root_snapshot_created;
+ bool incremental_snapshot_enabled;
- bool root_snapshot_created;
- bool incremental_snapshot_enabled;
-
- /* copy of the fuzzing bitmap & ijon state buffer */
- nyx_coverage_bitmap_copy_t* bitmap_copy;
+ /* copy of the fuzzing bitmap & ijon state buffer */
+ nyx_coverage_bitmap_copy_t *bitmap_copy;
-
- uint32_t dirty_pages;
+ uint32_t dirty_pages;
} fast_reload_t;
-fast_reload_t* fast_reload_new(void);
+fast_reload_t *fast_reload_new(void);
/* 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);
+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);
/* keep this */
-void fast_reload_create_in_memory(fast_reload_t* self);
+void fast_reload_create_in_memory(fast_reload_t *self);
-void fast_reload_serialize_to_file(fast_reload_t* self, const char* folder, bool is_pre_snapshot);
+void fast_reload_serialize_to_file(fast_reload_t *self,
+ const char *folder,
+ bool is_pre_snapshot);
-void fast_reload_restore(fast_reload_t* self);
-void fast_reload_blacklist_page(fast_reload_t* self, uint64_t physaddr);
-void* fast_reload_get_physmem_shadow_ptr(fast_reload_t* self, uint64_t physaddr);
-bool fast_reload_snapshot_exists(fast_reload_t* self);
+void fast_reload_restore(fast_reload_t *self);
+void fast_reload_blacklist_page(fast_reload_t *self, uint64_t physaddr);
+void *fast_reload_get_physmem_shadow_ptr(fast_reload_t *self, uint64_t physaddr);
+bool fast_reload_snapshot_exists(fast_reload_t *self);
-bool read_snapshot_memory(fast_reload_t* self, uint64_t address, void* ptr, size_t size);
+bool read_snapshot_memory(fast_reload_t *self, uint64_t address, void *ptr, size_t size);
-void fast_reload_destroy(fast_reload_t* self);
+void fast_reload_destroy(fast_reload_t *self);
-void fast_reload_qemu_user_fdl_set_dirty(fast_reload_t* self, MemoryRegion *mr, uint64_t addr, uint64_t length);
+void fast_reload_qemu_user_fdl_set_dirty(fast_reload_t *self,
+ MemoryRegion *mr,
+ uint64_t addr,
+ uint64_t length);
-void fast_reload_create_tmp_snapshot(fast_reload_t* self);
-void fast_reload_discard_tmp_snapshot(fast_reload_t* self);
+void fast_reload_create_tmp_snapshot(fast_reload_t *self);
+void fast_reload_discard_tmp_snapshot(fast_reload_t *self);
-bool fast_reload_root_created(fast_reload_t* self);
-bool fast_reload_tmp_created(fast_reload_t* self);
+bool fast_reload_root_created(fast_reload_t *self);
+bool fast_reload_tmp_created(fast_reload_t *self);
-bool fast_reload_set_bitmap(fast_reload_t* self);
+bool fast_reload_set_bitmap(fast_reload_t *self);
-uint32_t get_dirty_page_num(fast_reload_t* self);
+uint32_t get_dirty_page_num(fast_reload_t *self);
-void fast_reload_init(fast_reload_t* self);
+void fast_reload_init(fast_reload_t *self);
-void fast_reload_set_mode(fast_reload_t* self, FastReloadMemoryMode m);
+void fast_reload_set_mode(fast_reload_t *self, FastReloadMemoryMode m);
-void fast_reload_handle_dirty_ring_full(fast_reload_t* self);
-FastReloadMemoryMode fast_reload_get_mode(fast_reload_t* self);
+void fast_reload_handle_dirty_ring_full(fast_reload_t *self);
+FastReloadMemoryMode fast_reload_get_mode(fast_reload_t *self);
diff --git a/nyx/fast_vm_reload_sync.c b/nyx/fast_vm_reload_sync.c
index 1ca9def223..fcbce67e15 100644
--- a/nyx/fast_vm_reload_sync.c
+++ b/nyx/fast_vm_reload_sync.c
@@ -1,346 +1,360 @@
-#include"qemu/osdep.h"
+#include "qemu/osdep.h"
-#include
-#include
-#include
+#include
+#include
+#include
-#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 "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 "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"
+#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);
-static void adjust_rip(CPUX86State *env, fast_reload_t* snapshot){
- switch(fast_reload_get_mode(snapshot)){
- case RELOAD_MEMORY_MODE_DEBUG:
- case RELOAD_MEMORY_MODE_DEBUG_QUIET:
- env->eip -= 1; /* out */
- break;
+static void adjust_rip(CPUX86State *env, fast_reload_t *snapshot)
+{
+ switch (fast_reload_get_mode(snapshot)) {
+ case RELOAD_MEMORY_MODE_DEBUG:
+ case RELOAD_MEMORY_MODE_DEBUG_QUIET:
+ env->eip -= 1; /* out */
+ break;
case RELOAD_MEMORY_MODE_FDL:
case RELOAD_MEMORY_MODE_FDL_DEBUG:
- env->eip -= 3; /* vmcall */
- break;
+ env->eip -= 3; /* vmcall */
+ break;
case RELOAD_MEMORY_MODE_DIRTY_RING:
case RELOAD_MEMORY_MODE_DIRTY_RING_DEBUG:
- env->eip -= 1; /* out */
- break;
- }
-}
-
-fast_vm_reload_sync_t* init_fast_vm_reload_sync(void){
- fast_vm_reload_sync_t* self = malloc(sizeof(fast_vm_reload_sync_t));
- memset(self, 0, sizeof(fast_vm_reload_sync_t));
-
- self->request_exists = false;
- self->request_exists_pre = false;
- self->current_request = REQUEST_VOID;
- self->debug_mode = false;
-
- /* TODO: only RELOAD_MODE_NO_BLOCK is supported for actual fuzzing */
- self->mode = RELOAD_MODE_NO_BLOCK;
-
- return self;
-}
-
-bool fast_snapshot_exists(fast_vm_reload_sync_t* self, FastReloadRequest type){
-
- assert(self->mode != RELOAD_MODE_DEBUG);
-
- switch(type){
- case REQUEST_PRE_EXISTS:
- abort();
- case REQUEST_ROOT_EXISTS:
- return fast_reload_root_created(get_fast_reload_snapshot());
- case REQUEST_TMP_EXISTS:
- return fast_reload_tmp_created(get_fast_reload_snapshot());
- default:
- abort();
- }
-}
-
-
-
-static inline void perform_task_debug_mode(fast_vm_reload_sync_t* self, FastReloadRequest request){
- struct Error* errp = NULL;
-
- switch(request){
- case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
- abort();
- case REQUEST_SAVE_SNAPSHOT_PRE:
- vm_stop(RUN_STATE_SAVE_VM);
- save_snapshot("pre_root", &errp);
- qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
- return; /* return here to skip the vm_start call */
- case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
- abort();
- case REQUEST_SAVE_SNAPSHOT_ROOT:
- vm_stop(RUN_STATE_SAVE_VM);
- save_snapshot("root", &errp);
- break;
- case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
- abort();
- case REQUEST_SAVE_SNAPSHOT_TMP:
- vm_stop(RUN_STATE_SAVE_VM);
- save_snapshot("tmp", &errp);
- break;
- case REQUEST_LOAD_SNAPSHOT_PRE:
- /* probably never called */
- abort();
- break;
- case REQUEST_LOAD_SNAPSHOT_ROOT:
- vm_stop(RUN_STATE_RESTORE_VM);
- load_snapshot("root", &errp);
- break;
- case REQUEST_LOAD_SNAPSHOT_TMP:
- vm_stop(RUN_STATE_RESTORE_VM);
- load_snapshot("tmp", &errp);
- break;
-
- default:
- abort();
- }
- if (errp) {
- error_reportf_err(errp, "Error: ");
- errp = NULL;
- abort();
- }
- vm_start();
-}
-
-static inline void create_root_snapshot(void){
- if (GET_GLOBAL_STATE()->fast_reload_enabled){
- nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_enabled: TRUE\n");
- if (GET_GLOBAL_STATE()->fast_reload_mode){
- nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_mode: TRUE\n");
- /* we've loaded an external snapshot folder - so do nothing and don't create any new snapshot files */
- }
- else{
- nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_mode: FALSE\n");
- /* store the current state as a snapshot folder */
- fast_reload_create_in_memory(get_fast_reload_snapshot());
- fast_reload_serialize_to_file(get_fast_reload_snapshot(), GET_GLOBAL_STATE()->fast_reload_path, false);
+ env->eip -= 1; /* out */
+ break;
}
- }
- else{
- nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_enabled: FALSE\n");
- /* so we haven't set a path for our snapshot files - just store everything in memory */
- fast_reload_create_in_memory(get_fast_reload_snapshot());
- }
}
-static inline void perform_task_no_block_mode(fast_vm_reload_sync_t* self, FastReloadRequest request){
- CPUState* cpu = qemu_get_cpu(0);
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
-
- qemu_mutex_lock_iothread();
+fast_vm_reload_sync_t *init_fast_vm_reload_sync(void)
+{
+ fast_vm_reload_sync_t *self = malloc(sizeof(fast_vm_reload_sync_t));
+ memset(self, 0, sizeof(fast_vm_reload_sync_t));
- switch(request){
- case REQUEST_SAVE_SNAPSHOT_PRE:
- vm_stop(RUN_STATE_SAVE_VM);
- 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);
- qemu_mutex_unlock_iothread();
- return; /* return here to skip the vm_start call */
- case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
- 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());
- 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:
- fast_reload_restore(get_fast_reload_snapshot());
- break;
- case REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP:
- kvm_arch_get_registers(cpu);
-
- adjust_rip(env, get_fast_reload_snapshot());
- set_nested_rip(cpu, env->eip);
- kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
-
- 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();
- cpu_resume(cpu);
- qemu_mutex_unlock_iothread();
-}
-
-static inline void perform_task_block_mode(fast_vm_reload_sync_t* self, FastReloadRequest request){
- switch(request){
- case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
- case REQUEST_SAVE_SNAPSHOT_PRE:
- vm_stop(RUN_STATE_SAVE_VM);
- 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);
- return; /* return here to skip the vm_start call */
- case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
- case REQUEST_SAVE_SNAPSHOT_ROOT:
- /* TODO: fix this */
- vm_stop(RUN_STATE_SAVE_VM);
- create_root_snapshot(); /* TODO: fix this -> broken in ahci mode */
- break;
- case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
- case REQUEST_SAVE_SNAPSHOT_TMP:
- vm_stop(RUN_STATE_SAVE_VM);
- fast_reload_create_tmp_snapshot(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());
- break;
- default:
- abort();
- }
- vm_start();
-}
-
-static inline void perform_task(fast_vm_reload_sync_t* self, FastReloadRequest request){
- switch(self->mode){
- case RELOAD_MODE_DEBUG:
- abort();
- perform_task_debug_mode(self, request);
- break;
- case RELOAD_MODE_NO_BLOCK:
- perform_task_no_block_mode(self, request);
- break;
- case RELOAD_MODE_BLOCK:
- perform_task_block_mode(self, request);
- break;
- }
-}
-
-void request_fast_vm_reload(fast_vm_reload_sync_t* self, FastReloadRequest request){
- assert(!self->request_exists);
- assert(self->current_request == REQUEST_VOID);
-
- if(self->mode == RELOAD_MODE_NO_BLOCK){
- CPUState* cpu = qemu_get_cpu(0);
- kvm_arch_get_registers(cpu);
- //perform_task(self, request);
- perform_task_no_block_mode(self, request);
- }
- else{
- self->current_request = request;
- self->request_exists = true;
- self->request_exists_pre = true;
- }
-}
-
-bool reload_request_exists(fast_vm_reload_sync_t* self){
- return self->request_exists_pre;
-}
-
-void reload_request_discard_tmp(fast_vm_reload_sync_t* self){
- fast_reload_discard_tmp_snapshot(get_fast_reload_snapshot());
-}
-
-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 = false;
self->request_exists_pre = false;
- abort();
+ self->current_request = REQUEST_VOID;
+ self->debug_mode = false;
- CPUState* cpu = qemu_get_cpu(0);
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
+ /* TODO: only RELOAD_MODE_NO_BLOCK is supported for actual fuzzing */
+ self->mode = RELOAD_MODE_NO_BLOCK;
- kvm_arch_get_registers(cpu);
+ return self;
+}
- switch(self->current_request){
- case REQUEST_VOID:
- fprintf(stderr, "%s: REQUEST_VOID requested!\n", __func__);
+bool fast_snapshot_exists(fast_vm_reload_sync_t *self, FastReloadRequest type)
+{
+ assert(self->mode != RELOAD_MODE_DEBUG);
+
+ switch (type) {
+ case REQUEST_PRE_EXISTS:
abort();
+ case REQUEST_ROOT_EXISTS:
+ return fast_reload_root_created(get_fast_reload_snapshot());
+ case REQUEST_TMP_EXISTS:
+ return fast_reload_tmp_created(get_fast_reload_snapshot());
+ default:
+ abort();
+ }
+}
- case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
- case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
- case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
+
+static inline void perform_task_debug_mode(fast_vm_reload_sync_t *self,
+ FastReloadRequest request)
+{
+ struct Error *errp = NULL;
+
+ switch (request) {
+ case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
+ abort();
+ case REQUEST_SAVE_SNAPSHOT_PRE:
+ vm_stop(RUN_STATE_SAVE_VM);
+ save_snapshot("pre_root", &errp);
+ qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+ return; /* return here to skip the vm_start call */
+ case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
+ abort();
+ case REQUEST_SAVE_SNAPSHOT_ROOT:
+ vm_stop(RUN_STATE_SAVE_VM);
+ save_snapshot("root", &errp);
+ break;
+ case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
+ abort();
+ case REQUEST_SAVE_SNAPSHOT_TMP:
+ vm_stop(RUN_STATE_SAVE_VM);
+ save_snapshot("tmp", &errp);
+ break;
+ case REQUEST_LOAD_SNAPSHOT_PRE:
+ /* probably never called */
+ abort();
+ break;
+ case REQUEST_LOAD_SNAPSHOT_ROOT:
+ vm_stop(RUN_STATE_RESTORE_VM);
+ load_snapshot("root", &errp);
+ break;
+ case REQUEST_LOAD_SNAPSHOT_TMP:
+ vm_stop(RUN_STATE_RESTORE_VM);
+ load_snapshot("tmp", &errp);
+ break;
+
+ default:
+ abort();
+ }
+ if (errp) {
+ error_reportf_err(errp, "Error: ");
+ errp = NULL;
+ abort();
+ }
+ vm_start();
+}
+
+static inline void create_root_snapshot(void)
+{
+ if (GET_GLOBAL_STATE()->fast_reload_enabled) {
+ nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_enabled: TRUE\n");
+ if (GET_GLOBAL_STATE()->fast_reload_mode) {
+ nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_mode: TRUE\n");
+ /* we've loaded an external snapshot folder - so do nothing and don't create any new snapshot files */
+ } else {
+ nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_mode: FALSE\n");
+ /* store the current state as a snapshot folder */
+ fast_reload_create_in_memory(get_fast_reload_snapshot());
+ fast_reload_serialize_to_file(get_fast_reload_snapshot(),
+ GET_GLOBAL_STATE()->fast_reload_path, false);
+ }
+ } else {
+ nyx_debug("===> GET_GLOBAL_STATE()->fast_reload_enabled: FALSE\n");
+ /* so we haven't set a path for our snapshot files - just store everything in memory */
+ fast_reload_create_in_memory(get_fast_reload_snapshot());
+ }
+}
+
+static inline void perform_task_no_block_mode(fast_vm_reload_sync_t *self,
+ FastReloadRequest request)
+{
+ CPUState *cpu = qemu_get_cpu(0);
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+
+ qemu_mutex_lock_iothread();
+
+ switch (request) {
+ case REQUEST_SAVE_SNAPSHOT_PRE:
+ vm_stop(RUN_STATE_SAVE_VM);
+ 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);
+ qemu_mutex_unlock_iothread();
+ return; /* return here to skip the vm_start call */
+ case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
adjust_rip(env, get_fast_reload_snapshot());
- kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
- qemu_system_vmstop_request(RUN_STATE_SAVE_VM);
- break;
+ 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();
- case REQUEST_SAVE_SNAPSHOT_PRE:
- case REQUEST_SAVE_SNAPSHOT_ROOT:
- case REQUEST_SAVE_SNAPSHOT_TMP:
- qemu_system_vmstop_request(RUN_STATE_SAVE_VM);
+ fast_reload_restore(get_fast_reload_snapshot());
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:
+ fast_reload_restore(get_fast_reload_snapshot());
+ break;
+ case REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP:
+ kvm_arch_get_registers(cpu);
- case REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP:
- case REQUEST_SAVE_SNAPSHOT_TMP_NESTED_FIX_RIP:
adjust_rip(env, get_fast_reload_snapshot());
set_nested_rip(cpu, env->eip);
kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
- qemu_system_vmstop_request(RUN_STATE_SAVE_VM);
- case REQUEST_LOAD_SNAPSHOT_PRE:
- case REQUEST_LOAD_SNAPSHOT_ROOT:
- case REQUEST_LOAD_SNAPSHOT_TMP:
- qemu_system_vmstop_request(RUN_STATE_RESTORE_VM);
+ kvm_arch_get_registers(cpu);
+ vm_stop(RUN_STATE_SAVE_VM);
+ create_root_snapshot();
+
+ fast_reload_restore(get_fast_reload_snapshot());
break;
-
- default:
- fprintf(stderr, "%s: Unkown request: %d\n", __func__, self->current_request);
+ default:
abort();
}
- return true;
- }
- return false;
+
+ vm_start();
+ cpu_resume(cpu);
+ qemu_mutex_unlock_iothread();
}
-bool check_if_relood_request_exists_post(fast_vm_reload_sync_t* self){
- if(self->request_exists){
- FastReloadRequest request = self->current_request;
- self->request_exists = false;
-
- assert(self->current_request != REQUEST_VOID);
- self->current_request = REQUEST_VOID;
- perform_task(self, request);
-
- return true;
- }
- return false;
+static inline void perform_task_block_mode(fast_vm_reload_sync_t *self,
+ FastReloadRequest request)
+{
+ switch (request) {
+ case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
+ case REQUEST_SAVE_SNAPSHOT_PRE:
+ vm_stop(RUN_STATE_SAVE_VM);
+ 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);
+ return; /* return here to skip the vm_start call */
+ case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
+ case REQUEST_SAVE_SNAPSHOT_ROOT:
+ /* TODO: fix this */
+ vm_stop(RUN_STATE_SAVE_VM);
+ create_root_snapshot(); /* TODO: fix this -> broken in ahci mode */
+ break;
+ case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
+ case REQUEST_SAVE_SNAPSHOT_TMP:
+ vm_stop(RUN_STATE_SAVE_VM);
+ fast_reload_create_tmp_snapshot(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());
+ break;
+ default:
+ abort();
+ }
+ vm_start();
+}
+
+static inline void perform_task(fast_vm_reload_sync_t *self, FastReloadRequest request)
+{
+ switch (self->mode) {
+ case RELOAD_MODE_DEBUG:
+ abort();
+ perform_task_debug_mode(self, request);
+ break;
+ case RELOAD_MODE_NO_BLOCK:
+ perform_task_no_block_mode(self, request);
+ break;
+ case RELOAD_MODE_BLOCK:
+ perform_task_block_mode(self, request);
+ break;
+ }
+}
+
+void request_fast_vm_reload(fast_vm_reload_sync_t *self, FastReloadRequest request)
+{
+ assert(!self->request_exists);
+ assert(self->current_request == REQUEST_VOID);
+
+ if (self->mode == RELOAD_MODE_NO_BLOCK) {
+ CPUState *cpu = qemu_get_cpu(0);
+ kvm_arch_get_registers(cpu);
+ // perform_task(self, request);
+ perform_task_no_block_mode(self, request);
+ } else {
+ self->current_request = request;
+ self->request_exists = true;
+ self->request_exists_pre = true;
+ }
+}
+
+bool reload_request_exists(fast_vm_reload_sync_t *self)
+{
+ return self->request_exists_pre;
+}
+
+void reload_request_discard_tmp(fast_vm_reload_sync_t *self)
+{
+ fast_reload_discard_tmp_snapshot(get_fast_reload_snapshot());
+}
+
+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();
+
+ CPUState *cpu = qemu_get_cpu(0);
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+
+ kvm_arch_get_registers(cpu);
+
+ switch (self->current_request) {
+ case REQUEST_VOID:
+ fprintf(stderr, "%s: REQUEST_VOID requested!\n", __func__);
+ abort();
+
+ case REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP:
+ case REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP:
+ case REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP:
+ adjust_rip(env, get_fast_reload_snapshot());
+ kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
+ qemu_system_vmstop_request(RUN_STATE_SAVE_VM);
+ break;
+
+ case REQUEST_SAVE_SNAPSHOT_PRE:
+ case REQUEST_SAVE_SNAPSHOT_ROOT:
+ case REQUEST_SAVE_SNAPSHOT_TMP:
+ qemu_system_vmstop_request(RUN_STATE_SAVE_VM);
+ break;
+
+ case REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP:
+ case REQUEST_SAVE_SNAPSHOT_TMP_NESTED_FIX_RIP:
+ adjust_rip(env, get_fast_reload_snapshot());
+ set_nested_rip(cpu, env->eip);
+ kvm_arch_put_registers(cpu, KVM_PUT_FULL_STATE);
+ qemu_system_vmstop_request(RUN_STATE_SAVE_VM);
+
+ case REQUEST_LOAD_SNAPSHOT_PRE:
+ case REQUEST_LOAD_SNAPSHOT_ROOT:
+ case REQUEST_LOAD_SNAPSHOT_TMP:
+ qemu_system_vmstop_request(RUN_STATE_RESTORE_VM);
+ break;
+
+ default:
+ fprintf(stderr, "%s: Unkown request: %d\n", __func__,
+ self->current_request);
+ abort();
+ }
+ return true;
+ }
+ return false;
+}
+
+bool check_if_relood_request_exists_post(fast_vm_reload_sync_t *self)
+{
+ if (self->request_exists) {
+ FastReloadRequest request = self->current_request;
+ self->request_exists = false;
+
+ assert(self->current_request != REQUEST_VOID);
+ self->current_request = REQUEST_VOID;
+ perform_task(self, request);
+
+ return true;
+ }
+ return false;
}
diff --git a/nyx/fast_vm_reload_sync.h b/nyx/fast_vm_reload_sync.h
index 0df77168b0..46c9f7788c 100644
--- a/nyx/fast_vm_reload_sync.h
+++ b/nyx/fast_vm_reload_sync.h
@@ -3,59 +3,57 @@
#include
typedef enum FastReloadRequest {
- REQUEST_VOID,
+ REQUEST_VOID,
- /* create snapshots */
- REQUEST_SAVE_SNAPSHOT_PRE,
- REQUEST_SAVE_SNAPSHOT_ROOT,
- REQUEST_SAVE_SNAPSHOT_TMP,
+ /* create snapshots */
+ REQUEST_SAVE_SNAPSHOT_PRE,
+ REQUEST_SAVE_SNAPSHOT_ROOT,
+ REQUEST_SAVE_SNAPSHOT_TMP,
- /* create snapshot and fix RIP (- sizeof(vmcall)) */
- REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP,
- REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP,
- REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP,
+ /* create snapshot and fix RIP (- sizeof(vmcall)) */
+ REQUEST_SAVE_SNAPSHOT_PRE_FIX_RIP,
+ REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP,
+ REQUEST_SAVE_SNAPSHOT_TMP_FIX_RIP,
- /* create nested snapshots */
- REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP,
- REQUEST_SAVE_SNAPSHOT_TMP_NESTED_FIX_RIP,
+ /* create nested snapshots */
+ REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP,
+ REQUEST_SAVE_SNAPSHOT_TMP_NESTED_FIX_RIP,
- /* load snapshots*/
- REQUEST_LOAD_SNAPSHOT_PRE,
- REQUEST_LOAD_SNAPSHOT_ROOT,
- REQUEST_LOAD_SNAPSHOT_TMP,
+ /* load snapshots*/
+ REQUEST_LOAD_SNAPSHOT_PRE,
+ REQUEST_LOAD_SNAPSHOT_ROOT,
+ REQUEST_LOAD_SNAPSHOT_TMP,
- /* check if snapshot exists */
- REQUEST_PRE_EXISTS,
- REQUEST_ROOT_EXISTS,
- REQUEST_TMP_EXISTS,
+ /* check if snapshot exists */
+ REQUEST_PRE_EXISTS,
+ REQUEST_ROOT_EXISTS,
+ REQUEST_TMP_EXISTS,
- //REQUEST_DISCARD_SNAPSHOT_TMP,
+ // REQUEST_DISCARD_SNAPSHOT_TMP,
} FastReloadRequest;
typedef enum FastReloadMode {
- RELOAD_MODE_DEBUG, /* savevm / loadvm based on QEMU's qcow2 storage - only for debug purposes */
- RELOAD_MODE_NO_BLOCK, /* fastest mode - works only if no active block devices is attached (e.g. initramfs mode) */
- RELOAD_MODE_BLOCK,
+ RELOAD_MODE_DEBUG, /* savevm / loadvm based on QEMU's qcow2 storage - only for debug purposes */
+ RELOAD_MODE_NO_BLOCK, /* fastest mode - works only if no active block devices is attached (e.g. initramfs mode) */
+ RELOAD_MODE_BLOCK,
} FastReloadMode;
-
-typedef struct fast_vm_reload_sync_s{
-
- bool request_exists;
- bool request_exists_pre;
- bool debug_mode;
- FastReloadMode mode;
- FastReloadRequest current_request;
+typedef struct fast_vm_reload_sync_s {
+ bool request_exists;
+ bool request_exists_pre;
+ bool debug_mode;
+ FastReloadMode mode;
+ FastReloadRequest current_request;
} fast_vm_reload_sync_t;
-fast_vm_reload_sync_t* init_fast_vm_reload_sync(void);
-void request_fast_vm_reload(fast_vm_reload_sync_t* self, FastReloadRequest request);
-bool reload_request_exists(fast_vm_reload_sync_t* self);
-bool check_if_relood_request_exists_pre(fast_vm_reload_sync_t* self);
-bool check_if_relood_request_exists_post(fast_vm_reload_sync_t* self);
+fast_vm_reload_sync_t *init_fast_vm_reload_sync(void);
+void request_fast_vm_reload(fast_vm_reload_sync_t *self, FastReloadRequest request);
+bool reload_request_exists(fast_vm_reload_sync_t *self);
+bool check_if_relood_request_exists_pre(fast_vm_reload_sync_t *self);
+bool check_if_relood_request_exists_post(fast_vm_reload_sync_t *self);
-bool fast_snapshot_exists(fast_vm_reload_sync_t* self, FastReloadRequest type);
-void reload_request_discard_tmp(fast_vm_reload_sync_t* self);
\ No newline at end of file
+bool fast_snapshot_exists(fast_vm_reload_sync_t *self, FastReloadRequest type);
+void reload_request_discard_tmp(fast_vm_reload_sync_t *self);
\ No newline at end of file
diff --git a/nyx/file_helper.c b/nyx/file_helper.c
index 35805586e8..a215c210ca 100644
--- a/nyx/file_helper.c
+++ b/nyx/file_helper.c
@@ -1,13 +1,13 @@
#include
#include
-#include
-#include
-#include
#include
+#include
+#include
+#include
#include "nyx/redqueen.h"
-//#include "debug.h"
+// #include "debug.h"
#include "nyx/file_helper.h"
@@ -15,106 +15,119 @@
* Private Helper Functions Declarations
*/
-size_t _count_lines_in_file(FILE* fp);
+size_t _count_lines_in_file(FILE *fp);
-void _parse_addresses_in_file(FILE* fp, size_t num_addrs, uint64_t* addrs);
+void _parse_addresses_in_file(FILE *fp, size_t num_addrs, uint64_t *addrs);
/*
* Public Functions
*/
-void write_debug_result(char* buf){
- int unused __attribute__((unused));
- int fd = open("/tmp/qemu_debug.txt", O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
- assert(fd > 0);
- unused = write(fd, buf, strlen(buf));
- close(fd);
+void write_debug_result(char *buf)
+{
+ int unused __attribute__((unused));
+ int fd = open("/tmp/qemu_debug.txt", O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
+ assert(fd > 0);
+ unused = write(fd, buf, strlen(buf));
+ close(fd);
}
-void parse_address_file(char* path, size_t* num_addrs, uint64_t** addrs){
- FILE* fp = fopen(path,"r");
- if(!fp){
- *num_addrs = 0;
- *addrs = NULL;
- return;
- }
+void parse_address_file(char *path, size_t *num_addrs, uint64_t **addrs)
+{
+ FILE *fp = fopen(path, "r");
+ if (!fp) {
+ *num_addrs = 0;
+ *addrs = NULL;
+ return;
+ }
- *num_addrs = _count_lines_in_file(fp);
- if(*num_addrs == 0){
- *addrs = NULL;
- goto exit_function;
- }
+ *num_addrs = _count_lines_in_file(fp);
+ if (*num_addrs == 0) {
+ *addrs = NULL;
+ goto exit_function;
+ }
- assert(*num_addrs < 0xffff);
- *addrs = malloc(sizeof(uint64_t)*(*num_addrs));
- _parse_addresses_in_file(fp, *num_addrs, *addrs);
+ assert(*num_addrs < 0xffff);
+ *addrs = malloc(sizeof(uint64_t) * (*num_addrs));
+ _parse_addresses_in_file(fp, *num_addrs, *addrs);
- exit_function:
- fclose(fp);
+exit_function:
+ fclose(fp);
}
int re_fd = 0;
int se_fd = 0;
-void write_re_result(char* buf){
- int unused __attribute__((unused));
- if (!re_fd)
- re_fd = open(redqueen_workdir.redqueen_results, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
- unused = write(re_fd, buf, strlen(buf));
+void write_re_result(char *buf)
+{
+ int unused __attribute__((unused));
+ if (!re_fd)
+ re_fd = open(redqueen_workdir.redqueen_results,
+ O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
+ unused = write(re_fd, buf, strlen(buf));
}
-void fsync_redqueen_files(void){
- if (!se_fd){
- fsync(se_fd);
- }
- if (!re_fd){
- fsync(re_fd);
- }
+void fsync_redqueen_files(void)
+{
+ if (!se_fd) {
+ fsync(se_fd);
+ }
+ if (!re_fd) {
+ fsync(re_fd);
+ }
}
-void write_se_result(char* buf){
- //int fd;
- int unused __attribute__((unused));
- if (!se_fd)
- se_fd = open(redqueen_workdir.symbolic_results, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
- unused = write(se_fd, buf, strlen(buf));
- //close(fd);
+void write_se_result(char *buf)
+{
+ // int fd;
+ int unused __attribute__((unused));
+ if (!se_fd)
+ se_fd = open(redqueen_workdir.symbolic_results,
+ O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
+ unused = write(se_fd, buf, strlen(buf));
+ // close(fd);
}
-void delete_redqueen_files(void){
- int unused __attribute__((unused));
- if (!re_fd)
- re_fd = open(redqueen_workdir.redqueen_results, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
- if (!se_fd)
- se_fd = open(redqueen_workdir.symbolic_results, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
- unused = ftruncate(re_fd, 0);
- unused = ftruncate(se_fd, 0);
+void delete_redqueen_files(void)
+{
+ int unused __attribute__((unused));
+ if (!re_fd)
+ re_fd = open(redqueen_workdir.redqueen_results,
+ O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
+ if (!se_fd)
+ se_fd = open(redqueen_workdir.symbolic_results,
+ O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
+ unused = ftruncate(re_fd, 0);
+ unused = ftruncate(se_fd, 0);
}
/*
* Private Helper Functions Definitions
*/
-size_t _count_lines_in_file(FILE* fp){
- size_t val = 0;
- size_t count = 0;
- while(1){
- int scanres = fscanf(fp, "%lx", &val);
- if(scanres == 0){
- printf("WARNING, invalid line in address file");
- assert(scanres != 0);
+size_t _count_lines_in_file(FILE *fp)
+{
+ size_t val = 0;
+ size_t count = 0;
+ while (1) {
+ int scanres = fscanf(fp, "%lx", &val);
+ if (scanres == 0) {
+ printf("WARNING, invalid line in address file");
+ assert(scanres != 0);
+ }
+ if (scanres == -1) {
+ break;
+ }
+ count += 1;
}
- if(scanres == -1){break;}
- count+=1;
- }
- rewind(fp);
- return count;
+ rewind(fp);
+ return count;
}
-void _parse_addresses_in_file(FILE* fp, size_t num_addrs, uint64_t* addrs){
- for(size_t i = 0; i < num_addrs; i++){
- assert(fscanf(fp, "%lx", &addrs[i]) == 1);
- }
+void _parse_addresses_in_file(FILE *fp, size_t num_addrs, uint64_t *addrs)
+{
+ for (size_t i = 0; i < num_addrs; i++) {
+ assert(fscanf(fp, "%lx", &addrs[i]) == 1);
+ }
}
-
diff --git a/nyx/file_helper.h b/nyx/file_helper.h
index 020ebc83d1..fa78ce712e 100644
--- a/nyx/file_helper.h
+++ b/nyx/file_helper.h
@@ -1,20 +1,21 @@
-#include
-#include
-#include
-
#pragma once
-//doesn't take ownership of path, num_addrs or addrs
-void parse_address_file(char* path, size_t* num_addrs, uint64_t** addrs);
+#include
+#include
+#include
-//doesn't take ownership of buf
-void write_re_result(char* buf);
-//doesn't take ownership of buf
-void write_se_result(char* buf);
+// doesn't take ownership of path, num_addrs or addrs
+void parse_address_file(char *path, size_t *num_addrs, uint64_t **addrs);
-//doesn' take ownership of buf
-void write_debug_result(char* buf);
+// doesn't take ownership of buf
+void write_re_result(char *buf);
+
+// doesn't take ownership of buf
+void write_se_result(char *buf);
+
+// doesn' take ownership of buf
+void write_debug_result(char *buf);
void delete_redqueen_files(void);
diff --git a/nyx/helpers.c b/nyx/helpers.c
index 6af3a57673..13f9bca3a9 100644
--- a/nyx/helpers.c
+++ b/nyx/helpers.c
@@ -12,175 +12,226 @@
#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));
- synchronization_lock();
- exit(1);
+void nyx_abort(char *msg)
+{
+ set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, msg,
+ strlen(msg));
+ synchronization_lock();
+ exit(1);
}
-bool is_called_in_fuzzing_mode(const char* hypercall){
- if(GET_GLOBAL_STATE()->in_fuzzing_mode){
- char* tmp = NULL;
- assert(asprintf(&tmp, "Hypercall <%s> called during fuzzing...", hypercall) != -1);
- nyx_abort((char*)tmp);
- free(tmp);
- return true;
- }
- return false;
-}
-
-uint64_t get_rip(CPUState *cpu){
- kvm_arch_get_registers(cpu);
- X86CPU *x86_cpu = X86_CPU(cpu);
- CPUX86State *env = &x86_cpu->env;
- kvm_cpu_synchronize_state(cpu);
- return env->eip;
-}
-
-int get_capstone_mode(int word_width_in_bits){
- switch(word_width_in_bits){
- case 64:
- return CS_MODE_64;
- case 32:
- return CS_MODE_32;
- default:
- assert(false);
- }
-}
-
-nyx_coverage_bitmap_copy_t* new_coverage_bitmaps(void){
- nyx_coverage_bitmap_copy_t* bitmaps = malloc(sizeof(nyx_coverage_bitmap_copy_t));
- memset(bitmaps, 0, sizeof(nyx_coverage_bitmap_copy_t));
-
- assert(GET_GLOBAL_STATE()->shared_bitmap_size);
- bitmaps->coverage_bitmap = malloc(GET_GLOBAL_STATE()->shared_bitmap_size);
-
- assert(GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
- bitmaps->ijon_bitmap_buffer = malloc(GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
-
- return bitmaps;
-}
-
-void coverage_bitmap_reset(void){
- if(GET_GLOBAL_STATE()->shared_bitmap_ptr){
- memset(GET_GLOBAL_STATE()->shared_bitmap_ptr, 0x00, GET_GLOBAL_STATE()->shared_bitmap_real_size);
- }
- if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr && GET_GLOBAL_STATE()->shared_ijon_bitmap_size){
- memset(GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, 0x00, GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
- }
-}
-
-void coverage_bitmap_copy_to_buffer(nyx_coverage_bitmap_copy_t* buffer){
-
- if(GET_GLOBAL_STATE()->shared_bitmap_ptr){
- memcpy(buffer->coverage_bitmap, GET_GLOBAL_STATE()->shared_bitmap_ptr, GET_GLOBAL_STATE()->shared_bitmap_real_size);
- }
- if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr){
- memcpy(buffer->ijon_bitmap_buffer, GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
- }
-}
-
-void coverage_bitmap_copy_from_buffer(nyx_coverage_bitmap_copy_t* buffer){
-
- if(GET_GLOBAL_STATE()->shared_bitmap_ptr){
- memcpy(GET_GLOBAL_STATE()->shared_bitmap_ptr, buffer->coverage_bitmap, GET_GLOBAL_STATE()->shared_bitmap_real_size);
- }
- if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr){
- memcpy(GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, buffer->ijon_bitmap_buffer, GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
- }
-}
-
-static void resize_coverage_bitmap(uint32_t new_bitmap_size){
- uint32_t new_bitmap_shm_size = new_bitmap_size;
-
- if (new_bitmap_shm_size % 64 > 0) {
- new_bitmap_shm_size = ((new_bitmap_shm_size + 64) >> 6) << 6;
+bool is_called_in_fuzzing_mode(const char *hypercall)
+{
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
+ char *tmp = NULL;
+ assert(asprintf(&tmp, "Hypercall <%s> called during fuzzing...", hypercall) !=
+ -1);
+ nyx_abort((char *)tmp);
+ free(tmp);
+ return true;
}
+ return false;
+}
- GET_GLOBAL_STATE()->shared_bitmap_real_size = new_bitmap_shm_size;
- resize_shared_memory(new_bitmap_shm_size, &GET_GLOBAL_STATE()->shared_bitmap_size, &GET_GLOBAL_STATE()->shared_bitmap_ptr, GET_GLOBAL_STATE()->shared_bitmap_fd);
+uint64_t get_rip(CPUState *cpu)
+{
+ kvm_arch_get_registers(cpu);
+ X86CPU *x86_cpu = X86_CPU(cpu);
+ CPUX86State *env = &x86_cpu->env;
+ kvm_cpu_synchronize_state(cpu);
+ return env->eip;
+}
- /* pass the actual bitmap buffer size to the front-end */
- GET_GLOBAL_STATE()->auxilary_buffer->capabilites.agent_coverage_bitmap_size = new_bitmap_size;
-
- if(new_bitmap_size & (PAGE_SIZE-1)){
- GET_GLOBAL_STATE()->shared_bitmap_size = (new_bitmap_size & ~(PAGE_SIZE-1)) + PAGE_SIZE;
+int get_capstone_mode(int word_width_in_bits)
+{
+ switch (word_width_in_bits) {
+ case 64:
+ return CS_MODE_64;
+ case 32:
+ return CS_MODE_32;
+ default:
+ assert(false);
}
}
-bool apply_capabilities(CPUState *cpu){
+nyx_coverage_bitmap_copy_t *new_coverage_bitmaps(void)
+{
+ nyx_coverage_bitmap_copy_t *bitmaps = malloc(sizeof(nyx_coverage_bitmap_copy_t));
+ memset(bitmaps, 0, sizeof(nyx_coverage_bitmap_copy_t));
- 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);
- nyx_debug("%s: agent supports compile-time tracing: %d\n", __func__, GET_GLOBAL_STATE()->cap_compile_time_tracing );
+ assert(GET_GLOBAL_STATE()->shared_bitmap_size);
+ bitmaps->coverage_bitmap = malloc(GET_GLOBAL_STATE()->shared_bitmap_size);
- if(GET_GLOBAL_STATE()->cap_compile_time_tracing){
- GET_GLOBAL_STATE()->pt_trace_mode = false;
+ assert(GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
+ bitmaps->ijon_bitmap_buffer = malloc(GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
- nyx_debug("%s: agent trace buffer at vaddr: %lx\n", __func__, GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr);
- kvm_arch_get_registers_fast(cpu);
-
- nyx_debug("--------------------------\n");
- nyx_debug("GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr: %lx\n", GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr);
- nyx_debug("GET_GLOBAL_STATE()->shared_bitmap_fd: %d\n", GET_GLOBAL_STATE()->shared_bitmap_fd);
- nyx_debug("GET_GLOBAL_STATE()->shared_bitmap_size: %x\n", GET_GLOBAL_STATE()->shared_bitmap_size);
- nyx_debug("GET_GLOBAL_STATE()->cap_cr3: %lx\n", GET_GLOBAL_STATE()->cap_cr3);
- nyx_debug("--------------------------\n");
-
- if (GET_GLOBAL_STATE()->input_buffer_size != GET_GLOBAL_STATE()->shared_payload_buffer_size){
- resize_shared_memory(GET_GLOBAL_STATE()->input_buffer_size, &GET_GLOBAL_STATE()->shared_payload_buffer_size, NULL, GET_GLOBAL_STATE()->shared_payload_buffer_fd);
- GET_GLOBAL_STATE()->shared_payload_buffer_size = GET_GLOBAL_STATE()->input_buffer_size;
- }
-
- if(GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr&0xfff){
- fprintf(stderr, "[QEMU-Nyx] Error: guest's trace bitmap v_addr (0x%lx) is not page aligned!\n", GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr);
- return false;
- }
-
- if (GET_GLOBAL_STATE()->cap_coverage_bitmap_size){
- resize_coverage_bitmap(GET_GLOBAL_STATE()->cap_coverage_bitmap_size);
- }
-
- for(uint64_t i = 0; i < GET_GLOBAL_STATE()->shared_bitmap_size; i += 0x1000){
- assert(remap_slot(GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr+ i, i/0x1000, cpu, GET_GLOBAL_STATE()->shared_bitmap_fd, GET_GLOBAL_STATE()->shared_bitmap_size, true, GET_GLOBAL_STATE()->cap_cr3));
- }
- set_cap_agent_trace_bitmap(GET_GLOBAL_STATE()->auxilary_buffer, true);
- }
-
- if(GET_GLOBAL_STATE()->cap_ijon_tracing){
- nyx_debug("%s: agent trace buffer at vaddr: %lx\n", __func__, GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr);
-
- if(GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr&0xfff){
- error_printf("[QEMU-Nyx] Error: guest's ijon buffer v_addr (0x%lx) is not page aligned!\n", GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr);
- return false;
- }
-
- kvm_arch_get_registers_fast(cpu);
- for(uint64_t i = 0; i < GET_GLOBAL_STATE()->shared_ijon_bitmap_size; i += 0x1000){
- assert(remap_slot(GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr + i, i/0x1000, cpu, GET_GLOBAL_STATE()->shared_ijon_bitmap_fd, GET_GLOBAL_STATE()->shared_ijon_bitmap_size+GET_GLOBAL_STATE()->shared_ijon_bitmap_size, true, GET_GLOBAL_STATE()->cap_cr3));
- }
- set_cap_agent_ijon_trace_bitmap(GET_GLOBAL_STATE()->auxilary_buffer, true);
- }
-
-
- /* pass the actual input buffer size to the front-end */
- GET_GLOBAL_STATE()->auxilary_buffer->capabilites.agent_input_buffer_size = GET_GLOBAL_STATE()->shared_payload_buffer_size;
-
- return true;
+ return bitmaps;
}
-bool folder_exits(const char* path){
- struct stat sb;
- return (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
+void coverage_bitmap_reset(void)
+{
+ if (GET_GLOBAL_STATE()->shared_bitmap_ptr) {
+ memset(GET_GLOBAL_STATE()->shared_bitmap_ptr, 0x00,
+ GET_GLOBAL_STATE()->shared_bitmap_real_size);
+ }
+ if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr &&
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size)
+ {
+ memset(GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, 0x00,
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
+ }
}
-bool file_exits(const char* path){
- struct stat sb;
- return (stat (path, &sb) == 0);
+void coverage_bitmap_copy_to_buffer(nyx_coverage_bitmap_copy_t *buffer)
+{
+ if (GET_GLOBAL_STATE()->shared_bitmap_ptr) {
+ memcpy(buffer->coverage_bitmap, GET_GLOBAL_STATE()->shared_bitmap_ptr,
+ GET_GLOBAL_STATE()->shared_bitmap_real_size);
+ }
+ if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr) {
+ memcpy(buffer->ijon_bitmap_buffer, GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr,
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
+ }
+}
+
+void coverage_bitmap_copy_from_buffer(nyx_coverage_bitmap_copy_t *buffer)
+{
+ if (GET_GLOBAL_STATE()->shared_bitmap_ptr) {
+ memcpy(GET_GLOBAL_STATE()->shared_bitmap_ptr, buffer->coverage_bitmap,
+ GET_GLOBAL_STATE()->shared_bitmap_real_size);
+ }
+ if (GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr) {
+ memcpy(GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr, buffer->ijon_bitmap_buffer,
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size);
+ }
+}
+
+static void resize_coverage_bitmap(uint32_t new_bitmap_size)
+{
+ uint32_t new_bitmap_shm_size = new_bitmap_size;
+
+ if (new_bitmap_shm_size % 64 > 0) {
+ new_bitmap_shm_size = ((new_bitmap_shm_size + 64) >> 6) << 6;
+ }
+
+ GET_GLOBAL_STATE()->shared_bitmap_real_size = new_bitmap_shm_size;
+ resize_shared_memory(new_bitmap_shm_size, &GET_GLOBAL_STATE()->shared_bitmap_size,
+ &GET_GLOBAL_STATE()->shared_bitmap_ptr,
+ GET_GLOBAL_STATE()->shared_bitmap_fd);
+
+ /* pass the actual bitmap buffer size to the front-end */
+ GET_GLOBAL_STATE()->auxilary_buffer->capabilites.agent_coverage_bitmap_size =
+ new_bitmap_size;
+
+ if (new_bitmap_size & (PAGE_SIZE - 1)) {
+ GET_GLOBAL_STATE()->shared_bitmap_size =
+ (new_bitmap_size & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
+ }
+}
+
+bool apply_capabilities(CPUState *cpu)
+{
+ 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);
+ nyx_debug("%s: agent supports compile-time tracing: %d\n", __func__,
+ GET_GLOBAL_STATE()->cap_compile_time_tracing);
+
+ if (GET_GLOBAL_STATE()->cap_compile_time_tracing) {
+ GET_GLOBAL_STATE()->pt_trace_mode = false;
+
+ nyx_debug("%s: agent trace buffer at vaddr: %lx\n", __func__,
+ GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr);
+ kvm_arch_get_registers_fast(cpu);
+
+ nyx_debug("--------------------------\n");
+ nyx_debug("GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr: %lx\n",
+ GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr);
+ nyx_debug("GET_GLOBAL_STATE()->shared_bitmap_fd: %d\n",
+ GET_GLOBAL_STATE()->shared_bitmap_fd);
+ nyx_debug("GET_GLOBAL_STATE()->shared_bitmap_size: %x\n",
+ GET_GLOBAL_STATE()->shared_bitmap_size);
+ nyx_debug("GET_GLOBAL_STATE()->cap_cr3: %lx\n", GET_GLOBAL_STATE()->cap_cr3);
+ nyx_debug("--------------------------\n");
+
+ if (GET_GLOBAL_STATE()->input_buffer_size !=
+ GET_GLOBAL_STATE()->shared_payload_buffer_size)
+ {
+ resize_shared_memory(GET_GLOBAL_STATE()->input_buffer_size,
+ &GET_GLOBAL_STATE()->shared_payload_buffer_size,
+ NULL, GET_GLOBAL_STATE()->shared_payload_buffer_fd);
+ GET_GLOBAL_STATE()->shared_payload_buffer_size =
+ GET_GLOBAL_STATE()->input_buffer_size;
+ }
+
+ if (GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr & 0xfff) {
+ fprintf(stderr, "[QEMU-Nyx] Error: guest's trace bitmap v_addr (0x%lx) is not page aligned!\n",
+ GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr);
+ return false;
+ }
+
+ if (GET_GLOBAL_STATE()->cap_coverage_bitmap_size) {
+ resize_coverage_bitmap(GET_GLOBAL_STATE()->cap_coverage_bitmap_size);
+ }
+
+ for (uint64_t i = 0; i < GET_GLOBAL_STATE()->shared_bitmap_size; i += 0x1000)
+ {
+ assert(remap_slot(GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr +
+ i,
+ i / 0x1000, cpu, GET_GLOBAL_STATE()->shared_bitmap_fd,
+ GET_GLOBAL_STATE()->shared_bitmap_size, true,
+ GET_GLOBAL_STATE()->cap_cr3));
+ }
+ set_cap_agent_trace_bitmap(GET_GLOBAL_STATE()->auxilary_buffer, true);
+ }
+
+ if (GET_GLOBAL_STATE()->cap_ijon_tracing) {
+ nyx_debug("%s: agent trace buffer at vaddr: %lx\n", __func__,
+ GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr);
+
+ if (GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr & 0xfff) {
+ error_printf("[QEMU-Nyx] Error: guest's ijon buffer v_addr (0x%lx) is "
+ "not page aligned!\n",
+ GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr);
+ return false;
+ }
+
+ kvm_arch_get_registers_fast(cpu);
+ for (uint64_t i = 0; i < GET_GLOBAL_STATE()->shared_ijon_bitmap_size;
+ i += 0x1000)
+ {
+ assert(remap_slot(GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr + i,
+ i / 0x1000, cpu,
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_fd,
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size +
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size,
+ true, GET_GLOBAL_STATE()->cap_cr3));
+ }
+ set_cap_agent_ijon_trace_bitmap(GET_GLOBAL_STATE()->auxilary_buffer, true);
+ }
+
+
+ /* pass the actual input buffer size to the front-end */
+ GET_GLOBAL_STATE()->auxilary_buffer->capabilites.agent_input_buffer_size =
+ GET_GLOBAL_STATE()->shared_payload_buffer_size;
+
+ return true;
+}
+
+bool folder_exits(const char *path)
+{
+ struct stat sb;
+ return (stat(path, &sb) == 0 && S_ISDIR(sb.st_mode));
+}
+
+bool file_exits(const char *path)
+{
+ struct stat sb;
+ return (stat(path, &sb) == 0);
}
diff --git a/nyx/helpers.h b/nyx/helpers.h
index 031dac3910..648aed02ad 100644
--- a/nyx/helpers.h
+++ b/nyx/helpers.h
@@ -1,23 +1,23 @@
-#pragma once
+#pragma once
uint64_t get_rip(CPUState *cpu);
-typedef struct nyx_coverage_bitmap_copy_s{
- void* coverage_bitmap;
- void* ijon_bitmap_buffer;
-}nyx_coverage_bitmap_copy_t;
+typedef struct nyx_coverage_bitmap_copy_s {
+ void *coverage_bitmap;
+ void *ijon_bitmap_buffer;
+} nyx_coverage_bitmap_copy_t;
-void nyx_abort(char* msg);
-bool is_called_in_fuzzing_mode(const char* hypercall);
+void nyx_abort(char *msg);
+bool is_called_in_fuzzing_mode(const char *hypercall);
-nyx_coverage_bitmap_copy_t* new_coverage_bitmaps(void);
-void coverage_bitmap_reset(void);
-void coverage_bitmap_copy_to_buffer(nyx_coverage_bitmap_copy_t* buffer);
-void coverage_bitmap_copy_from_buffer(nyx_coverage_bitmap_copy_t* buffer);
+nyx_coverage_bitmap_copy_t *new_coverage_bitmaps(void);
+void coverage_bitmap_reset(void);
+void coverage_bitmap_copy_to_buffer(nyx_coverage_bitmap_copy_t *buffer);
+void coverage_bitmap_copy_from_buffer(nyx_coverage_bitmap_copy_t *buffer);
int get_capstone_mode(int word_width_in_bits);
bool apply_capabilities(CPUState *cpu);
-bool folder_exits(const char* path);
-bool file_exits(const char* path);
+bool folder_exits(const char *path);
+bool file_exits(const char *path);
diff --git a/nyx/hypercall/configuration.c b/nyx/hypercall/configuration.c
index db465d8317..3b470e87eb 100644
--- a/nyx/hypercall/configuration.c
+++ b/nyx/hypercall/configuration.c
@@ -1,108 +1,125 @@
#include "qemu/osdep.h"
-#include "nyx/state/state.h"
+#include "nyx/helpers.h"
#include "nyx/hypercall/configuration.h"
#include "nyx/memory_access.h"
-#include "nyx/helpers.h"
+#include "nyx/state/state.h"
-void handle_hypercall_kafl_get_host_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- uint64_t vaddr = hypercall_arg;
- host_config_t config;
+void handle_hypercall_kafl_get_host_config(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ uint64_t vaddr = hypercall_arg;
+ host_config_t config;
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_GET_HOST_CONFIG")){
- return;
- }
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_GET_HOST_CONFIG")) {
+ return;
+ }
- if (GET_GLOBAL_STATE()->get_host_config_done){
- nyx_abort((char*)"KVM_EXIT_KAFL_GET_HOST_CONFIG called twice...");
- return;
- }
+ if (GET_GLOBAL_STATE()->get_host_config_done) {
+ nyx_abort((char *)"KVM_EXIT_KAFL_GET_HOST_CONFIG called twice...");
+ return;
+ }
- memset((void*)&config, 0, sizeof(host_config_t));
+ memset((void *)&config, 0, sizeof(host_config_t));
- config.host_magic = NYX_HOST_MAGIC;
- config.host_version = NYX_HOST_VERSION;
- config.bitmap_size = GET_GLOBAL_STATE()->shared_bitmap_size;
- config.ijon_bitmap_size = GET_GLOBAL_STATE()->shared_ijon_bitmap_size;
- config.payload_buffer_size = GET_GLOBAL_STATE()->shared_payload_buffer_size;
- config.worker_id = GET_GLOBAL_STATE()->worker_id;
+ config.host_magic = NYX_HOST_MAGIC;
+ config.host_version = NYX_HOST_VERSION;
+ config.bitmap_size = GET_GLOBAL_STATE()->shared_bitmap_size;
+ config.ijon_bitmap_size = GET_GLOBAL_STATE()->shared_ijon_bitmap_size;
+ config.payload_buffer_size = GET_GLOBAL_STATE()->shared_payload_buffer_size;
+ config.worker_id = GET_GLOBAL_STATE()->worker_id;
- write_virtual_memory(vaddr, (uint8_t*)&config, sizeof(host_config_t), cpu);
- GET_GLOBAL_STATE()->get_host_config_done = true;
+ write_virtual_memory(vaddr, (uint8_t *)&config, sizeof(host_config_t), cpu);
+ GET_GLOBAL_STATE()->get_host_config_done = true;
}
-void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- uint64_t vaddr = hypercall_arg;
- agent_config_t config;
+void handle_hypercall_kafl_set_agent_config(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ uint64_t vaddr = hypercall_arg;
+ agent_config_t config;
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_SET_AGENT_CONFIG")){
- return;
- }
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_SET_AGENT_CONFIG")) {
+ return;
+ }
- if (GET_GLOBAL_STATE()->set_agent_config_done){
- nyx_abort((char*)"KVM_EXIT_KAFL_SET_AGENT_CONFIG called twice...");
- return;
- }
+ if (GET_GLOBAL_STATE()->set_agent_config_done) {
+ nyx_abort((char *)"KVM_EXIT_KAFL_SET_AGENT_CONFIG called twice...");
+ return;
+ }
- X86CPU *cpux86 = X86_CPU(cpu);
- CPUX86State *env = &cpux86->env;
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- if(read_virtual_memory(vaddr, (uint8_t*)&config, sizeof(agent_config_t), cpu)){
+ if (read_virtual_memory(vaddr, (uint8_t *)&config, sizeof(agent_config_t), cpu)) {
+ if (config.agent_magic != NYX_AGENT_MAGIC) {
+ fprintf(stderr,
+ "[QEMU-Nyx] Error: NYX_AGENT_MAGIC not found in agent "
+ "configuration - You are probably using an outdated agent...\n");
+ exit(1);
+ }
- if (config.agent_magic != NYX_AGENT_MAGIC){
- fprintf(stderr, "[QEMU-Nyx] Error: NYX_AGENT_MAGIC not found in agent configuration - You are probably using an outdated agent...\n");
- exit(1);
- }
+ 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);
+ exit(1);
+ }
- 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);
- exit(1);
- }
+ GET_GLOBAL_STATE()->cap_timeout_detection = config.agent_timeout_detection;
+ GET_GLOBAL_STATE()->cap_only_reload_mode =
+ !!!config.agent_non_reload_mode; /* fix this */
+ GET_GLOBAL_STATE()->cap_compile_time_tracing = config.agent_tracing;
- GET_GLOBAL_STATE()->cap_timeout_detection = config.agent_timeout_detection;
- GET_GLOBAL_STATE()->cap_only_reload_mode = !!!config.agent_non_reload_mode; /* fix this */
- GET_GLOBAL_STATE()->cap_compile_time_tracing = config.agent_tracing;
+ if (!GET_GLOBAL_STATE()->cap_compile_time_tracing &&
+ !GET_GLOBAL_STATE()->nyx_fdl)
+ {
+ fprintf(
+ stderr,
+ "[QEMU-Nyx] Error: Attempt to fuzz target without compile-time "
+ "instrumentation - Intel PT is not supported on this KVM build!\n");
+ exit(1);
+ }
- if(!GET_GLOBAL_STATE()->cap_compile_time_tracing && !GET_GLOBAL_STATE()->nyx_fdl){
- fprintf(stderr, "[QEMU-Nyx] Error: Attempt to fuzz target without compile-time instrumentation - Intel PT is not supported on this KVM build!\n");
- exit(1);
- }
+ GET_GLOBAL_STATE()->cap_ijon_tracing = config.agent_ijon_tracing;
- GET_GLOBAL_STATE()->cap_ijon_tracing = config.agent_ijon_tracing;
-
- if(config.agent_tracing){
- GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr = config.trace_buffer_vaddr;
+ if (config.agent_tracing) {
+ GET_GLOBAL_STATE()->cap_compile_time_tracing_buffer_vaddr =
+ config.trace_buffer_vaddr;
GET_GLOBAL_STATE()->pt_trace_mode = false;
- }
- if(config.agent_ijon_tracing){
- GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr = config.ijon_trace_buffer_vaddr;
- }
+ }
+ if (config.agent_ijon_tracing) {
+ GET_GLOBAL_STATE()->cap_ijon_tracing_buffer_vaddr =
+ config.ijon_trace_buffer_vaddr;
+ }
- 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;
+ 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){
- abort();
- }
+ if (config.input_buffer_size) {
+ abort();
+ }
- if(apply_capabilities(cpu) == false){
- nyx_abort((char*)"applying agent configuration failed...");
- }
+ if (apply_capabilities(cpu) == false) {
+ nyx_abort((char *)"applying agent configuration failed...");
+ }
- if(getenv("DUMP_PAYLOAD_MODE")){
- config.dump_payloads = 1;
- write_virtual_memory(vaddr, (uint8_t*)&config, sizeof(agent_config_t), cpu);
- }
+ if (getenv("DUMP_PAYLOAD_MODE")) {
+ config.dump_payloads = 1;
+ write_virtual_memory(vaddr, (uint8_t *)&config, sizeof(agent_config_t),
+ cpu);
+ }
- }
- else{
- fprintf(stderr, "[QEMU-Nyx] Error: %s - failed (vaddr: 0x%lx)!\n", __func__, vaddr);
- exit(1);
- }
- GET_GLOBAL_STATE()->set_agent_config_done = true;
+ } else {
+ fprintf(stderr, "[QEMU-Nyx] Error: %s - failed (vaddr: 0x%lx)!\n", __func__,
+ vaddr);
+ exit(1);
+ }
+ GET_GLOBAL_STATE()->set_agent_config_done = true;
}
diff --git a/nyx/hypercall/configuration.h b/nyx/hypercall/configuration.h
index f73927f9ba..3ec7677b33 100644
--- a/nyx/hypercall/configuration.h
+++ b/nyx/hypercall/configuration.h
@@ -5,40 +5,44 @@
#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_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);
+void handle_hypercall_kafl_set_agent_config(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
#define NYX_HOST_MAGIC 0x4878794e
#define NYX_AGENT_MAGIC 0x4178794e
-#define NYX_HOST_VERSION 2
+#define NYX_HOST_VERSION 2
#define NYX_AGENT_VERSION 1
-typedef struct host_config_s{
- uint32_t host_magic;
- uint32_t host_version;
- uint32_t bitmap_size;
- uint32_t ijon_bitmap_size;
- uint32_t payload_buffer_size;
- uint32_t worker_id;
- /* more to come */
+typedef struct host_config_s {
+ uint32_t host_magic;
+ uint32_t host_version;
+ uint32_t bitmap_size;
+ uint32_t ijon_bitmap_size;
+ uint32_t payload_buffer_size;
+ uint32_t worker_id;
+ /* more to come */
} __attribute__((packed)) host_config_t;
-typedef struct agent_config_s{
- uint32_t agent_magic;
- uint32_t agent_version;
- uint8_t agent_timeout_detection;
- uint8_t agent_tracing;
- uint8_t agent_ijon_tracing;
- uint8_t agent_non_reload_mode;
- uint64_t trace_buffer_vaddr;
- uint64_t ijon_trace_buffer_vaddr;
-
- uint32_t coverage_bitmap_size;
- uint32_t input_buffer_size;
+typedef struct agent_config_s {
+ uint32_t agent_magic;
+ uint32_t agent_version;
+ uint8_t agent_timeout_detection;
+ uint8_t agent_tracing;
+ uint8_t agent_ijon_tracing;
+ uint8_t agent_non_reload_mode;
+ uint64_t trace_buffer_vaddr;
+ uint64_t ijon_trace_buffer_vaddr;
- uint8_t dump_payloads; /* set by hypervisor */
- /* more to come */
+ uint32_t coverage_bitmap_size;
+ uint32_t input_buffer_size;
+
+ uint8_t dump_payloads; /* set by hypervisor */
+ /* more to come */
} __attribute__((packed)) agent_config_t;
diff --git a/nyx/hypercall/debug.c b/nyx/hypercall/debug.c
index e4570d74d1..64531d3e52 100644
--- a/nyx/hypercall/debug.c
+++ b/nyx/hypercall/debug.c
@@ -1,103 +1,119 @@
#include "qemu/osdep.h"
-#include
#include "sysemu/kvm.h"
+#include
-#include "nyx/synchronization.h"
#include "nyx/fast_vm_reload.h"
-#include "nyx/state/state.h"
#include "nyx/hypercall/debug.h"
+#include "nyx/state/state.h"
+#include "nyx/synchronization.h"
-//#define NYX_ENABLE_DEBUG_HYPERCALLS
+// #define NYX_ENABLE_DEBUG_HYPERCALLS
#ifdef NYX_ENABLE_DEBUG_HYPERCALLS
-static double get_time(void){
- struct timeval t;
- struct timezone tzp;
- gettimeofday(&t, &tzp);
- return t.tv_sec + t.tv_usec*1e-6;
+static double get_time(void)
+{
+ struct timeval t;
+ struct timezone tzp;
+ gettimeofday(&t, &tzp);
+ return t.tv_sec + t.tv_usec * 1e-6;
}
-static void print_time_diff(int iterations){
+static void print_time_diff(int iterations)
+{
+ static bool init = true;
+ static double start_time = 0.0;
+ static double end_time = 0.0;
- static bool init = true;
- static double start_time = 0.0;
- static double end_time = 0.0;
-
- if(init){
- init = false;
- printf("start time is zero!\n");
- start_time = get_time();
- }
- else{
- end_time = get_time();
- double elapsed_time = end_time - start_time;
- printf("Done in %f seconds\n", elapsed_time);
- printf("Performance: %f\n", iterations/elapsed_time);
- start_time = get_time();
- }
+ if (init) {
+ init = false;
+ printf("start time is zero!\n");
+ start_time = get_time();
+ } else {
+ end_time = get_time();
+ double elapsed_time = end_time - start_time;
+ printf("Done in %f seconds\n", elapsed_time);
+ printf("Performance: %f\n", iterations / elapsed_time);
+ start_time = get_time();
+ }
}
-static void meassure_performance(void){
- static int perf_counter = 0;
- if ((perf_counter%1000) == 0){
- print_time_diff(1000);
- }
- perf_counter++;
+static void meassure_performance(void)
+{
+ static int perf_counter = 0;
+ if ((perf_counter % 1000) == 0) {
+ print_time_diff(1000);
+ }
+ perf_counter++;
}
-void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- static bool first = true;
+void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ static bool first = true;
- switch(hypercall_arg&0xFFF){
- case 0: /* create root snapshot */
- if(!fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_ROOT_EXISTS)){
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_ROOT);
- }
- break;
- case 1: /* create tmp snapshot */
- 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) */
- if(fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_TMP_EXISTS)){
- reload_request_discard_tmp(GET_GLOBAL_STATE()->reload_state);
- }
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_LOAD_SNAPSHOT_ROOT);
- meassure_performance();
- break;
- case 3: /* load tmp snapshot */
- if(fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_TMP_EXISTS)){
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_LOAD_SNAPSHOT_TMP);
- meassure_performance();
- }
- break;
- case 5: // firefox debug hypercall
- if(first){
- first = false;
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_ROOT);
- //request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_TMP);
+ switch (hypercall_arg & 0xFFF) {
+ case 0: /* create root snapshot */
+ if (!fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_ROOT_EXISTS))
+ {
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_SAVE_SNAPSHOT_ROOT);
+ }
+ break;
+ case 1: /* create tmp snapshot */
+ 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) */
+ if (fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_TMP_EXISTS))
+ {
+ reload_request_discard_tmp(GET_GLOBAL_STATE()->reload_state);
+ }
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_LOAD_SNAPSHOT_ROOT);
+ meassure_performance();
+ break;
+ case 3: /* load tmp snapshot */
+ if (fast_snapshot_exists(GET_GLOBAL_STATE()->reload_state, REQUEST_TMP_EXISTS))
+ {
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_LOAD_SNAPSHOT_TMP);
+ meassure_performance();
+ }
+ break;
+ case 5: // firefox debug hypercall
+ if (first) {
+ first = false;
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_SAVE_SNAPSHOT_ROOT);
+ // request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_TMP);
- break;
- }
- else{
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_LOAD_SNAPSHOT_ROOT);
- break;
- }
- default:
- abort();
- }
+ break;
+ } else {
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_LOAD_SNAPSHOT_ROOT);
+ break;
+ }
+ default:
+ abort();
+ }
}
#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: HYPERCALL_KAFL_DEBUG_TMP not enabled!\n");
+void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ 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();
+ synchronization_lock();
}
#endif
\ No newline at end of file
diff --git a/nyx/hypercall/debug.h b/nyx/hypercall/debug.h
index 334bd4ae18..8b25c4d3e3 100644
--- a/nyx/hypercall/debug.h
+++ b/nyx/hypercall/debug.h
@@ -1,6 +1,8 @@
#pragma once
-#include
#include "sysemu/kvm.h"
+#include
-void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
\ No newline at end of file
+void handle_hypercall_kafl_debug_tmp_snapshot(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
\ No newline at end of file
diff --git a/nyx/hypercall/hypercall.c b/nyx/hypercall/hypercall.c
index 3f90d8b10d..be1d8a2f82 100644
--- a/nyx/hypercall/hypercall.c
+++ b/nyx/hypercall/hypercall.c
@@ -21,884 +21,1018 @@ along with QEMU-PT. If not, see .
#include "qemu/osdep.h"
-#include
-#include
-#include
-#include "qemu-common.h"
#include "exec/memory.h"
#include "qemu/main-loop.h"
#include "qemu-common.h"
+#include
+#include
+#include
#include "sysemu/cpus.h"
+#include "sysemu/hw_accel.h"
#include "sysemu/kvm.h"
#include "sysemu/kvm_int.h"
#include "sysemu/runstate.h"
-#include "sysemu/hw_accel.h"
+
+
#include "sysemu/runstate.h"
-
-
-#include "nyx/pt.h"
-#include "nyx/hypercall/hypercall.h"
-#include "nyx/memory_access.h"
-#include "nyx/interface.h"
#include "nyx/debug.h"
-#include "nyx/synchronization.h"
#include "nyx/fast_vm_reload.h"
-#include "nyx/kvm_nested.h"
-#include "nyx/state/state.h"
-#include "sysemu/runstate.h"
-#include "nyx/helpers.h"
-#include "nyx/nested_hypercalls.h"
#include "nyx/fast_vm_reload_sync.h"
-#include "nyx/redqueen.h"
+#include "nyx/helpers.h"
#include "nyx/hypercall/configuration.h"
#include "nyx/hypercall/debug.h"
+#include "nyx/hypercall/hypercall.h"
+#include "nyx/interface.h"
+#include "nyx/kvm_nested.h"
+#include "nyx/memory_access.h"
+#include "nyx/nested_hypercalls.h"
+#include "nyx/pt.h"
+#include "nyx/redqueen.h"
+#include "nyx/state/state.h"
+#include "nyx/synchronization.h"
-//#define DEBUG_HPRINTF
-#define HPRINTF_SIZE 0x1000 /* FIXME: take from nyx.h */
+// #define DEBUG_HPRINTF
+#define HPRINTF_SIZE 0x1000 /* FIXME: take from nyx.h */
bool hypercall_enabled = false;
char hprintf_buffer[HPRINTF_SIZE];
static bool init_state = true;
-void skip_init(void){
- init_state = false;
+void skip_init(void)
+{
+ init_state = false;
}
-bool pt_hypercalls_enabled(void){
- return hypercall_enabled;
+bool pt_hypercalls_enabled(void)
+{
+ return hypercall_enabled;
}
-void pt_setup_enable_hypercalls(void){
- hypercall_enabled = true;
+void pt_setup_enable_hypercalls(void)
+{
+ hypercall_enabled = true;
}
-void pt_setup_ip_filters(uint8_t filter_id, uint64_t start, uint64_t end){
- nyx_trace();
- if (filter_id < INTEL_PT_MAX_RANGES){
-
- GET_GLOBAL_STATE()->pt_ip_filter_configured[filter_id] = true;
- GET_GLOBAL_STATE()->pt_ip_filter_a[filter_id] = start;
- GET_GLOBAL_STATE()->pt_ip_filter_b[filter_id] = end;
-
- }
+void pt_setup_ip_filters(uint8_t filter_id, uint64_t start, uint64_t end)
+{
+ nyx_trace();
+ if (filter_id < INTEL_PT_MAX_RANGES) {
+ GET_GLOBAL_STATE()->pt_ip_filter_configured[filter_id] = true;
+ GET_GLOBAL_STATE()->pt_ip_filter_a[filter_id] = start;
+ GET_GLOBAL_STATE()->pt_ip_filter_b[filter_id] = end;
+ }
}
-void hypercall_commit_filter(void){
+void hypercall_commit_filter(void)
+{
}
bool setup_snapshot_once = false;
-bool handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
+bool handle_hypercall_kafl_next_payload(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
- if(hypercall_enabled){
- if (init_state){
- set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 2);
- synchronization_lock();
+ if (hypercall_enabled) {
+ if (init_state) {
+ set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 2);
+ synchronization_lock();
- } else {
+ } else {
+ if (GET_GLOBAL_STATE()->set_agent_config_done == false) {
+ nyx_abort(
+ (char *)"KVM_EXIT_KAFL_SET_AGENT_CONFIG was not called...");
+ return false;
+ }
- if (GET_GLOBAL_STATE()->set_agent_config_done == false){
- nyx_abort((char*)"KVM_EXIT_KAFL_SET_AGENT_CONFIG was not called...");
- return false;
- }
+ if (!setup_snapshot_once) {
+ coverage_bitmap_reset();
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_SAVE_SNAPSHOT_ROOT_FIX_RIP);
+ setup_snapshot_once = true;
- if(!setup_snapshot_once){
- 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++) {
+ 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);
- for(int i = 0; i < INTEL_PT_MAX_RANGES; 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);
+ GET_GLOBAL_STATE()->in_fuzzing_mode = true;
+ set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ 3);
+ } else {
+ synchronization_lock();
+ reset_timeout_detector(&GET_GLOBAL_STATE()->timeout_detector);
+ GET_GLOBAL_STATE()->in_fuzzing_mode = true;
- GET_GLOBAL_STATE()->in_fuzzing_mode = true;
- set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 3);
- }
- else{
- synchronization_lock();
- reset_timeout_detector(&GET_GLOBAL_STATE()->timeout_detector);
- GET_GLOBAL_STATE()->in_fuzzing_mode = true;
-
- return true;
- }
- }
- }
- return false;
+ return true;
+ }
+ }
+ }
+ return false;
}
bool acquire_print_once_bool = true;
bool release_print_once_bool = true;
-static void acquire_print_once(CPUState *cpu){
- if(acquire_print_once_bool){
- acquire_print_once_bool = false;
- kvm_arch_get_registers(cpu);
- nyx_debug("handle_hypercall_kafl_acquire at:%lx\n", get_rip(cpu));
- }
+static void acquire_print_once(CPUState *cpu)
+{
+ if (acquire_print_once_bool) {
+ acquire_print_once_bool = false;
+ kvm_arch_get_registers(cpu);
+ nyx_debug("handle_hypercall_kafl_acquire at:%lx\n", get_rip(cpu));
+ }
}
-void handle_hypercall_kafl_acquire(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(hypercall_enabled){
- if (!init_state){
- acquire_print_once(cpu);
- synchronization_enter_fuzzing_loop(cpu);
- }
- }
+void handle_hypercall_kafl_acquire(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (hypercall_enabled) {
+ if (!init_state) {
+ acquire_print_once(cpu);
+ synchronization_enter_fuzzing_loop(cpu);
+ }
+ }
}
-static void handle_hypercall_get_payload(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
+static void handle_hypercall_get_payload(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_GET_PAYLOAD")){
- return;
- }
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_GET_PAYLOAD")) {
+ return;
+ }
- if (GET_GLOBAL_STATE()->get_host_config_done == false){
- nyx_abort((char*)"KVM_EXIT_KAFL_GET_HOST_CONFIG was not called...");
- return;
- }
+ if (GET_GLOBAL_STATE()->get_host_config_done == false) {
+ nyx_abort((char *)"KVM_EXIT_KAFL_GET_HOST_CONFIG was not called...");
+ return;
+ }
- if(hypercall_enabled && !setup_snapshot_once){
- nyx_debug_p(CORE_PREFIX, "Payload Address:\t%lx", hypercall_arg);
- kvm_arch_get_registers(cpu);
- CPUX86State *env = &(X86_CPU(cpu))->env;
- GET_GLOBAL_STATE()->parent_cr3 = env->cr[3] & 0xFFFFFFFFFFFFF000ULL;
- nyx_debug_p(CORE_PREFIX, "Payload CR3:\t%lx", (uint64_t)GET_GLOBAL_STATE()->parent_cr3 );
- //print_48_pagetables(GET_GLOBAL_STATE()->parent_cr3);
+ if (hypercall_enabled && !setup_snapshot_once) {
+ nyx_debug_p(CORE_PREFIX, "Payload Address:\t%lx", hypercall_arg);
+ kvm_arch_get_registers(cpu);
+ CPUX86State *env = &(X86_CPU(cpu))->env;
+ GET_GLOBAL_STATE()->parent_cr3 = env->cr[3] & 0xFFFFFFFFFFFFF000ULL;
+ nyx_debug_p(CORE_PREFIX, "Payload CR3:\t%lx",
+ (uint64_t)GET_GLOBAL_STATE()->parent_cr3);
+ // print_48_pagetables(GET_GLOBAL_STATE()->parent_cr3);
- if(hypercall_arg&0xFFF){
- fprintf(stderr, "[QEMU-Nyx] Error: Payload buffer is not page-aligned! (0x%lx)\n", hypercall_arg);
- abort();
- }
+ if (hypercall_arg & 0xFFF) {
+ fprintf(stderr, "[QEMU-Nyx] Error: Payload buffer is not page-aligned! (0x%lx)\n",
+ hypercall_arg);
+ abort();
+ }
- remap_payload_buffer(hypercall_arg, cpu);
- set_payload_buffer(hypercall_arg);
- }
+ remap_payload_buffer(hypercall_arg, cpu);
+ set_payload_buffer(hypercall_arg);
+ }
}
-static void set_return_value(CPUState *cpu, uint64_t return_value){
- kvm_arch_get_registers(cpu);
- CPUX86State *env = &(X86_CPU(cpu))->env;
- env->regs[R_EAX] = return_value;
- kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE);
+static void set_return_value(CPUState *cpu, uint64_t return_value)
+{
+ kvm_arch_get_registers(cpu);
+ CPUX86State *env = &(X86_CPU(cpu))->env;
+ env->regs[R_EAX] = return_value;
+ kvm_arch_put_registers(cpu, KVM_PUT_RUNTIME_STATE);
}
-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;
- }
+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;
+ }
- kvm_arch_get_registers(cpu);
- /* address has to be page aligned */
- if((hypercall_arg&0xFFF) != 0){
- nyx_debug("%s: ERROR -> address is not page aligned!\n", __func__);
- set_return_value(cpu, 0xFFFFFFFFFFFFFFFFULL);
- }
- else{
- read_virtual_memory(hypercall_arg, (uint8_t*)req_stream_buffer, 0x100, cpu);
- uint64_t bytes = sharedir_request_file(GET_GLOBAL_STATE()->sharedir, (const char *)req_stream_buffer, req_stream_buffer);
- if(bytes != 0xFFFFFFFFFFFFFFFFULL){
- write_virtual_memory(hypercall_arg, (uint8_t*)req_stream_buffer, bytes, cpu);
- }
- set_return_value(cpu, bytes);
- }
+ kvm_arch_get_registers(cpu);
+ /* address has to be page aligned */
+ if ((hypercall_arg & 0xFFF) != 0) {
+ nyx_debug("%s: ERROR -> address is not page aligned!\n", __func__);
+ set_return_value(cpu, 0xFFFFFFFFFFFFFFFFULL);
+ } else {
+ read_virtual_memory(hypercall_arg, (uint8_t *)req_stream_buffer, 0x100, cpu);
+ uint64_t bytes = sharedir_request_file(GET_GLOBAL_STATE()->sharedir,
+ (const char *)req_stream_buffer,
+ req_stream_buffer);
+ if (bytes != 0xFFFFFFFFFFFFFFFFULL) {
+ write_virtual_memory(hypercall_arg, (uint8_t *)req_stream_buffer, bytes,
+ cpu);
+ }
+ set_return_value(cpu, bytes);
+ }
}
-typedef struct req_data_bulk_s{
- char file_name[256];
- uint64_t num_addresses;
- uint64_t addresses[479];
+typedef struct req_data_bulk_s {
+ char file_name[256];
+ uint64_t num_addresses;
+ uint64_t addresses[479];
} req_data_bulk_t;
-static void handle_hypercall_kafl_req_stream_data_bulk(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- static uint8_t req_stream_buffer[0x1000];
- //static uint64_t addresses[512];
- req_data_bulk_t req_data_bulk_data;
+static void handle_hypercall_kafl_req_stream_data_bulk(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ static uint8_t req_stream_buffer[0x1000];
+ // static uint64_t addresses[512];
+ req_data_bulk_t req_data_bulk_data;
- if(is_called_in_fuzzing_mode("HYPERCALL_KAFL_REQ_STREAM_DATA_BULK")){
- return;
- }
+ if (is_called_in_fuzzing_mode("HYPERCALL_KAFL_REQ_STREAM_DATA_BULK")) {
+ return;
+ }
- kvm_arch_get_registers(cpu);
- /* address has to be page aligned */
- if((hypercall_arg&0xFFF) != 0){
- nyx_debug("%s: ERROR -> address is not page aligned!\n", __func__);
- set_return_value(cpu, 0xFFFFFFFFFFFFFFFFUL);
- }
- else{
- uint64_t bytes = 0;
- read_virtual_memory(hypercall_arg, (uint8_t*)&req_data_bulk_data, 0x1000, cpu);
+ kvm_arch_get_registers(cpu);
+ /* address has to be page aligned */
+ if ((hypercall_arg & 0xFFF) != 0) {
+ nyx_debug("%s: ERROR -> address is not page aligned!\n", __func__);
+ set_return_value(cpu, 0xFFFFFFFFFFFFFFFFUL);
+ } else {
+ uint64_t bytes = 0;
+ read_virtual_memory(hypercall_arg, (uint8_t *)&req_data_bulk_data, 0x1000,
+ cpu);
- assert(req_data_bulk_data.num_addresses <= 479);
- for(int i = 0; i < req_data_bulk_data.num_addresses; i++){
- uint64_t ret_val = sharedir_request_file(GET_GLOBAL_STATE()->sharedir, (const char *)req_data_bulk_data.file_name, req_stream_buffer);
- if(ret_val != 0xFFFFFFFFFFFFFFFFUL){
- bytes += ret_val;
- write_virtual_memory((uint64_t)req_data_bulk_data.addresses[i], (uint8_t*)req_stream_buffer, ret_val, cpu);
- }
- else if(ret_val == 0){
- break;
- }
- else{
- bytes = 0xFFFFFFFFFFFFFFFFUL;
- break;
- }
-
- }
+ assert(req_data_bulk_data.num_addresses <= 479);
+ for (int i = 0; i < req_data_bulk_data.num_addresses; i++) {
+ uint64_t ret_val =
+ sharedir_request_file(GET_GLOBAL_STATE()->sharedir,
+ (const char *)req_data_bulk_data.file_name,
+ req_stream_buffer);
+ if (ret_val != 0xFFFFFFFFFFFFFFFFUL) {
+ bytes += ret_val;
+ write_virtual_memory((uint64_t)req_data_bulk_data.addresses[i],
+ (uint8_t *)req_stream_buffer, ret_val, cpu);
+ } else if (ret_val == 0) {
+ break;
+ } else {
+ bytes = 0xFFFFFFFFFFFFFFFFUL;
+ break;
+ }
+ }
- set_return_value(cpu, bytes);
- }
+ set_return_value(cpu, bytes);
+ }
}
-static void handle_hypercall_kafl_range_submit(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- uint64_t buffer[3];
+static void handle_hypercall_kafl_range_submit(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ uint64_t buffer[3];
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_RANGE_SUBMIT")){
- return;
- }
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_RANGE_SUBMIT")) {
+ return;
+ }
- read_virtual_memory(hypercall_arg, (uint8_t*)&buffer, sizeof(buffer), cpu);
+ read_virtual_memory(hypercall_arg, (uint8_t *)&buffer, sizeof(buffer), cpu);
- if(buffer[2] >= 2){
- nyx_debug_p(CORE_PREFIX, "%s: illegal range=%ld\n", __func__, buffer[2]);
- return;
- }
+ if (buffer[2] >= 2) {
+ nyx_debug_p(CORE_PREFIX, "%s: illegal range=%ld\n", __func__, buffer[2]);
+ return;
+ }
- if(GET_GLOBAL_STATE()->pt_ip_filter_configured[buffer[2]]){
- nyx_debug_p(CORE_PREFIX, "Ignoring agent-provided address ranges (abort reason: 1) - %ld", buffer[2]);
- return;
- }
-
- if (buffer[0] != 0 && buffer[1] != 0 ){
- GET_GLOBAL_STATE()->pt_ip_filter_a[buffer[2]] = buffer[0];
- GET_GLOBAL_STATE()->pt_ip_filter_b[buffer[2]] = buffer[1];
- GET_GLOBAL_STATE()->pt_ip_filter_configured[buffer[2]] = true;
- nyx_debug_p(CORE_PREFIX, "Configuring agent-provided address ranges:");
- nyx_debug_p(CORE_PREFIX, "\tIP%ld: %lx-%lx [ENABLED]", buffer[2], GET_GLOBAL_STATE()->pt_ip_filter_a[buffer[2]], GET_GLOBAL_STATE()->pt_ip_filter_b[buffer[2]]);
- }
- else{
- nyx_debug_p(CORE_PREFIX, "Ignoring agent-provided address ranges (abort reason: 2)");
- }
+ if (GET_GLOBAL_STATE()->pt_ip_filter_configured[buffer[2]]) {
+ nyx_debug_p(CORE_PREFIX,
+ "Ignoring agent-provided address ranges (abort reason: 1) - %ld",
+ buffer[2]);
+ return;
+ }
+ if (buffer[0] != 0 && buffer[1] != 0) {
+ GET_GLOBAL_STATE()->pt_ip_filter_a[buffer[2]] = buffer[0];
+ GET_GLOBAL_STATE()->pt_ip_filter_b[buffer[2]] = buffer[1];
+ GET_GLOBAL_STATE()->pt_ip_filter_configured[buffer[2]] = true;
+ nyx_debug_p(CORE_PREFIX, "Configuring agent-provided address ranges:");
+ nyx_debug_p(CORE_PREFIX, "\tIP%ld: %lx-%lx [ENABLED]", buffer[2],
+ GET_GLOBAL_STATE()->pt_ip_filter_a[buffer[2]],
+ GET_GLOBAL_STATE()->pt_ip_filter_b[buffer[2]]);
+ } else {
+ nyx_debug_p(CORE_PREFIX,
+ "Ignoring agent-provided address ranges (abort reason: 2)");
+ }
}
-static void release_print_once(CPUState *cpu){
- if(release_print_once_bool){
- release_print_once_bool = false;
- kvm_arch_get_registers(cpu);
- nyx_debug("handle_hypercall_kafl_release at:%lx\n", get_rip(cpu));
- }
+static void release_print_once(CPUState *cpu)
+{
+ if (release_print_once_bool) {
+ release_print_once_bool = false;
+ kvm_arch_get_registers(cpu);
+ nyx_debug("handle_hypercall_kafl_release at:%lx\n", get_rip(cpu));
+ }
}
-void handle_hypercall_kafl_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(hypercall_enabled){
- if (init_state){
- init_state = false;
- } else {
- if (hypercall_arg > 0) {
- GET_GLOBAL_STATE()->starved = 1;
- } else {
- GET_GLOBAL_STATE()->starved = 0;
- }
+void handle_hypercall_kafl_release(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (hypercall_enabled) {
+ if (init_state) {
+ init_state = false;
+ } else {
+ if (hypercall_arg > 0) {
+ GET_GLOBAL_STATE()->starved = 1;
+ } else {
+ GET_GLOBAL_STATE()->starved = 0;
+ }
- synchronization_disable_pt(cpu);
- release_print_once(cpu);
- }
- }
+ synchronization_disable_pt(cpu);
+ release_print_once(cpu);
+ }
+ }
}
struct kvm_set_guest_debug_data {
struct kvm_guest_debug dbg;
- int err;
+ int err;
};
-void handle_hypercall_kafl_mtf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- //assert(false);
- kvm_arch_get_registers_fast(cpu);
-
- fprintf(stderr, "%s --> %lx\n", __func__, get_rip(cpu));
-
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_MTF);
-
- kvm_remove_all_breakpoints(cpu);
- kvm_insert_breakpoint(cpu, GET_GLOBAL_STATE()->dump_page_addr, 1, 1);
- kvm_update_guest_debug(cpu, 0);
-
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SET_PAGE_DUMP_CR3, GET_GLOBAL_STATE()->pt_c3_filter);
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_PAGE_DUMP_CR3);
-}
-
-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;
- //fprintf(stderr, "page_cache_fetch = %lx\n", page_cache_fetch(GET_GLOBAL_STATE()->page_cache, page, &success, false));
- page_cache_fetch(GET_GLOBAL_STATE()->page_cache, page, &success, false);
- if(success){
-
- nyx_debug("%s: SUCCESS: %d\n", __func__, success);
- kvm_remove_all_breakpoints(cpu);
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
-
- }
- else{
- nyx_debug("%s: FAIL: %d\n", __func__, success);
-
- 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);
- }
-
-}
-
-static inline void set_page_dump_bp(CPUState *cpu, uint64_t cr3, uint64_t 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);
-
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SET_PAGE_DUMP_CR3, cr3);
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_PAGE_DUMP_CR3);
-}
-
-static void handle_hypercall_kafl_cr3(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(hypercall_enabled){
- //nyx_debug_p(CORE_PREFIX, "CR3 address:\t\t%lx", hypercall_arg);
- pt_set_cr3(cpu, hypercall_arg & 0xFFFFFFFFFFFFF000ULL, false);
- if(GET_GLOBAL_STATE()->dump_page){
- set_page_dump_bp(cpu, hypercall_arg & 0xFFFFFFFFFFFFF000ULL, GET_GLOBAL_STATE()->dump_page_addr);
- }
- }
-}
-
-static void handle_hypercall_kafl_submit_panic(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
-
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_SUBMIT_PANIC")){
- return;
- }
-
- if(hypercall_enabled){
- nyx_debug_p(CORE_PREFIX, "Panic address:\t%lx", hypercall_arg);
-
- switch (get_current_mem_mode(cpu)){
- case mm_32_protected:
- case mm_32_paging:
- case mm_32_pae:
- write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_32, PAYLOAD_BUFFER_SIZE_32, cpu);
- break;
- case mm_64_l4_paging:
- case mm_64_l5_paging:
- write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_64, PAYLOAD_BUFFER_SIZE_64, cpu);
- break;
- default:
- abort();
- break;
- }
- }
-}
-
-static void handle_hypercall_kafl_submit_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(hypercall_enabled){
- nyx_debug_p(CORE_PREFIX, "kASAN address:\t%lx", hypercall_arg);
-
- switch (get_current_mem_mode(cpu)){
- case mm_32_protected:
- case mm_32_paging:
- case mm_32_pae:
- write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_32, PAYLOAD_BUFFER_SIZE_32, cpu);
- break;
- case mm_64_l4_paging:
- case mm_64_l5_paging:
- write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_64, PAYLOAD_BUFFER_SIZE_64, cpu);
- break;
- default:
- abort();
- break;
- }
- }
-}
-
-void handle_hypercall_kafl_panic(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- static char reason[1024];
- if(hypercall_enabled){
- 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';
-
- uint64_t address = hypercall_arg & 0x7FFFFFFFFFFFULL;
- uint64_t signal = (hypercall_arg & 0x7800000000000ULL) >> 47;
-
- snprintf(reason, 1024, "PANIC IN USER MODE (SIG: %d\tat 0x%lx)\n", (uint8_t)signal, address);
- set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, reason, strlen(reason));
- }
- else{
- switch(hypercall_arg){
- case 0:
- set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)"PANIC IN KERNEL MODE!\n", strlen("PANIC IN KERNEL MODE!\n"));
- break;
- case 1:
- set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)"PANIC IN USER MODE!\n", strlen("PANIC IN USER MODE!\n"));
- break;
- default:
- set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, (char*)"???\n", strlen("???\n"));
- break;
- }
-
- }
- synchronization_lock_crash_found();
- } else{
- nyx_abort((char*)"Agent has crashed before initializing the fuzzing loop...");
- }
- }
-}
-
-static void handle_hypercall_kafl_create_tmp_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(!fast_reload_tmp_created(get_fast_reload_snapshot())){
- /* decode PT data */
- pt_disable(qemu_get_cpu(0), false);
-
- 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_release(run, cpu, hypercall_arg);
- }
- else{
- // TODO: raise an error?
- }
-}
-
-static void handle_hypercall_kafl_panic_extended(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(fast_reload_snapshot_exists(get_fast_reload_snapshot()) && GET_GLOBAL_STATE()->in_fuzzing_mode){
- read_virtual_memory(hypercall_arg, (uint8_t*)hprintf_buffer, HPRINTF_SIZE, cpu);
- set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strlen(hprintf_buffer));
- synchronization_lock_crash_found();
- } else{
- read_virtual_memory(hypercall_arg, (uint8_t*)hprintf_buffer, HPRINTF_SIZE, cpu);
- char* report = NULL;
- assert(asprintf(&report, "Agent has crashed before initializing the fuzzing loop: %s", hprintf_buffer) != -1);
- nyx_abort(report);
- }
-}
-
-static void handle_hypercall_kafl_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- if(hypercall_enabled){
- if(fast_reload_snapshot_exists(get_fast_reload_snapshot())){
- synchronization_lock_asan_found();
- } else{
- nyx_debug_p(CORE_PREFIX, "KASAN detected during initialization of stage 1 or stage 2 loader");
- }
- }
-}
-
-static void handle_hypercall_kafl_lock(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
-
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_LOCK")){
- return;
- }
-
- if(!GET_GLOBAL_STATE()->fast_reload_pre_image){
- nyx_debug_p(CORE_PREFIX, "Skipping pre image creation (hint: set pre=on) ...");
- return;
- }
-
- nyx_debug_p(CORE_PREFIX, "Creating pre image snapshot <%s> ...", GET_GLOBAL_STATE()->fast_reload_pre_path);
-
- nyx_debug("Creating pre image snapshot");
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_PRE);
-}
-
-static void handle_hypercall_kafl_printf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- read_virtual_memory(hypercall_arg, (uint8_t*)hprintf_buffer, HPRINTF_SIZE, cpu);
-#ifdef DEBUG_HPRINTF
- fprintf(stderr, "%s %s\n", __func__, hprintf_buffer);
-#endif
- set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strnlen(hprintf_buffer, HPRINTF_SIZE));
- synchronization_lock();
-}
-
-static void handle_hypercall_kafl_user_range_advise(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
-
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_USER_RANGE_ADVISE")){
- return;
- }
-
- kAFL_ranges* buf = malloc(sizeof(kAFL_ranges));
-
- for(int i = 0; i < INTEL_PT_MAX_RANGES; i++){
- buf->ip[i] = GET_GLOBAL_STATE()->pt_ip_filter_a[i];
- buf->size[i] = (GET_GLOBAL_STATE()->pt_ip_filter_b[i]-GET_GLOBAL_STATE()->pt_ip_filter_a[i]);
- buf->enabled[i] = (uint8_t)GET_GLOBAL_STATE()->pt_ip_filter_configured[i];
- }
-
- write_virtual_memory(hypercall_arg, (uint8_t *)buf, sizeof(kAFL_ranges), cpu);
- free(buf);
-}
-
-static void handle_hypercall_kafl_user_submit_mode(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
-
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_USER_SUBMIT_MODE")){
- return;
- }
-
- switch(hypercall_arg){
- case KAFL_MODE_64:
- nyx_debug_p(CORE_PREFIX, "target runs in KAFL_MODE_64 ...");
- GET_GLOBAL_STATE()->disassembler_word_width = 64;
- break;
- case KAFL_MODE_32:
- nyx_debug_p(CORE_PREFIX, "target runs in KAFL_MODE_32 ...");
- GET_GLOBAL_STATE()->disassembler_word_width = 32;
- break;
- case KAFL_MODE_16:
- nyx_debug_p(CORE_PREFIX, "target runs in KAFL_MODE_16 ...");
- GET_GLOBAL_STATE()->disassembler_word_width = 16;
- abort(); /* not implemented in this version (due to hypertrash hacks) */
- break;
- default:
- nyx_debug_p(CORE_PREFIX, "target runs in unkown mode...");
- GET_GLOBAL_STATE()->disassembler_word_width = 0;
- abort(); /* not implemented in this version (due to hypertrash hacks) */
- break;
- }
-}
-
-bool handle_hypercall_kafl_hook(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- X86CPU *cpux86 = X86_CPU(cpu);
- CPUX86State *env = &cpux86->env;
-
- for(uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++){
- if (GET_GLOBAL_STATE()->redqueen_state && (env->eip >= GET_GLOBAL_STATE()->pt_ip_filter_a[i]) && (env->eip <= GET_GLOBAL_STATE()->pt_ip_filter_b[i])){
- handle_hook(GET_GLOBAL_STATE()->redqueen_state);
- return true;
- }else if (cpu->singlestep_enabled && (GET_GLOBAL_STATE()->redqueen_state)->singlestep_enabled){
- handle_hook(GET_GLOBAL_STATE()->redqueen_state);
- return true;
- }
- }
- return false;
-}
-
-static void handle_hypercall_kafl_user_abort(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- read_virtual_memory(hypercall_arg, (uint8_t*)hprintf_buffer, HPRINTF_SIZE, cpu);
- set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strlen(hprintf_buffer));
- synchronization_lock();
-}
-
-void pt_enable_rqi(CPUState *cpu){
- GET_GLOBAL_STATE()->redqueen_enable_pending = true;
-}
-
-void pt_disable_rqi(CPUState *cpu){
- GET_GLOBAL_STATE()->redqueen_disable_pending = true;
- GET_GLOBAL_STATE()->redqueen_instrumentation_mode = REDQUEEN_NO_INSTRUMENTATION;
-}
-
-void pt_set_enable_patches_pending(CPUState *cpu){
- GET_GLOBAL_STATE()->patches_enable_pending = true;
-}
-
-void pt_set_redqueen_instrumentation_mode(CPUState *cpu, int redqueen_mode){
- GET_GLOBAL_STATE()->redqueen_instrumentation_mode = redqueen_mode;
-}
-
-void pt_set_redqueen_update_blacklist(CPUState *cpu, bool newval){
- assert(!newval || !GET_GLOBAL_STATE()->redqueen_update_blacklist);
- GET_GLOBAL_STATE()->redqueen_update_blacklist = newval;
-}
-
-void pt_set_disable_patches_pending(CPUState *cpu){
- GET_GLOBAL_STATE()->patches_disable_pending = true;
-}
-
-static void handle_hypercall_kafl_dump_file(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg)
+void handle_hypercall_kafl_mtf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg)
{
- kafl_dump_file_t file_obj;
- char filename[256] = {0};
- char* host_path = NULL;
- FILE* f = NULL;
+ // assert(false);
+ kvm_arch_get_registers_fast(cpu);
- uint64_t vaddr = hypercall_arg;
- memset((void*)&file_obj, 0, sizeof(kafl_dump_file_t));
+ fprintf(stderr, "%s --> %lx\n", __func__, get_rip(cpu));
- if (!read_virtual_memory(vaddr, (uint8_t*)&file_obj, sizeof(kafl_dump_file_t), cpu)){
- fprintf(stderr, "Failed to read file_obj in %s. Skipping..\n", __func__);
- goto err_out1;
- }
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_MTF);
- if (file_obj.file_name_str_ptr != 0) {
- if (!read_virtual_memory(file_obj.file_name_str_ptr, (uint8_t*)filename, sizeof(filename)-1, cpu)) {
- fprintf(stderr, "Failed to read file_name_str_ptr in %s. Skipping..\n", __func__);
- goto err_out1;
- }
- filename[sizeof(filename)-1] = 0;
- }
-
- //fprintf(stderr, "%s: dump %lu fbytes from %s (append=%u)\n",
- // __func__, file_obj.bytes, filename, file_obj.append);
+ kvm_remove_all_breakpoints(cpu);
+ kvm_insert_breakpoint(cpu, GET_GLOBAL_STATE()->dump_page_addr, 1, 1);
+ kvm_update_guest_debug(cpu, 0);
- // use a tempfile if file_name_ptr == NULL or points to empty string
- if (0 == strnlen(filename, sizeof(filename))) {
- strncpy(filename, "tmp.XXXXXX", sizeof(filename)-1);
- }
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SET_PAGE_DUMP_CR3,
+ GET_GLOBAL_STATE()->pt_c3_filter);
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_PAGE_DUMP_CR3);
+}
- char *base_name = basename(filename); // clobbers the filename buffer!
- assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path , base_name) != -1);
+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);
- // check if base_name is mkstemp() pattern, otherwise write/append to exact name
- char *pattern = strstr(base_name, "XXXXXX");
- if (pattern) {
- unsigned suffix = strlen(pattern) - strlen("XXXXXX");
- f = fdopen(mkstemps(host_path, suffix), "w+");
- if (file_obj.append) {
- fprintf(stderr, "Warning in %s: Writing unique generated file in append mode?\n", __func__);
- }
- } else {
- if (file_obj.append){
- f = fopen(host_path, "a+");
- } else{
- f = fopen(host_path, "w+");
- }
- }
+ bool success = false;
+ // fprintf(stderr, "page_cache_fetch = %lx\n",
+ // page_cache_fetch(GET_GLOBAL_STATE()->page_cache, page, &success, false));
+ page_cache_fetch(GET_GLOBAL_STATE()->page_cache, page, &success, false);
+ if (success) {
+ nyx_debug("%s: SUCCESS: %d\n", __func__, success);
+ kvm_remove_all_breakpoints(cpu);
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
- if (!f) {
- fprintf(stderr, "Error in %s(%s): %s\n", host_path, __func__, strerror(errno));
- goto err_out1;
- }
+ } else {
+ nyx_debug("%s: FAIL: %d\n", __func__, success);
- uint32_t pos = 0;
- int32_t bytes = file_obj.bytes;
- void* page = malloc(PAGE_SIZE);
- uint32_t written = 0;
+ 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);
+ }
+}
- nyx_debug_p(CORE_PREFIX, "%s: dump %d bytes to %s (append=%u)",
- __func__, bytes, host_path, file_obj.append);
+static inline void set_page_dump_bp(CPUState *cpu, uint64_t cr3, uint64_t 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);
- while (bytes > 0) {
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SET_PAGE_DUMP_CR3, cr3);
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_PAGE_DUMP_CR3);
+}
- if (bytes >= PAGE_SIZE) {
- read_virtual_memory(file_obj.data_ptr+pos, (uint8_t*)page, PAGE_SIZE, cpu);
- written = fwrite(page, 1, PAGE_SIZE, f);
- }
- else {
- read_virtual_memory(file_obj.data_ptr+pos, (uint8_t*)page, bytes, cpu);
- written = fwrite(page, 1, bytes, f);
- break;
- }
+static void handle_hypercall_kafl_cr3(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (hypercall_enabled) {
+ // nyx_debug_p(CORE_PREFIX, "CR3 address:\t\t%lx", hypercall_arg);
+ pt_set_cr3(cpu, hypercall_arg & 0xFFFFFFFFFFFFF000ULL, false);
+ if (GET_GLOBAL_STATE()->dump_page) {
+ set_page_dump_bp(cpu, hypercall_arg & 0xFFFFFFFFFFFFF000ULL,
+ GET_GLOBAL_STATE()->dump_page_addr);
+ }
+ }
+}
- if (!written) {
- fprintf(stderr, "Error in %s(%s): %s\n", host_path, __func__, strerror(errno));
- goto err_out2;
- }
+static void handle_hypercall_kafl_submit_panic(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_SUBMIT_PANIC")) {
+ return;
+ }
- bytes -= written;
- pos += written;
+ if (hypercall_enabled) {
+ nyx_debug_p(CORE_PREFIX, "Panic address:\t%lx", hypercall_arg);
- }
+ switch (get_current_mem_mode(cpu)) {
+ case mm_32_protected:
+ case mm_32_paging:
+ case mm_32_pae:
+ write_virtual_memory(hypercall_arg, (uint8_t *)PANIC_PAYLOAD_32,
+ PAYLOAD_BUFFER_SIZE_32, cpu);
+ break;
+ case mm_64_l4_paging:
+ case mm_64_l5_paging:
+ write_virtual_memory(hypercall_arg, (uint8_t *)PANIC_PAYLOAD_64,
+ PAYLOAD_BUFFER_SIZE_64, cpu);
+ break;
+ default:
+ abort();
+ break;
+ }
+ }
+}
+
+static void handle_hypercall_kafl_submit_kasan(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (hypercall_enabled) {
+ nyx_debug_p(CORE_PREFIX, "kASAN address:\t%lx", hypercall_arg);
+
+ switch (get_current_mem_mode(cpu)) {
+ case mm_32_protected:
+ case mm_32_paging:
+ case mm_32_pae:
+ write_virtual_memory(hypercall_arg, (uint8_t *)KASAN_PAYLOAD_32,
+ PAYLOAD_BUFFER_SIZE_32, cpu);
+ break;
+ case mm_64_l4_paging:
+ case mm_64_l5_paging:
+ write_virtual_memory(hypercall_arg, (uint8_t *)KASAN_PAYLOAD_64,
+ PAYLOAD_BUFFER_SIZE_64, cpu);
+ break;
+ default:
+ abort();
+ break;
+ }
+ }
+}
+
+void handle_hypercall_kafl_panic(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ static char reason[1024];
+ if (hypercall_enabled) {
+ 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';
+
+ uint64_t address = hypercall_arg & 0x7FFFFFFFFFFFULL;
+ uint64_t signal = (hypercall_arg & 0x7800000000000ULL) >> 47;
+
+ snprintf(reason, 1024, "PANIC IN USER MODE (SIG: %d\tat 0x%lx)\n",
+ (uint8_t)signal, address);
+ set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ reason, strlen(reason));
+ } else {
+ switch (hypercall_arg) {
+ case 0:
+ set_crash_reason_auxiliary_buffer(
+ GET_GLOBAL_STATE()->auxilary_buffer,
+ (char *)"PANIC IN KERNEL MODE!\n",
+ strlen("PANIC IN KERNEL MODE!\n"));
+ break;
+ case 1:
+ set_crash_reason_auxiliary_buffer(
+ GET_GLOBAL_STATE()->auxilary_buffer,
+ (char *)"PANIC IN USER MODE!\n",
+ strlen("PANIC IN USER MODE!\n"));
+ break;
+ default:
+ set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ (char *)"???\n",
+ strlen("???\n"));
+ break;
+ }
+ }
+ synchronization_lock_crash_found();
+ } else {
+ nyx_abort(
+ (char *)"Agent has crashed before initializing the fuzzing loop...");
+ }
+ }
+}
+
+static void handle_hypercall_kafl_create_tmp_snapshot(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (!fast_reload_tmp_created(get_fast_reload_snapshot())) {
+ /* decode PT data */
+ pt_disable(qemu_get_cpu(0), false);
+
+ 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_release(run, cpu, hypercall_arg);
+ } else {
+ // TODO: raise an error?
+ }
+}
+
+static void handle_hypercall_kafl_panic_extended(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (fast_reload_snapshot_exists(get_fast_reload_snapshot()) &&
+ GET_GLOBAL_STATE()->in_fuzzing_mode)
+ {
+ read_virtual_memory(hypercall_arg, (uint8_t *)hprintf_buffer, HPRINTF_SIZE,
+ cpu);
+ set_crash_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ hprintf_buffer, strlen(hprintf_buffer));
+ synchronization_lock_crash_found();
+ } else {
+ read_virtual_memory(hypercall_arg, (uint8_t *)hprintf_buffer, HPRINTF_SIZE,
+ cpu);
+ char *report = NULL;
+ assert(asprintf(&report,
+ "Agent has crashed before initializing the fuzzing loop: %s",
+ hprintf_buffer) != -1);
+ nyx_abort(report);
+ }
+}
+
+static void handle_hypercall_kafl_kasan(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (hypercall_enabled) {
+ if (fast_reload_snapshot_exists(get_fast_reload_snapshot())) {
+ synchronization_lock_asan_found();
+ } else {
+ nyx_debug_p(
+ CORE_PREFIX,
+ "KASAN detected during initialization of stage 1 or stage 2 loader");
+ }
+ }
+}
+
+static void handle_hypercall_kafl_lock(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_LOCK")) {
+ return;
+ }
+
+ if (!GET_GLOBAL_STATE()->fast_reload_pre_image) {
+ nyx_debug_p(CORE_PREFIX,
+ "Skipping pre image creation (hint: set pre=on) ...");
+ return;
+ }
+
+ nyx_debug_p(CORE_PREFIX, "Creating pre image snapshot <%s> ...",
+ GET_GLOBAL_STATE()->fast_reload_pre_path);
+
+ nyx_debug("Creating pre image snapshot");
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_SAVE_SNAPSHOT_PRE);
+}
+
+static void handle_hypercall_kafl_printf(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ read_virtual_memory(hypercall_arg, (uint8_t *)hprintf_buffer, HPRINTF_SIZE, cpu);
+#ifdef DEBUG_HPRINTF
+ fprintf(stderr, "%s %s\n", __func__, hprintf_buffer);
+#endif
+ set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer,
+ strnlen(hprintf_buffer, HPRINTF_SIZE));
+ synchronization_lock();
+}
+
+static void handle_hypercall_kafl_user_range_advise(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_USER_RANGE_ADVISE")) {
+ return;
+ }
+
+ kAFL_ranges *buf = malloc(sizeof(kAFL_ranges));
+
+ for (int i = 0; i < INTEL_PT_MAX_RANGES; i++) {
+ buf->ip[i] = GET_GLOBAL_STATE()->pt_ip_filter_a[i];
+ buf->size[i] = (GET_GLOBAL_STATE()->pt_ip_filter_b[i] -
+ GET_GLOBAL_STATE()->pt_ip_filter_a[i]);
+ buf->enabled[i] = (uint8_t)GET_GLOBAL_STATE()->pt_ip_filter_configured[i];
+ }
+
+ write_virtual_memory(hypercall_arg, (uint8_t *)buf, sizeof(kAFL_ranges), cpu);
+ free(buf);
+}
+
+static void handle_hypercall_kafl_user_submit_mode(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
+
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_USER_SUBMIT_MODE")) {
+ return;
+ }
+
+ switch (hypercall_arg) {
+ case KAFL_MODE_64:
+ nyx_debug_p(CORE_PREFIX, "target runs in KAFL_MODE_64 ...");
+ GET_GLOBAL_STATE()->disassembler_word_width = 64;
+ break;
+ case KAFL_MODE_32:
+ nyx_debug_p(CORE_PREFIX, "target runs in KAFL_MODE_32 ...");
+ GET_GLOBAL_STATE()->disassembler_word_width = 32;
+ break;
+ case KAFL_MODE_16:
+ nyx_debug_p(CORE_PREFIX, "target runs in KAFL_MODE_16 ...");
+ GET_GLOBAL_STATE()->disassembler_word_width = 16;
+ abort(); /* not implemented in this version (due to hypertrash hacks) */
+ break;
+ default:
+ nyx_debug_p(CORE_PREFIX, "target runs in unkown mode...");
+ GET_GLOBAL_STATE()->disassembler_word_width = 0;
+ abort(); /* not implemented in this version (due to hypertrash hacks) */
+ break;
+ }
+}
+
+bool handle_hypercall_kafl_hook(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
+
+ for (uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++) {
+ if (GET_GLOBAL_STATE()->redqueen_state &&
+ (env->eip >= GET_GLOBAL_STATE()->pt_ip_filter_a[i]) &&
+ (env->eip <= GET_GLOBAL_STATE()->pt_ip_filter_b[i]))
+ {
+ handle_hook(GET_GLOBAL_STATE()->redqueen_state);
+ return true;
+ } else if (cpu->singlestep_enabled &&
+ (GET_GLOBAL_STATE()->redqueen_state)->singlestep_enabled)
+ {
+ handle_hook(GET_GLOBAL_STATE()->redqueen_state);
+ return true;
+ }
+ }
+ return false;
+}
+
+static void handle_hypercall_kafl_user_abort(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ read_virtual_memory(hypercall_arg, (uint8_t *)hprintf_buffer, HPRINTF_SIZE, cpu);
+ set_abort_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ hprintf_buffer, strlen(hprintf_buffer));
+ synchronization_lock();
+}
+
+void pt_enable_rqi(CPUState *cpu)
+{
+ GET_GLOBAL_STATE()->redqueen_enable_pending = true;
+}
+
+void pt_disable_rqi(CPUState *cpu)
+{
+ GET_GLOBAL_STATE()->redqueen_disable_pending = true;
+ GET_GLOBAL_STATE()->redqueen_instrumentation_mode = REDQUEEN_NO_INSTRUMENTATION;
+}
+
+void pt_set_enable_patches_pending(CPUState *cpu)
+{
+ GET_GLOBAL_STATE()->patches_enable_pending = true;
+}
+
+void pt_set_redqueen_instrumentation_mode(CPUState *cpu, int redqueen_mode)
+{
+ GET_GLOBAL_STATE()->redqueen_instrumentation_mode = redqueen_mode;
+}
+
+void pt_set_redqueen_update_blacklist(CPUState *cpu, bool newval)
+{
+ assert(!newval || !GET_GLOBAL_STATE()->redqueen_update_blacklist);
+ GET_GLOBAL_STATE()->redqueen_update_blacklist = newval;
+}
+
+void pt_set_disable_patches_pending(CPUState *cpu)
+{
+ GET_GLOBAL_STATE()->patches_disable_pending = true;
+}
+
+static void handle_hypercall_kafl_dump_file(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ kafl_dump_file_t file_obj;
+ char filename[256] = { 0 };
+ char *host_path = NULL;
+ FILE *f = NULL;
+
+ uint64_t vaddr = hypercall_arg;
+ memset((void *)&file_obj, 0, sizeof(kafl_dump_file_t));
+
+ if (!read_virtual_memory(vaddr, (uint8_t *)&file_obj, sizeof(kafl_dump_file_t),
+ cpu))
+ {
+ fprintf(stderr, "Failed to read file_obj in %s. Skipping..\n", __func__);
+ goto err_out1;
+ }
+
+ if (file_obj.file_name_str_ptr != 0) {
+ if (!read_virtual_memory(file_obj.file_name_str_ptr, (uint8_t *)filename,
+ sizeof(filename) - 1, cpu))
+ {
+ fprintf(stderr, "Failed to read file_name_str_ptr in %s. Skipping..\n",
+ __func__);
+ goto err_out1;
+ }
+ filename[sizeof(filename) - 1] = 0;
+ }
+
+ // fprintf(stderr, "%s: dump %lu fbytes from %s (append=%u)\n",
+ // __func__, file_obj.bytes, filename, file_obj.append);
+
+ // use a tempfile if file_name_ptr == NULL or points to empty string
+ if (0 == strnlen(filename, sizeof(filename))) {
+ strncpy(filename, "tmp.XXXXXX", sizeof(filename) - 1);
+ }
+
+ char *base_name = basename(filename); // clobbers the filename buffer!
+ assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path,
+ base_name) != -1);
+
+ // check if base_name is mkstemp() pattern, otherwise write/append to exact name
+ char *pattern = strstr(base_name, "XXXXXX");
+ if (pattern) {
+ unsigned suffix = strlen(pattern) - strlen("XXXXXX");
+ f = fdopen(mkstemps(host_path, suffix), "w+");
+ if (file_obj.append) {
+ fprintf(stderr,
+ "Warning in %s: Writing unique generated file in append mode?\n",
+ __func__);
+ }
+ } else {
+ if (file_obj.append) {
+ f = fopen(host_path, "a+");
+ } else {
+ f = fopen(host_path, "w+");
+ }
+ }
+
+ if (!f) {
+ fprintf(stderr, "Error in %s(%s): %s\n", host_path, __func__, strerror(errno));
+ goto err_out1;
+ }
+
+ uint32_t pos = 0;
+ int32_t bytes = file_obj.bytes;
+ void *page = malloc(PAGE_SIZE);
+ uint32_t written = 0;
+
+ nyx_debug_p(CORE_PREFIX, "%s: dump %d bytes to %s (append=%u)", __func__, bytes,
+ host_path, file_obj.append);
+
+ while (bytes > 0) {
+ if (bytes >= PAGE_SIZE) {
+ read_virtual_memory(file_obj.data_ptr + pos, (uint8_t *)page, PAGE_SIZE,
+ cpu);
+ written = fwrite(page, 1, PAGE_SIZE, f);
+ } else {
+ read_virtual_memory(file_obj.data_ptr + pos, (uint8_t *)page, bytes, cpu);
+ written = fwrite(page, 1, bytes, f);
+ break;
+ }
+
+ if (!written) {
+ fprintf(stderr, "Error in %s(%s): %s\n", host_path, __func__,
+ strerror(errno));
+ goto err_out2;
+ }
+
+ bytes -= written;
+ pos += written;
+ }
err_out2:
- free(page);
- fclose(f);
+ free(page);
+ fclose(f);
err_out1:
- free(host_path);
+ free(host_path);
}
-static void handle_hypercall_kafl_persist_page_past_snapshot(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
+static void handle_hypercall_kafl_persist_page_past_snapshot(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ if (is_called_in_fuzzing_mode("KVM_EXIT_KAFL_PERSIST_PAGE_PAST_SNAPSHOT")) {
+ return;
+ }
- if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_PERSIST_PAGE_PAST_SNAPSHOT")){
- return;
- }
-
- 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));
- assert(phys_addr != 0xffffffffffffffffULL);
- fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
+ 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));
+ assert(phys_addr != 0xffffffffffffffffULL);
+ fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
}
-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);
+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:
- handle_hypercall_kafl_acquire(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_GET_PAYLOAD:
- handle_hypercall_get_payload(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_GET_PROGRAM:
- nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_GET_PROGRAM)...");
- ret = 0;
- break;
- case KVM_EXIT_KAFL_GET_ARGV:
- nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_GET_ARGV)...");
- ret = 0;
- break;
- case KVM_EXIT_KAFL_RELEASE:
- handle_hypercall_kafl_release(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_SUBMIT_CR3:
- handle_hypercall_kafl_cr3(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_SUBMIT_PANIC:
- handle_hypercall_kafl_submit_panic(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_SUBMIT_KASAN:
- handle_hypercall_kafl_submit_kasan(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_PANIC:
- handle_hypercall_kafl_panic(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_KASAN:
- handle_hypercall_kafl_kasan(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_LOCK:
- handle_hypercall_kafl_lock(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_INFO:
- nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_INFO)...");
- ret = 0;
- break;
- case KVM_EXIT_KAFL_NEXT_PAYLOAD:
- handle_hypercall_kafl_next_payload(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_PRINTF:
- handle_hypercall_kafl_printf(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_PRINTK_ADDR:
- nyx_abort((char*)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK_ADDR)...");
- ret = 0;
- break;
- case KVM_EXIT_KAFL_PRINTK:
- nyx_abort((char*)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK)...");
- ret = 0;
- break;
- case KVM_EXIT_KAFL_USER_RANGE_ADVISE:
- handle_hypercall_kafl_user_range_advise(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_USER_SUBMIT_MODE:
- handle_hypercall_kafl_user_submit_mode(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_USER_FAST_ACQUIRE:
- if(handle_hypercall_kafl_next_payload(run, cpu, arg)){
- handle_hypercall_kafl_cr3(run, cpu, arg);
- handle_hypercall_kafl_acquire(run, cpu, arg);
- }
- ret = 0;
- break;
- case KVM_EXIT_KAFL_TOPA_MAIN_FULL:
- pt_handle_overflow(cpu);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_USER_ABORT:
- handle_hypercall_kafl_user_abort(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_NESTED_CONFIG:
- handle_hypercall_kafl_nested_config(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_NESTED_PREPARE:
- handle_hypercall_kafl_nested_prepare(run, cpu, arg);
- ret = 0;
- break;
+ // FIXME: ret is always 0. no default case.
+ switch (hypercall) {
+ case KVM_EXIT_KAFL_ACQUIRE:
+ handle_hypercall_kafl_acquire(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_GET_PAYLOAD:
+ handle_hypercall_get_payload(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_GET_PROGRAM:
+ nyx_abort(
+ (char *)"Deprecated hypercall called (HYPERCALL_KAFL_GET_PROGRAM)...");
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_GET_ARGV:
+ nyx_abort(
+ (char *)"Deprecated hypercall called (HYPERCALL_KAFL_GET_ARGV)...");
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_RELEASE:
+ handle_hypercall_kafl_release(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_SUBMIT_CR3:
+ handle_hypercall_kafl_cr3(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_SUBMIT_PANIC:
+ handle_hypercall_kafl_submit_panic(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_SUBMIT_KASAN:
+ handle_hypercall_kafl_submit_kasan(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_PANIC:
+ handle_hypercall_kafl_panic(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_KASAN:
+ handle_hypercall_kafl_kasan(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_LOCK:
+ handle_hypercall_kafl_lock(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_INFO:
+ nyx_abort((char *)"Deprecated hypercall called (HYPERCALL_KAFL_INFO)...");
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_NEXT_PAYLOAD:
+ handle_hypercall_kafl_next_payload(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_PRINTF:
+ handle_hypercall_kafl_printf(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_PRINTK_ADDR:
+ nyx_abort(
+ (char *)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK_ADDR)...");
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_PRINTK:
+ nyx_abort((char *)"Deprecated hypercall called (KVM_EXIT_KAFL_PRINTK)...");
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_USER_RANGE_ADVISE:
+ handle_hypercall_kafl_user_range_advise(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_USER_SUBMIT_MODE:
+ handle_hypercall_kafl_user_submit_mode(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_USER_FAST_ACQUIRE:
+ if (handle_hypercall_kafl_next_payload(run, cpu, arg)) {
+ handle_hypercall_kafl_cr3(run, cpu, arg);
+ handle_hypercall_kafl_acquire(run, cpu, arg);
+ }
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_TOPA_MAIN_FULL:
+ pt_handle_overflow(cpu);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_USER_ABORT:
+ handle_hypercall_kafl_user_abort(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_NESTED_CONFIG:
+ handle_hypercall_kafl_nested_config(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_NESTED_PREPARE:
+ handle_hypercall_kafl_nested_prepare(run, cpu, arg);
+ ret = 0;
+ break;
- case KVM_EXIT_KAFL_NESTED_ACQUIRE:
- handle_hypercall_kafl_nested_acquire(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_NESTED_RELEASE:
- handle_hypercall_kafl_nested_release(run, cpu, arg);
- 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;
- break;
- case KVM_EXIT_KAFL_MTF:
- handle_hypercall_kafl_mtf(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_RANGE_SUBMIT:
- handle_hypercall_kafl_range_submit(run, cpu, arg);
- ret = 0;
- break;
- case HYPERCALL_KAFL_REQ_STREAM_DATA:
- handle_hypercall_kafl_req_stream_data(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_NESTED_EARLY_RELEASE:
- handle_hypercall_kafl_nested_early_release(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_PANIC_EXTENDED:
- handle_hypercall_kafl_panic_extended(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_CREATE_TMP_SNAPSHOT:
- handle_hypercall_kafl_create_tmp_snapshot(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_DEBUG_TMP_SNAPSHOT:
- handle_hypercall_kafl_debug_tmp_snapshot(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_GET_HOST_CONFIG:
- handle_hypercall_kafl_get_host_config(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_SET_AGENT_CONFIG:
- handle_hypercall_kafl_set_agent_config(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_DUMP_FILE:
- handle_hypercall_kafl_dump_file(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_REQ_STREAM_DATA_BULK:
- handle_hypercall_kafl_req_stream_data_bulk(run, cpu, arg);
- ret = 0;
- break;
- case KVM_EXIT_KAFL_PERSIST_PAGE_PAST_SNAPSHOT:
- handle_hypercall_kafl_persist_page_past_snapshot(run, cpu, arg);
- ret = 0;
- break;
- }
- return ret;
+ case KVM_EXIT_KAFL_NESTED_ACQUIRE:
+ handle_hypercall_kafl_nested_acquire(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_NESTED_RELEASE:
+ handle_hypercall_kafl_nested_release(run, cpu, arg);
+ 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;
+ break;
+ case KVM_EXIT_KAFL_MTF:
+ handle_hypercall_kafl_mtf(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_RANGE_SUBMIT:
+ handle_hypercall_kafl_range_submit(run, cpu, arg);
+ ret = 0;
+ break;
+ case HYPERCALL_KAFL_REQ_STREAM_DATA:
+ handle_hypercall_kafl_req_stream_data(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_NESTED_EARLY_RELEASE:
+ handle_hypercall_kafl_nested_early_release(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_PANIC_EXTENDED:
+ handle_hypercall_kafl_panic_extended(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_CREATE_TMP_SNAPSHOT:
+ handle_hypercall_kafl_create_tmp_snapshot(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_DEBUG_TMP_SNAPSHOT:
+ handle_hypercall_kafl_debug_tmp_snapshot(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_GET_HOST_CONFIG:
+ handle_hypercall_kafl_get_host_config(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_SET_AGENT_CONFIG:
+ handle_hypercall_kafl_set_agent_config(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_DUMP_FILE:
+ handle_hypercall_kafl_dump_file(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_REQ_STREAM_DATA_BULK:
+ handle_hypercall_kafl_req_stream_data_bulk(run, cpu, arg);
+ ret = 0;
+ break;
+ case KVM_EXIT_KAFL_PERSIST_PAGE_PAST_SNAPSHOT:
+ handle_hypercall_kafl_persist_page_past_snapshot(run, cpu, arg);
+ ret = 0;
+ break;
+ }
+ return ret;
}
-
diff --git a/nyx/hypercall/hypercall.h b/nyx/hypercall/hypercall.h
index 091521f0d6..776d366b1c 100644
--- a/nyx/hypercall/hypercall.h
+++ b/nyx/hypercall/hypercall.h
@@ -19,27 +19,27 @@ along with QEMU-PT. If not, see .
*/
-#pragma once
+#pragma once
#include
-#define PAYLOAD_BUFFER_SIZE_64 26
-#define PAYLOAD_BUFFER_SIZE_32 20
+#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
+#define KAFL_MODE_64 0
+#define KAFL_MODE_32 1
+#define KAFL_MODE_16 2
-typedef struct{
- uint64_t ip[4];
- uint64_t size[4];
- uint8_t enabled[4];
-} kAFL_ranges;
+typedef struct {
+ uint64_t ip[4];
+ uint64_t size[4];
+ uint8_t enabled[4];
+} kAFL_ranges;
bool check_bitmap_byte(uint32_t value);
-//#define PANIC_DEBUG
+// #define PANIC_DEBUG
/*
* Panic Notifier Payload (x86-64)
@@ -50,7 +50,9 @@ bool check_bitmap_byte(uint32_t value);
* 0f 01 c1 vmcall
* f4 hlt
*/
-#define PANIC_PAYLOAD_64 "\xFA\x48\xC7\xC0\x1F\x00\x00\x00\x48\xC7\xC3\x08\x00\x00\x00\x48\xC7\xC1\x00\x00\x00\x00\x0F\x01\xC1\xF4"
+#define PANIC_PAYLOAD_64 \
+ "\xFA\x48\xC7\xC0\x1F\x00\x00\x00\x48\xC7\xC3\x08\x00\x00\x00\x48\xC7\xC1\x00" \
+ "\x00\x00\x00\x0F\x01\xC1\xF4"
/*
* Panic Notifier Payload (x86-32)
@@ -61,7 +63,9 @@ bool check_bitmap_byte(uint32_t value);
* 0f 01 c1 vmcall
* f4 hlt
*/
-#define PANIC_PAYLOAD_32 "\xFA\xB8\x1F\x00\x00\x00\xBB\x08\x00\x00\x00\xB9\x00\x00\x00\x00\x0F\x01\xC1\xF4"
+#define PANIC_PAYLOAD_32 \
+ "\xFA\xB8\x1F\x00\x00\x00\xBB\x08\x00\x00\x00\xB9\x00\x00\x00\x00\x0F\x01\xC1" \
+ "\xF4"
/*
* KASAN Notifier Payload (x86-64)
@@ -72,7 +76,9 @@ bool check_bitmap_byte(uint32_t value);
* 0f 01 c1 vmcall
* f4 hlt
*/
-#define KASAN_PAYLOAD_64 "\xFA\x48\xC7\xC0\x1F\x00\x00\x00\x48\xC7\xC3\x09\x00\x00\x00\x48\xC7\xC1\x00\x00\x00\x00\x0F\x01\xC1\xF4"
+#define KASAN_PAYLOAD_64 \
+ "\xFA\x48\xC7\xC0\x1F\x00\x00\x00\x48\xC7\xC3\x09\x00\x00\x00\x48\xC7\xC1\x00" \
+ "\x00\x00\x00\x0F\x01\xC1\xF4"
/*
* KASAN Notifier Payload (x86-32)
@@ -83,10 +89,12 @@ bool check_bitmap_byte(uint32_t value);
* 0f 01 c1 vmcall
* f4 hlt
*/
-#define KASAN_PAYLOAD_32 "\xFA\xB8\x1F\x00\x00\x00\xBB\x09\x00\x00\x00\xB9\x00\x00\x00\x00\x0F\x01\xC1\xF4"
+#define KASAN_PAYLOAD_32 \
+ "\xFA\xB8\x1F\x00\x00\x00\xBB\x09\x00\x00\x00\xB9\x00\x00\x00\x00\x0F\x01\xC1" \
+ "\xF4"
-void pt_setup_program(void* ptr);
-void pt_setup_snd_handler(void (*tmp)(char, void*), void* tmp_s);
+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);
void pt_setup_enable_hypercalls(void);
@@ -107,38 +115,56 @@ bool pt_hypercalls_enabled(void);
void hypercall_unlock(void);
void hypercall_reload(void);
-void handle_hypercall_kafl_acquire(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
-void handle_hypercall_kafl_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
-void handle_hypercall_kafl_panic(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
+void handle_hypercall_kafl_acquire(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
+void handle_hypercall_kafl_release(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
+void handle_hypercall_kafl_panic(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
-void handle_hypercall_kafl_page_dump_bp(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg, uint64_t page);
+void handle_hypercall_kafl_page_dump_bp(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg,
+ uint64_t page);
-void hprintf(char* msg);
+void hprintf(char *msg);
-bool handle_hypercall_kafl_next_payload(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
+bool handle_hypercall_kafl_next_payload(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
void hypercall_reset_hprintf_counter(void);
-bool handle_hypercall_kafl_hook(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
-void handle_hypercall_kafl_mtf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
+bool handle_hypercall_kafl_hook(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
+void handle_hypercall_kafl_mtf(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
void pt_enable_rqo(CPUState *cpu);
void pt_disable_rqo(CPUState *cpu);
void pt_enable_rqi(CPUState *cpu);
void pt_disable_rqi(CPUState *cpu);
-void pt_set_redqueen_instrumentation_mode(CPUState *cpu, int redqueen_instruction_mode);
+void pt_set_redqueen_instrumentation_mode(CPUState *cpu,
+ int redqueen_instruction_mode);
void pt_set_redqueen_update_blacklist(CPUState *cpu, bool newval);
void pt_set_enable_patches_pending(CPUState *cpu);
void pt_set_disable_patches_pending(CPUState *cpu);
void create_fast_snapshot(CPUState *cpu, bool nested);
-int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall, uint64_t arg);
+int handle_kafl_hypercall(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall,
+ uint64_t arg);
void skip_init(void);
-typedef struct kafl_dump_file_s{
- uint64_t file_name_str_ptr;
- uint64_t data_ptr;
- uint64_t bytes;
- uint8_t append;
+typedef struct kafl_dump_file_s {
+ uint64_t file_name_str_ptr;
+ uint64_t data_ptr;
+ uint64_t bytes;
+ uint8_t append;
} __attribute__((packed)) kafl_dump_file_t;
-
diff --git a/nyx/interface.c b/nyx/interface.c
index c191805087..d9935a6e40 100644
--- a/nyx/interface.c
+++ b/nyx/interface.c
@@ -26,449 +26,476 @@ along with QEMU-PT. If not, see .
#include
#include
-#include "qapi/error.h"
-#include "qemu/cutils.h"
-#include "hw/qdev-properties.h"
+#include "chardev/char-fe.h"
+#include "exec/ram_addr.h"
#include "hw/hw.h"
#include "hw/i386/pc.h"
-#include "hw/pci/pci.h"
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
-#include "sysemu/kvm.h"
+#include "hw/pci/pci.h"
+#include "hw/qdev-properties.h"
#include "migration/migration.h"
+#include "qapi/error.h"
+#include "qapi/visitor.h"
+#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qemu/event_notifier.h"
#include "qom/object_interfaces.h"
-#include "chardev/char-fe.h"
#include "sysemu/hostmem.h"
+#include "sysemu/kvm.h"
#include "sysemu/qtest.h"
-#include "qapi/visitor.h"
-#include "exec/ram_addr.h"
-#include "pt.h"
+#include "nyx/debug.h"
+#include "nyx/helpers.h"
#include "nyx/hypercall/hypercall.h"
#include "nyx/interface.h"
-#include "nyx/debug.h"
-#include "nyx/synchronization.h"
-#include "nyx/snapshot/devices/state_reallocation.h"
#include "nyx/memory_access.h"
-#include "nyx/state/state.h"
#include "nyx/sharedir.h"
-#include "nyx/helpers.h"
+#include "nyx/snapshot/devices/state_reallocation.h"
+#include "nyx/state/state.h"
+#include "nyx/synchronization.h"
#include "nyx/trace_dump.h"
+#include "pt.h"
#include "redqueen.h"
#define CONVERT_UINT64(x) (uint64_t)(strtoull(x, NULL, 16))
#define TYPE_NYX_MEM "nyx"
-#define NYX_MEM(obj) \
- OBJECT_CHECK(nyx_interface_state, (obj), TYPE_NYX_MEM)
+#define NYX_MEM(obj) OBJECT_CHECK(nyx_interface_state, (obj), TYPE_NYX_MEM)
static void nyx_realize(DeviceState *dev, Error **errp);
typedef struct nyx_interface_state {
- DeviceState parent_obj;
+ DeviceState parent_obj;
- Chardev *nyx_chr_drv_state;
- CharBackend chr;
+ Chardev *nyx_chr_drv_state;
+ CharBackend chr;
- char* sharedir;
+ char *sharedir;
- char* workdir;
- uint32_t worker_id;
- uint64_t cow_primary_size;
-
- char* redqueen_workdir;
- char* data_bar_fd_0;
- char* data_bar_fd_1;
- char* data_bar_fd_2;
- char* bitmap_file;
+ char *workdir;
+ uint32_t worker_id;
+ uint64_t cow_primary_size;
- char* filter_bitmap[4];
- char* ip_filter[4][2];
+ char *redqueen_workdir;
+ char *data_bar_fd_0;
+ char *data_bar_fd_1;
+ char *data_bar_fd_2;
+ char *bitmap_file;
- uint32_t bitmap_size;
- uint32_t input_buffer_size;
+ char *filter_bitmap[4];
+ char *ip_filter[4][2];
- bool dump_pt_trace;
- bool edge_cb_trace;
+ uint32_t bitmap_size;
+ uint32_t input_buffer_size;
+
+ bool dump_pt_trace;
+ bool edge_cb_trace;
+
+ bool redqueen;
- bool redqueen;
-
} nyx_interface_state;
-static void nyx_interface_event(void *opaque, int event){
+static void nyx_interface_event(void *opaque, int event)
+{
}
-static void send_char(char val, void* tmp_s){
- nyx_interface_state *s = tmp_s;
+static void send_char(char val, void *tmp_s)
+{
+ nyx_interface_state *s = tmp_s;
- assert(val == NYX_INTERFACE_PING);
- __sync_synchronize();
+ assert(val == NYX_INTERFACE_PING);
+ __sync_synchronize();
- qemu_chr_fe_write(&s->chr, (const uint8_t *) &val, 1);
+ qemu_chr_fe_write(&s->chr, (const uint8_t *)&val, 1);
}
-static int nyx_interface_can_receive(void * opaque){
- return sizeof(int64_t);
+static int nyx_interface_can_receive(void *opaque)
+{
+ return sizeof(int64_t);
}
-static nyx_interface_state* state = NULL;
+static nyx_interface_state *state = NULL;
-static void init_send_char(nyx_interface_state* s){
- state = s;
+static void init_send_char(nyx_interface_state *s)
+{
+ state = s;
}
-bool interface_send_char(char val){
-
- if(state){
- send_char(val, state);
- return true;
- }
- return false;
+bool interface_send_char(char val)
+{
+ if (state) {
+ send_char(val, state);
+ return true;
+ }
+ return false;
}
-static void nyx_interface_receive(void *opaque, const uint8_t * buf, int size){
- int i;
- for(i = 0; i < size; i++){
- switch(buf[i]){
- case NYX_INTERFACE_PING:
- synchronization_unlock();
- break;
- case '\n':
- break;
- case 'E':
- exit(0);
- default:
- break;
- assert(false);
- }
- }
+static void nyx_interface_receive(void *opaque, const uint8_t *buf, int size)
+{
+ int i;
+ for (i = 0; i < size; i++) {
+ switch (buf[i]) {
+ case NYX_INTERFACE_PING:
+ synchronization_unlock();
+ break;
+ case '\n':
+ break;
+ case 'E':
+ exit(0);
+ default:
+ break;
+ assert(false);
+ }
+ }
}
-static int nyx_create_payload_buffer(nyx_interface_state *s, uint64_t buffer_size, const char* file, Error **errp){
- void * ptr;
- int fd;
- struct stat st;
+static int nyx_create_payload_buffer(nyx_interface_state *s,
+ uint64_t buffer_size,
+ const char *file,
+ Error **errp)
+{
+ void *ptr;
+ int fd;
+ struct stat st;
- fd = open(file, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
- assert(ftruncate(fd, buffer_size) == 0);
- stat(file, &st);
- nyx_debug_p(INTERFACE_PREFIX, "new shm file: (max size: %lx) %lx", buffer_size, st.st_size);
-
- assert(buffer_size == st.st_size);
- ptr = mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ fd = open(file, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ assert(ftruncate(fd, buffer_size) == 0);
+ stat(file, &st);
+ nyx_debug_p(INTERFACE_PREFIX, "new shm file: (max size: %lx) %lx", buffer_size,
+ st.st_size);
- if (ptr == MAP_FAILED) {
- error_setg_errno(errp, errno, "Failed to mmap memory");
- return -1;
- }
+ assert(buffer_size == st.st_size);
+ ptr = mmap(0, buffer_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- GET_GLOBAL_STATE()->shared_payload_buffer_fd = fd;
- GET_GLOBAL_STATE()->shared_payload_buffer_size = buffer_size;
+ if (ptr == MAP_FAILED) {
+ error_setg_errno(errp, errno, "Failed to mmap memory");
+ return -1;
+ }
- init_send_char(s);
+ GET_GLOBAL_STATE()->shared_payload_buffer_fd = fd;
+ GET_GLOBAL_STATE()->shared_payload_buffer_size = buffer_size;
- return 0;
+ init_send_char(s);
+
+ return 0;
}
-static void nyx_guest_setup_bitmap(nyx_interface_state *s, char* filename, uint32_t bitmap_size){
- void * ptr;
- int fd;
- struct stat st;
-
- fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
- assert(ftruncate(fd, bitmap_size) == 0);
- stat(filename, &st);
- assert(bitmap_size == st.st_size);
- ptr = mmap(0, bitmap_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
- GET_GLOBAL_STATE()->shared_bitmap_ptr = (void*)ptr;
- GET_GLOBAL_STATE()->shared_bitmap_fd = fd;
- GET_GLOBAL_STATE()->shared_bitmap_size = bitmap_size;
- GET_GLOBAL_STATE()->shared_bitmap_real_size = bitmap_size;
+static void nyx_guest_setup_bitmap(nyx_interface_state *s,
+ char *filename,
+ uint32_t bitmap_size)
+{
+ void *ptr;
+ int fd;
+ struct stat st;
+
+ fd = open(filename, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ assert(ftruncate(fd, bitmap_size) == 0);
+ stat(filename, &st);
+ assert(bitmap_size == st.st_size);
+ ptr = mmap(0, bitmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ GET_GLOBAL_STATE()->shared_bitmap_ptr = (void *)ptr;
+ GET_GLOBAL_STATE()->shared_bitmap_fd = fd;
+ GET_GLOBAL_STATE()->shared_bitmap_size = bitmap_size;
+ GET_GLOBAL_STATE()->shared_bitmap_real_size = bitmap_size;
}
-static void nyx_guest_setup_ijon_buffer(nyx_interface_state *s, char* filename){
- void * ptr;
- int fd;
- struct stat st;
-
- fd = open(filename, O_CREAT|O_RDWR, S_IRWXU|S_IRWXG|S_IRWXO);
- assert(ftruncate(fd, DEFAULT_NYX_IJON_BITMAP_SIZE) == 0);
- stat(filename, &st);
- assert(DEFAULT_NYX_IJON_BITMAP_SIZE == st.st_size);
- ptr = mmap(0, DEFAULT_NYX_IJON_BITMAP_SIZE, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-
- GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr = (void*)ptr;
- GET_GLOBAL_STATE()->shared_ijon_bitmap_fd = fd;
- GET_GLOBAL_STATE()->shared_ijon_bitmap_size = DEFAULT_NYX_IJON_BITMAP_SIZE;
+static void nyx_guest_setup_ijon_buffer(nyx_interface_state *s, char *filename)
+{
+ void *ptr;
+ int fd;
+ struct stat st;
+
+ fd = open(filename, O_CREAT | O_RDWR, S_IRWXU | S_IRWXG | S_IRWXO);
+ assert(ftruncate(fd, DEFAULT_NYX_IJON_BITMAP_SIZE) == 0);
+ stat(filename, &st);
+ assert(DEFAULT_NYX_IJON_BITMAP_SIZE == st.st_size);
+ ptr = mmap(0, DEFAULT_NYX_IJON_BITMAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
+ fd, 0);
+
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_ptr = (void *)ptr;
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_fd = fd;
+ GET_GLOBAL_STATE()->shared_ijon_bitmap_size = DEFAULT_NYX_IJON_BITMAP_SIZE;
}
-static bool verify_workdir_state(nyx_interface_state *s, Error **errp){
+static bool verify_workdir_state(nyx_interface_state *s, Error **errp)
+{
+ char *workdir = s->workdir;
+ uint32_t id = s->worker_id;
+ char *tmp;
- char* workdir = s->workdir;
- uint32_t id = s->worker_id;
- char* tmp;
+ if (!folder_exits(workdir)) {
+ nyx_error("Error: %s does not exist...\n", workdir);
+ return false;
+ }
- if (!folder_exits(workdir)){
- nyx_error("Error: %s does not exist...\n", workdir);
- return false;
- }
+ set_workdir_path(workdir);
- set_workdir_path(workdir);
+ assert(asprintf(&tmp, "%s/dump/", workdir) != -1);
+ if (!folder_exits(tmp)) {
+ mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/dump/", workdir) != -1);
- if (!folder_exits(tmp)){
- mkdir(tmp, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/interface_%d", workdir, id) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/interface_%d", workdir, id) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...\n", tmp);
- free(tmp);
- return false;
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/payload_%d", workdir, id) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ } else {
+ nyx_create_payload_buffer(s, s->input_buffer_size, tmp, errp);
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/payload_%d", workdir, id) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...\n", tmp);
- free(tmp);
- return false;
- }
- else {
- nyx_create_payload_buffer(s, s->input_buffer_size, tmp, errp);
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/bitmap_%d", workdir, id) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ } else {
+ nyx_guest_setup_bitmap(s, tmp, s->bitmap_size);
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/bitmap_%d", workdir, id) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...\n", tmp);
- free(tmp);
- return false;
- } else {
- nyx_guest_setup_bitmap(s, tmp, s->bitmap_size);
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/ijon_%d", workdir, id) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ } else {
+ nyx_guest_setup_ijon_buffer(s, tmp);
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/ijon_%d", workdir, id) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...\n", tmp);
- free(tmp);
- return false;
- } else {
- nyx_guest_setup_ijon_buffer(s, tmp);
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/page_cache.lock", workdir) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...", tmp);
+ free(tmp);
+ return false;
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/page_cache.lock", workdir) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...", tmp);
- free(tmp);
- return false;
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/page_cache.addr", workdir) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/page_cache.addr", workdir) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...\n", tmp);
- free(tmp);
- return false;
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/page_cache.dump", workdir) != -1);
+ if (!file_exits(tmp)) {
+ nyx_error("Error: %s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/page_cache.dump", workdir) != -1);
- if (!file_exits(tmp)){
- nyx_error("Error: %s does not exist...\n", tmp);
- free(tmp);
- return false;
- }
- free(tmp);
+ assert(asprintf(&tmp, "%s/page_cache", workdir) != -1);
+ init_page_cache(tmp);
- assert(asprintf(&tmp, "%s/page_cache", workdir) != -1);
- init_page_cache(tmp);
+ assert(asprintf(&tmp, "%s/redqueen_workdir_%d/", workdir, id) != -1);
+ if (!folder_exits(tmp)) {
+ nyx_error("%s does not exist...\n", tmp);
+ free(tmp);
+ return false;
+ } else {
+ setup_redqueen_workdir(tmp);
+ }
+ free(tmp);
- assert(asprintf(&tmp, "%s/redqueen_workdir_%d/", workdir, id) != -1);
- if (!folder_exits(tmp)){
- nyx_error("%s does not exist...\n", tmp);
- free(tmp);
- return false;
- }
- else {
- setup_redqueen_workdir(tmp);
- }
- free(tmp);
+ init_redqueen_state();
- init_redqueen_state();
+ if (s->dump_pt_trace) {
+ assert(asprintf(&tmp, "%s/pt_trace_dump_%d", workdir, id) != -1);
+ pt_trace_dump_init(tmp);
+ free(tmp);
+ }
- if(s->dump_pt_trace){
- assert(asprintf(&tmp, "%s/pt_trace_dump_%d", workdir, id) != -1);
- pt_trace_dump_init(tmp);
- free(tmp);
- }
-
- if(s->edge_cb_trace){
- redqueen_trace_init();
- }
+ if (s->edge_cb_trace) {
+ redqueen_trace_init();
+ }
- assert(asprintf(&tmp, "%s/aux_buffer_%d", workdir, id) != -1);
- init_aux_buffer(tmp);
- free(tmp);
+ assert(asprintf(&tmp, "%s/aux_buffer_%d", workdir, id) != -1);
+ init_aux_buffer(tmp);
+ free(tmp);
- return true;
+ return true;
}
-#define KVM_VMX_PT_GET_ADDRN _IO(KVMIO, 0xe9)
+#define KVM_VMX_PT_GET_ADDRN _IO(KVMIO, 0xe9)
-static void check_ipt_range(uint8_t i){
- int ret = 0;
- int kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
- ret = ioctl(kvm, KVM_VMX_PT_GET_ADDRN, NULL);
+static void check_ipt_range(uint8_t i)
+{
+ int ret = 0;
+ int kvm = open("/dev/kvm", O_RDWR | O_CLOEXEC);
+ ret = ioctl(kvm, KVM_VMX_PT_GET_ADDRN, NULL);
- if(ret == -1){
- nyx_error("Error: Multi range tracing is not supported!\n");
- exit(1);
- }
+ if (ret == -1) {
+ nyx_error("Error: Multi range tracing is not supported!\n");
+ exit(1);
+ }
- if(ret < (i+1)){
- nyx_error("Error: CPU supports only %d IP filters!\n", ret);
- exit(1);
- }
- close(kvm);
+ if (ret < (i + 1)) {
+ nyx_error("Error: CPU supports only %d IP filters!\n", ret);
+ exit(1);
+ }
+ close(kvm);
}
-static void check_available_ipt_ranges(nyx_interface_state* s){
- uint64_t addr_a, addr_b;
+static void check_available_ipt_ranges(nyx_interface_state *s)
+{
+ uint64_t addr_a, addr_b;
- int kvm_fd = qemu_open("/dev/kvm", O_RDWR);
- if (kvm_fd == -1) {
- nyx_error("Error: could not access KVM kernel module: %m\n");
- exit(1);
- }
+ int kvm_fd = qemu_open("/dev/kvm", O_RDWR);
+ if (kvm_fd == -1) {
+ nyx_error("Error: could not access KVM kernel module: %m\n");
+ exit(1);
+ }
- if (ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_PT) == 1 && ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_FDL) == 1) {
- for(uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++){
- if(s->ip_filter[i][0] && s->ip_filter[i][1]){
- if(i >= 1){
- check_ipt_range(i);
- }
- addr_a = CONVERT_UINT64(s->ip_filter[i][0]);
- addr_b = CONVERT_UINT64(s->ip_filter[i][1]);
- if (addr_a < addr_b){
- pt_setup_ip_filters(i, addr_a, addr_b);
- }
- }
- }
- }
- close(kvm_fd);
+ if (ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_PT) == 1 &&
+ ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_NYX_FDL) == 1)
+ {
+ for (uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++) {
+ if (s->ip_filter[i][0] && s->ip_filter[i][1]) {
+ if (i >= 1) {
+ check_ipt_range(i);
+ }
+ addr_a = CONVERT_UINT64(s->ip_filter[i][0]);
+ addr_b = CONVERT_UINT64(s->ip_filter[i][1]);
+ if (addr_a < addr_b) {
+ pt_setup_ip_filters(i, addr_a, addr_b);
+ }
+ }
+ }
+ }
+ close(kvm_fd);
}
-static bool verify_sharedir_state(nyx_interface_state *s, Error **errp){
+static bool verify_sharedir_state(nyx_interface_state *s, Error **errp)
+{
+ char *sharedir = s->sharedir;
- char* sharedir = s->sharedir;
-
- if (!folder_exits(sharedir)){
- return false;
- }
- return true;
+ if (!folder_exits(sharedir)) {
+ return false;
+ }
+ return true;
}
-static void nyx_realize(DeviceState *dev, Error **errp){
- nyx_interface_state *s = NYX_MEM(dev);
+static void nyx_realize(DeviceState *dev, Error **errp)
+{
+ nyx_interface_state *s = NYX_MEM(dev);
- if(s->bitmap_size <= 0){
- s->bitmap_size = DEFAULT_NYX_BITMAP_SIZE;
- }
+ if (s->bitmap_size <= 0) {
+ s->bitmap_size = DEFAULT_NYX_BITMAP_SIZE;
+ }
- if(s->worker_id == 0xFFFF){
- nyx_error("Error: Invalid worker id...\n");
- exit(1);
- }
+ if (s->worker_id == 0xFFFF) {
+ nyx_error("Error: Invalid worker id...\n");
+ exit(1);
+ }
- if(s->cow_primary_size){
- set_global_cow_cache_primary_size(s->cow_primary_size);
- }
- GET_GLOBAL_STATE()->worker_id = s->worker_id;
+ if (s->cow_primary_size) {
+ set_global_cow_cache_primary_size(s->cow_primary_size);
+ }
+ GET_GLOBAL_STATE()->worker_id = s->worker_id;
- if (!s->workdir || !verify_workdir_state(s, errp)){
- nyx_error("Error: Invalid work dir...\n");
- exit(1);
- }
+ if (!s->workdir || !verify_workdir_state(s, errp)) {
+ nyx_error("Error: Invalid work dir...\n");
+ exit(1);
+ }
- if (!s->sharedir || !verify_sharedir_state(s, errp)){
- nyx_error("Warning: Invalid sharedir...\n");
- }
- else{
- sharedir_set_dir(GET_GLOBAL_STATE()->sharedir, s->sharedir);
- }
+ if (!s->sharedir || !verify_sharedir_state(s, errp)) {
+ nyx_error("Warning: Invalid sharedir...\n");
+ } else {
+ sharedir_set_dir(GET_GLOBAL_STATE()->sharedir, s->sharedir);
+ }
- if(&s->chr){
- qemu_chr_fe_set_handlers(&s->chr, nyx_interface_can_receive, nyx_interface_receive, nyx_interface_event, NULL, s, NULL, true);
- }
+ if (&s->chr) {
+ qemu_chr_fe_set_handlers(&s->chr, nyx_interface_can_receive,
+ nyx_interface_receive, nyx_interface_event, NULL, s,
+ NULL, true);
+ }
- check_available_ipt_ranges(s);
+ check_available_ipt_ranges(s);
- pt_setup_enable_hypercalls();
- init_crash_handler();
+ pt_setup_enable_hypercalls();
+ init_crash_handler();
}
static Property nyx_interface_properties[] = {
- DEFINE_PROP_CHR("chardev", nyx_interface_state, chr),
+ 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),
- * let's use DEFINE_PROP_STRING and post-process all values by strtol...
- */
- DEFINE_PROP_STRING("ip0_a", nyx_interface_state, ip_filter[0][0]),
- DEFINE_PROP_STRING("ip0_b", nyx_interface_state, ip_filter[0][1]),
- DEFINE_PROP_STRING("ip1_a", nyx_interface_state, ip_filter[1][0]),
- DEFINE_PROP_STRING("ip1_b", nyx_interface_state, ip_filter[1][1]),
- DEFINE_PROP_STRING("ip2_a", nyx_interface_state, ip_filter[2][0]),
- DEFINE_PROP_STRING("ip2_b", nyx_interface_state, ip_filter[2][1]),
- DEFINE_PROP_STRING("ip3_a", nyx_interface_state, ip_filter[3][0]),
- DEFINE_PROP_STRING("ip3_b", nyx_interface_state, ip_filter[3][1]),
+ 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),
+ * let's use DEFINE_PROP_STRING and post-process all values by strtol...
+ */
+ DEFINE_PROP_STRING("ip0_a", nyx_interface_state, ip_filter[0][0]),
+ DEFINE_PROP_STRING("ip0_b", nyx_interface_state, ip_filter[0][1]),
+ DEFINE_PROP_STRING("ip1_a", nyx_interface_state, ip_filter[1][0]),
+ DEFINE_PROP_STRING("ip1_b", nyx_interface_state, ip_filter[1][1]),
+ DEFINE_PROP_STRING("ip2_a", nyx_interface_state, ip_filter[2][0]),
+ DEFINE_PROP_STRING("ip2_b", nyx_interface_state, ip_filter[2][1]),
+ DEFINE_PROP_STRING("ip3_a", nyx_interface_state, ip_filter[3][0]),
+ DEFINE_PROP_STRING("ip3_b", nyx_interface_state, ip_filter[3][1]),
- DEFINE_PROP_UINT32("bitmap_size", nyx_interface_state, bitmap_size, DEFAULT_NYX_BITMAP_SIZE),
- DEFINE_PROP_UINT32("input_buffer_size", nyx_interface_state, input_buffer_size, DEFAULT_NYX_BITMAP_SIZE),
- DEFINE_PROP_BOOL("dump_pt_trace", nyx_interface_state, dump_pt_trace, false),
- DEFINE_PROP_BOOL("edge_cb_trace", nyx_interface_state, edge_cb_trace, false),
+ DEFINE_PROP_UINT32("bitmap_size",
+ nyx_interface_state,
+ bitmap_size,
+ DEFAULT_NYX_BITMAP_SIZE),
+ DEFINE_PROP_UINT32("input_buffer_size",
+ nyx_interface_state,
+ input_buffer_size,
+ DEFAULT_NYX_BITMAP_SIZE),
+ DEFINE_PROP_BOOL("dump_pt_trace", nyx_interface_state, dump_pt_trace, false),
+ DEFINE_PROP_BOOL("edge_cb_trace", nyx_interface_state, edge_cb_trace, false),
- DEFINE_PROP_END_OF_LIST(),
+ DEFINE_PROP_END_OF_LIST(),
};
-static void nyx_interface_class_init(ObjectClass *klass, void *data){
- DeviceClass *dc = DEVICE_CLASS(klass);
- dc->realize = nyx_realize;
- dc->props = nyx_interface_properties;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
- dc->desc = "Nyx Interface";
+static void nyx_interface_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ dc->realize = nyx_realize;
+ dc->props = nyx_interface_properties;
+ set_bit(DEVICE_CATEGORY_MISC, dc->categories);
+ dc->desc = "Nyx Interface";
}
-static void nyx_interface_init(Object *obj){
+static void nyx_interface_init(Object *obj)
+{
}
static const TypeInfo nyx_interface_info = {
- .name = TYPE_NYX_MEM,
- .parent = TYPE_DEVICE,
- .instance_size = sizeof(nyx_interface_state),
- .instance_init = nyx_interface_init,
- .class_init = nyx_interface_class_init,
+ .name = TYPE_NYX_MEM,
+ .parent = TYPE_DEVICE,
+ .instance_size = sizeof(nyx_interface_state),
+ .instance_init = nyx_interface_init,
+ .class_init = nyx_interface_class_init,
};
-static void nyx_interface_register_types(void){
- type_register_static(&nyx_interface_info);
+static void nyx_interface_register_types(void)
+{
+ type_register_static(&nyx_interface_info);
}
type_init(nyx_interface_register_types)
diff --git a/nyx/interface.h b/nyx/interface.h
index e75e22d90a..a3157f421e 100644
--- a/nyx/interface.h
+++ b/nyx/interface.h
@@ -23,10 +23,10 @@ along with QEMU-PT. If not, see .
#define INTERFACE_H
/* 64k bitmap + 4k ijon buffer */
-#define DEFAULT_NYX_IJON_BITMAP_SIZE 0x1000 /* fixed size buffer for IJON -> 4k */
-#define DEFAULT_NYX_BITMAP_SIZE 0x10000 /* default bitmap size => 64k */
+#define DEFAULT_NYX_IJON_BITMAP_SIZE 0x1000 /* fixed size buffer for IJON -> 4k */
+#define DEFAULT_NYX_BITMAP_SIZE 0x10000 /* default bitmap size => 64k */
-#define NYX_INTERFACE_PING 'x'
+#define NYX_INTERFACE_PING 'x'
bool interface_send_char(char val);
diff --git a/nyx/kvm_nested.c b/nyx/kvm_nested.c
index f6eca246d1..3971742298 100644
--- a/nyx/kvm_nested.c
+++ b/nyx/kvm_nested.c
@@ -1,282 +1,319 @@
#include "qemu/osdep.h"
-#include
#include "sysemu/kvm.h"
+#include
-#include "qemu-common.h"
-#include "nyx/kvm_nested.h"
-#include "cpu.h"
-#include "nyx/debug.h"
#include "exec/ram_addr.h"
#include "qemu/rcu_queue.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "nyx/debug.h"
+#include "nyx/kvm_nested.h"
#include "nyx/state/state.h"
#include "pt.h"
-#define PPAGE_SIZE 0x1000
-#define PENTRIES 0x200
-#define PLEVEL_4_SHIFT 12
-#define PLEVEL_3_SHIFT 21
-#define PLEVEL_2_SHIFT 30
-#define PLEVEL_1_SHIFT 39
+#define PPAGE_SIZE 0x1000
+#define PENTRIES 0x200
+#define PLEVEL_4_SHIFT 12
+#define PLEVEL_3_SHIFT 21
+#define PLEVEL_2_SHIFT 30
+#define PLEVEL_1_SHIFT 39
#define SIGN_EXTEND_TRESHOLD 0x100
-#define SIGN_EXTEND 0xFFFF000000000000ULL
-#define PAGETABLE_MASK 0xFFFFFFFFFF000ULL
-#define CHECK_BIT(var,pos) !!(((var) & (1ULL<<(pos))))
+#define SIGN_EXTEND 0xFFFF000000000000ULL
+#define PAGETABLE_MASK 0xFFFFFFFFFF000ULL
+#define CHECK_BIT(var, pos) !!(((var) & (1ULL << (pos))))
struct vmcs_hdr {
- uint32_t revision_id:31;
- uint32_t shadow_vmcs:1;
+ uint32_t revision_id : 31;
+ uint32_t shadow_vmcs : 1;
};
struct __attribute__((__packed__)) vmcs12 {
- /* According to the Intel spec, a VMCS region must start with the
- * following two fields. Then follow implementation-specific data.
- */
- struct vmcs_hdr hdr;
- uint32_t abort;
+ /* According to the Intel spec, a VMCS region must start with the
+ * following two fields. Then follow implementation-specific data.
+ */
+ struct vmcs_hdr hdr;
+ uint32_t abort;
- uint32_t launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
- uint32_t padding[7]; /* room for future expansion */
+ uint32_t launch_state; /* set to 0 by VMCLEAR, to 1 by VMLAUNCH */
+ uint32_t padding[7]; /* room for future expansion */
- uint64_t io_bitmap_a;
- uint64_t io_bitmap_b;
- uint64_t msr_bitmap;
- uint64_t vm_exit_msr_store_addr;
- uint64_t vm_exit_msr_load_addr;
- uint64_t vm_entry_msr_load_addr;
- uint64_t tsc_offset;
- uint64_t virtual_apic_page_addr;
- uint64_t apic_access_addr;
- uint64_t posted_intr_desc_addr;
- uint64_t ept_pointer;
- uint64_t eoi_exit_bitmap0;
- uint64_t eoi_exit_bitmap1;
- uint64_t eoi_exit_bitmap2;
- uint64_t eoi_exit_bitmap3;
- uint64_t xss_exit_bitmap;
- uint64_t guest_physical_address;
- uint64_t vmcs_link_pointer;
- uint64_t guest_ia32_debugctl;
- uint64_t guest_ia32_pat;
- uint64_t guest_ia32_efer;
- uint64_t guest_ia32_perf_global_ctrl;
- uint64_t guest_pdptr0;
- uint64_t guest_pdptr1;
- uint64_t guest_pdptr2;
- uint64_t guest_pdptr3;
- uint64_t guest_bndcfgs;
- uint64_t host_ia32_pat;
- uint64_t host_ia32_efer;
- uint64_t host_ia32_perf_global_ctrl;
- uint64_t vmread_bitmap;
- uint64_t vmwrite_bitmap;
- uint64_t vm_function_control;
- uint64_t eptp_list_address;
- uint64_t pml_address;
- uint64_t padding64[3]; /* room for future expansion */
- /*
- * To allow migration of L1 (complete with its L2 guests) between
- * machines of different natural widths (32 or 64 bit), we cannot have
- * unsigned long fields with no explict size. We use uint64_t (aliased
- * uint64_t) instead. Luckily, x86 is little-endian.
- */
- uint64_t cr0_guest_host_mask;
- uint64_t cr4_guest_host_mask;
- uint64_t cr0_read_shadow;
- uint64_t cr4_read_shadow;
- uint64_t cr3_target_value0;
- uint64_t cr3_target_value1;
- uint64_t cr3_target_value2;
- uint64_t cr3_target_value3;
- uint64_t exit_qualification;
- uint64_t guest_linear_address;
- uint64_t guest_cr0;
- uint64_t guest_cr3;
- uint64_t guest_cr4;
- uint64_t guest_es_base;
- uint64_t guest_cs_base;
- uint64_t guest_ss_base;
- uint64_t guest_ds_base;
- uint64_t guest_fs_base;
- uint64_t guest_gs_base;
- uint64_t guest_ldtr_base;
- uint64_t guest_tr_base;
- uint64_t guest_gdtr_base;
- uint64_t guest_idtr_base;
- uint64_t guest_dr7;
- uint64_t guest_rsp;
- uint64_t guest_rip;
- uint64_t guest_rflags;
- uint64_t guest_pending_dbg_exceptions;
- uint64_t guest_sysenter_esp;
- uint64_t guest_sysenter_eip;
- uint64_t host_cr0;
- uint64_t host_cr3;
- uint64_t host_cr4;
- uint64_t host_fs_base;
- uint64_t host_gs_base;
- uint64_t host_tr_base;
- uint64_t host_gdtr_base;
- uint64_t host_idtr_base;
- uint64_t host_ia32_sysenter_esp;
- uint64_t host_ia32_sysenter_eip;
- uint64_t host_rsp;
- uint64_t host_rip;
- uint64_t paddingl[8]; /* room for future expansion */
- uint32_t pin_based_vm_exec_control;
- uint32_t cpu_based_vm_exec_control;
- uint32_t exception_bitmap;
- uint32_t page_fault_error_code_mask;
- uint32_t page_fault_error_code_match;
- uint32_t cr3_target_count;
- uint32_t vm_exit_controls;
- uint32_t vm_exit_msr_store_count;
- uint32_t vm_exit_msr_load_count;
- uint32_t vm_entry_controls;
- uint32_t vm_entry_msr_load_count;
- uint32_t vm_entry_intr_info_field;
- uint32_t vm_entry_exception_error_code;
- uint32_t vm_entry_instruction_len;
- uint32_t tpr_threshold;
- uint32_t secondary_vm_exec_control;
- uint32_t vm_instruction_error;
- uint32_t vm_exit_reason;
- uint32_t vm_exit_intr_info;
- uint32_t vm_exit_intr_error_code;
- uint32_t idt_vectoring_info_field;
- uint32_t idt_vectoring_error_code;
- uint32_t vm_exit_instruction_len;
- uint32_t vmx_instruction_info;
- uint32_t guest_es_limit;
- uint32_t guest_cs_limit;
- uint32_t guest_ss_limit;
- uint32_t guest_ds_limit;
- uint32_t guest_fs_limit;
- uint32_t guest_gs_limit;
- uint32_t guest_ldtr_limit;
- uint32_t guest_tr_limit;
- uint32_t guest_gdtr_limit;
- uint32_t guest_idtr_limit;
- uint32_t guest_es_ar_bytes;
- uint32_t guest_cs_ar_bytes;
- uint32_t guest_ss_ar_bytes;
- uint32_t guest_ds_ar_bytes;
- uint32_t guest_fs_ar_bytes;
- uint32_t guest_gs_ar_bytes;
- uint32_t guest_ldtr_ar_bytes;
- uint32_t guest_tr_ar_bytes;
- uint32_t guest_interruptibility_info;
- uint32_t guest_activity_state;
- uint32_t guest_sysenter_cs;
- uint32_t host_ia32_sysenter_cs;
- uint32_t vmx_preemption_timer_value;
- uint32_t padding32[7]; /* room for future expansion */
- uint16_t virtual_processor_id;
- uint16_t posted_intr_nv;
- uint16_t guest_es_selector;
- uint16_t guest_cs_selector;
- uint16_t guest_ss_selector;
- uint16_t guest_ds_selector;
- uint16_t guest_fs_selector;
- uint16_t guest_gs_selector;
- uint16_t guest_ldtr_selector;
- uint16_t guest_tr_selector;
- uint16_t guest_intr_status;
- uint16_t host_es_selector;
- uint16_t host_cs_selector;
- uint16_t host_ss_selector;
- uint16_t host_ds_selector;
- uint16_t host_fs_selector;
- uint16_t host_gs_selector;
- uint16_t host_tr_selector;
- uint16_t guest_pml_index;
+ uint64_t io_bitmap_a;
+ uint64_t io_bitmap_b;
+ uint64_t msr_bitmap;
+ uint64_t vm_exit_msr_store_addr;
+ uint64_t vm_exit_msr_load_addr;
+ uint64_t vm_entry_msr_load_addr;
+ uint64_t tsc_offset;
+ uint64_t virtual_apic_page_addr;
+ uint64_t apic_access_addr;
+ uint64_t posted_intr_desc_addr;
+ uint64_t ept_pointer;
+ uint64_t eoi_exit_bitmap0;
+ uint64_t eoi_exit_bitmap1;
+ uint64_t eoi_exit_bitmap2;
+ uint64_t eoi_exit_bitmap3;
+ uint64_t xss_exit_bitmap;
+ uint64_t guest_physical_address;
+ uint64_t vmcs_link_pointer;
+ uint64_t guest_ia32_debugctl;
+ uint64_t guest_ia32_pat;
+ uint64_t guest_ia32_efer;
+ uint64_t guest_ia32_perf_global_ctrl;
+ uint64_t guest_pdptr0;
+ uint64_t guest_pdptr1;
+ uint64_t guest_pdptr2;
+ uint64_t guest_pdptr3;
+ uint64_t guest_bndcfgs;
+ uint64_t host_ia32_pat;
+ uint64_t host_ia32_efer;
+ uint64_t host_ia32_perf_global_ctrl;
+ uint64_t vmread_bitmap;
+ uint64_t vmwrite_bitmap;
+ uint64_t vm_function_control;
+ uint64_t eptp_list_address;
+ uint64_t pml_address;
+ uint64_t padding64[3]; /* room for future expansion */
+ /*
+ * To allow migration of L1 (complete with its L2 guests) between
+ * machines of different natural widths (32 or 64 bit), we cannot have
+ * unsigned long fields with no explict size. We use uint64_t (aliased
+ * uint64_t) instead. Luckily, x86 is little-endian.
+ */
+ uint64_t cr0_guest_host_mask;
+ uint64_t cr4_guest_host_mask;
+ uint64_t cr0_read_shadow;
+ uint64_t cr4_read_shadow;
+ uint64_t cr3_target_value0;
+ uint64_t cr3_target_value1;
+ uint64_t cr3_target_value2;
+ uint64_t cr3_target_value3;
+ uint64_t exit_qualification;
+ uint64_t guest_linear_address;
+ uint64_t guest_cr0;
+ uint64_t guest_cr3;
+ uint64_t guest_cr4;
+ uint64_t guest_es_base;
+ uint64_t guest_cs_base;
+ uint64_t guest_ss_base;
+ uint64_t guest_ds_base;
+ uint64_t guest_fs_base;
+ uint64_t guest_gs_base;
+ uint64_t guest_ldtr_base;
+ uint64_t guest_tr_base;
+ uint64_t guest_gdtr_base;
+ uint64_t guest_idtr_base;
+ uint64_t guest_dr7;
+ uint64_t guest_rsp;
+ uint64_t guest_rip;
+ uint64_t guest_rflags;
+ uint64_t guest_pending_dbg_exceptions;
+ uint64_t guest_sysenter_esp;
+ uint64_t guest_sysenter_eip;
+ uint64_t host_cr0;
+ uint64_t host_cr3;
+ uint64_t host_cr4;
+ uint64_t host_fs_base;
+ uint64_t host_gs_base;
+ uint64_t host_tr_base;
+ uint64_t host_gdtr_base;
+ uint64_t host_idtr_base;
+ uint64_t host_ia32_sysenter_esp;
+ uint64_t host_ia32_sysenter_eip;
+ uint64_t host_rsp;
+ uint64_t host_rip;
+ uint64_t paddingl[8]; /* room for future expansion */
+ uint32_t pin_based_vm_exec_control;
+ uint32_t cpu_based_vm_exec_control;
+ uint32_t exception_bitmap;
+ uint32_t page_fault_error_code_mask;
+ uint32_t page_fault_error_code_match;
+ uint32_t cr3_target_count;
+ uint32_t vm_exit_controls;
+ uint32_t vm_exit_msr_store_count;
+ uint32_t vm_exit_msr_load_count;
+ uint32_t vm_entry_controls;
+ uint32_t vm_entry_msr_load_count;
+ uint32_t vm_entry_intr_info_field;
+ uint32_t vm_entry_exception_error_code;
+ uint32_t vm_entry_instruction_len;
+ uint32_t tpr_threshold;
+ uint32_t secondary_vm_exec_control;
+ uint32_t vm_instruction_error;
+ uint32_t vm_exit_reason;
+ uint32_t vm_exit_intr_info;
+ uint32_t vm_exit_intr_error_code;
+ uint32_t idt_vectoring_info_field;
+ uint32_t idt_vectoring_error_code;
+ uint32_t vm_exit_instruction_len;
+ uint32_t vmx_instruction_info;
+ uint32_t guest_es_limit;
+ uint32_t guest_cs_limit;
+ uint32_t guest_ss_limit;
+ uint32_t guest_ds_limit;
+ uint32_t guest_fs_limit;
+ uint32_t guest_gs_limit;
+ uint32_t guest_ldtr_limit;
+ uint32_t guest_tr_limit;
+ uint32_t guest_gdtr_limit;
+ uint32_t guest_idtr_limit;
+ uint32_t guest_es_ar_bytes;
+ uint32_t guest_cs_ar_bytes;
+ uint32_t guest_ss_ar_bytes;
+ uint32_t guest_ds_ar_bytes;
+ uint32_t guest_fs_ar_bytes;
+ uint32_t guest_gs_ar_bytes;
+ uint32_t guest_ldtr_ar_bytes;
+ uint32_t guest_tr_ar_bytes;
+ uint32_t guest_interruptibility_info;
+ uint32_t guest_activity_state;
+ uint32_t guest_sysenter_cs;
+ uint32_t host_ia32_sysenter_cs;
+ uint32_t vmx_preemption_timer_value;
+ uint32_t padding32[7]; /* room for future expansion */
+ uint16_t virtual_processor_id;
+ uint16_t posted_intr_nv;
+ uint16_t guest_es_selector;
+ uint16_t guest_cs_selector;
+ uint16_t guest_ss_selector;
+ uint16_t guest_ds_selector;
+ uint16_t guest_fs_selector;
+ uint16_t guest_gs_selector;
+ uint16_t guest_ldtr_selector;
+ uint16_t guest_tr_selector;
+ uint16_t guest_intr_status;
+ uint16_t host_es_selector;
+ uint16_t host_cs_selector;
+ uint16_t host_ss_selector;
+ uint16_t host_ds_selector;
+ uint16_t host_fs_selector;
+ uint16_t host_gs_selector;
+ uint16_t host_tr_selector;
+ uint16_t guest_pml_index;
};
-static void write_address(uint64_t address, uint64_t size, uint64_t prot){
- static uint64_t next_address = PAGETABLE_MASK;
- static uint64_t last_address = 0x0;
- static uint64_t last_prot = 0;
- if(address != next_address || prot != last_prot){
- /* do not print guard pages or empty pages without any permissions */
- if(last_address && (CHECK_BIT(last_prot, 1) || !CHECK_BIT(last_prot, 63))){
- if(CHECK_BIT(last_prot, 1) && !CHECK_BIT(last_prot, 63)){
- nyx_debug_p(NESTED_VM_PREFIX, "%016lx - %016lx %c%c%c [WARNING]",
- last_address, next_address,
- CHECK_BIT(last_prot, 1) ? 'W' : '-',
- CHECK_BIT(last_prot, 2) ? 'U' : 'K',
- !CHECK_BIT(last_prot, 63)? 'X' : '-');
- }
- else{
- nyx_debug_p(NESTED_VM_PREFIX, "%016lx - %016lx %c%c%c",
- last_address, next_address,
- CHECK_BIT(last_prot, 1) ? 'W' : '-',
- CHECK_BIT(last_prot, 2) ? 'U' : 'K',
- !CHECK_BIT(last_prot, 63)? 'X' : '-');
- }
- }
- last_address = address;
- }
- next_address = address+size;
- last_prot = prot;
-
+static void write_address(uint64_t address, uint64_t size, uint64_t prot)
+{
+ static uint64_t next_address = PAGETABLE_MASK;
+ static uint64_t last_address = 0x0;
+ static uint64_t last_prot = 0;
+ if (address != next_address || prot != last_prot) {
+ /* do not print guard pages or empty pages without any permissions */
+ if (last_address && (CHECK_BIT(last_prot, 1) || !CHECK_BIT(last_prot, 63))) {
+ if (CHECK_BIT(last_prot, 1) && !CHECK_BIT(last_prot, 63)) {
+ nyx_debug_p(NESTED_VM_PREFIX, "%016lx - %016lx %c%c%c [WARNING]",
+ last_address, next_address,
+ CHECK_BIT(last_prot, 1) ? 'W' : '-',
+ CHECK_BIT(last_prot, 2) ? 'U' : 'K',
+ !CHECK_BIT(last_prot, 63) ? 'X' : '-');
+ } else {
+ nyx_debug_p(NESTED_VM_PREFIX, "%016lx - %016lx %c%c%c", last_address,
+ next_address, CHECK_BIT(last_prot, 1) ? 'W' : '-',
+ CHECK_BIT(last_prot, 2) ? 'U' : 'K',
+ !CHECK_BIT(last_prot, 63) ? 'X' : '-');
+ }
+ }
+ last_address = address;
+ }
+ next_address = address + size;
+ last_prot = prot;
}
-void print_48_paging(uint64_t cr3){
+void print_48_paging(uint64_t cr3)
+{
uint64_t paging_entries_level_1[PENTRIES];
uint64_t paging_entries_level_2[PENTRIES];
uint64_t paging_entries_level_3[PENTRIES];
uint64_t paging_entries_level_4[PENTRIES];
- uint64_t address_identifier_1, address_identifier_2, address_identifier_3, address_identifier_4;
- uint32_t i1, i2, i3,i4;
+ uint64_t address_identifier_1, address_identifier_2, address_identifier_3,
+ address_identifier_4;
+ uint32_t i1, i2, i3, i4;
- cpu_physical_memory_rw((cr3&PAGETABLE_MASK), (uint8_t *) paging_entries_level_1, PPAGE_SIZE, false);
- for(i1 = 0; i1 < 512; i1++){
- if(paging_entries_level_1[i1]){
+ cpu_physical_memory_rw((cr3 & PAGETABLE_MASK), (uint8_t *)paging_entries_level_1,
+ PPAGE_SIZE, false);
+ for (i1 = 0; i1 < 512; i1++) {
+ if (paging_entries_level_1[i1]) {
address_identifier_1 = ((uint64_t)i1) << PLEVEL_1_SHIFT;
- if (i1 & SIGN_EXTEND_TRESHOLD){
+ if (i1 & SIGN_EXTEND_TRESHOLD) {
address_identifier_1 |= SIGN_EXTEND;
}
- if(CHECK_BIT(paging_entries_level_1[i1], 0)){ /* otherwise swapped out */
- cpu_physical_memory_rw((paging_entries_level_1[i1]&PAGETABLE_MASK), (uint8_t *) paging_entries_level_2, PPAGE_SIZE, false);
- for(i2 = 0; i2 < PENTRIES; i2++){
- if(paging_entries_level_2[i2]){
- address_identifier_2 = (((uint64_t)i2) << PLEVEL_2_SHIFT) + address_identifier_1;
- if (CHECK_BIT(paging_entries_level_2[i2], 0)){ /* otherwise swapped out */
- if((paging_entries_level_2[i2]&PAGETABLE_MASK) == (paging_entries_level_1[i1]&PAGETABLE_MASK)){
+ if (CHECK_BIT(paging_entries_level_1[i1], 0))
+ { /* otherwise swapped out */
+ cpu_physical_memory_rw((paging_entries_level_1[i1] & PAGETABLE_MASK),
+ (uint8_t *)paging_entries_level_2, PPAGE_SIZE,
+ false);
+ for (i2 = 0; i2 < PENTRIES; i2++) {
+ if (paging_entries_level_2[i2]) {
+ address_identifier_2 = (((uint64_t)i2) << PLEVEL_2_SHIFT) +
+ address_identifier_1;
+ if (CHECK_BIT(paging_entries_level_2[i2], 0))
+ { /* otherwise swapped out */
+ if ((paging_entries_level_2[i2] & PAGETABLE_MASK) ==
+ (paging_entries_level_1[i1] & PAGETABLE_MASK))
+ {
/* loop */
continue;
}
- if (CHECK_BIT(paging_entries_level_2[i2], 7)){
- write_address(address_identifier_2, 0x40000000, (uint64_t)paging_entries_level_2[i2] & ((1ULL<<63) | (1ULL<<2) | (1ULL<<1)));
- }
- else{
+ if (CHECK_BIT(paging_entries_level_2[i2], 7)) {
+ write_address(address_identifier_2, 0x40000000,
+ (uint64_t)paging_entries_level_2[i2] &
+ ((1ULL << 63) | (1ULL << 2) |
+ (1ULL << 1)));
+ } else {
/* otherwise this PDPE references a 1GB page */
- cpu_physical_memory_rw((paging_entries_level_2[i2]&PAGETABLE_MASK), (uint8_t *) paging_entries_level_3, PPAGE_SIZE, false);
- for(i3 = 0; i3 < PENTRIES; i3++){
- if(paging_entries_level_3[i3]){
- address_identifier_3 = (((uint64_t)i3) << PLEVEL_3_SHIFT) + address_identifier_2;
- if (CHECK_BIT(paging_entries_level_3[i3], 0)){ /* otherwise swapped out */
- if (CHECK_BIT(paging_entries_level_3[i3], 7)){
- write_address(address_identifier_3, 0x200000, (uint64_t)paging_entries_level_3[i3] & ((1ULL<<63) | (1ULL<<2) | (1ULL<<1)));
- }
- else{
- cpu_physical_memory_rw((paging_entries_level_3[i3]&PAGETABLE_MASK), (uint8_t *) paging_entries_level_4, PPAGE_SIZE, false);
- for(i4 = 0; i4 < PENTRIES; i4++){
- if(paging_entries_level_4[i4]){
- address_identifier_4 = (((uint64_t)i4) << PLEVEL_4_SHIFT) + address_identifier_3;
- if (CHECK_BIT(paging_entries_level_4[i4], 0)){
- write_address(address_identifier_4, 0x1000, (uint64_t)paging_entries_level_4[i4] & ((1ULL<<63) | (1ULL<<2) | (1ULL<<1)));
- }
- }
- }
- }
- }
- }
- }
-
+ cpu_physical_memory_rw((paging_entries_level_2[i2] &
+ PAGETABLE_MASK),
+ (uint8_t *)paging_entries_level_3,
+ PPAGE_SIZE, false);
+ for (i3 = 0; i3 < PENTRIES; i3++) {
+ if (paging_entries_level_3[i3]) {
+ address_identifier_3 =
+ (((uint64_t)i3) << PLEVEL_3_SHIFT) +
+ address_identifier_2;
+ if (CHECK_BIT(paging_entries_level_3[i3], 0))
+ { /* otherwise swapped out */
+ if (CHECK_BIT(paging_entries_level_3[i3],
+ 7))
+ {
+ write_address(
+ address_identifier_3, 0x200000,
+ (uint64_t)paging_entries_level_3[i3] &
+ ((1ULL << 63) | (1ULL << 2) |
+ (1ULL << 1)));
+ } else {
+ cpu_physical_memory_rw(
+ (paging_entries_level_3[i3] &
+ PAGETABLE_MASK),
+ (uint8_t *)paging_entries_level_4,
+ PPAGE_SIZE, false);
+ for (i4 = 0; i4 < PENTRIES; i4++) {
+ if (paging_entries_level_4[i4]) {
+ address_identifier_4 =
+ (((uint64_t)i4)
+ << PLEVEL_4_SHIFT) +
+ address_identifier_3;
+ if (CHECK_BIT(
+ paging_entries_level_4[i4],
+ 0))
+ {
+ write_address(
+ address_identifier_4,
+ 0x1000,
+ (uint64_t)paging_entries_level_4
+ [i4] &
+ ((1ULL << 63) |
+ (1ULL << 2) |
+ (1ULL << 1)));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -284,107 +321,119 @@ void print_48_paging(uint64_t cr3){
}
}
}
- write_address(0, 0x1000, 0);
+ write_address(0, 0x1000, 0);
}
-uint64_t get_nested_guest_rip(CPUState *cpu){
+uint64_t get_nested_guest_rip(CPUState *cpu)
+{
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- 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);
- 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;
+ return saved_vmcs->guest_rip;
}
-uint64_t get_nested_host_rip(CPUState *cpu){
+uint64_t get_nested_host_rip(CPUState *cpu)
+{
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- 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);
- 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;
+ return saved_vmcs->host_rip;
}
-uint64_t get_nested_host_cr3(CPUState *cpu){
+uint64_t get_nested_host_cr3(CPUState *cpu)
+{
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- 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);
- 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;
+ return saved_vmcs->host_cr3;
}
-void set_nested_rip(CPUState *cpu, uint64_t rip){
+void set_nested_rip(CPUState *cpu, uint64_t rip)
+{
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- X86CPU *cpux86 = X86_CPU(cpu);
- CPUX86State *env = &cpux86->env;
+ struct vmcs12 *saved_vmcs = (struct vmcs12 *)&(env->nested_state->data);
- struct vmcs12* saved_vmcs = (struct vmcs12*)&(env->nested_state->data);
-
- saved_vmcs->guest_rip = rip;
+ saved_vmcs->guest_rip = rip;
}
-void kvm_nested_get_info(CPUState *cpu){
+void kvm_nested_get_info(CPUState *cpu)
+{
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- X86CPU *cpux86 = X86_CPU(cpu);
- CPUX86State *env = &cpux86->env;
+ kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
- kvm_vcpu_ioctl(cpu, KVM_GET_NESTED_STATE, env->nested_state);
-
- __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);
+ __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;
+ return;
}
-#define AREA_DESC_LEN 256
-#define MAGIC_NUMBER 0x41584548U
+#define AREA_DESC_LEN 256
+#define MAGIC_NUMBER 0x41584548U
typedef struct {
- uint32_t base;
- uint32_t size;
- uint32_t virtual_base;
- char desc[AREA_DESC_LEN];
-}area_t_export_t;
+ uint32_t base;
+ uint32_t size;
+ uint32_t virtual_base;
+ char desc[AREA_DESC_LEN];
+} area_t_export_t;
typedef struct {
- uint32_t magic;
- uint8_t num_mmio_areas;
- uint8_t num_io_areas;
- uint8_t num_alloc_areas;
- uint8_t padding;
-}config_t;
+ uint32_t magic;
+ uint8_t num_mmio_areas;
+ uint8_t num_io_areas;
+ uint8_t num_alloc_areas;
+ uint8_t padding;
+} config_t;
-void print_configuration(FILE *stream, void* configuration, size_t size){
- fprintf(stream, "%s: size: %lx\n", __func__, size);
- assert((size-sizeof(config_t))%sizeof(area_t_export_t) == 0);
+void print_configuration(FILE *stream, void *configuration, size_t size)
+{
+ fprintf(stream, "%s: size: %lx\n", __func__, size);
+ assert((size - sizeof(config_t)) % sizeof(area_t_export_t) == 0);
- assert(((config_t*)configuration)->magic == MAGIC_NUMBER);
+ assert(((config_t *)configuration)->magic == MAGIC_NUMBER);
- fprintf(stream, "%s: num_mmio_areas: %x\n", __func__, ((config_t*)configuration)->num_mmio_areas);
- fprintf(stream, "%s: num_io_areas: %x\n", __func__, ((config_t*)configuration)->num_io_areas);
- fprintf(stream, "%s: num_alloc_areas: %x\n", __func__, ((config_t*)configuration)->num_alloc_areas);
+ fprintf(stream, "%s: num_mmio_areas: %x\n", __func__,
+ ((config_t *)configuration)->num_mmio_areas);
+ fprintf(stream, "%s: num_io_areas: %x\n", __func__,
+ ((config_t *)configuration)->num_io_areas);
+ fprintf(stream, "%s: num_alloc_areas: %x\n", __func__,
+ ((config_t *)configuration)->num_alloc_areas);
- for(int i = 0; i < ((config_t*)configuration)->num_mmio_areas; i++){
- fprintf(stream, "\t-> MMIO: 0x%x (V: 0x%x) [0x%x]\t%s\n", ((area_t_export_t*)(configuration+sizeof(config_t)))[i].base,
- ((area_t_export_t*)(configuration+sizeof(config_t)))[i].virtual_base,
- ((area_t_export_t*)(configuration+sizeof(config_t)))[i].size,
- ((area_t_export_t*)(configuration+sizeof(config_t)))[i].desc );
- }
+ for (int i = 0; i < ((config_t *)configuration)->num_mmio_areas; i++) {
+ fprintf(stream, "\t-> MMIO: 0x%x (V: 0x%x) [0x%x]\t%s\n",
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].base,
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].virtual_base,
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].size,
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].desc);
+ }
- for(int i = ((config_t*)configuration)->num_mmio_areas; i < (((config_t*)configuration)->num_mmio_areas+((config_t*)configuration)->num_io_areas); i++){
- fprintf(stream, "\t-> IO: 0x%x [0x%x]\t%s\n", ((area_t_export_t*)(configuration+sizeof(config_t)))[i].base,
- ((area_t_export_t*)(configuration+sizeof(config_t)))[i].size,
- ((area_t_export_t*)(configuration+sizeof(config_t)))[i].desc );
- }
+ for (int i = ((config_t *)configuration)->num_mmio_areas;
+ i < (((config_t *)configuration)->num_mmio_areas +
+ ((config_t *)configuration)->num_io_areas);
+ i++)
+ {
+ fprintf(stream, "\t-> IO: 0x%x [0x%x]\t%s\n",
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].base,
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].size,
+ ((area_t_export_t *)(configuration + sizeof(config_t)))[i].desc);
+ }
}
\ No newline at end of file
diff --git a/nyx/kvm_nested.h b/nyx/kvm_nested.h
index a270c2aa60..0fcd263dfa 100644
--- a/nyx/kvm_nested.h
+++ b/nyx/kvm_nested.h
@@ -1,8 +1,8 @@
#pragma once
#include
-void print_48_paging(uint64_t cr3);
-void kvm_nested_get_info(CPUState *cpu);
+void print_48_paging(uint64_t cr3);
+void kvm_nested_get_info(CPUState *cpu);
uint64_t get_nested_guest_rip(CPUState *cpu);
uint64_t get_nested_host_rip(CPUState *cpu);
@@ -10,4 +10,4 @@ uint64_t get_nested_host_rip(CPUState *cpu);
uint64_t get_nested_host_cr3(CPUState *cpu);
void set_nested_rip(CPUState *cpu, uint64_t rip);
-void print_configuration(FILE *stream, void* configuration, size_t size);
\ No newline at end of file
+void print_configuration(FILE *stream, void *configuration, size_t size);
\ No newline at end of file
diff --git a/nyx/memory_access.c b/nyx/memory_access.c
index 53cb8fd037..e842b85646 100644
--- a/nyx/memory_access.c
+++ b/nyx/memory_access.c
@@ -20,164 +20,183 @@ along with QEMU-PT. If not, see .
*/
#include "qemu/osdep.h"
-#include
#include "exec/gdbstub.h"
+#include
-#include "sysemu/sysemu.h"
-#include "cpu.h"
#include "exec/ram_addr.h"
#include "qemu/rcu_queue.h"
+#include "sysemu/sysemu.h"
+#include "cpu.h"
-#include "memory_access.h"
-#include "nyx/hypercall/hypercall.h"
#include "debug.h"
+#include "memory_access.h"
#include "nyx/fast_vm_reload.h"
-#include "nyx/state/state.h"
#include "nyx/helpers.h"
+#include "nyx/hypercall/hypercall.h"
+#include "nyx/state/state.h"
#define INVALID_ADDRESS 0xFFFFFFFFFFFFFFFFULL
-static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_from_snapshot);
+static uint64_t get_48_paging_phys_addr(uint64_t cr3,
+ uint64_t addr,
+ bool read_from_snapshot);
-#define x86_64_PAGE_SIZE 0x1000
-#define x86_64_PAGE_MASK ~(x86_64_PAGE_SIZE - 1)
+#define x86_64_PAGE_SIZE 0x1000
+#define x86_64_PAGE_MASK ~(x86_64_PAGE_SIZE - 1)
-mem_mode_t get_current_mem_mode(CPUState *cpu){
- kvm_arch_get_registers(cpu);
+mem_mode_t get_current_mem_mode(CPUState *cpu)
+{
+ kvm_arch_get_registers(cpu);
- X86CPU *cpux86 = X86_CPU(cpu);
- CPUX86State *env = &cpux86->env;
+ X86CPU *cpux86 = X86_CPU(cpu);
+ CPUX86State *env = &cpux86->env;
- if (!(env->cr[0] & CR0_PG_MASK)) {
+ if (!(env->cr[0] & CR0_PG_MASK)) {
return mm_32_protected;
- }
- else{
- if (env->cr[4] & CR4_PAE_MASK) {
- if (env->hflags & HF_LMA_MASK) {
- if (env->cr[4] & CR4_LA57_MASK) {
+ } else {
+ if (env->cr[4] & CR4_PAE_MASK) {
+ if (env->hflags & HF_LMA_MASK) {
+ if (env->cr[4] & CR4_LA57_MASK) {
return mm_64_l5_paging;
- } else {
+ } else {
return mm_64_l4_paging;
- }
- }
- else{
+ }
+ } else {
return mm_32_pae;
- }
- }
- else {
- return mm_32_paging;
- }
+ }
+ } else {
+ return mm_32_paging;
+ }
}
return mm_unkown;
}
-static void set_mem_mode(CPUState *cpu){
+static void set_mem_mode(CPUState *cpu)
+{
GET_GLOBAL_STATE()->mem_mode = get_current_mem_mode(cpu);
}
/* Warning: This might break memory handling for hypervisor fuzzing => FIXME LATER */
-uint64_t get_paging_phys_addr(CPUState *cpu, uint64_t cr3, uint64_t addr){
- if(GET_GLOBAL_STATE()->mem_mode == mm_unkown){
+uint64_t get_paging_phys_addr(CPUState *cpu, uint64_t cr3, uint64_t addr)
+{
+ if (GET_GLOBAL_STATE()->mem_mode == mm_unkown) {
set_mem_mode(cpu);
}
- switch(GET_GLOBAL_STATE()->mem_mode){
- case mm_32_protected:
- return addr & 0xFFFFFFFFULL;
- case mm_32_paging:
- fprintf(stderr, "mem_mode: mm_32_paging not implemented!\n");
- abort();
- case mm_32_pae:
- fprintf(stderr, "mem_mode: mm_32_pae not implemented!\n");
- abort();
- case mm_64_l4_paging:
- return get_48_paging_phys_addr(cr3, addr, false);
- case mm_64_l5_paging:
- fprintf(stderr, "mem_mode: mm_64_l5_paging not implemented!\n");
- abort();
- case mm_unkown:
- fprintf(stderr, "mem_mode: unkown!\n");
- abort();
+ switch (GET_GLOBAL_STATE()->mem_mode) {
+ case mm_32_protected:
+ return addr & 0xFFFFFFFFULL;
+ case mm_32_paging:
+ fprintf(stderr, "mem_mode: mm_32_paging not implemented!\n");
+ abort();
+ case mm_32_pae:
+ fprintf(stderr, "mem_mode: mm_32_pae not implemented!\n");
+ abort();
+ case mm_64_l4_paging:
+ return get_48_paging_phys_addr(cr3, addr, false);
+ case mm_64_l5_paging:
+ fprintf(stderr, "mem_mode: mm_64_l5_paging not implemented!\n");
+ abort();
+ case mm_unkown:
+ fprintf(stderr, "mem_mode: unkown!\n");
+ abort();
}
return 0;
}
-static uint64_t get_paging_phys_addr_snapshot(CPUState *cpu, uint64_t cr3, uint64_t addr){
- if(GET_GLOBAL_STATE()->mem_mode == mm_unkown){
+static uint64_t get_paging_phys_addr_snapshot(CPUState *cpu, uint64_t cr3, uint64_t addr)
+{
+ if (GET_GLOBAL_STATE()->mem_mode == mm_unkown) {
set_mem_mode(cpu);
}
- switch(GET_GLOBAL_STATE()->mem_mode){
- case mm_32_protected:
- return addr & 0xFFFFFFFFULL;
- case mm_32_paging:
- fprintf(stderr, "mem_mode: mm_32_paging not implemented!\n");
- abort();
- case mm_32_pae:
- fprintf(stderr, "mem_mode: mm_32_pae not implemented!\n");
- abort();
- case mm_64_l4_paging:
- return get_48_paging_phys_addr(cr3, addr, true);
- case mm_64_l5_paging:
- fprintf(stderr, "mem_mode: mm_64_l5_paging not implemented!\n");
- abort();
- case mm_unkown:
- fprintf(stderr, "mem_mode: unkown!\n");
- abort();
+ switch (GET_GLOBAL_STATE()->mem_mode) {
+ case mm_32_protected:
+ return addr & 0xFFFFFFFFULL;
+ case mm_32_paging:
+ fprintf(stderr, "mem_mode: mm_32_paging not implemented!\n");
+ abort();
+ case mm_32_pae:
+ fprintf(stderr, "mem_mode: mm_32_pae not implemented!\n");
+ abort();
+ case mm_64_l4_paging:
+ return get_48_paging_phys_addr(cr3, addr, true);
+ case mm_64_l5_paging:
+ fprintf(stderr, "mem_mode: mm_64_l5_paging not implemented!\n");
+ abort();
+ case mm_unkown:
+ fprintf(stderr, "mem_mode: unkown!\n");
+ abort();
}
return 0;
}
-bool read_physical_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu){
+bool read_physical_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu)
+{
kvm_arch_get_registers(cpu);
cpu_physical_memory_read(address, data, size);
return true;
}
-bool write_physical_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu){
+bool write_physical_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu)
+{
kvm_arch_get_registers(cpu);
cpu_physical_memory_write(address, data, size);
return true;
}
-static void refresh_kvm(CPUState *cpu){
+static void refresh_kvm(CPUState *cpu)
+{
if (!cpu->vcpu_dirty) {
kvm_arch_get_registers(cpu);
}
}
-static void refresh_kvm_non_dirty(CPUState *cpu){
+static void refresh_kvm_non_dirty(CPUState *cpu)
+{
if (!cpu->vcpu_dirty) {
kvm_arch_get_registers_fast(cpu);
}
}
-bool remap_payload_slot(uint64_t phys_addr, uint32_t slot, CPUState *cpu){
- assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size);
+bool remap_payload_slot(uint64_t phys_addr, uint32_t slot, CPUState *cpu)
+{
+ 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;
+ uint32_t i = slot;
uint64_t phys_addr_ram_offset = address_to_ram_offset(phys_addr);
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
- if(!memcmp(block->idstr, "pc.ram", 6)){
- /* TODO: put assert calls here */
- 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));
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
+ if (!memcmp(block->idstr, "pc.ram", 6)) {
+ /* TODO: put assert calls here */
+ 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));
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
break;
}
}
-
+
return true;
}
-bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t shm_size, bool virtual, uint64_t cr3){
+bool remap_slot(uint64_t addr,
+ uint32_t slot,
+ CPUState *cpu,
+ int fd,
+ uint64_t shm_size,
+ bool virtual,
+ uint64_t cr3)
+{
assert(fd && shm_size);
- assert((slot*x86_64_PAGE_SIZE) < shm_size);
+ assert((slot * x86_64_PAGE_SIZE) < shm_size);
RAMBlock *block;
refresh_kvm_non_dirty(cpu);
@@ -185,41 +204,50 @@ bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t sh
uint32_t i = slot;
uint64_t phys_addr = addr;
- if(virtual){
+ if (virtual) {
phys_addr = get_paging_phys_addr(cpu, cr3, (addr & x86_64_PAGE_MASK));
- if(phys_addr == INVALID_ADDRESS){
- fprintf(stderr, "[QEMU-Nyx] Error: failed to translate v_addr (0x%lx) to p_addr!\n", addr);
- fprintf(stderr, "[QEMU-Nyx] Check if the buffer is present in the guest's memory...\n");
+ if (phys_addr == INVALID_ADDRESS) {
+ fprintf(stderr, "[QEMU-Nyx] Error: failed to translate v_addr (0x%lx) to p_addr!\n",
+ addr);
+ fprintf(stderr, "[QEMU-Nyx] Check if the buffer is present in the "
+ "guest's memory...\n");
exit(1);
}
}
uint64_t phys_addr_ram_offset = address_to_ram_offset(phys_addr);
-
+
nyx_debug("%s: addr => %lx phys_addr => %lx\n", __func__, addr, phys_addr);
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
- if(!memcmp(block->idstr, "pc.ram", 6)){
- /* TODO: put assert calls here */
- if (munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE) == -1) {
- nyx_error("%s: munmap failed!\n", __func__);
- assert(false);
- }
- if (mmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, (i*x86_64_PAGE_SIZE)) == MAP_FAILED) {
- nyx_error("%s: mmap failed!\n", __func__);
- assert(false);
- }
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
+ if (!memcmp(block->idstr, "pc.ram", 6)) {
+ /* TODO: put assert calls here */
+ if (munmap((void *)(((uint64_t)block->host) + phys_addr_ram_offset),
+ x86_64_PAGE_SIZE) == -1)
+ {
+ nyx_error("%s: munmap failed!\n", __func__);
+ assert(false);
+ }
+ if (mmap((void *)(((uint64_t)block->host) + phys_addr_ram_offset),
+ 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd,
+ (i * x86_64_PAGE_SIZE)) == MAP_FAILED)
+ {
+ nyx_error("%s: mmap failed!\n", __func__);
+ assert(false);
+ }
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
break;
}
}
-
+
return true;
}
-bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *cpu){
- assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size);
+bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *cpu)
+{
+ assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd &&
+ GET_GLOBAL_STATE()->shared_payload_buffer_size);
RAMBlock *block;
refresh_kvm_non_dirty(cpu);
@@ -227,30 +255,33 @@ bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *c
uint64_t phys_addr_ram_offset = address_to_ram_offset(phys_addr);
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
- if(!memcmp(block->idstr, "pc.ram", 6)){
-
- /* TODO: put assert calls here */
- 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));
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
+ if (!memcmp(block->idstr, "pc.ram", 6)) {
+ /* TODO: put assert calls here */
+ 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));
fast_reload_blacklist_page(get_fast_reload_snapshot(), phys_addr);
break;
}
}
-
+
return true;
}
-void resize_shared_memory(uint32_t new_size, uint32_t* shm_size, void** shm_ptr, int fd){
+void resize_shared_memory(uint32_t new_size, uint32_t *shm_size, void **shm_ptr, int fd)
+{
assert(fd && *shm_size);
/* check if the new_size is a multiple of PAGE_SIZE */
- if(new_size & (PAGE_SIZE-1)){
- new_size = (new_size & ~(PAGE_SIZE-1)) + PAGE_SIZE;
+ if (new_size & (PAGE_SIZE - 1)) {
+ new_size = (new_size & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
}
- if(*shm_size >= new_size){
+ if (*shm_size >= new_size) {
/* no need no resize the buffer -> early exit */
return;
}
@@ -258,42 +289,56 @@ void resize_shared_memory(uint32_t new_size, uint32_t* shm_size, void** shm_ptr,
assert(!GET_GLOBAL_STATE()->in_fuzzing_mode);
assert(ftruncate(fd, new_size) == 0);
- if(shm_ptr){
- munmap(*shm_ptr , *shm_size);
- *shm_ptr = (void*)mmap(0, new_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+ if (shm_ptr) {
+ munmap(*shm_ptr, *shm_size);
+ *shm_ptr =
+ (void *)mmap(0, new_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
assert(*shm_ptr != MAP_FAILED);
}
*shm_size = new_size;
}
-bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){
- assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size);
+bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu)
+{
+ assert(GET_GLOBAL_STATE()->shared_payload_buffer_fd &&
+ GET_GLOBAL_STATE()->shared_payload_buffer_size);
assert(GET_GLOBAL_STATE()->shared_payload_buffer_size % x86_64_PAGE_SIZE == 0);
RAMBlock *block;
refresh_kvm_non_dirty(cpu);
- for(uint32_t i = 0; i < (GET_GLOBAL_STATE()->shared_payload_buffer_size/x86_64_PAGE_SIZE); i++){
- 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));
+ for (uint32_t i = 0;
+ i < (GET_GLOBAL_STATE()->shared_payload_buffer_size / x86_64_PAGE_SIZE); i++)
+ {
+ 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);
uint64_t phys_addr_ram_offset = address_to_ram_offset(phys_addr);
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
- if(!memcmp(block->idstr, "pc.ram", 6)){
- if(munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE) == -1){
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
+ if (!memcmp(block->idstr, "pc.ram", 6)) {
+ if (munmap((void *)(((uint64_t)block->host) + phys_addr_ram_offset),
+ x86_64_PAGE_SIZE) == -1)
+ {
nyx_error("munmap failed!\n");
assert(false);
}
- 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){
+ 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");
assert(false);
}
memset((block->host) + phys_addr_ram_offset, 0xab, 0x1000);
- if(GET_GLOBAL_STATE()->protect_payload_buffer){
+ if (GET_GLOBAL_STATE()->protect_payload_buffer) {
mprotect((block->host) + phys_addr_ram_offset, 0x1000, PROT_READ);
}
@@ -305,18 +350,18 @@ bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){
return true;
}
-bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, 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 */
- int asidx;
- MemTxAttrs attrs;
- hwaddr phys_addr;
+ int asidx;
+ MemTxAttrs attrs;
+ hwaddr phys_addr;
MemTxResult res;
uint64_t counter, l, i;
counter = size;
- while(counter != 0){
+ while (counter != 0) {
l = x86_64_PAGE_SIZE;
if (l > counter)
l = counter;
@@ -324,19 +369,21 @@ bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUSta
refresh_kvm(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);
+ phys_addr =
+ cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs);
- if (phys_addr == INVALID_ADDRESS){
+ if (phys_addr == INVALID_ADDRESS) {
nyx_debug_p(MEM_PREFIX, "phys_addr == -1:\t%lx", address);
return false;
}
-
- phys_addr += (address & ~x86_64_PAGE_MASK);
- res = address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, data, l, true);
- if (res != MEMTX_OK){
+
+ phys_addr += (address & ~x86_64_PAGE_MASK);
+ res = address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, data, l, true);
+ if (res != MEMTX_OK) {
nyx_debug_p(MEM_PREFIX, "!MEMTX_OK:\t%lx", address);
return false;
- }
+ }
i++;
data += l;
@@ -348,22 +395,23 @@ bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUSta
}
-void hexdump_virtual_memory(uint64_t address, uint32_t size, CPUState *cpu){
- assert(size < 0x100000); // 1MB max
+void hexdump_virtual_memory(uint64_t address, uint32_t size, CPUState *cpu)
+{
+ assert(size < 0x100000); // 1MB max
uint64_t i = 0;
- uint8_t tmp[17];
- uint8_t* data = malloc(size);
- bool success = read_virtual_memory(address, data, size, cpu);
+ uint8_t tmp[17];
+ uint8_t *data = malloc(size);
+ bool success = read_virtual_memory(address, data, size, cpu);
- if(success){
- for (i = 0; i < size; i++){
- if(!(i % 16)){
- if (i != 0){
- printf (" %s\n", tmp);
+ if (success) {
+ for (i = 0; i < size; i++) {
+ if (!(i % 16)) {
+ if (i != 0) {
+ printf(" %s\n", tmp);
}
- printf (" %04lx ", i);
+ printf(" %04lx ", i);
}
- printf (" %02x", data[i]);
+ printf(" %02x", data[i]);
if ((data[i] < 0x20) || (data[i] > 0x7e))
tmp[i % 16] = '.';
@@ -373,10 +421,10 @@ void hexdump_virtual_memory(uint64_t address, uint32_t size, CPUState *cpu){
}
while ((i % 16) != 0) {
- printf (" ");
+ printf(" ");
i++;
}
- printf (" %s\n", tmp);
+ printf(" %s\n", tmp);
}
free(data);
@@ -387,12 +435,16 @@ static int redqueen_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint
{
static const uint8_t int3 = 0xcc;
- hwaddr phys_addr = (hwaddr) get_paging_phys_addr(cs, GET_GLOBAL_STATE()->parent_cr3, bp->pc);
+ hwaddr phys_addr =
+ (hwaddr)get_paging_phys_addr(cs, GET_GLOBAL_STATE()->parent_cr3, bp->pc);
int asidx = cpu_asidx_from_attrs(cs, MEMTXATTRS_UNSPECIFIED);
- if (address_space_rw(cpu_get_address_space(cs, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, (uint8_t *)&bp->saved_insn, 1, 0) ||
- address_space_rw(cpu_get_address_space(cs, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, (uint8_t *)&int3, 1, 1)) {
- //fprintf(stderr, "%s WRITTE AT %lx %lx failed!\n", __func__, bp->pc, phys_addr);
+ if (address_space_rw(cpu_get_address_space(cs, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)&bp->saved_insn, 1, 0) ||
+ address_space_rw(cpu_get_address_space(cs, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)&int3, 1, 1))
+ {
+ // fprintf(stderr, "%s WRITTE AT %lx %lx failed!\n", __func__, bp->pc, phys_addr);
return -EINVAL;
}
@@ -403,22 +455,29 @@ static int redqueen_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint
{
uint8_t int3;
- hwaddr phys_addr = (hwaddr) get_paging_phys_addr(cs, GET_GLOBAL_STATE()->parent_cr3, bp->pc);
+ hwaddr phys_addr =
+ (hwaddr)get_paging_phys_addr(cs, GET_GLOBAL_STATE()->parent_cr3, bp->pc);
int asidx = cpu_asidx_from_attrs(cs, MEMTXATTRS_UNSPECIFIED);
- if (address_space_rw(cpu_get_address_space(cs, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, (uint8_t *)&int3, 1, 0) || int3 != 0xcc ||
- address_space_rw(cpu_get_address_space(cs, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, (uint8_t *)&bp->saved_insn, 1, 1)) {
- //fprintf(stderr, "%s failed\n", __func__);
+ if (address_space_rw(cpu_get_address_space(cs, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)&int3, 1, 0) ||
+ int3 != 0xcc ||
+ address_space_rw(cpu_get_address_space(cs, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, (uint8_t *)&bp->saved_insn, 1, 1))
+ {
+ // fprintf(stderr, "%s failed\n", __func__);
return -EINVAL;
}
return 0;
}
-static struct kvm_sw_breakpoint *redqueen_find_breakpoint(CPUState *cpu, target_ulong pc){
+static struct kvm_sw_breakpoint *redqueen_find_breakpoint(CPUState *cpu,
+ target_ulong pc)
+{
struct kvm_sw_breakpoint *bp;
- QTAILQ_FOREACH(bp, &GET_GLOBAL_STATE()->redqueen_breakpoints, entry) {
+ QTAILQ_FOREACH (bp, &GET_GLOBAL_STATE()->redqueen_breakpoints, entry) {
if (bp->pc == pc) {
return bp;
}
@@ -426,16 +485,18 @@ static struct kvm_sw_breakpoint *redqueen_find_breakpoint(CPUState *cpu, target_
return NULL;
}
-static int redqueen_breakpoints_active(CPUState *cpu){
+static int redqueen_breakpoints_active(CPUState *cpu)
+{
return !QTAILQ_EMPTY(&GET_GLOBAL_STATE()->redqueen_breakpoints);
}
struct kvm_set_guest_debug_data {
struct kvm_guest_debug dbg;
- int err;
+ int err;
};
-static int redqueen_update_guest_debug(CPUState *cpu) {
+static int redqueen_update_guest_debug(CPUState *cpu)
+{
struct kvm_set_guest_debug_data data;
data.dbg.control = 0;
@@ -447,10 +508,11 @@ static int redqueen_update_guest_debug(CPUState *cpu) {
return kvm_vcpu_ioctl(cpu, KVM_SET_GUEST_DEBUG, &data.dbg);
}
-static void redqueen_remove_all_breakpoints(CPUState *cpu) {
+static void redqueen_remove_all_breakpoints(CPUState *cpu)
+{
struct kvm_sw_breakpoint *bp, *next;
- QTAILQ_FOREACH_SAFE(bp, &GET_GLOBAL_STATE()->redqueen_breakpoints, entry, next) {
+ QTAILQ_FOREACH_SAFE (bp, &GET_GLOBAL_STATE()->redqueen_breakpoints, entry, next) {
redqueen_remove_sw_breakpoint(cpu, bp);
QTAILQ_REMOVE(&GET_GLOBAL_STATE()->redqueen_breakpoints, bp, entry);
g_free(bp);
@@ -459,9 +521,10 @@ static void redqueen_remove_all_breakpoints(CPUState *cpu) {
redqueen_update_guest_debug(cpu);
}
-static int redqueen_insert_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len){
+static int redqueen_insert_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len)
+{
struct kvm_sw_breakpoint *bp;
- int err;
+ int err;
bp = redqueen_find_breakpoint(cpu, addr);
if (bp) {
@@ -469,8 +532,8 @@ static int redqueen_insert_breakpoint(CPUState *cpu, target_ulong addr, target_u
return 0;
}
- bp = g_malloc(sizeof(struct kvm_sw_breakpoint));
- bp->pc = addr;
+ bp = g_malloc(sizeof(struct kvm_sw_breakpoint));
+ bp->pc = addr;
bp->use_count = 1;
err = redqueen_insert_sw_breakpoint(cpu, bp);
@@ -480,18 +543,19 @@ static int redqueen_insert_breakpoint(CPUState *cpu, target_ulong addr, target_u
}
QTAILQ_INSERT_HEAD(&GET_GLOBAL_STATE()->redqueen_breakpoints, bp, entry);
-
+
err = redqueen_update_guest_debug(cpu);
- if(err){
+ if (err) {
return err;
}
return 0;
}
-static int redqueen_remove_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len){
+static int redqueen_remove_breakpoint(CPUState *cpu, target_ulong addr, target_ulong len)
+{
struct kvm_sw_breakpoint *bp;
- int err;
+ int err;
bp = redqueen_find_breakpoint(cpu, addr);
if (!bp) {
@@ -510,70 +574,81 @@ static int redqueen_remove_breakpoint(CPUState *cpu, target_ulong addr, target_u
QTAILQ_REMOVE(&GET_GLOBAL_STATE()->redqueen_breakpoints, bp, entry);
g_free(bp);
-
+
err = redqueen_update_guest_debug(cpu);
- if(err){
+ if (err) {
return err;
}
return 0;
}
-int insert_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len){
+int insert_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len)
+{
redqueen_insert_breakpoint(cpu, addr, len);
redqueen_update_guest_debug(cpu);
return 0;
}
-int remove_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len){
+int remove_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len)
+{
redqueen_remove_breakpoint(cpu, addr, len);
redqueen_update_guest_debug(cpu);
return 0;
}
-void remove_all_breakpoints(CPUState *cpu){
+void remove_all_breakpoints(CPUState *cpu)
+{
redqueen_remove_all_breakpoints(cpu);
}
-#define PENTRIES 0x200
+#define PENTRIES 0x200
#define PPAGE_SIZE 0x1000
-static bool read_memory(uint64_t address, uint64_t* buffer, size_t size, bool read_from_snapshot) {
+static bool read_memory(uint64_t address,
+ uint64_t *buffer,
+ size_t size,
+ bool read_from_snapshot)
+{
if (unlikely(address == INVALID_ADDRESS)) {
return false;
}
if (unlikely(read_from_snapshot)) {
- return read_snapshot_memory(
- get_fast_reload_snapshot(),
- address, (uint8_t *)buffer, size);
- }
-
+ return read_snapshot_memory(get_fast_reload_snapshot(), address,
+ (uint8_t *)buffer, size);
+ }
+
// NB: This API exposed by exec.h doesn't signal failure, although it can
// fail. Figure out how to expose the address space object instead and then
// we can actually check the return value here. Until then, will clear the
// buffer contents first.
memset(buffer, 0, size);
- cpu_physical_memory_rw(address, (uint8_t*)buffer, size, false);
+ cpu_physical_memory_rw(address, (uint8_t *)buffer, size, false);
return true;
}
-__attribute__((always_inline)) inline
-static bool bit(uint64_t value, uint8_t lsb) {
- return (value >> lsb) & 1;
+__attribute__((always_inline)) inline static bool bit(uint64_t value, uint8_t lsb)
+{
+ return (value >> lsb) & 1;
}
-__attribute__((always_inline)) inline
-static uint64_t bits(uint64_t value, uint8_t lsb, uint8_t msb) {
- return (value & ((0xffffffffffffffffull >> (64 - (msb - lsb + 1))) << lsb)) >> lsb;
+__attribute__((always_inline)) inline static uint64_t bits(uint64_t value,
+ uint8_t lsb,
+ uint8_t msb)
+{
+ return (value & ((0xffffffffffffffffull >> (64 - (msb - lsb + 1))) << lsb)) >> lsb;
}
// Helper function to load an entire pagetable table. These are PENTRIES
// 64-bit entries, so entries must point to a sufficiently large buffer.
-static bool load_table(uint64_t address, uint64_t* entries, bool read_from_snapshot) {
- if (unlikely(!read_memory(address, entries, 512 * sizeof(*entries), read_from_snapshot))) {
+static bool load_table(uint64_t address, uint64_t *entries, bool read_from_snapshot)
+{
+ if (unlikely(!read_memory(address, entries, 512 * sizeof(*entries),
+ read_from_snapshot)))
+ {
return false;
}
@@ -584,11 +659,12 @@ static bool load_table(uint64_t address, uint64_t* entries, bool read_from_snaps
// returning the same invalid value (0) for both non-present entries and
// any other error conditions, since we don't need to handle these cases
// differently.
-static uint64_t load_entry(uint64_t address, uint64_t index,
- bool read_from_snapshot) {
+static uint64_t load_entry(uint64_t address, uint64_t index, bool read_from_snapshot)
+{
uint64_t entry = 0;
- if (unlikely(!read_memory(address + (index * sizeof(entry)), &entry, sizeof(entry),
- read_from_snapshot))) {
+ if (unlikely(!read_memory(address + (index * sizeof(entry)), &entry,
+ sizeof(entry), read_from_snapshot)))
+ {
return 0;
}
@@ -600,14 +676,20 @@ static uint64_t load_entry(uint64_t address, uint64_t index,
return entry;
}
-static void print_page(uint64_t address, uint64_t entry, size_t size, bool s, bool w, bool x) {
- fprintf(stderr, " %c%c%c %016lx %zx",
- s ? 's' : 'u', w ? 'w' : 'r', x ? 'x' : '-',
- (bits(entry, 12, 51) << 12) & ~(size - 1), size);
+static void print_page(
+ uint64_t address, uint64_t entry, size_t size, bool s, bool w, bool x)
+{
+ fprintf(stderr, " %c%c%c %016lx %zx", s ? 's' : 'u', w ? 'w' : 'r',
+ x ? 'x' : '-', (bits(entry, 12, 51) << 12) & ~(size - 1), size);
}
-static void print_48_pte(uint64_t address, uint64_t pde_entry, bool read_from_snapshot,
- bool s, bool w, bool x) {
+static void print_48_pte(uint64_t address,
+ uint64_t pde_entry,
+ bool read_from_snapshot,
+ bool s,
+ bool w,
+ bool x)
+{
uint64_t pte_address = bits(pde_entry, 12, 51) << 12;
uint64_t pte_table[PENTRIES];
@@ -625,14 +707,19 @@ static void print_48_pte(uint64_t address, uint64_t pde_entry, bool read_from_sn
if (!bit(entry, 0)) {
// Not present.
} else {
- print_page(address | i << 12, entry, 0x1000,
- s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
+ print_page(address | i << 12, entry, 0x1000, s & !bit(entry, 2),
+ w & bit(entry, 1), x & !bit(entry, 63));
}
}
}
-static void print_48_pde(uint64_t address, uint64_t pdpte_entry, bool read_from_snapshot,
- bool s, bool w, bool x) {
+static void print_48_pde(uint64_t address,
+ uint64_t pdpte_entry,
+ bool read_from_snapshot,
+ bool s,
+ bool w,
+ bool x)
+{
uint64_t pde_address = bits(pdpte_entry, 12, 51) << 12;
uint64_t pde_table[PENTRIES];
@@ -650,17 +737,22 @@ static void print_48_pde(uint64_t address, uint64_t pdpte_entry, bool read_from_
if (!bit(entry, 0)) {
// Not present.
} else if (bit(entry, 7)) {
- print_page(address | i << 21, entry, 0x200000,
- s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
+ print_page(address | i << 21, entry, 0x200000, s & !bit(entry, 2),
+ w & bit(entry, 1), x & !bit(entry, 63));
} else {
print_48_pte(address | i << 21, entry, read_from_snapshot,
- s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
+ s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
}
}
}
-static void print_48_pdpte(uint64_t address, uint64_t pml4_entry, bool read_from_snapshot,
- bool s, bool w, bool x) {
+static void print_48_pdpte(uint64_t address,
+ uint64_t pml4_entry,
+ bool read_from_snapshot,
+ bool s,
+ bool w,
+ bool x)
+{
uint64_t pdpte_address = bits(pml4_entry, 12, 51) << 12;
uint64_t pdpte_table[PENTRIES];
@@ -678,16 +770,17 @@ static void print_48_pdpte(uint64_t address, uint64_t pml4_entry, bool read_from
if (!bit(entry, 0)) {
// Not present.
} else if (bit(entry, 7)) {
- print_page(address | i << 30, entry, 0x40000000,
- s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
+ print_page(address | i << 30, entry, 0x40000000, s & !bit(entry, 2),
+ w & bit(entry, 1), x & !bit(entry, 63));
} else {
print_48_pde(address | i << 30, entry, read_from_snapshot,
- s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
+ s & !bit(entry, 2), w & bit(entry, 1), x & !bit(entry, 63));
}
}
}
-static void print_48_pagetables_(uint64_t cr3, bool read_from_snapshot) {
+static void print_48_pagetables_(uint64_t cr3, bool read_from_snapshot)
+{
uint64_t pml4_address = bits(cr3, 12, 51) << 12;
uint64_t pml4_table[PENTRIES];
@@ -696,7 +789,7 @@ static void print_48_pagetables_(uint64_t cr3, bool read_from_snapshot) {
}
for (size_t i = 0; i < PENTRIES; ++i) {
- uint64_t entry = pml4_table[i];
+ uint64_t entry = pml4_table[i];
uint64_t address = i << 39;
// Ensure canonical virtual address
if (bit(address, 47)) {
@@ -708,13 +801,14 @@ static void print_48_pagetables_(uint64_t cr3, bool read_from_snapshot) {
}
if (bit(entry, 0)) {
- print_48_pdpte(address, entry, read_from_snapshot,
- !bit(entry, 2), bit(entry, 1), !bit(entry, 63));
+ print_48_pdpte(address, entry, read_from_snapshot, !bit(entry, 2),
+ bit(entry, 1), !bit(entry, 63));
}
}
}
-void print_48_pagetables(uint64_t cr3) {
+void print_48_pagetables(uint64_t cr3)
+{
static bool printed = false;
if (!printed) {
fprintf(stderr, "pagetables for cr3 %lx", cr3);
@@ -724,16 +818,19 @@ void print_48_pagetables(uint64_t cr3) {
}
}
-static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_from_snapshot) {
+static uint64_t get_48_paging_phys_addr(uint64_t cr3,
+ uint64_t addr,
+ bool read_from_snapshot)
+{
uint64_t pml4_address = bits(cr3, 12, 51) << 12;
- uint64_t pml4_offset = bits(addr, 39, 47);
+ uint64_t pml4_offset = bits(addr, 39, 47);
uint64_t pml4_entry = load_entry(pml4_address, pml4_offset, read_from_snapshot);
if (unlikely(!pml4_entry)) {
return INVALID_ADDRESS;
}
uint64_t pdpte_address = bits(pml4_entry, 12, 51) << 12;
- uint64_t pdpte_offset = bits(addr, 30, 38);
+ uint64_t pdpte_offset = bits(addr, 30, 38);
uint64_t pdpte_entry = load_entry(pdpte_address, pdpte_offset, read_from_snapshot);
if (unlikely(!pdpte_entry)) {
return INVALID_ADDRESS;
@@ -742,13 +839,13 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f
if (unlikely(bit(pdpte_entry, 7))) {
// 1GByte page translation.
uint64_t page_address = bits(pdpte_entry, 12, 51) << 12;
- uint64_t page_offset = bits(addr, 0, 29);
+ uint64_t page_offset = bits(addr, 0, 29);
return page_address + page_offset;
}
uint64_t pde_address = bits(pdpte_entry, 12, 51) << 12;
- uint64_t pde_offset = bits(addr, 21, 29);
- uint64_t pde_entry = load_entry(pde_address, pde_offset, read_from_snapshot);
+ uint64_t pde_offset = bits(addr, 21, 29);
+ uint64_t pde_entry = load_entry(pde_address, pde_offset, read_from_snapshot);
if (unlikely(!pde_entry)) {
return INVALID_ADDRESS;
}
@@ -756,170 +853,191 @@ static uint64_t get_48_paging_phys_addr(uint64_t cr3, uint64_t addr, bool read_f
if (unlikely(bit(pde_entry, 7))) {
// 2MByte page translation.
uint64_t page_address = bits(pde_entry, 12, 51) << 12;
- uint64_t page_offset = bits(addr, 0, 20);
+ uint64_t page_offset = bits(addr, 0, 20);
return page_address + page_offset;
}
uint64_t pte_address = bits(pde_entry, 12, 51) << 12;
- uint64_t pte_offset = bits(addr, 12, 20);
- uint64_t pte_entry = load_entry(pte_address, pte_offset, read_from_snapshot);
+ uint64_t pte_offset = bits(addr, 12, 20);
+ uint64_t pte_entry = load_entry(pte_address, pte_offset, read_from_snapshot);
if (unlikely(!pte_entry)) {
- return INVALID_ADDRESS;
+ return INVALID_ADDRESS;
}
// 4Kbyte page translation.
uint64_t page_address = bits(pte_entry, 12, 51) << 12;
- uint64_t page_offset = bits(addr, 0, 11);
+ uint64_t page_offset = bits(addr, 0, 11);
return page_address + page_offset;
}
-//#define DEBUG_48BIT_WALK
+// #define DEBUG_48BIT_WALK
-bool read_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu){
+bool read_virtual_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu)
+{
uint8_t tmp_buf[x86_64_PAGE_SIZE];
- hwaddr phys_addr;
- int asidx;
-
+ hwaddr phys_addr;
+ int asidx;
+
uint64_t amount_copied = 0;
-
+
kvm_arch_get_registers_fast(cpu);
CPUX86State *env = &(X86_CPU(cpu))->env;
- // copy per page
- while(amount_copied < size){
+ // copy per page
+ while (amount_copied < size) {
uint64_t len_to_copy = (size - amount_copied);
- if(len_to_copy > x86_64_PAGE_SIZE)
+ if (len_to_copy > x86_64_PAGE_SIZE)
len_to_copy = x86_64_PAGE_SIZE;
asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
#ifdef DEBUG_48BIT_WALK
- phys_addr_2 = cpu_get_phys_page_attrs_debug(cpu, (address & x86_64_PAGE_MASK), &attrs);
+ 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)
+ phys_addr = (hwaddr)get_paging_phys_addr(cpu, env->cr[3], address) &
+ 0xFFFFFFFFFFFFF000ULL; // != 0xFFFFFFFFFFFFFFFFULL)
#ifdef DEBUG_48BIT_WALK
assert(phys_addr == phys_addr_2);
#endif
- if (phys_addr == INVALID_ADDRESS){
- uint64_t next_page = (address & x86_64_PAGE_MASK) + x86_64_PAGE_SIZE;
- uint64_t len_skipped =next_page-address;
- if(len_skipped > size-amount_copied){
- len_skipped = size-amount_copied;
+ if (phys_addr == INVALID_ADDRESS) {
+ uint64_t next_page = (address & x86_64_PAGE_MASK) + x86_64_PAGE_SIZE;
+ uint64_t len_skipped = next_page - address;
+ if (len_skipped > size - amount_copied) {
+ len_skipped = size - amount_copied;
}
- nyx_error("Warning, read from unmapped memory:\t%lx, skipping to %lx", address, next_page);
- nyx_debug_p(MEM_PREFIX, "Warning, read from unmapped memory:\t%lx, skipping to %lx", address, next_page);
- memset( data+amount_copied, ' ', len_skipped);
+ nyx_error("Warning, read from unmapped memory:\t%lx, skipping to %lx",
+ address, next_page);
+ nyx_debug_p(MEM_PREFIX,
+ "Warning, read from unmapped memory:\t%lx, skipping to %lx",
+ address, next_page);
+ memset(data + amount_copied, ' ', len_skipped);
address += len_skipped;
amount_copied += len_skipped;
continue;
}
-
+
phys_addr += (address & ~x86_64_PAGE_MASK);
uint64_t remaining_on_page = x86_64_PAGE_SIZE - (address & ~x86_64_PAGE_MASK);
- if(len_to_copy > remaining_on_page){
+ if (len_to_copy > remaining_on_page) {
len_to_copy = remaining_on_page;
}
- MemTxResult txt = address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, tmp_buf, len_to_copy, 0);
- if(txt){
- nyx_debug_p(MEM_PREFIX, "Warning, read failed:\t%lx (%lx)", address, phys_addr);
+ MemTxResult txt = address_space_rw(cpu_get_address_space(cpu, asidx),
+ phys_addr, MEMTXATTRS_UNSPECIFIED,
+ tmp_buf, len_to_copy, 0);
+ if (txt) {
+ nyx_debug_p(MEM_PREFIX, "Warning, read failed:\t%lx (%lx)", address,
+ phys_addr);
}
-
- memcpy(data+amount_copied, tmp_buf, len_to_copy);
-
+
+ memcpy(data + amount_copied, tmp_buf, len_to_copy);
+
address += len_to_copy;
amount_copied += len_to_copy;
}
-
+
return true;
}
-bool is_addr_mapped_cr3(uint64_t address, CPUState *cpu, uint64_t cr3){
+bool is_addr_mapped_cr3(uint64_t address, CPUState *cpu, uint64_t cr3)
+{
return (get_paging_phys_addr(cpu, cr3, address) != INVALID_ADDRESS);
-}
+}
-bool is_addr_mapped(uint64_t address, CPUState *cpu){
+bool is_addr_mapped(uint64_t address, CPUState *cpu)
+{
CPUX86State *env = &(X86_CPU(cpu))->env;
kvm_arch_get_registers_fast(cpu);
return (get_paging_phys_addr(cpu, env->cr[3], address) != INVALID_ADDRESS);
-}
+}
-bool is_addr_mapped_cr3_snapshot(uint64_t address, CPUState *cpu, uint64_t cr3){
+bool is_addr_mapped_cr3_snapshot(uint64_t address, CPUState *cpu, uint64_t cr3)
+{
return (get_paging_phys_addr_snapshot(cpu, cr3, address) != INVALID_ADDRESS);
-}
+}
-bool dump_page_cr3_snapshot(uint64_t address, uint8_t* data, CPUState *cpu, uint64_t cr3){
- fast_reload_t* snapshot = get_fast_reload_snapshot();
- uint64_t phys_addr = get_paging_phys_addr_snapshot(cpu, cr3, address);
- if(phys_addr == INVALID_ADDRESS){
+bool dump_page_cr3_snapshot(uint64_t address, uint8_t *data, CPUState *cpu, uint64_t cr3)
+{
+ fast_reload_t *snapshot = get_fast_reload_snapshot();
+ uint64_t phys_addr = get_paging_phys_addr_snapshot(cpu, cr3, address);
+ if (phys_addr == INVALID_ADDRESS) {
return false;
- }
- else{
- return read_snapshot_memory(snapshot, phys_addr, data, PPAGE_SIZE);
+ } else {
+ return read_snapshot_memory(snapshot, phys_addr, data, PPAGE_SIZE);
}
}
-bool dump_page_cr3_ht(uint64_t address, uint8_t* data, CPUState *cpu, uint64_t cr3){
- hwaddr phys_addr = (hwaddr) get_paging_phys_addr(cpu, cr3, address);
- int asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
- if(phys_addr == INVALID_ADDRESS || address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, data, 0x1000, 0)){
- if(phys_addr != INVALID_ADDRESS){
- nyx_error("%s: Warning, read failed:\t%lx (%lx)\n", __func__, address, phys_addr);
+bool dump_page_cr3_ht(uint64_t address, uint8_t *data, CPUState *cpu, uint64_t cr3)
+{
+ hwaddr phys_addr = (hwaddr)get_paging_phys_addr(cpu, cr3, address);
+ int asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
+ if (phys_addr == INVALID_ADDRESS ||
+ address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, data, 0x1000, 0))
+ {
+ if (phys_addr != INVALID_ADDRESS) {
+ nyx_error("%s: Warning, read failed:\t%lx (%lx)\n", __func__, address,
+ phys_addr);
}
return false;
}
return true;
}
-bool dump_page_ht(uint64_t address, uint8_t* data, CPUState *cpu){
+bool dump_page_ht(uint64_t address, uint8_t *data, CPUState *cpu)
+{
CPUX86State *env = &(X86_CPU(cpu))->env;
kvm_arch_get_registers_fast(cpu);
- hwaddr phys_addr = (hwaddr) get_paging_phys_addr(cpu, env->cr[3], address);
- int asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
- if(phys_addr == 0xffffffffffffffffULL || address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr, MEMTXATTRS_UNSPECIFIED, data, 0x1000, 0)){
- if(phys_addr != 0xffffffffffffffffULL){
- nyx_error("%s: Warning, read failed:\t%lx (%lx)\n", __func__, address, phys_addr);
+ hwaddr phys_addr = (hwaddr)get_paging_phys_addr(cpu, env->cr[3], address);
+ int asidx = cpu_asidx_from_attrs(cpu, MEMTXATTRS_UNSPECIFIED);
+ if (phys_addr == 0xffffffffffffffffULL ||
+ address_space_rw(cpu_get_address_space(cpu, asidx), phys_addr,
+ MEMTXATTRS_UNSPECIFIED, data, 0x1000, 0))
+ {
+ if (phys_addr != 0xffffffffffffffffULL) {
+ nyx_error("%s: Warning, read failed:\t%lx (%lx)\n", __func__, address,
+ phys_addr);
}
}
return true;
}
-uint64_t disassemble_at_rip(int fd, uint64_t address, CPUState *cpu, uint64_t cr3){
+uint64_t disassemble_at_rip(int fd, uint64_t address, CPUState *cpu, uint64_t cr3)
+{
+ csh handle;
- csh handle;
-
- size_t code_size = 256;
+ size_t code_size = 256;
uint8_t code_ptr[256];
/* don't => GET_GLOBAL_STATE()->disassembler_word_width */
- if (cs_open(CS_ARCH_X86, get_capstone_mode(GET_GLOBAL_STATE()->disassembler_word_width), &handle) != CS_ERR_OK)
- assert(false);
-
- cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+ if (cs_open(CS_ARCH_X86,
+ get_capstone_mode(GET_GLOBAL_STATE()->disassembler_word_width),
+ &handle) != CS_ERR_OK)
+ assert(false);
- cs_insn* insn = cs_malloc(handle);
+ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
+
+ cs_insn *insn = cs_malloc(handle);
read_virtual_memory(address, code_ptr, code_size, cpu);
int count = cs_disasm(handle, code_ptr, code_size, address, 5, &insn);
- if(count > 0){
- for(int i = 0; i < count; i++){
- nyx_error("=> 0x%"PRIx64":\t%s\t\t%s\n", insn[i].address, insn[i].mnemonic, insn[i].op_str);
+ if (count > 0) {
+ for (int i = 0; i < count; i++) {
+ nyx_error("=> 0x%" PRIx64 ":\t%s\t\t%s\n", insn[i].address,
+ insn[i].mnemonic, insn[i].op_str);
}
- }
- else{
+ } else {
nyx_error("ERROR in %s at %lx (cr3: %lx)\n", __func__, address, cr3);
}
-
-
+
+
cs_free(insn, 1);
cs_close(&handle);
return 0;
}
-
-
-
diff --git a/nyx/memory_access.h b/nyx/memory_access.h
index 9423611833..934a2191eb 100644
--- a/nyx/memory_access.h
+++ b/nyx/memory_access.h
@@ -22,53 +22,68 @@ along with QEMU-PT. If not, see .
#ifndef MEMORY_ACCESS_H
#define MEMORY_ACCESS_H
-#include
-#include "qemu-common.h"
#include "sysemu/kvm_int.h"
+#include "qemu-common.h"
#include "nyx/types.h"
+#include
#define MEM_SPLIT_START 0x0C0000000
#define MEM_SPLIT_END 0x100000000
/* i386 pc_piix low_mem address translation */
-#define address_to_ram_offset(offset) (offset >= MEM_SPLIT_END ? (offset - MEM_SPLIT_END) + MEM_SPLIT_START : offset)
-#define ram_offset_to_address(offset) (offset >= MEM_SPLIT_START ? (offset - MEM_SPLIT_START) + MEM_SPLIT_END : offset)
+#define address_to_ram_offset(offset) \
+ (offset >= MEM_SPLIT_END ? (offset - MEM_SPLIT_END) + MEM_SPLIT_START : offset)
+#define ram_offset_to_address(offset) \
+ (offset >= MEM_SPLIT_START ? (offset - MEM_SPLIT_START) + MEM_SPLIT_END : offset)
mem_mode_t get_current_mem_mode(CPUState *cpu);
uint64_t get_paging_phys_addr(CPUState *cpu, uint64_t cr3, uint64_t addr);
-bool read_physical_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu);
-bool write_physical_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu);
+bool read_physical_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu);
+bool write_physical_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu);
bool remap_payload_slot(uint64_t phys_addr, uint32_t slot, CPUState *cpu);
bool remap_payload_slot_protected(uint64_t phys_addr, uint32_t slot, CPUState *cpu);
bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu);
-bool remap_slots(uint64_t addr, uint32_t slots, CPUState *cpu, int fd, uint64_t shm_size, bool virtual, uint64_t cr3);
-bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t shm_size, bool virtual, uint64_t cr3);
+bool remap_slots(uint64_t addr,
+ uint32_t slots,
+ CPUState *cpu,
+ int fd,
+ uint64_t shm_size,
+ bool virtual,
+ uint64_t cr3);
+bool remap_slot(uint64_t addr,
+ uint32_t slot,
+ CPUState *cpu,
+ int fd,
+ uint64_t shm_size,
+ bool virtual,
+ uint64_t cr3);
-bool read_virtual_memory_cr3(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu, uint64_t cr3);
+bool read_virtual_memory_cr3(
+ uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu, uint64_t cr3);
-bool read_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu);
-bool write_virtual_memory(uint64_t address, uint8_t* data, uint32_t size, CPUState *cpu);
+bool read_virtual_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu);
+bool write_virtual_memory(uint64_t address, uint8_t *data, uint32_t size, CPUState *cpu);
void hexdump_virtual_memory(uint64_t address, uint32_t size, CPUState *cpu);
bool is_addr_mapped(uint64_t address, CPUState *cpu);
bool is_addr_mapped_cr3(uint64_t address, CPUState *cpu, uint64_t cr3);
-int insert_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len);
-int remove_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len);
+int insert_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len);
+int remove_breakpoint(CPUState *cpu, uint64_t addr, uint64_t len);
void remove_all_breakpoints(CPUState *cpu);
uint64_t disassemble_at_rip(int fd, uint64_t address, CPUState *cpu, uint64_t cr3);
-bool dump_page_cr3_snapshot(uint64_t address, uint8_t* data, CPUState *cpu, uint64_t cr3);
-bool dump_page_cr3_ht(uint64_t address, uint8_t* data, CPUState *cpu, uint64_t cr3);
+bool dump_page_cr3_snapshot(uint64_t address, uint8_t *data, CPUState *cpu, uint64_t cr3);
+bool dump_page_cr3_ht(uint64_t address, uint8_t *data, CPUState *cpu, uint64_t cr3);
bool is_addr_mapped_cr3_snapshot(uint64_t address, CPUState *cpu, uint64_t cr3);
void print_48_pagetables(uint64_t cr3);
-bool dump_page_ht(uint64_t address, uint8_t* data, CPUState *cpu);
+bool dump_page_ht(uint64_t address, uint8_t *data, CPUState *cpu);
-void resize_shared_memory(uint32_t new_size, uint32_t* shm_size, void** shm_ptr, int fd);
+void resize_shared_memory(uint32_t new_size, uint32_t *shm_size, void **shm_ptr, int fd);
#endif
diff --git a/nyx/nested_hypercalls.c b/nyx/nested_hypercalls.c
index bad1c1c736..703070c325 100644
--- a/nyx/nested_hypercalls.c
+++ b/nyx/nested_hypercalls.c
@@ -1,25 +1,25 @@
#include "qemu/osdep.h"
-#include
-#include
+#include "qemu/main-loop.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
+#include "nested_hypercalls.h"
+#include "debug.h"
+#include "interface.h"
#include "kvm_nested.h"
#include "memory_access.h"
-#include "debug.h"
-#include "nested_hypercalls.h"
-#include "interface.h"
-#include "state/state.h"
-#include "pt.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
-#include "qemu/main-loop.h"
#include "nyx/helpers.h"
+#include "pt.h"
+#include "state/state.h"
+#include
+#include
-//#define DEBUG_NESTED_HYPERCALLS
+// #define DEBUG_NESTED_HYPERCALLS
bool hypercalls_enabled = false;
-bool create_snapshot = false;
+bool create_snapshot = false;
-uint64_t htos_cr3 = 0;
+uint64_t htos_cr3 = 0;
uint64_t htos_config = 0;
int nested_once = 0;
@@ -27,149 +27,174 @@ int nested_once = 0;
bool nested_setup_snapshot_once = false;
+void handle_hypercall_kafl_nested_config(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ /* magic */
+ nyx_trace();
+ uint32_t size = 0;
+ read_physical_memory(htos_config, (uint8_t *)&size, sizeof(uint32_t), cpu);
-void handle_hypercall_kafl_nested_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- /* magic */
- nyx_trace();
- uint32_t size = 0;
- read_physical_memory(htos_config, (uint8_t*) &size, sizeof(uint32_t), cpu);
+ void *buffer = malloc(size);
- void* buffer = malloc(size);
+ read_physical_memory(htos_config + sizeof(uint32_t), buffer, size, cpu);
+ print_configuration(stderr, buffer, size);
- read_physical_memory(htos_config+sizeof(uint32_t), buffer, size, cpu);
- print_configuration(stderr, buffer, size);
+ FILE *f = fopen("/tmp/hypertrash_configration", "w");
+ print_configuration(f, buffer, size);
+ fclose(f);
- FILE* f = fopen("/tmp/hypertrash_configration", "w");
- print_configuration(f, buffer, size);
- fclose(f);
-
- free(buffer);
+ free(buffer);
}
-void handle_hypercall_kafl_nested_hprintf(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
- char hprintf_buffer[0x1000];
- read_physical_memory((uint64_t)run->hypercall.args[0], (uint8_t*)hprintf_buffer, 0x1000, cpu);
+void handle_hypercall_kafl_nested_hprintf(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
+ char hprintf_buffer[0x1000];
+ read_physical_memory((uint64_t)run->hypercall.args[0], (uint8_t *)hprintf_buffer,
+ 0x1000, cpu);
- set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strnlen(hprintf_buffer, 0x1000)+1);
- synchronization_lock_hprintf();
+ set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer,
+ strnlen(hprintf_buffer, 0x1000) + 1);
+ synchronization_lock_hprintf();
}
-void handle_hypercall_kafl_nested_prepare(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
- kvm_arch_get_registers(cpu);
+void handle_hypercall_kafl_nested_prepare(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
+ kvm_arch_get_registers(cpu);
- if((uint64_t)run->hypercall.args[0]){
- nyx_debug_p(CORE_PREFIX, "handle_hypercall_kafl_nested_prepare:\t NUM:\t%lx\t ADDRESS:\t%lx\t CR3:\t%lx", (uint64_t)run->hypercall.args[0], (uint64_t)run->hypercall.args[1], (uint64_t)run->hypercall.args[2]);
- }
- else{
- abort();
- }
+ if ((uint64_t)run->hypercall.args[0]) {
+ nyx_debug_p(CORE_PREFIX,
+ "handle_hypercall_kafl_nested_prepare:\t NUM:\t%lx\t "
+ "ADDRESS:\t%lx\t CR3:\t%lx",
+ (uint64_t)run->hypercall.args[0], (uint64_t)run->hypercall.args[1],
+ (uint64_t)run->hypercall.args[2]);
+ } 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);
+ 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);
- read_physical_memory((uint64_t)run->hypercall.args[1], (uint8_t*)buffer, buffer_size, cpu);
- htos_cr3 = (uint64_t)run->hypercall.args[0];
+ read_physical_memory((uint64_t)run->hypercall.args[1], (uint8_t *)buffer,
+ buffer_size, cpu);
+ htos_cr3 = (uint64_t)run->hypercall.args[0];
- for(uint64_t i = 0; i < (uint64_t)run->hypercall.args[0]; i++){
- if(i == 0){
- htos_config = buffer[i];
- }
- nyx_debug_p(CORE_PREFIX, "ADDRESS: %lx", buffer[i]);
- remap_payload_slot(buffer[i], i, cpu);
- }
+ for (uint64_t i = 0; i < (uint64_t)run->hypercall.args[0]; i++) {
+ if (i == 0) {
+ htos_config = buffer[i];
+ }
+ nyx_debug_p(CORE_PREFIX, "ADDRESS: %lx", buffer[i]);
+ remap_payload_slot(buffer[i], i, cpu);
+ }
- set_payload_pages(buffer, (uint32_t)run->hypercall.args[0]);
+ set_payload_pages(buffer, (uint32_t)run->hypercall.args[0]);
- // wipe memory
- memset(buffer, 0x00, buffer_size);
- write_physical_memory((uint64_t)run->hypercall.args[1], (uint8_t*)buffer, buffer_size, cpu);
+ // wipe memory
+ memset(buffer, 0x00, buffer_size);
+ write_physical_memory((uint64_t)run->hypercall.args[1], (uint8_t *)buffer,
+ buffer_size, cpu);
- free(buffer);
+ free(buffer);
}
bool acquired = false;
-void handle_hypercall_kafl_nested_early_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
+void handle_hypercall_kafl_nested_early_release(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
- if(!hypercalls_enabled){
- return;
- }
+ if (!hypercalls_enabled) {
+ return;
+ }
- bool state = GET_GLOBAL_STATE()->in_reload_mode;
- if(!state){
- GET_GLOBAL_STATE()->in_reload_mode = true;
- synchronization_disable_pt(cpu);
- GET_GLOBAL_STATE()->in_reload_mode = false;
- }
- else{
- synchronization_disable_pt(cpu);
- }
+ bool state = GET_GLOBAL_STATE()->in_reload_mode;
+ if (!state) {
+ GET_GLOBAL_STATE()->in_reload_mode = true;
+ synchronization_disable_pt(cpu);
+ GET_GLOBAL_STATE()->in_reload_mode = false;
+ } else {
+ synchronization_disable_pt(cpu);
+ }
}
-void handle_hypercall_kafl_nested_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
+void handle_hypercall_kafl_nested_release(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ 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){
- nyx_trace();
+static inline void set_page_dump_bp_nested(CPUState *cpu, uint64_t cr3, uint64_t addr)
+{
+ nyx_trace();
- kvm_remove_all_breakpoints(cpu);
- kvm_insert_breakpoint(cpu, addr, 1, 1);
- kvm_update_guest_debug(cpu, 0);
+ kvm_remove_all_breakpoints(cpu);
+ kvm_insert_breakpoint(cpu, addr, 1, 1);
+ kvm_update_guest_debug(cpu, 0);
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SET_PAGE_DUMP_CR3, cr3);
- kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_PAGE_DUMP_CR3);
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_SET_PAGE_DUMP_CR3, cr3);
+ kvm_vcpu_ioctl(cpu, KVM_VMX_PT_ENABLE_PAGE_DUMP_CR3);
}
-void handle_hypercall_kafl_nested_acquire(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
- nyx_trace();
-
- if (!acquired){
- acquired = true;
+void handle_hypercall_kafl_nested_acquire(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg)
+{
+ nyx_trace();
- //create_fast_snapshot(cpu, true);
- request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state, REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP);
+ if (!acquired) {
+ acquired = true;
- for(int i = 0; i < INTEL_PT_MAX_RANGES; i++){
- if(GET_GLOBAL_STATE()->pt_ip_filter_configured[i]){
- pt_enable_ip_filtering(cpu, i, true, false);
- }
- }
- pt_init_decoder(cpu);
+ // create_fast_snapshot(cpu, true);
+ request_fast_vm_reload(GET_GLOBAL_STATE()->reload_state,
+ REQUEST_SAVE_SNAPSHOT_ROOT_NESTED_FIX_RIP);
-
- qemu_mutex_lock_iothread();
- fast_reload_restore(get_fast_reload_snapshot());
- qemu_mutex_unlock_iothread();
+ for (int i = 0; i < INTEL_PT_MAX_RANGES; i++) {
+ if (GET_GLOBAL_STATE()->pt_ip_filter_configured[i]) {
+ pt_enable_ip_filtering(cpu, i, true, false);
+ }
+ }
+ pt_init_decoder(cpu);
- kvm_arch_get_registers(cpu);
- GET_GLOBAL_STATE()->in_fuzzing_mode = true;
- set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 3);
- }
+ qemu_mutex_lock_iothread();
+ fast_reload_restore(get_fast_reload_snapshot());
+ qemu_mutex_unlock_iothread();
- synchronization_lock();
-
- kvm_arch_get_registers(cpu);
+ kvm_arch_get_registers(cpu);
- uint64_t cr3 = get_nested_host_cr3(cpu) & 0xFFFFFFFFFFFFF000ULL;
- pt_set_cr3(cpu, cr3, false);
- GET_GLOBAL_STATE()->parent_cr3 = cr3;
+ GET_GLOBAL_STATE()->in_fuzzing_mode = true;
+ set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 3);
+ }
- if(GET_GLOBAL_STATE()->dump_page){
- set_page_dump_bp_nested(cpu, cr3, GET_GLOBAL_STATE()->dump_page_addr);
- }
+ synchronization_lock();
- kvm_nested_get_info(cpu);
+ kvm_arch_get_registers(cpu);
- synchronization_enter_fuzzing_loop(cpu);
+ uint64_t cr3 = get_nested_host_cr3(cpu) & 0xFFFFFFFFFFFFF000ULL;
+ pt_set_cr3(cpu, cr3, false);
+ GET_GLOBAL_STATE()->parent_cr3 = cr3;
- return;
+ if (GET_GLOBAL_STATE()->dump_page) {
+ set_page_dump_bp_nested(cpu, cr3, GET_GLOBAL_STATE()->dump_page_addr);
+ }
+
+ kvm_nested_get_info(cpu);
+
+ synchronization_enter_fuzzing_loop(cpu);
+
+ return;
}
\ No newline at end of file
diff --git a/nyx/nested_hypercalls.h b/nyx/nested_hypercalls.h
index e3104f7f2f..b5b1f93102 100644
--- a/nyx/nested_hypercalls.h
+++ b/nyx/nested_hypercalls.h
@@ -1,11 +1,23 @@
-#pragma once
+#pragma once
#include
/* 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);
-void handle_hypercall_kafl_nested_config(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
-void handle_hypercall_kafl_nested_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
-void handle_hypercall_kafl_nested_acquire(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
-void handle_hypercall_kafl_nested_early_release(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg);
\ No newline at end of file
+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);
+void handle_hypercall_kafl_nested_config(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
+void handle_hypercall_kafl_nested_release(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
+void handle_hypercall_kafl_nested_acquire(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
+void handle_hypercall_kafl_nested_early_release(struct kvm_run *run,
+ CPUState *cpu,
+ uint64_t hypercall_arg);
\ No newline at end of file
diff --git a/nyx/page_cache.c b/nyx/page_cache.c
index 5e97e9d551..221bc9b78c 100644
--- a/nyx/page_cache.c
+++ b/nyx/page_cache.c
@@ -1,329 +1,353 @@
#include "qemu/osdep.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
#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/memory_access.h"
#include "nyx/state/state.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#define PAGE_CACHE_ADDR_LINE_SIZE sizeof(uint64_t)
#define UNMAPPED_PAGE 0xFFFFFFFFFFFFFFFFULL
-static bool reload_addresses(page_cache_t* self){
- khiter_t k;
- int ret;
- uint64_t addr, offset;
- uint64_t value = 0;
+static bool reload_addresses(page_cache_t *self)
+{
+ khiter_t k;
+ int ret;
+ uint64_t addr, offset;
+ uint64_t value = 0;
- size_t self_offset = lseek(self->fd_address_file, 0, SEEK_END);
+ size_t self_offset = lseek(self->fd_address_file, 0, SEEK_END);
- if(self_offset != self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE){
- /* 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)){
- addr = value & 0xFFFFFFFFFFFFF000ULL;
- offset++;
+ if (self_offset != self->num_pages * PAGE_CACHE_ADDR_LINE_SIZE) {
+ /* 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)) {
+ addr = value & 0xFFFFFFFFFFFFF000ULL;
+ offset++;
- /* put new addresses and offsets into the hash map */
- k = kh_get(PC_CACHE, self->lookup, addr);
- if(k == kh_end(self->lookup)){
+ /* put new addresses and offsets into the hash map */
+ k = kh_get(PC_CACHE, self->lookup, addr);
+ if (k == kh_end(self->lookup)) {
+ if (value & 0xFFF) {
+ fprintf(stderr, "Load page: %lx (UNMAPPED)\n", addr);
+ } else {
+ 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);
+ // abort();
+ }
+ }
- if(value & 0xFFF){
- fprintf(stderr, "Load page: %lx (UNMAPPED)\n", addr);
- }
- else{
- 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);
- //abort();
- }
- }
+ /* reload page dump file */
+ munmap(self->page_data, self->num_pages * PAGE_SIZE);
+ self->num_pages = self_offset / PAGE_CACHE_ADDR_LINE_SIZE;
+ self->page_data = mmap(NULL, (self->num_pages) * PAGE_SIZE,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ self->fd_page_file, 0);
- /* reload page dump file */
- munmap(self->page_data, self->num_pages*PAGE_SIZE);
- self->num_pages = self_offset/PAGE_CACHE_ADDR_LINE_SIZE;
- self->page_data = mmap(NULL, (self->num_pages)*PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd_page_file, 0);
+ return true;
+ }
- return true;
- }
-
- return false;
+ return false;
}
-static bool append_page(page_cache_t* self, uint64_t page, uint64_t cr3){
- 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);
- }
+static bool append_page(page_cache_t *self, uint64_t page, uint64_t cr3)
+{
+ 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);
+ }
- 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)){
+ 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))
+ {
+ 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);
- 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);
-
- success = false;
- return success;
- }
- }
- }
- fsync(self->fd_page_file);
- self->num_pages++;
- return success;
+ success = false;
+ return success;
+ }
+ }
+ }
+ fsync(self->fd_page_file);
+ self->num_pages++;
+ return success;
}
-static void page_cache_lock(page_cache_t* self){
- int ret = 0;
- while (true){
- ret = flock(self->fd_lock, LOCK_EX);
- if (ret == 0){
- return;
- }
- else if (ret == EINTR){
- /* try again if acquiring this lock has failed */
- fprintf(stderr, "%s: interrupted by signal...\n", __func__);
- }
- else{
- assert(false);
- }
- }
+static void page_cache_lock(page_cache_t *self)
+{
+ int ret = 0;
+ while (true) {
+ ret = flock(self->fd_lock, LOCK_EX);
+ if (ret == 0) {
+ return;
+ } else if (ret == EINTR) {
+ /* try again if acquiring this lock has failed */
+ fprintf(stderr, "%s: interrupted by signal...\n", __func__);
+ } else {
+ assert(false);
+ }
+ }
}
-static void page_cache_unlock(page_cache_t* self){
- int ret = 0;
- while (true){
- ret = flock(self->fd_lock, LOCK_UN);
- if (ret == 0){
- return;
- }
- else if (ret == EINTR){
- /* try again if releasing this lock has failed */
- fprintf(stderr, "%s: interrupted by signal...\n", __func__);
- }
- else{
- assert(false);
- }
- }
+static void page_cache_unlock(page_cache_t *self)
+{
+ int ret = 0;
+ while (true) {
+ ret = flock(self->fd_lock, LOCK_UN);
+ if (ret == 0) {
+ return;
+ } else if (ret == EINTR) {
+ /* try again if releasing this lock has failed */
+ fprintf(stderr, "%s: interrupted by signal...\n", __func__);
+ } else {
+ assert(false);
+ }
+ }
}
-static bool update_page_cache(page_cache_t* self, uint64_t page, khiter_t* k){
- page_cache_lock(self);
+static bool update_page_cache(page_cache_t *self, uint64_t page, khiter_t *k)
+{
+ page_cache_lock(self);
- if(reload_addresses(self)){
- *k = kh_get(PC_CACHE, self->lookup, page);
- }
+ if (reload_addresses(self)) {
+ *k = kh_get(PC_CACHE, self->lookup, page);
+ }
- if(*k == kh_end(self->lookup)){
- int ret;
+ if (*k == kh_end(self->lookup)) {
+ int ret;
- 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! */
- }
+ 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);
- }
- else{
-
+ *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);
+ } else {
+ if (append_page(self, page, cr3)) {
+ *k = kh_put(PC_CACHE, self->lookup, page, &ret);
+ assert(write(self->fd_address_file, &page,
+ PAGE_CACHE_ADDR_LINE_SIZE) == PAGE_CACHE_ADDR_LINE_SIZE);
+ kh_value(self->lookup, *k) = (self->num_pages - 1) * PAGE_SIZE;
+ } else {
+ page_cache_unlock(self);
+ return false;
+ }
- if(append_page(self, page, cr3)){
- *k = kh_put(PC_CACHE, self->lookup, page, &ret);
- assert(write(self->fd_address_file, &page, PAGE_CACHE_ADDR_LINE_SIZE) == PAGE_CACHE_ADDR_LINE_SIZE);
- kh_value(self->lookup, *k) = (self->num_pages-1)*PAGE_SIZE;
- }
- else{
- page_cache_unlock(self);
- return false;
- }
-
- *k = kh_get(PC_CACHE, self->lookup, page);
- }
- }
- page_cache_unlock(self);
- return true;
+ *k = kh_get(PC_CACHE, self->lookup, page);
+ }
+ }
+ page_cache_unlock(self);
+ return true;
}
-uint64_t page_cache_fetch(page_cache_t* self, uint64_t page, bool* success, bool test_mode){
- page &= 0xFFFFFFFFFFFFF000ULL;
+uint64_t page_cache_fetch(page_cache_t *self, uint64_t page, bool *success, bool test_mode)
+{
+ page &= 0xFFFFFFFFFFFFF000ULL;
- if (self->last_page == page){
- *success = true;
- return self->last_addr;
- }
-
- 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){
- *success = false;
- return 0;
- }
- }
+ if (self->last_page == page) {
+ *success = true;
+ return self->last_addr;
+ }
- self->last_page = 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) {
+ *success = false;
+ return 0;
+ }
+ }
- if(kh_value(self->lookup, k) == UNMAPPED_PAGE){
- self->last_addr = UNMAPPED_PAGE;
- }
- else{
- self->last_addr = (uint64_t)self->page_data+kh_value(self->lookup, k);
- }
+ self->last_page = page;
- *success = true;
- return self->last_addr;
+ if (kh_value(self->lookup, k) == UNMAPPED_PAGE) {
+ self->last_addr = UNMAPPED_PAGE;
+ } else {
+ self->last_addr = (uint64_t)self->page_data + kh_value(self->lookup, k);
+ }
+
+ *success = true;
+ return self->last_addr;
}
/* FIXME */
-uint64_t page_cache_fetch2(page_cache_t* self, uint64_t page, bool* success){
- return page_cache_fetch(self, page, success, false);
+uint64_t page_cache_fetch2(page_cache_t *self, uint64_t page, bool *success)
+{
+ return page_cache_fetch(self, page, success, false);
}
-page_cache_t* page_cache_new(CPUState *cpu, const char* cache_file){
- page_cache_t* self = malloc(sizeof(page_cache_t));
+page_cache_t *page_cache_new(CPUState *cpu, const char *cache_file)
+{
+ page_cache_t *self = malloc(sizeof(page_cache_t));
- char* tmp1;
- char* tmp2;
- char* tmp3;
- assert(asprintf(&tmp1, "%s.dump", cache_file) != -1);
- assert(asprintf(&tmp2, "%s.addr", cache_file) != -1);
- assert(asprintf(&tmp3, "%s.lock", cache_file) != -1);
+ char *tmp1;
+ char *tmp2;
+ char *tmp3;
+ assert(asprintf(&tmp1, "%s.dump", cache_file) != -1);
+ 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);
+ 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);
- self->cpu = cpu;
- self->fd_lock = open(tmp3, O_CLOEXEC);
- assert(self->fd_lock > 0);
+ self->cpu = cpu;
+ self->fd_lock = open(tmp3, O_CLOEXEC);
+ assert(self->fd_lock > 0);
- memset(self->disassemble_cache, 0x0, 16);
+ memset(self->disassemble_cache, 0x0, 16);
- self->page_data = NULL;
- self->num_pages = 0;
+ self->page_data = NULL;
+ self->num_pages = 0;
- self->last_page = 0xFFFFFFFFFFFFFFFF;
- self->last_addr = 0xFFFFFFFFFFFFFFFF;
+ self->last_page = 0xFFFFFFFFFFFFFFFF;
+ self->last_addr = 0xFFFFFFFFFFFFFFFF;
- nyx_debug_p(PAGE_CACHE_PREFIX, "%s (%s - %s)", __func__, tmp1, tmp2);
+ nyx_debug_p(PAGE_CACHE_PREFIX, "%s (%s - %s)", __func__, tmp1, tmp2);
- free(tmp3);
- free(tmp2);
- free(tmp1);
+ free(tmp3);
+ free(tmp2);
+ free(tmp1);
- if (cs_open(CS_ARCH_X86, CS_MODE_16, &self->handle_16) != CS_ERR_OK)
- assert(false);
+ if (cs_open(CS_ARCH_X86, CS_MODE_16, &self->handle_16) != CS_ERR_OK)
+ assert(false);
- if (cs_open(CS_ARCH_X86, CS_MODE_32, &self->handle_32) != CS_ERR_OK)
- assert(false);
+ if (cs_open(CS_ARCH_X86, CS_MODE_32, &self->handle_32) != CS_ERR_OK)
+ assert(false);
- if (cs_open(CS_ARCH_X86, CS_MODE_64, &self->handle_64) != CS_ERR_OK)
- assert(false);
+ if (cs_open(CS_ARCH_X86, CS_MODE_64, &self->handle_64) != CS_ERR_OK)
+ assert(false);
- cs_option(self->handle_16, CS_OPT_DETAIL, CS_OPT_ON);
- cs_option(self->handle_32, CS_OPT_DETAIL, CS_OPT_ON);
- cs_option(self->handle_64, CS_OPT_DETAIL, CS_OPT_ON);
+ cs_option(self->handle_16, CS_OPT_DETAIL, CS_OPT_ON);
+ cs_option(self->handle_32, CS_OPT_DETAIL, CS_OPT_ON);
+ cs_option(self->handle_64, CS_OPT_DETAIL, CS_OPT_ON);
- return self;
+ return self;
}
-bool page_cache_disassemble(page_cache_t* self, uint64_t address, cs_insn **insn){
- return true;
+bool page_cache_disassemble(page_cache_t *self, uint64_t address, cs_insn **insn)
+{
+ return true;
}
-cs_insn* page_cache_cs_malloc(page_cache_t* self, disassembler_mode_t mode){
- switch(mode){
- case mode_16:
- return cs_malloc(self->handle_16);
- case mode_32:
- return cs_malloc(self->handle_32);
- case mode_64:
- return cs_malloc(self->handle_64);
- default:
- assert(false);
- }
- return NULL;
+cs_insn *page_cache_cs_malloc(page_cache_t *self, disassembler_mode_t mode)
+{
+ switch (mode) {
+ case mode_16:
+ return cs_malloc(self->handle_16);
+ case mode_32:
+ return cs_malloc(self->handle_32);
+ case mode_64:
+ return cs_malloc(self->handle_64);
+ default:
+ assert(false);
+ }
+ return NULL;
}
-bool page_cache_disassemble_iter(page_cache_t* self, uint64_t* address, cs_insn *insn, uint64_t* failed_page, disassembler_mode_t mode){
- *failed_page = 0xFFFFFFFFFFFFFFFFULL;
+bool page_cache_disassemble_iter(page_cache_t *self,
+ uint64_t *address,
+ cs_insn *insn,
+ uint64_t *failed_page,
+ disassembler_mode_t mode)
+{
+ *failed_page = 0xFFFFFFFFFFFFFFFFULL;
- bool success = true;
- size_t code_size = 16;
+ bool success = true;
+ size_t code_size = 16;
- uint8_t* code = (uint8_t*)page_cache_fetch(self, *address, &success, false);
- uint8_t* code_ptr = 0;
+ uint8_t *code = (uint8_t *)page_cache_fetch(self, *address, &success, false);
+ uint8_t *code_ptr = 0;
- csh* current_handle = NULL;
+ csh *current_handle = NULL;
- switch(mode){
- case mode_16:
- current_handle = &self->handle_16;
- break;
- case mode_32:
- current_handle = &self->handle_32;
- break;
- case mode_64:
- current_handle = &self->handle_64;
- break;
- default:
- assert(false);
- }
+ switch (mode) {
+ case mode_16:
+ current_handle = &self->handle_16;
+ break;
+ case mode_32:
+ current_handle = &self->handle_32;
+ break;
+ case mode_64:
+ current_handle = &self->handle_64;
+ break;
+ default:
+ assert(false);
+ }
- if (code == (void*)UNMAPPED_PAGE || success == false){
- *failed_page = *address;
- return false;
- }
+ if (code == (void *)UNMAPPED_PAGE || success == false) {
+ *failed_page = *address;
+ return false;
+ }
- if ((*address & 0xFFF) >= (0x1000-16)){
- memcpy((void*)self->disassemble_cache, (void*)((uint64_t)code+(0x1000-16)), 16);
- code_ptr = self->disassemble_cache + 0xf-(0xfff-(*address&0xfff));
- code = (uint8_t*)page_cache_fetch(self, *address+0x1000, &success, false);
+ if ((*address & 0xFFF) >= (0x1000 - 16)) {
+ memcpy((void *)self->disassemble_cache,
+ (void *)((uint64_t)code + (0x1000 - 16)), 16);
+ code_ptr = self->disassemble_cache + 0xf - (0xfff - (*address & 0xfff));
+ code = (uint8_t *)page_cache_fetch(self, *address + 0x1000, &success, false);
- if(success == true){
- memcpy((void*)(self->disassemble_cache+16), (void*)code, 16);
- return cs_disasm_iter(*current_handle, (const uint8_t**) &code_ptr, &code_size, address, insn);
- }
- else{
- code_size = (0xfff-(*address&0xfff));
- if(!cs_disasm_iter(*current_handle, (const uint8_t**) &code_ptr, &code_size, address, insn)){
- *failed_page = (*address+0x1000) & 0xFFFFFFFFFFFFF000ULL;
- return false;
- }
- return true;
- }
- }
- else {
- code_ptr = code + (*address&0xFFF);
- return cs_disasm_iter(*current_handle, (const uint8_t**) &code_ptr, &code_size, address, insn);
- }
+ if (success == true) {
+ memcpy((void *)(self->disassemble_cache + 16), (void *)code, 16);
+ return cs_disasm_iter(*current_handle, (const uint8_t **)&code_ptr,
+ &code_size, address, insn);
+ } else {
+ code_size = (0xfff - (*address & 0xfff));
+ if (!cs_disasm_iter(*current_handle, (const uint8_t **)&code_ptr,
+ &code_size, address, insn))
+ {
+ *failed_page = (*address + 0x1000) & 0xFFFFFFFFFFFFF000ULL;
+ return false;
+ }
+ return true;
+ }
+ } else {
+ code_ptr = code + (*address & 0xFFF);
+ return cs_disasm_iter(*current_handle, (const uint8_t **)&code_ptr,
+ &code_size, address, insn);
+ }
}
-
-
diff --git a/nyx/page_cache.h b/nyx/page_cache.h
index 2434266f4b..8176d9e034 100644
--- a/nyx/page_cache.h
+++ b/nyx/page_cache.h
@@ -1,8 +1,8 @@
#pragma once
+#include "khash.h"
#include
#include
-#include "khash.h"
#include
#include "qemu-common.h"
@@ -10,30 +10,37 @@
KHASH_MAP_INIT_INT64(PC_CACHE, uint64_t)
-typedef struct page_cache_s{
- CPUState *cpu;
- khash_t(PC_CACHE) *lookup;
- int fd_page_file;
- int fd_address_file;
- int fd_lock;
- uint8_t disassemble_cache[32];
- void* page_data;
- uint32_t num_pages;
+typedef struct page_cache_s {
+ CPUState *cpu;
+ khash_t(PC_CACHE) * lookup;
+ int fd_page_file;
+ int fd_address_file;
+ int fd_lock;
+ uint8_t disassemble_cache[32];
+ void *page_data;
+ uint32_t num_pages;
- csh handle_16;
- csh handle_32;
- csh handle_64;
+ csh handle_16;
+ csh handle_32;
+ csh handle_64;
- uint64_t last_page;
- uint64_t last_addr;
+ uint64_t last_page;
+ uint64_t last_addr;
} page_cache_t;
-page_cache_t* page_cache_new(CPUState *cpu, const char* cache_file);
-uint64_t page_cache_fetch(page_cache_t* self, uint64_t page, bool* success, bool test_mode);
+page_cache_t *page_cache_new(CPUState *cpu, const char *cache_file);
+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);
-bool page_cache_disassemble_iter(page_cache_t* self, uint64_t* address, cs_insn *insn, uint64_t* failed_page, disassembler_mode_t mode);
+bool page_cache_disassemble(page_cache_t *self, uint64_t address, cs_insn **insn);
+bool page_cache_disassemble_iter(page_cache_t *self,
+ uint64_t *address,
+ cs_insn *insn,
+ uint64_t *failed_page,
+ disassembler_mode_t mode);
-cs_insn* page_cache_cs_malloc(page_cache_t* self, disassembler_mode_t mode);
+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);
\ No newline at end of file
+uint64_t page_cache_fetch2(page_cache_t *self, uint64_t page, bool *success);
\ No newline at end of file
diff --git a/nyx/patcher.c b/nyx/patcher.c
index c7a44a30c1..90ceaf2216 100644
--- a/nyx/patcher.c
+++ b/nyx/patcher.c
@@ -1,10 +1,12 @@
#include "patcher.h"
-#include "nyx/memory_access.h"
-#include "nyx/disassembler.h"
#include "debug.h"
+#include "nyx/disassembler.h"
+#include "nyx/memory_access.h"
#include "nyx/state/state.h"
-uint8_t cmp_patch_data[] = { 0x38, 0xC0, [2 ... MAX_INSTRUCTION_SIZE]=0x90 }; // CMP AL,AL; NOP, NOP ...
+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];
/*
@@ -14,106 +16,128 @@ static void _patcher_apply_patch(patcher_t *self, size_t index);
static void _patcher_restore_patch(patcher_t *self, size_t index);
-static void _patcher_save_patch(patcher_t *self, size_t index, uint8_t* data, size_t instruction_size, uint64_t addr);
+static void _patcher_save_patch(patcher_t *self,
+ size_t index,
+ uint8_t *data,
+ size_t instruction_size,
+ uint64_t addr);
-static size_t _patcher_disassemble_size(patcher_t *self, uint8_t* data, uint64_t addr, x86_insn id);
+static size_t _patcher_disassemble_size(patcher_t *self,
+ uint8_t *data,
+ uint64_t addr,
+ x86_insn id);
static void _patcher_alloc_patch_infos(patcher_t *self, size_t num_patches);
static void _patcher_free_patch_infos(patcher_t *self);
-static redqueen_t* _redq_ptr(patcher_t *self);
+static redqueen_t *_redq_ptr(patcher_t *self);
/*
* Public Functions
*/
-patcher_t* patcher_new(CPUState *cpu){
- patcher_t *res = malloc(sizeof(patcher_t));
- res->cpu = cpu;
- res->num_patches = 0;
- res->patches = NULL;
+patcher_t *patcher_new(CPUState *cpu)
+{
+ patcher_t *res = malloc(sizeof(patcher_t));
+ res->cpu = cpu;
+ res->num_patches = 0;
+ res->patches = NULL;
res->is_currently_applied = false;
return res;
}
-void patcher_free(patcher_t* self){
+void patcher_free(patcher_t *self)
+{
assert(!self->is_currently_applied);
_patcher_free_patch_infos(self);
free(self);
}
-void patcher_apply_all(patcher_t *self){
- assert(!self->is_currently_applied);
- assert(!_redq_ptr(self)->hooks_applied);
- //assert(patcher_validate_patches(self));
- for(size_t i=0; i < self->num_patches; i++){
- _patcher_apply_patch(self, i);
- }
- self->is_currently_applied = true;
-}
-
-void patcher_restore_all(patcher_t *self){
- assert(self->is_currently_applied);
- assert(!_redq_ptr(self)->hooks_applied);
- //assert(patcher_validate_patches(self));
- for(size_t i = 0; i < self->num_patches; i++){
- _patcher_restore_patch(self, i);
- }
- self->is_currently_applied = false;
-}
-
-void patcher_set_addrs(patcher_t *self, uint64_t* addrs, size_t num_addrs){
- _patcher_free_patch_infos(self);
- _patcher_alloc_patch_infos(self, num_addrs);
- uint8_t curr_instruction_code[MAX_INSTRUCTION_SIZE];
- memset(&curr_instruction_code[0], 0, MAX_INSTRUCTION_SIZE);
-
- for(size_t i=0; i < self->num_patches; i++){
- //nyx_debug_p(REDQUEEN_PREFIX, "patching %lx", addrs[i]);
- if( read_virtual_memory(addrs[i], &curr_instruction_code[0], MAX_INSTRUCTION_SIZE, self->cpu) ) {
- size_t size =_patcher_disassemble_size(self, &curr_instruction_code[0], addrs[i], X86_INS_CMP);
- assert(size != 0); //csopen failed, shouldn't happen
- _patcher_save_patch(self, i, &curr_instruction_code[0], size, addrs[i]);
+void patcher_apply_all(patcher_t *self)
+{
+ assert(!self->is_currently_applied);
+ assert(!_redq_ptr(self)->hooks_applied);
+ // assert(patcher_validate_patches(self));
+ for (size_t i = 0; i < self->num_patches; i++) {
+ _patcher_apply_patch(self, i);
}
- }
+ self->is_currently_applied = true;
}
-static void print_hexdump(const uint8_t* addr, size_t size){
- for(size_t i = 0; i < size; i++){
- printf (" %02x", addr[i]);
- }
- printf("\n");
+void patcher_restore_all(patcher_t *self)
+{
+ assert(self->is_currently_applied);
+ assert(!_redq_ptr(self)->hooks_applied);
+ // assert(patcher_validate_patches(self));
+ for (size_t i = 0; i < self->num_patches; i++) {
+ _patcher_restore_patch(self, i);
+ }
+ self->is_currently_applied = false;
}
-bool patcher_validate_patches(patcher_t *self){
- bool was_rq = _redq_ptr(self)->hooks_applied;
- if(was_rq)
- redqueen_remove_hooks(_redq_ptr(self));
- if(!self->patches){return true;}
- for(size_t i=0; inum_patches; i++){
- uint8_t buf[MAX_INSTRUCTION_SIZE];
- read_virtual_memory(self->patches[i].addr, &buf[0], MAX_INSTRUCTION_SIZE, self->cpu);
- const uint8_t* should_value = NULL;
- if(self->is_currently_applied){
- should_value = cmp_patch;
- } else {
- should_value = &self->patches[i].orig_bytes[0];
- }
+void patcher_set_addrs(patcher_t *self, uint64_t *addrs, size_t num_addrs)
+{
+ _patcher_free_patch_infos(self);
+ _patcher_alloc_patch_infos(self, num_addrs);
+ uint8_t curr_instruction_code[MAX_INSTRUCTION_SIZE];
+ memset(&curr_instruction_code[0], 0, MAX_INSTRUCTION_SIZE);
- nyx_debug_p(REDQUEEN_PREFIX, "Validating, mem:");
- print_hexdump(&buf[0], self->patches[i].size);
- nyx_debug_p(REDQUEEN_PREFIX, "should_be:");
- print_hexdump(should_value, self->patches[i].size);
- if(0 != memcmp(&buf[0], should_value, self->patches[i].size)){
- nyx_debug_p(REDQUEEN_PREFIX, "validating patches failed self->is_currently_applied = %d", self->is_currently_applied);
- return false;
+ for (size_t i = 0; i < self->num_patches; i++) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "patching %lx", addrs[i]);
+ if (read_virtual_memory(addrs[i], &curr_instruction_code[0],
+ MAX_INSTRUCTION_SIZE, self->cpu))
+ {
+ size_t size = _patcher_disassemble_size(self, &curr_instruction_code[0],
+ addrs[i], X86_INS_CMP);
+ assert(size != 0); // csopen failed, shouldn't happen
+ _patcher_save_patch(self, i, &curr_instruction_code[0], size, addrs[i]);
+ }
}
- }
- if(was_rq)
- redqueen_insert_hooks(_redq_ptr(self));
- return true;
+}
+
+static void print_hexdump(const uint8_t *addr, size_t size)
+{
+ for (size_t i = 0; i < size; i++) {
+ printf(" %02x", addr[i]);
+ }
+ printf("\n");
+}
+
+bool patcher_validate_patches(patcher_t *self)
+{
+ bool was_rq = _redq_ptr(self)->hooks_applied;
+ if (was_rq)
+ redqueen_remove_hooks(_redq_ptr(self));
+ if (!self->patches) {
+ return true;
+ }
+ for (size_t i = 0; i < self->num_patches; i++) {
+ uint8_t buf[MAX_INSTRUCTION_SIZE];
+ read_virtual_memory(self->patches[i].addr, &buf[0], MAX_INSTRUCTION_SIZE,
+ self->cpu);
+ const uint8_t *should_value = NULL;
+ if (self->is_currently_applied) {
+ should_value = cmp_patch;
+ } else {
+ should_value = &self->patches[i].orig_bytes[0];
+ }
+
+ nyx_debug_p(REDQUEEN_PREFIX, "Validating, mem:");
+ print_hexdump(&buf[0], self->patches[i].size);
+ nyx_debug_p(REDQUEEN_PREFIX, "should_be:");
+ print_hexdump(should_value, self->patches[i].size);
+ if (0 != memcmp(&buf[0], should_value, self->patches[i].size)) {
+ nyx_debug_p(REDQUEEN_PREFIX,
+ "validating patches failed self->is_currently_applied = %d",
+ self->is_currently_applied);
+ return false;
+ }
+ }
+ if (was_rq)
+ redqueen_insert_hooks(_redq_ptr(self));
+ return true;
}
@@ -121,60 +145,77 @@ bool patcher_validate_patches(patcher_t *self){
* Private Helper Functions Definitions
*/
-static void _patcher_apply_patch(patcher_t *self, size_t index) {
- abort(); // deprecated function -> remove this code later
+static void _patcher_apply_patch(patcher_t *self, size_t index)
+{
+ abort(); // deprecated function -> remove this code later
}
-static void _patcher_restore_patch(patcher_t *self, size_t index){
- abort(); // deprecated function -> remove this code later
+static void _patcher_restore_patch(patcher_t *self, size_t index)
+{
+ abort(); // deprecated function -> remove this code later
}
-static void _patcher_save_patch(patcher_t *self, size_t index, uint8_t* data, size_t instruction_size, uint64_t addr) {
- assert(instruction_size >= 2);
- assert(instruction_size < MAX_INSTRUCTION_SIZE);
- patch_info_t *info = &self->patches[index];
- memset(&info->orig_bytes[0], 0, MAX_INSTRUCTION_SIZE);
- memcpy(&info->orig_bytes[0], data, instruction_size);
- info->addr = addr;
- info->size = instruction_size;
+static void _patcher_save_patch(patcher_t *self,
+ size_t index,
+ uint8_t *data,
+ size_t instruction_size,
+ uint64_t addr)
+{
+ assert(instruction_size >= 2);
+ assert(instruction_size < MAX_INSTRUCTION_SIZE);
+ patch_info_t *info = &self->patches[index];
+ memset(&info->orig_bytes[0], 0, MAX_INSTRUCTION_SIZE);
+ memcpy(&info->orig_bytes[0], data, instruction_size);
+ info->addr = addr;
+ info->size = instruction_size;
}
-static size_t _patcher_disassemble_size(patcher_t *self, uint8_t* data, uint64_t addr, x86_insn type){
-
+static size_t _patcher_disassemble_size(patcher_t *self,
+ uint8_t *data,
+ uint64_t addr,
+ x86_insn type)
+{
csh handle;
- if (cs_open(CS_ARCH_X86, get_capstone_mode(GET_GLOBAL_STATE()->disassembler_word_width), &handle) == CS_ERR_OK){
- cs_insn *insn = cs_malloc(handle);
- uint8_t* cur_offset = data;
- uint64_t cs_address = addr;
- uint64_t code_size = MAX_INSTRUCTION_SIZE;
- cs_disasm_iter(handle, (const uint8_t **) &cur_offset, &code_size, &cs_address, insn);
- size_t size = insn->size;
- if(type != X86_INS_INVALID){
- assert(insn->id == type);
- }
- cs_free(insn, 1);
- cs_close(&handle);
- return size;
+ if (cs_open(CS_ARCH_X86,
+ get_capstone_mode(GET_GLOBAL_STATE()->disassembler_word_width),
+ &handle) == CS_ERR_OK)
+ {
+ cs_insn *insn = cs_malloc(handle);
+ uint8_t *cur_offset = data;
+ uint64_t cs_address = addr;
+ uint64_t code_size = MAX_INSTRUCTION_SIZE;
+ cs_disasm_iter(handle, (const uint8_t **)&cur_offset, &code_size,
+ &cs_address, insn);
+ size_t size = insn->size;
+ if (type != X86_INS_INVALID) {
+ assert(insn->id == type);
+ }
+ cs_free(insn, 1);
+ cs_close(&handle);
+ return size;
}
return 0;
}
-static void _patcher_alloc_patch_infos(patcher_t *self, size_t num_patches){
- assert(self->num_patches == 0);
- assert(self->patches == NULL);
- assert(num_patches < 10000);
- self->num_patches = num_patches;
- self->patches = malloc(sizeof(patch_info_t)*num_patches);
+static void _patcher_alloc_patch_infos(patcher_t *self, size_t num_patches)
+{
+ assert(self->num_patches == 0);
+ assert(self->patches == NULL);
+ assert(num_patches < 10000);
+ self->num_patches = num_patches;
+ self->patches = malloc(sizeof(patch_info_t) * num_patches);
}
-static void _patcher_free_patch_infos(patcher_t *self){
- assert(!self->is_currently_applied);
- free(self->patches);
- self->patches = NULL;
- self->num_patches = 0;
+static void _patcher_free_patch_infos(patcher_t *self)
+{
+ assert(!self->is_currently_applied);
+ free(self->patches);
+ self->patches = NULL;
+ self->num_patches = 0;
}
-static redqueen_t* _redq_ptr(patcher_t *self){
- redqueen_t* res = GET_GLOBAL_STATE()->redqueen_state; //self->cpu->redqueen_state;
- return res;
+static redqueen_t *_redq_ptr(patcher_t *self)
+{
+ redqueen_t *res = GET_GLOBAL_STATE()->redqueen_state; // self->cpu->redqueen_state;
+ return res;
}
diff --git a/nyx/patcher.h b/nyx/patcher.h
index 997d29d135..912a26526f 100644
--- a/nyx/patcher.h
+++ b/nyx/patcher.h
@@ -1,8 +1,8 @@
#ifndef __GUARD_REDQUEEN_PATCHER_STRUCT__
#define __GUARD_REDQUEEN_PATCHER_STRUCT__
-#include
#include
+#include
#include
#include
@@ -15,24 +15,23 @@
* 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;
+extern const uint8_t *cmp_patch;
-typedef struct patch_info_s{
- uint64_t addr;
- size_t size;
- uint8_t orig_bytes[MAX_INSTRUCTION_SIZE];
+typedef struct patch_info_s {
+ uint64_t addr;
+ size_t size;
+ uint8_t orig_bytes[MAX_INSTRUCTION_SIZE];
} patch_info_t;
-typedef struct patcher_s{
+typedef struct patcher_s {
+ CPUState *cpu;
- CPUState *cpu;
-
- patch_info_t *patches;
- size_t num_patches;
- bool is_currently_applied;
+ patch_info_t *patches;
+ size_t num_patches;
+ bool is_currently_applied;
} patcher_t;
-patcher_t* patcher_new(CPUState *cpu);
+patcher_t *patcher_new(CPUState *cpu);
void patcher_free(patcher_t *self);
@@ -40,8 +39,8 @@ void patcher_apply_all(patcher_t *self);
void patcher_restore_all(patcher_t *self);
-//Doesn't take ownership of addrs
-void patcher_set_addrs(patcher_t *self, uint64_t* addrs, size_t num_addrs);
+// Doesn't take ownership of addrs
+void patcher_set_addrs(patcher_t *self, uint64_t *addrs, size_t num_addrs);
bool patcher_validate_patches(patcher_t *self);
diff --git a/nyx/pt.c b/nyx/pt.c
index 1e66510112..c5864dbc8c 100644
--- a/nyx/pt.c
+++ b/nyx/pt.c
@@ -53,320 +53,365 @@ along with QEMU-PT. If not, see .
#define PT_BUFFER_MMAP_ADDR 0x3ffff0000000
-static void pt_set(CPUState *cpu, run_on_cpu_data arg){
- asm volatile("" ::: "memory");
+static void pt_set(CPUState *cpu, run_on_cpu_data arg)
+{
+ asm volatile("" ::: "memory");
}
-static inline int pt_cmd_hmp_context(CPUState *cpu, uint64_t cmd){
- cpu->pt_ret = -1;
- if(pt_hypercalls_enabled()){
- nyx_debug_p(PT_PREFIX, "Error: HMP commands are ignored if kafl tracing mode is enabled (-kafl)!");
- }
- else{
- cpu->pt_cmd = cmd;
- run_on_cpu(cpu, pt_set, RUN_ON_CPU_NULL);
- }
- return cpu->pt_ret;
+static inline int pt_cmd_hmp_context(CPUState *cpu, uint64_t cmd)
+{
+ cpu->pt_ret = -1;
+ if (pt_hypercalls_enabled()) {
+ nyx_debug_p(PT_PREFIX, "Error: HMP commands are ignored if kafl tracing "
+ "mode is enabled (-kafl)!");
+ } else {
+ cpu->pt_cmd = cmd;
+ run_on_cpu(cpu, pt_set, RUN_ON_CPU_NULL);
+ }
+ return cpu->pt_ret;
}
-static int pt_cmd(CPUState *cpu, uint64_t cmd, bool hmp_mode){
- if (hmp_mode){
- return pt_cmd_hmp_context(cpu, cmd);
- }
- else {
- cpu->pt_cmd = cmd;
- pt_pre_kvm_run(cpu);
- return cpu->pt_ret;
- }
+static int pt_cmd(CPUState *cpu, uint64_t cmd, bool hmp_mode)
+{
+ if (hmp_mode) {
+ return pt_cmd_hmp_context(cpu, cmd);
+ } else {
+ cpu->pt_cmd = cmd;
+ pt_pre_kvm_run(cpu);
+ return cpu->pt_ret;
+ }
}
-static inline int pt_ioctl(int fd, unsigned long request, unsigned long arg){
- if (!fd){
- return -EINVAL;
- }
- return ioctl(fd, request, arg);
+static inline int pt_ioctl(int fd, unsigned long request, unsigned long arg)
+{
+ if (!fd) {
+ return -EINVAL;
+ }
+ return ioctl(fd, request, arg);
}
-void pt_dump(CPUState *cpu, int 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;
- 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){
- case decoder_success:
- break;
- case decoder_success_pt_overflow:
- cpu->intel_pt_run_trashed = true;
- break;
- case decoder_page_fault:
- //fprintf(stderr, "Page not found => 0x%lx\n", libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder));
- GET_GLOBAL_STATE()->decoder_page_fault = true;
- GET_GLOBAL_STATE()->decoder_page_fault_addr = libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder);
- break;
- case decoder_unkown_packet:
- fprintf(stderr, "WARNING: libxdc_decode returned unknown_packet\n");
- break;
- case decoder_error:
- fprintf(stderr, "WARNING: libxdc_decode returned decoder_error\n");
- break;
- }
- }
- }
+void pt_dump(CPUState *cpu, int 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;
+ 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) {
+ case decoder_success:
+ break;
+ case decoder_success_pt_overflow:
+ cpu->intel_pt_run_trashed = true;
+ break;
+ case decoder_page_fault:
+ // fprintf(stderr, "Page not found => 0x%lx\n", libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder));
+ GET_GLOBAL_STATE()->decoder_page_fault = true;
+ GET_GLOBAL_STATE()->decoder_page_fault_addr =
+ libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder);
+ break;
+ case decoder_unkown_packet:
+ fprintf(stderr, "WARNING: libxdc_decode returned unknown_packet\n");
+ break;
+ case decoder_error:
+ fprintf(stderr, "WARNING: libxdc_decode returned decoder_error\n");
+ break;
+ }
+ }
+ }
}
-int pt_enable(CPUState *cpu, bool hmp_mode){
- if(!fast_reload_set_bitmap(get_fast_reload_snapshot())){
- coverage_bitmap_reset();
- }
- if (GET_GLOBAL_STATE()->trace_mode) {
- redqueen_trace_reset();
- alt_bitmap_reset();
- }
- pt_truncate_pt_dump_file();
- return pt_cmd(cpu, KVM_VMX_PT_ENABLE, hmp_mode);
-}
-
-int pt_disable(CPUState *cpu, bool hmp_mode){
- int r = pt_cmd(cpu, KVM_VMX_PT_DISABLE, hmp_mode);
- return r;
+int pt_enable(CPUState *cpu, bool hmp_mode)
+{
+ if (!fast_reload_set_bitmap(get_fast_reload_snapshot())) {
+ coverage_bitmap_reset();
+ }
+ if (GET_GLOBAL_STATE()->trace_mode) {
+ redqueen_trace_reset();
+ alt_bitmap_reset();
+ }
+ pt_truncate_pt_dump_file();
+ return pt_cmd(cpu, KVM_VMX_PT_ENABLE, hmp_mode);
}
-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
- }
-
- if (cpu->pt_enabled){
- return -EINVAL;
- }
- if (GET_GLOBAL_STATE()->pt_c3_filter && GET_GLOBAL_STATE()->pt_c3_filter != val){
- //nyx_debug_p(PT_PREFIX, "Reconfigure CR3-Filtering!");
- GET_GLOBAL_STATE()->pt_c3_filter = val;
- r += pt_cmd(cpu, KVM_VMX_PT_CONFIGURE_CR3, hmp_mode);
- r += pt_cmd(cpu, KVM_VMX_PT_ENABLE_CR3, hmp_mode);
- return r;
- }
- GET_GLOBAL_STATE()->pt_c3_filter = val;
- r += pt_cmd(cpu, KVM_VMX_PT_CONFIGURE_CR3, hmp_mode);
- r += pt_cmd(cpu, KVM_VMX_PT_ENABLE_CR3, hmp_mode);
- return r;
+int pt_disable(CPUState *cpu, bool hmp_mode)
+{
+ int r = pt_cmd(cpu, KVM_VMX_PT_DISABLE, hmp_mode);
+ return r;
}
-int pt_enable_ip_filtering(CPUState *cpu, uint8_t addrn, bool redqueen, bool hmp_mode){
- int r = 0;
+int pt_set_cr3(CPUState *cpu, uint64_t val, bool hmp_mode)
+{
+ int r = 0;
- if(addrn > 3){
- return -1;
- }
+ if (val == GET_GLOBAL_STATE()->pt_c3_filter) {
+ return 0; // nothing changed
+ }
- if (cpu->pt_enabled){
- return -EINVAL;
- }
-
- if(GET_GLOBAL_STATE()->pt_ip_filter_a[addrn] > GET_GLOBAL_STATE()->pt_ip_filter_b[addrn]){
- nyx_debug_p(PT_PREFIX, "Error (ip_a > ip_b) 0x%lx-0x%lx", GET_GLOBAL_STATE()->pt_ip_filter_a[addrn] , GET_GLOBAL_STATE()->pt_ip_filter_b[addrn]);
- return -EINVAL;
- }
-
- if(GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn]){
- pt_disable_ip_filtering(cpu, addrn, hmp_mode);
- }
-
- nyx_debug_p(PT_PREFIX, "Configuring new trace region (addr%d, 0x%lx-0x%lx)", addrn, GET_GLOBAL_STATE()->pt_ip_filter_a[addrn] , GET_GLOBAL_STATE()->pt_ip_filter_b[addrn]);
-
- if(GET_GLOBAL_STATE()->pt_ip_filter_configured[addrn] && GET_GLOBAL_STATE()->pt_ip_filter_a[addrn] != 0 && GET_GLOBAL_STATE()->pt_ip_filter_b[addrn] != 0){
- r += pt_cmd(cpu, KVM_VMX_PT_CONFIGURE_ADDR0+addrn, hmp_mode);
- r += pt_cmd(cpu, KVM_VMX_PT_ENABLE_ADDR0+addrn, hmp_mode);
- GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn] = true;
- }
- return r;
+ if (cpu->pt_enabled) {
+ return -EINVAL;
+ }
+ if (GET_GLOBAL_STATE()->pt_c3_filter && GET_GLOBAL_STATE()->pt_c3_filter != val) {
+ // nyx_debug_p(PT_PREFIX, "Reconfigure CR3-Filtering!");
+ GET_GLOBAL_STATE()->pt_c3_filter = val;
+ r += pt_cmd(cpu, KVM_VMX_PT_CONFIGURE_CR3, hmp_mode);
+ r += pt_cmd(cpu, KVM_VMX_PT_ENABLE_CR3, hmp_mode);
+ return r;
+ }
+ GET_GLOBAL_STATE()->pt_c3_filter = val;
+ r += pt_cmd(cpu, KVM_VMX_PT_CONFIGURE_CR3, hmp_mode);
+ r += pt_cmd(cpu, KVM_VMX_PT_ENABLE_CR3, hmp_mode);
+ return r;
}
-void pt_init_decoder(CPUState *cpu){
- uint64_t filters[4][2] = {0};
+int pt_enable_ip_filtering(CPUState *cpu, uint8_t addrn, bool redqueen, bool hmp_mode)
+{
+ int r = 0;
- /* 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];
- filters[1][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[1];
- filters[2][0] = GET_GLOBAL_STATE()->pt_ip_filter_a[2];
- filters[2][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[2];
- filters[3][0] = GET_GLOBAL_STATE()->pt_ip_filter_a[3];
- filters[3][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[3];
+ if (addrn > 3) {
+ return -1;
+ }
- assert(GET_GLOBAL_STATE()->decoder == NULL);
- assert(GET_GLOBAL_STATE()->shared_bitmap_ptr != NULL);
- assert(GET_GLOBAL_STATE()->shared_bitmap_size != 0);
- GET_GLOBAL_STATE()->decoder = libxdc_init(filters, (void* (*)(void*, uint64_t, bool*))page_cache_fetch2, GET_GLOBAL_STATE()->page_cache, GET_GLOBAL_STATE()->shared_bitmap_ptr, GET_GLOBAL_STATE()->shared_bitmap_size);
+ if (cpu->pt_enabled) {
+ return -EINVAL;
+ }
- libxdc_register_bb_callback(GET_GLOBAL_STATE()->decoder, (void (*)(void*, disassembler_mode_t, uint64_t, uint64_t))redqueen_callback, GET_GLOBAL_STATE()->redqueen_state);
+ if (GET_GLOBAL_STATE()->pt_ip_filter_a[addrn] >
+ GET_GLOBAL_STATE()->pt_ip_filter_b[addrn])
+ {
+ nyx_debug_p(PT_PREFIX, "Error (ip_a > ip_b) 0x%lx-0x%lx",
+ GET_GLOBAL_STATE()->pt_ip_filter_a[addrn],
+ GET_GLOBAL_STATE()->pt_ip_filter_b[addrn]);
+ return -EINVAL;
+ }
- alt_bitmap_init(
- GET_GLOBAL_STATE()->shared_bitmap_ptr,
- GET_GLOBAL_STATE()->shared_bitmap_size);
+ if (GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn]) {
+ pt_disable_ip_filtering(cpu, addrn, hmp_mode);
+ }
+
+ nyx_debug_p(PT_PREFIX, "Configuring new trace region (addr%d, 0x%lx-0x%lx)",
+ addrn, GET_GLOBAL_STATE()->pt_ip_filter_a[addrn],
+ GET_GLOBAL_STATE()->pt_ip_filter_b[addrn]);
+
+ if (GET_GLOBAL_STATE()->pt_ip_filter_configured[addrn] &&
+ GET_GLOBAL_STATE()->pt_ip_filter_a[addrn] != 0 &&
+ GET_GLOBAL_STATE()->pt_ip_filter_b[addrn] != 0)
+ {
+ r += pt_cmd(cpu, KVM_VMX_PT_CONFIGURE_ADDR0 + addrn, hmp_mode);
+ r += pt_cmd(cpu, KVM_VMX_PT_ENABLE_ADDR0 + addrn, hmp_mode);
+ GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn] = true;
+ }
+ return r;
}
-int pt_disable_ip_filtering(CPUState *cpu, uint8_t addrn, bool hmp_mode){
- int r = 0;
- switch(addrn){
- case 0:
- case 1:
- case 2:
- case 3:
- r = pt_cmd(cpu, KVM_VMX_PT_DISABLE_ADDR0+addrn, hmp_mode);
- if(GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn]){
- GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn] = false;
- }
- break;
- default:
- r = -EINVAL;
- }
- return r;
+void pt_init_decoder(CPUState *cpu)
+{
+ uint64_t filters[4][2] = { 0 };
+
+ /* 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];
+ filters[1][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[1];
+ filters[2][0] = GET_GLOBAL_STATE()->pt_ip_filter_a[2];
+ filters[2][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[2];
+ filters[3][0] = GET_GLOBAL_STATE()->pt_ip_filter_a[3];
+ filters[3][1] = GET_GLOBAL_STATE()->pt_ip_filter_b[3];
+
+ assert(GET_GLOBAL_STATE()->decoder == NULL);
+ assert(GET_GLOBAL_STATE()->shared_bitmap_ptr != NULL);
+ assert(GET_GLOBAL_STATE()->shared_bitmap_size != 0);
+ GET_GLOBAL_STATE()->decoder =
+ libxdc_init(filters, (void *(*)(void *, uint64_t, bool *))page_cache_fetch2,
+ GET_GLOBAL_STATE()->page_cache,
+ GET_GLOBAL_STATE()->shared_bitmap_ptr,
+ GET_GLOBAL_STATE()->shared_bitmap_size);
+
+ libxdc_register_bb_callback(GET_GLOBAL_STATE()->decoder,
+ (void (*)(void *, disassembler_mode_t, uint64_t,
+ uint64_t))redqueen_callback,
+ GET_GLOBAL_STATE()->redqueen_state);
+
+ alt_bitmap_init(GET_GLOBAL_STATE()->shared_bitmap_ptr,
+ GET_GLOBAL_STATE()->shared_bitmap_size);
}
-void pt_kvm_init(CPUState *cpu){
- cpu->pt_cmd = 0;
- cpu->pt_enabled = false;
- cpu->pt_fd = 0;
+int pt_disable_ip_filtering(CPUState *cpu, uint8_t addrn, bool hmp_mode)
+{
+ int r = 0;
+ switch (addrn) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ r = pt_cmd(cpu, KVM_VMX_PT_DISABLE_ADDR0 + addrn, hmp_mode);
+ if (GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn]) {
+ GET_GLOBAL_STATE()->pt_ip_filter_enabled[addrn] = false;
+ }
+ break;
+ default:
+ r = -EINVAL;
+ }
+ return r;
+}
- cpu->pt_decoder_state = NULL;
+void pt_kvm_init(CPUState *cpu)
+{
+ cpu->pt_cmd = 0;
+ cpu->pt_enabled = false;
+ cpu->pt_fd = 0;
- cpu->reload_pending = false;
- cpu->intel_pt_run_trashed = false;
+ cpu->pt_decoder_state = NULL;
+
+ cpu->reload_pending = false;
+ cpu->intel_pt_run_trashed = false;
}
struct vmx_pt_filter_iprs {
- __u64 a;
- __u64 b;
+ __u64 a;
+ __u64 b;
};
pthread_mutex_t pt_dump_mutex = PTHREAD_MUTEX_INITIALIZER;
-void pt_pre_kvm_run(CPUState *cpu){
- pthread_mutex_lock(&pt_dump_mutex);
- int ret;
- struct vmx_pt_filter_iprs filter_iprs;
+void pt_pre_kvm_run(CPUState *cpu)
+{
+ pthread_mutex_lock(&pt_dump_mutex);
+ int ret;
+ struct vmx_pt_filter_iprs filter_iprs;
- if(GET_GLOBAL_STATE()->patches_disable_pending){
- //nyx_debug_p(REDQUEEN_PREFIX, "patches disable");
- assert(false); /* remove this branch */
- GET_GLOBAL_STATE()->patches_disable_pending = false;
- }
+ if (GET_GLOBAL_STATE()->patches_disable_pending) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "patches disable");
+ assert(false); /* remove this branch */
+ GET_GLOBAL_STATE()->patches_disable_pending = false;
+ }
- if(GET_GLOBAL_STATE()->patches_enable_pending){
- //nyx_debug_p(REDQUEEN_PREFIX, "patches enable");
- assert(false); /* remove this branch */
- GET_GLOBAL_STATE()->patches_enable_pending = false;
- }
+ if (GET_GLOBAL_STATE()->patches_enable_pending) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "patches enable");
+ assert(false); /* remove this branch */
+ GET_GLOBAL_STATE()->patches_enable_pending = false;
+ }
- 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);
- }
- GET_GLOBAL_STATE()->redqueen_enable_pending = false;
- }
+ 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);
+ }
+ GET_GLOBAL_STATE()->redqueen_enable_pending = false;
+ }
- 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);
- }
- GET_GLOBAL_STATE()->redqueen_disable_pending = false;
- }
+ 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);
+ }
+ GET_GLOBAL_STATE()->redqueen_disable_pending = false;
+ }
- 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);
- assert(cpu->pt_fd != -1);
- ret = ioctl(cpu->pt_fd, KVM_VMX_PT_GET_TOPA_SIZE, (unsigned long)0x0);
-
- 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);
- // add an extra page to have enough space for an additional PT_TRACE_END byte
+ 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);
+ assert(cpu->pt_fd != -1);
+ ret = ioctl(cpu->pt_fd, KVM_VMX_PT_GET_TOPA_SIZE, (unsigned long)0x0);
+
+ 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);
+ // 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);
- }
-
- if (cpu->pt_cmd){
- switch(cpu->pt_cmd){
- case KVM_VMX_PT_ENABLE:
- 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);
+ memset(cpu->pt_mmap + ret, 0x55, 0x1000);
+ }
- if (!ioctl(cpu->pt_fd, cpu->pt_cmd, 0)){
- cpu->pt_enabled = true;
- }
- }
- break;
- case KVM_VMX_PT_DISABLE:
- if (cpu->pt_fd){
- ret = ioctl(cpu->pt_fd, cpu->pt_cmd, 0);
- if (ret > 0){
- //nyx_debug_p(PT_PREFIX, "KVM_VMX_PT_DISABLE %d", ret);
- pt_dump(cpu, ret);
- cpu->pt_enabled = false;
- }
- }
- break;
-
- /* ip filtering configuration */
- case KVM_VMX_PT_CONFIGURE_ADDR0:
- case KVM_VMX_PT_CONFIGURE_ADDR1:
- case KVM_VMX_PT_CONFIGURE_ADDR2:
- case KVM_VMX_PT_CONFIGURE_ADDR3:
- filter_iprs.a = GET_GLOBAL_STATE()->pt_ip_filter_a[(cpu->pt_cmd)-KVM_VMX_PT_CONFIGURE_ADDR0];
- filter_iprs.b = GET_GLOBAL_STATE()->pt_ip_filter_b[(cpu->pt_cmd)-KVM_VMX_PT_CONFIGURE_ADDR0];
- ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)&filter_iprs);
- break;
- case KVM_VMX_PT_ENABLE_ADDR0:
- case KVM_VMX_PT_ENABLE_ADDR1:
- case KVM_VMX_PT_ENABLE_ADDR2:
- case KVM_VMX_PT_ENABLE_ADDR3:
- ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)0);
- break;
- case KVM_VMX_PT_CONFIGURE_CR3:
- ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, GET_GLOBAL_STATE()->pt_c3_filter);
- break;
- case KVM_VMX_PT_ENABLE_CR3:
- ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)0);
- break;
- default:
- if (cpu->pt_fd){
- ioctl(cpu->pt_fd, cpu->pt_cmd, 0);
- }
- break;
- }
- cpu->pt_cmd = 0;
- cpu->pt_ret = 0;
- }
- }
- pthread_mutex_unlock(&pt_dump_mutex);
+ if (cpu->pt_cmd) {
+ switch (cpu->pt_cmd) {
+ case KVM_VMX_PT_ENABLE:
+ 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);
+
+ if (!ioctl(cpu->pt_fd, cpu->pt_cmd, 0)) {
+ cpu->pt_enabled = true;
+ }
+ }
+ break;
+ case KVM_VMX_PT_DISABLE:
+ if (cpu->pt_fd) {
+ ret = ioctl(cpu->pt_fd, cpu->pt_cmd, 0);
+ if (ret > 0) {
+ // nyx_debug_p(PT_PREFIX, "KVM_VMX_PT_DISABLE %d", ret);
+ pt_dump(cpu, ret);
+ cpu->pt_enabled = false;
+ }
+ }
+ break;
+
+ /* ip filtering configuration */
+ case KVM_VMX_PT_CONFIGURE_ADDR0:
+ case KVM_VMX_PT_CONFIGURE_ADDR1:
+ case KVM_VMX_PT_CONFIGURE_ADDR2:
+ case KVM_VMX_PT_CONFIGURE_ADDR3:
+ filter_iprs.a =
+ GET_GLOBAL_STATE()
+ ->pt_ip_filter_a[(cpu->pt_cmd) - KVM_VMX_PT_CONFIGURE_ADDR0];
+ filter_iprs.b =
+ GET_GLOBAL_STATE()
+ ->pt_ip_filter_b[(cpu->pt_cmd) - KVM_VMX_PT_CONFIGURE_ADDR0];
+ ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)&filter_iprs);
+ break;
+ case KVM_VMX_PT_ENABLE_ADDR0:
+ case KVM_VMX_PT_ENABLE_ADDR1:
+ case KVM_VMX_PT_ENABLE_ADDR2:
+ case KVM_VMX_PT_ENABLE_ADDR3:
+ ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)0);
+ break;
+ case KVM_VMX_PT_CONFIGURE_CR3:
+ ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd,
+ GET_GLOBAL_STATE()->pt_c3_filter);
+ break;
+ case KVM_VMX_PT_ENABLE_CR3:
+ ret = pt_ioctl(cpu->pt_fd, cpu->pt_cmd, (unsigned long)0);
+ break;
+ default:
+ if (cpu->pt_fd) {
+ ioctl(cpu->pt_fd, cpu->pt_cmd, 0);
+ }
+ break;
+ }
+ cpu->pt_cmd = 0;
+ cpu->pt_ret = 0;
+ }
+ }
+ pthread_mutex_unlock(&pt_dump_mutex);
}
-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){
- pt_dump(cpu, overflow);
- }
- pthread_mutex_unlock(&pt_dump_mutex);
+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) {
+ pt_dump(cpu, overflow);
+ }
+ 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){
- pt_handle_overflow(cpu);
- }
+void pt_post_kvm_run(CPUState *cpu)
+{
+ if (GET_GLOBAL_STATE()->pt_trace_mode || GET_GLOBAL_STATE()->pt_trace_mode_force)
+ {
+ pt_handle_overflow(cpu);
+ }
}
diff --git a/nyx/pt.h b/nyx/pt.h
index 66c1678e2b..b69acfec42 100644
--- a/nyx/pt.h
+++ b/nyx/pt.h
@@ -38,4 +38,3 @@ void pt_handle_overflow(CPUState *cpu);
void pt_dump(CPUState *cpu, int bytes);
#endif
-
diff --git a/nyx/redqueen.c b/nyx/redqueen.c
index 7224049a89..f785a4d745 100644
--- a/nyx/redqueen.c
+++ b/nyx/redqueen.c
@@ -26,834 +26,1167 @@ along with QEMU-PT. If not, see .
#include
#include
-#include "nyx/redqueen.h"
#include "debug.h"
#include "file_helper.h"
#include "nyx/interface.h"
#include "nyx/memory_access.h"
+#include "nyx/redqueen.h"
#include "nyx/state/state.h"
#include "patcher.h"
#include "redqueen_trace.h"
-redqueen_workdir_t redqueen_workdir = {0};
+redqueen_workdir_t redqueen_workdir = { 0 };
-void setup_redqueen_workdir(char* workdir){
- assert(asprintf(&redqueen_workdir.redqueen_results,"%s/redqueen_results.txt", workdir)>0);
- assert(asprintf(&redqueen_workdir.symbolic_results,"%s/symbolic_results.txt", workdir)>0);
- assert(asprintf(&redqueen_workdir.pt_trace_results,"%s/pt_trace_results.txt", workdir)>0);
- assert(asprintf(&redqueen_workdir.redqueen_patches,"%s/redqueen_patches.txt", workdir)>0);
- assert(asprintf(&redqueen_workdir.breakpoint_white,"%s/breakpoint_white.txt", workdir)>0);
- assert(asprintf(&redqueen_workdir.breakpoint_black,"%s/breakpoint_black.txt", workdir)>0);
- assert(asprintf(&redqueen_workdir.target_code_dump,"%s/target_code_dump.img", workdir)>0);
+void setup_redqueen_workdir(char *workdir)
+{
+ assert(asprintf(&redqueen_workdir.redqueen_results, "%s/redqueen_results.txt",
+ workdir) > 0);
+ assert(asprintf(&redqueen_workdir.symbolic_results, "%s/symbolic_results.txt",
+ workdir) > 0);
+ assert(asprintf(&redqueen_workdir.pt_trace_results, "%s/pt_trace_results.txt",
+ workdir) > 0);
+ assert(asprintf(&redqueen_workdir.redqueen_patches, "%s/redqueen_patches.txt",
+ workdir) > 0);
+ assert(asprintf(&redqueen_workdir.breakpoint_white, "%s/breakpoint_white.txt",
+ workdir) > 0);
+ assert(asprintf(&redqueen_workdir.breakpoint_black, "%s/breakpoint_black.txt",
+ workdir) > 0);
+ assert(asprintf(&redqueen_workdir.target_code_dump, "%s/target_code_dump.img",
+ workdir) > 0);
}
-redqueen_t* new_rq_state(CPUState *cpu, page_cache_t* page_cache){
- redqueen_t* res = malloc(sizeof(redqueen_t));
+redqueen_t *new_rq_state(CPUState *cpu, page_cache_t *page_cache)
+{
+ redqueen_t *res = malloc(sizeof(redqueen_t));
- res->cpu = cpu;
- res->intercept_mode = false;
- res->singlestep_enabled = false;
- res->hooks_applied = 0;
- res->page_cache = page_cache;
+ res->cpu = cpu;
+ res->intercept_mode = false;
+ res->singlestep_enabled = false;
+ res->hooks_applied = 0;
+ res->page_cache = page_cache;
- res->lookup = kh_init(RQ);
- res->last_rip = 0x0;
- res->next_rip = 0x0;
- res->num_breakpoint_whitelist=0;
- res->breakpoint_whitelist=NULL;
+ res->lookup = kh_init(RQ);
+ res->last_rip = 0x0;
+ res->next_rip = 0x0;
+ res->num_breakpoint_whitelist = 0;
+ res->breakpoint_whitelist = NULL;
- res->trace_state=redqueen_trace_new();
+ res->trace_state = redqueen_trace_new();
- return res;
+ return res;
}
-static bool is_interessting_lea_at(redqueen_t* self, cs_insn *ins){
- bool res = false;
+static bool is_interessting_lea_at(redqueen_t *self, cs_insn *ins)
+{
+ bool res = false;
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
- assert(x86->op_count == 2);
- cs_x86_op *op2 = &(x86->operands[1]);
+ assert(x86->op_count == 2);
+ cs_x86_op *op2 = &(x86->operands[1]);
- assert(op2->type == X86_OP_MEM);
-
- x86_reg reg = op2->mem.index;
- int64_t disp = (int64_t)op2->mem.disp;
- res = disp < 0 && (-disp) > 0xff && op2->mem.scale == 1 && op2->mem.base == X86_REG_INVALID && reg != X86_REG_INVALID;
+ assert(op2->type == X86_OP_MEM);
- if(res){
- x86_reg reg = op2->mem.index;
- if(reg == X86_REG_EIP || reg == X86_REG_RIP || reg == X86_REG_EBP || reg == X86_REG_RBP){
- //nyx_debug_p(REDQUEEN_PREFIX, "got boring index");
- res = false;
- } //don't instrument local stack offset computations
- }
- return res;
-}
+ x86_reg reg = op2->mem.index;
+ int64_t disp = (int64_t)op2->mem.disp;
+ res = disp < 0 && (-disp) > 0xff && op2->mem.scale == 1 &&
+ op2->mem.base == X86_REG_INVALID && reg != X86_REG_INVALID;
-static bool uses_register(cs_x86_op* op, x86_reg reg){
-
- if (op->type == X86_OP_REG && op->reg == reg){
- return true;
- }
-
- if (op->type == X86_OP_MEM && op->mem.base == reg){
- return true;
- }
-
- return false;
-}
-
-static bool uses_stack_access(cs_x86_op* op){
- if (uses_register(op, X86_REG_RBP) || uses_register(op, X86_REG_EBP)){
- return true;
- }
-
- if (uses_register(op, X86_REG_RSP) || uses_register(op, X86_REG_ESP)){
- return true;
- }
-
- return false;
-}
-
-static bool is_interessting_add_at(redqueen_t* self, cs_insn *ins){
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
-
- assert(x86->op_count == 2);
- cs_x86_op *op1 = &(x86->operands[0]);
- cs_x86_op *op2 = &(x86->operands[1]);
-
- if(op2->type == X86_OP_IMM && (op1->type == X86_OP_REG || op1->type == X86_OP_MEM)){
- //offsets needs to be negative, < -0xff to ensure we only look at multi byte substractions
- if((op2->imm > 0x7fff && (((op2->imm>>8)&0xff) != 0xff))){
- if (!uses_stack_access(op1)){
- return true;
- }
- }
- }
- return false;
-}
-
-static bool is_interessting_sub_at(redqueen_t* self, cs_insn *ins){
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
-
- assert(x86->op_count == 2);
- cs_x86_op *op1 = &(x86->operands[0]);
- cs_x86_op *op2 = &(x86->operands[1]);
-
- if(op2->type == X86_OP_IMM && (op1->type == X86_OP_REG || op1->type == X86_OP_MEM)){
- if(op2->imm > 0xFF){
- if (!uses_stack_access(op1)){
- return true;
- }
- }
- }
- return false;
-}
-
-static bool is_interessting_xor_at(redqueen_t* self, cs_insn *ins){
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
-
- assert(x86->op_count == 2);
- cs_x86_op *op1 = &(x86->operands[0]);
- cs_x86_op *op2 = &(x86->operands[1]);
-
- if(op1->type == X86_OP_REG && op2->type == X86_OP_REG){
- if(op1->reg != op2->reg){
- return true;
- }
- }
- return false;
-}
-
-static void opcode_analyzer(redqueen_t* self, cs_insn *ins){
- //uint8_t i, j;
- //cs_x86 details = ins->detail->x86;
- //printf("SELF %p\n", self->redqueen_state);
- //printf("INS %lx\n", ins->address);
- if(ins->id == X86_INS_CMP){
- set_rq_instruction(self, ins->address);
- //nyx_debug_p(REDQUEEN_PREFIX, "hooking cmp %lx %s %s", ins->address, ins->mnemonic, ins->op_str);
- }
- if(ins->id == X86_INS_LEA && is_interessting_lea_at(self, ins)){
- //nyx_debug_p(REDQUEEN_PREFIX, "hooking lea %lx", ins->address);
- set_rq_instruction(self, ins->address);
- }
- if(ins->id == X86_INS_SUB && is_interessting_sub_at(self, ins)){
- //nyx_debug_p(REDQUEEN_PREFIX, "hooking sub %lx", ins->address);
- set_rq_instruction(self, ins->address);
- }
- if(ins->id == X86_INS_ADD && is_interessting_add_at(self, ins)){
- //nyx_debug_p(REDQUEEN_PREFIX, "hooking add %lx", ins->address);
- set_rq_instruction(self, ins->address);
- }
- if(ins->id == X86_INS_XOR && is_interessting_xor_at(self, ins)){
- //nyx_debug_p(REDQUEEN_PREFIX, "hooking xor %lx %s %s", ins->address, ins->mnemonic, ins->op_str);
- set_rq_instruction(self, ins->address);
- }
- if(ins->id ==X86_INS_CALL || ins->id == X86_INS_LCALL){
- //nyx_debug_p(REDQUEEN_PREFIX, "hooking call %lx %s %s", ins->address, ins->mnemonic, ins->op_str);
- set_rq_instruction(self, ins->address);
- }
-}
-
-void redqueen_callback(void* opaque, disassembler_mode_t mode, uint64_t start_addr, uint64_t end_addr){
- GET_GLOBAL_STATE()->bb_coverage++;
- redqueen_t* self = (redqueen_t*) opaque;
-
- if(start_addr != end_addr){
- uint64_t failed_page = 0;
- uint64_t code = start_addr;
-
- cs_insn *insn = page_cache_cs_malloc(self->page_cache, mode);
-
- while(page_cache_disassemble_iter(self->page_cache, &code, insn, &failed_page, mode)){
- if (insn->address > end_addr){
- break;
- }
- opcode_analyzer(self, insn);
+ if (res) {
+ x86_reg reg = op2->mem.index;
+ if (reg == X86_REG_EIP || reg == X86_REG_RIP || reg == X86_REG_EBP ||
+ reg == X86_REG_RBP)
+ {
+ // nyx_debug_p(REDQUEEN_PREFIX, "got boring index");
+ res = false;
+ } // don't instrument local stack offset computations
}
- cs_free(insn, 1);
- }
+ return res;
}
-void destroy_rq_state(redqueen_t* self){
- redqueen_trace_free(self->trace_state);
- kh_destroy(RQ, self->lookup);
- free(self);
-}
+static bool uses_register(cs_x86_op *op, x86_reg reg)
+{
+ if (op->type == X86_OP_REG && op->reg == reg) {
+ return true;
+ }
-static void redqueen_set_addr_flags(redqueen_t* self, uint64_t addr, uint32_t flags){
- int unused = 0;
+ if (op->type == X86_OP_MEM && op->mem.base == reg) {
+ return true;
+ }
- khiter_t k = kh_get(RQ, self->lookup, addr);
- if(k == kh_end(self->lookup)){
- k = kh_put(RQ, self->lookup, addr, &unused);
- kh_value(self->lookup, k) = 0;
- }
- kh_value(self->lookup, k) |= flags;
-}
-
-static bool redqueen_check_addr_flags(redqueen_t* self, uint64_t addr, uint32_t flags){
- khiter_t k = kh_get(RQ, self->lookup, addr);
- if(k != kh_end(self->lookup)){
- return !!(kh_value(self->lookup, k) & flags);
- }
- else{
- return false;
- }
-}
-
-static bool redqueen_check_addr(redqueen_t* self, uint64_t addr){
- khiter_t k = kh_get(RQ, self->lookup, addr);
- if(k != kh_end(self->lookup)){
- return true;
- }
- else{
- return false;
- }
-}
-
-static uint32_t redqueen_update_addr_count(redqueen_t* self, uint64_t addr){
- int unused __attribute__((unused));
- uint32_t value = 0;
- khiter_t k = kh_get(RQ, self->lookup, addr);
- if(k != kh_end(self->lookup)){
- value = kh_value(self->lookup, k);
- }
- else{
- k = kh_put(RQ, self->lookup, addr, &unused);
- }
- value++;
- kh_value(self->lookup, k) = value;
- return value & 0xFF000000UL;
-}
-
-void set_rq_instruction(redqueen_t* self, uint64_t addr){
- if( !redqueen_check_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED)){
- redqueen_set_addr_flags(self, addr, CMP_BITMAP_RQ_INSTRUCTION);
- }
-}
-
-void set_rq_blacklist(redqueen_t* self, uint64_t addr){
- redqueen_set_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED);
-}
-
-static void insert_hooks_whitelist(redqueen_t* self){
- for(size_t i = 0; i < self->num_breakpoint_whitelist; i++){
- insert_breakpoint(self->cpu, self->breakpoint_whitelist[i], 1);
- }
-}
-
-static void insert_hooks_bitmap(redqueen_t* self){
- uint64_t c = 0;
- uint64_t addr;
- uint32_t value __attribute__((unused));
- uint32_t mode = GET_GLOBAL_STATE()->redqueen_instrumentation_mode;
-
- kh_foreach(self->lookup, addr, value, {
- if(redqueen_check_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED)){ continue; }
-
- bool should_hook_rq = (mode == REDQUEEN_LIGHT_INSTRUMENTATION ) && redqueen_check_addr_flags(self, addr, CMP_BITMAP_SHOULD_HOOK_RQ);
-
- if( should_hook_rq ){
- insert_breakpoint(self->cpu, addr, 1);
- c++;
- }
- });
-}
-
-void redqueen_insert_hooks(redqueen_t* self){
-
- nyx_debug_p(REDQUEEN_PREFIX, "insert hooks");
- assert(!self->hooks_applied);
- switch(GET_GLOBAL_STATE()->redqueen_instrumentation_mode){
- case(REDQUEEN_LIGHT_INSTRUMENTATION):
- insert_hooks_bitmap(self);
- break;
- case(REDQUEEN_WHITELIST_INSTRUMENTATION):
- insert_hooks_whitelist(self);
- break;
- case(REDQUEEN_NO_INSTRUMENTATION):
- break;
- default:
- assert(false);
- }
- self->hooks_applied = 1;
-}
-
-void redqueen_remove_hooks(redqueen_t* self){
- nyx_debug_p(REDQUEEN_PREFIX, "remove hooks");
- assert(self->hooks_applied);
- remove_all_breakpoints(self->cpu);
-
- for (khiter_t i = kh_begin(self->lookup); i != kh_end(self->lookup); ++i) {
- if (!kh_exist(self->lookup,i)) continue;
- kh_val(self->lookup,i) &= 0xFF000000UL;
- }
- self->hooks_applied = 0;
- return;
-}
-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;
- case X86_REG_CS: return env->segs[R_CS].base;
- case X86_REG_DS: return env->segs[R_DS].base;
- case X86_REG_SS: return env->segs[R_SS].base;
- default:
- break;
- }
- assert(false);
-}
-
-static inline uint64_t sign_extend_from_size(uint64_t value, uint8_t size){
- switch(size){
- case 64: return value;
- case 32: return ((int32_t)(value)<0) ? 0xffffffff00000000 | value : value;
- case 16: return ((int16_t)(value)<0) ? 0xffffffffffff0000 | value : value;
- case 8: return (( int8_t)(value)<0) ? 0xffffffffffffff00 | value : value;
- }
- assert(false);
-}
-
-static uint64_t eval_reg(x86_reg reg, uint8_t *size){
- uint64_t value = 0;
- CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
-
- switch(reg) {
- case X86_REG_RAX: value=env->regs[RAX]; *size=64; break;
- case X86_REG_RCX: value=env->regs[RCX]; *size=64; break;
- case X86_REG_RDX: value=env->regs[RDX]; *size=64; break;
- case X86_REG_RBX: value=env->regs[RBX]; *size=64; break;
- case X86_REG_RSP: value=env->regs[RSP]; *size=64; break;
- case X86_REG_RBP: value=env->regs[RBP]; *size=64; break;
- case X86_REG_RSI: value=env->regs[RSI]; *size=64; break;
- case X86_REG_RDI: value=env->regs[RDI]; *size=64; break;
- case X86_REG_R8: value=env->regs[R8]; *size=64; break;
- case X86_REG_R9: value=env->regs[R9]; *size=64; break;
- case X86_REG_R10: value=env->regs[R10]; *size=64; break;
- case X86_REG_R11: value=env->regs[R11]; *size=64; break;
- case X86_REG_R12: value=env->regs[R12]; *size=64; break;
- case X86_REG_R13: value=env->regs[R13]; *size=64; break;
- case X86_REG_R14: value=env->regs[R14]; *size=64; break;
- case X86_REG_R15: value=env->regs[R15]; *size=64; break;
- case X86_REG_EAX: value=env->regs[RAX]&0xffffffff; *size=32; break;
- case X86_REG_ECX: value=env->regs[RCX]&0xffffffff; *size=32; break;
- case X86_REG_EDX: value=env->regs[RDX]&0xffffffff; *size=32; break;
- case X86_REG_EBX: value=env->regs[RBX]&0xffffffff; *size=32; break;
- case X86_REG_ESP: value=env->regs[RSP]&0xffffffff; *size=32; break;
- case X86_REG_EBP: value=env->regs[RBP]&0xffffffff; *size=32; break;
- case X86_REG_ESI: value=env->regs[RSI]&0xffffffff; *size=32; break;
- case X86_REG_EDI: value=env->regs[RDI]&0xffffffff; *size=32; break;
- case X86_REG_R8D: value=env->regs[R8]&0xffffffff; *size=32; break;
- case X86_REG_R9D: value=env->regs[R9]&0xffffffff; *size=32; break;
- case X86_REG_R10D: value=env->regs[R10]&0xffffffff; *size=32; break;
- case X86_REG_R11D: value=env->regs[R11]&0xffffffff; *size=32; break;
- case X86_REG_R12D: value=env->regs[R12]&0xffffffff; *size=32; break;
- case X86_REG_R13D: value=env->regs[R13]&0xffffffff; *size=32; break;
- case X86_REG_R14D: value=env->regs[R14]&0xffffffff; *size=32; break;
- case X86_REG_R15D: value=env->regs[R15]&0xffffffff; *size=32; break;
- case X86_REG_AX: value=env->regs[RAX]&0xffff; *size=16; break;
- case X86_REG_CX: value=env->regs[RCX]&0xffff; *size=16; break;
- case X86_REG_DX: value=env->regs[RDX]&0xffff; *size=16; break;
- case X86_REG_BX: value=env->regs[RBX]&0xffff; *size=16; break;
- case X86_REG_SP: value=env->regs[RSP]&0xffff; *size=16; break;
- case X86_REG_BP: value=env->regs[RBP]&0xffff; *size=16; break;
- case X86_REG_SI: value=env->regs[RSI]&0xffff; *size=16; break;
- case X86_REG_DI: value=env->regs[RDI]&0xffff; *size=16; break;
- case X86_REG_R8W: value=env->regs[R8]&0xffff; *size=16; break;
- case X86_REG_R9W: value=env->regs[R9]&0xffff; *size=16; break;
- case X86_REG_R10W: value=env->regs[R10]&0xffff; *size=16; break;
- case X86_REG_R11W: value=env->regs[R11]&0xffff; *size=16; break;
- case X86_REG_R12W: value=env->regs[R12]&0xffff; *size=16; break;
- case X86_REG_R13W: value=env->regs[R13]&0xffff; *size=16; break;
- case X86_REG_R14W: value=env->regs[R14]&0xffff; *size=16; break;
- case X86_REG_R15W: value=env->regs[R15]&0xffff; *size=16; break;
- case X86_REG_AL: value=env->regs[RAX]&0xff; *size=8; break;
- case X86_REG_CL: value=env->regs[RCX]&0xff; *size=8; break;
- case X86_REG_DL: value=env->regs[RDX]&0xff; *size=8; break;
- case X86_REG_BL: value=env->regs[RBX]&0xff; *size=8; break;
- case X86_REG_SPL: value=env->regs[RSP]&0xff; *size=8; break;
- case X86_REG_BPL: value=env->regs[RBP]&0xff; *size=8; break;
- case X86_REG_SIL: value=env->regs[RSI]&0xff; *size=8; break;
- case X86_REG_DIL: value=env->regs[RDI]&0xff; *size=8; break;
- case X86_REG_R8B: value=env->regs[R8]&0xff; *size=8; break;
- case X86_REG_R9B: value=env->regs[R9]&0xff; *size=8; break;
- case X86_REG_R10B: value=env->regs[R10]&0xff; *size=8; break;
- case X86_REG_R11B: value=env->regs[R11]&0xff; *size=8; break;
- case X86_REG_R12B: value=env->regs[R12]&0xff; *size=8; break;
- case X86_REG_R13B: value=env->regs[R13]&0xff; *size=8; break;
- case X86_REG_R14B: value=env->regs[R14]&0xff; *size=8; break;
- case X86_REG_R15B: value=env->regs[R15]&0xff; *size=8; break;
- case X86_REG_AH: value=(env->regs[RAX]>>8)&0xff; *size=8; break;
- case X86_REG_CH: value=(env->regs[RCX]>>8)&0xff; *size=8; break;
- case X86_REG_DH: value=(env->regs[RDX]>>8)&0xff; *size=8; break;
- case X86_REG_BH: value=(env->regs[RBX]>>8)&0xff; *size=8; break;
- case X86_REG_RIP: value=env->eip; *size=64; break;
- case X86_REG_EIP: value=env->eip&0xffffffff; *size=32; break;
- case X86_REG_IP: value=env->eip&0xfffff; *size=16; break;
- default:
- assert(false);
- }
- return value;
-}
-
-static uint64_t eval_addr(cs_x86_op* op){
- uint8_t size=0;
- uint64_t base = 0;
- uint64_t index = 0;
- uint64_t segment = 0;
-
- assert(op->type == X86_OP_MEM);
-
- if(op->mem.base != X86_REG_INVALID){
- base = eval_reg(op->mem.base, &size);
- }
- if(op->mem.index != X86_REG_INVALID){
- index = eval_reg(op->mem.index, &size);
- }
-
- if(op->mem.segment != X86_REG_INVALID){
- segment = get_segment_register(op->mem.segment);
- }
-
- uint64_t addr = segment + base + index*op->mem.scale + op->mem.disp;
- return addr;
-}
-
-static uint64_t eval_mem(cs_x86_op* op){
-
- uint64_t val = 0;
- assert(op->size == 1 || op->size == 2 || op->size == 4 || op->size == 8);
- //nyx_debug_p(REDQUEEN_PREFIX, "EVAL MEM FOR OP:");
-
- /* TODO @ sergej: replace me later */
- read_virtual_memory(eval_addr(op), (uint8_t*) &val, op->size, qemu_get_cpu(0));
- return val;
-}
-
-static uint64_t eval(cs_x86_op* op, uint8_t* size){
- switch((int)op->type) {
- case X86_OP_REG:
- return eval_reg(op->reg, size);
- case X86_OP_IMM:
- *size=0;
- return op->imm;
- case X86_OP_MEM:
- switch(op->size){
- case 1: *size =8; return eval_mem(op)&0xff;
- case 2: *size =16; return eval_mem(op)&0xffff;
- case 4: *size =32; return eval_mem(op)&0xffffffff;
- case 8: *size =64; return eval_mem(op);
- }
- }
-
- /* unreachable, dude! */
- assert(false);
- return 0;
-}
-
-static void print_comp_result(uint64_t addr, const char* type, uint64_t val1, uint64_t val2, uint8_t size, bool is_imm){
-
- 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);
- uint64_t mask = 0;
- switch(size){
- case 64: format = " 64\t%016lX-%016lX"; mask = 0xffffffffffffffff; break;
- case 32: format = " 32\t%08X-%08X"; mask = 0xffffffff; break;
- case 16: format = " 16\t%04X-%04X"; mask = 0xffff; break;
- case 8: format = " 8\t%02X-%02X"; mask = 0xff; break;
- default:
- assert(false);
- }
- pos += snprintf(result_buf+pos, 256-pos, format, val1 & mask, val2 & mask);
- if(is_imm){
- pos += snprintf(result_buf+pos, 256-pos, " IMM");
- }
- pos += snprintf(result_buf+pos, 256-pos, "\n");
- write_re_result(result_buf);
-}
-
-static void get_cmp_value(cs_insn *ins, const char* type){
- uint8_t size_1=0;
- uint8_t size_2=0;
-
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
-
- assert(x86->op_count == 2);
- cs_x86_op *op1 = &(x86->operands[0]);
- cs_x86_op *op2 = &(x86->operands[1]);
-
- uint64_t v1 = eval(op1, &size_1);
- uint64_t v2 = eval(op2, &size_2);
-
- if(GET_GLOBAL_STATE()->redqueen_instrumentation_mode == REDQUEEN_WHITELIST_INSTRUMENTATION || v1 != v2){
- print_comp_result(ins->address, type, v1, v2, (size_1 ? size_1 : size_2), op2->type == X86_OP_IMM);
- }
-}
-
-static void get_cmp_value_add(cs_insn *ins){
- uint8_t size_1=0;
- uint8_t size_2=0;
-
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
-
- assert(x86->op_count == 2);
- cs_x86_op *op1 = &(x86->operands[0]);
- cs_x86_op *op2 = &(x86->operands[1]);
-
- uint64_t v1 = eval(op1, &size_1);
- uint64_t v2 = -sign_extend_from_size(eval(op2, &size_2), size_1);
-
- if(op2->type != X86_OP_IMM){
- return;
- }
-
- if(GET_GLOBAL_STATE()->redqueen_instrumentation_mode == REDQUEEN_WHITELIST_INSTRUMENTATION || v1 != v2){
- bool is_imm = true;
- print_comp_result(ins->address, "SUB", v1, v2, size_1, is_imm);
- }
-}
-
-static void get_cmp_value_lea(cs_insn *ins){
- uint64_t index_val = 0;
-
- assert(ins);
- cs_x86 *x86 = &(ins->detail->x86);
-
- assert(x86->op_count == 2);
- cs_x86_op *op2 = &(x86->operands[1]);
-
- assert(op2->type == X86_OP_MEM);
-
- uint8_t size=0;
- if(op2->mem.base != X86_REG_INVALID && op2->mem.index != X86_REG_INVALID){
- return;
- }
-
- if(op2->mem.base == X86_REG_INVALID && op2->mem.index == X86_REG_INVALID){
- return;
- }
-
- if(op2->mem.base != X86_REG_INVALID ){
- index_val = eval_reg(op2->mem.base, &size);
- }
-
- if(op2->mem.index != X86_REG_INVALID ){
- index_val = eval_reg(op2->mem.index, &size);
- }
-
- if(GET_GLOBAL_STATE()->redqueen_instrumentation_mode == REDQUEEN_WHITELIST_INSTRUMENTATION || index_val != -op2->mem.disp){
- bool is_imm = false;
- print_comp_result(ins->address, "LEA", index_val, -op2->mem.disp, op2->size*8, is_imm);
- }
-}
-
-
-static uint64_t limit_to_word_width(uint64_t val){
- switch(GET_GLOBAL_STATE()->disassembler_word_width){
- case 64:
- return val;
- case 32:
- return val & 0xffffffff;
- default:
- assert(false);
- }
-}
-
-static uint64_t word_width_to_bytes(void){
- switch(GET_GLOBAL_STATE()->disassembler_word_width){
- case 64:
- return 8;
- case 32:
- return 4;
- default:
- assert(false);
- }
-}
-
-static uint64_t read_stack(uint64_t word_index){
- CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
- uint64_t rsp = env->regs[RSP];
- rsp = limit_to_word_width(rsp);
- uint64_t res = 0;
- uint64_t stack_ptr = rsp + word_index * word_width_to_bytes();
- /* TODO @ sergej */
- assert(read_virtual_memory(stack_ptr, (uint8_t*)(&res), 8, qemu_get_cpu(0)));
- return limit_to_word_width(res);
-}
-
-static void format_strcmp(uint8_t* buf1, uint8_t* buf2){
- char out_buf[REDQUEEN_MAX_STRCMP_LEN*4 + 2];
- char* tmp_hex_buf = &out_buf[0];
- for(int i = 0; i < REDQUEEN_MAX_STRCMP_LEN; i++){
- tmp_hex_buf += sprintf(tmp_hex_buf, "%02X", (uint8_t)buf1[i]);
- }
- *tmp_hex_buf++ = '-';
- for(int i = 0; i < REDQUEEN_MAX_STRCMP_LEN; i++){
- tmp_hex_buf += sprintf(tmp_hex_buf, "%02X", (uint8_t)buf2[i]);
- }
- char *res=0;
- CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
- uint64_t rip = env->eip;
- assert(asprintf( &res, "%lx\t\tSTR %d\t%s\n", rip, REDQUEEN_MAX_STRCMP_LEN*8, out_buf ) != -1);
- write_re_result(res);
- free(res);
-}
-
-static bool test_strchr(uint64_t arg1, uint64_t arg2){
- CPUState *cpu = qemu_get_cpu(0);
-
- /* 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 */
- 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);
- buf2[0]= (uint8_t)(arg2);
- format_strcmp(buf1, buf2);
- return true;
}
-static bool test_strcmp(uint64_t arg1, uint64_t arg2){
- CPUState *cpu = qemu_get_cpu(0);
- if(!is_addr_mapped(arg1, cpu) || ! is_addr_mapped(arg2, cpu)){
- return false;
- }
- //nyx_debug_p(REDQUEEN_PREFIX,"valid ptrs");
- uint8_t buf1[REDQUEEN_MAX_STRCMP_LEN];
- uint8_t buf2[REDQUEEN_MAX_STRCMP_LEN];
- /* 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);
- return true;
+static bool uses_stack_access(cs_x86_op *op)
+{
+ if (uses_register(op, X86_REG_RBP) || uses_register(op, X86_REG_EBP)) {
+ return true;
+ }
+
+ if (uses_register(op, X86_REG_RSP) || uses_register(op, X86_REG_ESP)) {
+ return true;
+ }
+
+ return false;
}
-static bool test_strcmp_cdecl(void){
- uint64_t arg1 = read_stack(0);
- uint64_t arg2 = read_stack(1);
- //nyx_debug_p(REDQUEEN_PREFIX, "extract call params cdecl %lx %lx", arg1, arg2);
- test_strchr(arg1, arg2);
- return test_strcmp(arg1, arg2) ;
+static bool is_interessting_add_at(redqueen_t *self, cs_insn *ins)
+{
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
+ assert(x86->op_count == 2);
+ cs_x86_op *op1 = &(x86->operands[0]);
+ cs_x86_op *op2 = &(x86->operands[1]);
+
+ if (op2->type == X86_OP_IMM && (op1->type == X86_OP_REG || op1->type == X86_OP_MEM))
+ {
+ // offsets needs to be negative, < -0xff to ensure we only look at multi byte substractions
+ if ((op2->imm > 0x7fff && (((op2->imm >> 8) & 0xff) != 0xff))) {
+ if (!uses_stack_access(op1)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
-static bool test_strcmp_fastcall(void){
- CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
- uint64_t arg1 = env->regs[RCX]; //rcx
- uint64_t arg2 = env->regs[RDX]; //rdx
- //nyx_debug_p(REDQUEEN_PREFIX, "extract call params fastcall %lx %lx", arg1, arg2);
- test_strchr(arg1, arg2);
- return test_strcmp(arg1, arg2);
+static bool is_interessting_sub_at(redqueen_t *self, cs_insn *ins)
+{
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
+
+ assert(x86->op_count == 2);
+ cs_x86_op *op1 = &(x86->operands[0]);
+ cs_x86_op *op2 = &(x86->operands[1]);
+
+ if (op2->type == X86_OP_IMM && (op1->type == X86_OP_REG || op1->type == X86_OP_MEM))
+ {
+ if (op2->imm > 0xFF) {
+ if (!uses_stack_access(op1)) {
+ return true;
+ }
+ }
+ }
+ return false;
}
-static bool test_strcmp_sys_v(void){
- if(GET_GLOBAL_STATE()->disassembler_word_width != 64 ){return false;}
- CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
- uint64_t arg1 = env->regs[RDI]; //rdx
- uint64_t arg2 = env->regs[RSI]; //rsi
- //nyx_debug_p(REDQUEEN_PREFIX, "extract call params sysv %lx %lx", arg1, arg2);
- test_strchr(arg1, arg2);
- return test_strcmp(arg1, arg2);
+static bool is_interessting_xor_at(redqueen_t *self, cs_insn *ins)
+{
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
+
+ assert(x86->op_count == 2);
+ cs_x86_op *op1 = &(x86->operands[0]);
+ cs_x86_op *op2 = &(x86->operands[1]);
+
+ if (op1->type == X86_OP_REG && op2->type == X86_OP_REG) {
+ if (op1->reg != op2->reg) {
+ return true;
+ }
+ }
+ return false;
}
-static void extract_call_params(void){
- //nyx_debug_p(REDQUEEN_PREFIX, "extract call at %lx", ip);
- test_strcmp_cdecl();
- test_strcmp_fastcall();
- test_strcmp_sys_v();
+static void opcode_analyzer(redqueen_t *self, cs_insn *ins)
+{
+ // uint8_t i, j;
+ // cs_x86 details = ins->detail->x86;
+ // printf("SELF %p\n", self->redqueen_state);
+ // printf("INS %lx\n", ins->address);
+ if (ins->id == X86_INS_CMP) {
+ set_rq_instruction(self, ins->address);
+ // nyx_debug_p(REDQUEEN_PREFIX, "hooking cmp %lx %s %s", ins->address, ins->mnemonic, ins->op_str);
+ }
+ if (ins->id == X86_INS_LEA && is_interessting_lea_at(self, ins)) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "hooking lea %lx", ins->address);
+ set_rq_instruction(self, ins->address);
+ }
+ if (ins->id == X86_INS_SUB && is_interessting_sub_at(self, ins)) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "hooking sub %lx", ins->address);
+ set_rq_instruction(self, ins->address);
+ }
+ if (ins->id == X86_INS_ADD && is_interessting_add_at(self, ins)) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "hooking add %lx", ins->address);
+ set_rq_instruction(self, ins->address);
+ }
+ if (ins->id == X86_INS_XOR && is_interessting_xor_at(self, ins)) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "hooking xor %lx %s %s", ins->address, ins->mnemonic, ins->op_str);
+ set_rq_instruction(self, ins->address);
+ }
+ if (ins->id == X86_INS_CALL || ins->id == X86_INS_LCALL) {
+ // nyx_debug_p(REDQUEEN_PREFIX, "hooking call %lx %s %s", ins->address, ins->mnemonic, ins->op_str);
+ set_rq_instruction(self, ins->address);
+ }
}
-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");
- } else if(insn->id == X86_INS_SUB){ //handle original redqueen case
- get_cmp_value(insn, "SUB");
- } else if(insn->id == X86_INS_LEA){ //handle original redqueen case
- get_cmp_value_lea(insn);
- } else if(insn->id == X86_INS_ADD){ //handle original redqueen case
- get_cmp_value_add(insn);
- } else if (insn->id == X86_INS_CALL || insn->id == X86_INS_LCALL){
- extract_call_params();
- }
+void redqueen_callback(void *opaque,
+ disassembler_mode_t mode,
+ uint64_t start_addr,
+ uint64_t end_addr)
+{
+ GET_GLOBAL_STATE()->bb_coverage++;
+ redqueen_t *self = (redqueen_t *)opaque;
+
+ if (start_addr != end_addr) {
+ uint64_t failed_page = 0;
+ uint64_t code = start_addr;
+
+ cs_insn *insn = page_cache_cs_malloc(self->page_cache, mode);
+
+ while (page_cache_disassemble_iter(self->page_cache, &code, insn,
+ &failed_page, mode))
+ {
+ if (insn->address > end_addr) {
+ break;
+ }
+ opcode_analyzer(self, insn);
+ }
+ cs_free(insn, 1);
+ }
}
-static uint8_t handle_hook_breakpoint(redqueen_t* self, bool write_data){
- X86CPU *cpu = X86_CPU(self->cpu);
- CPUX86State *env = &cpu->env;
+void destroy_rq_state(redqueen_t *self)
+{
+ redqueen_trace_free(self->trace_state);
+ kh_destroy(RQ, self->lookup);
+ free(self);
+}
- cs_insn *insn = NULL;
- switch(GET_GLOBAL_STATE()->disassembler_word_width){
- case 64:
- insn = page_cache_cs_malloc(self->page_cache, mode_64);
- break;
- case 32:
- insn = page_cache_cs_malloc(self->page_cache, mode_32);
- break;
+static void redqueen_set_addr_flags(redqueen_t *self, uint64_t addr, uint32_t flags)
+{
+ int unused = 0;
+
+ khiter_t k = kh_get(RQ, self->lookup, addr);
+ if (k == kh_end(self->lookup)) {
+ k = kh_put(RQ, self->lookup, addr, &unused);
+ kh_value(self->lookup, k) = 0;
+ }
+ kh_value(self->lookup, k) |= flags;
+}
+
+static bool redqueen_check_addr_flags(redqueen_t *self, uint64_t addr, uint32_t flags)
+{
+ khiter_t k = kh_get(RQ, self->lookup, addr);
+ if (k != kh_end(self->lookup)) {
+ return !!(kh_value(self->lookup, k) & flags);
+ } else {
+ return false;
+ }
+}
+
+static bool redqueen_check_addr(redqueen_t *self, uint64_t addr)
+{
+ khiter_t k = kh_get(RQ, self->lookup, addr);
+ if (k != kh_end(self->lookup)) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static uint32_t redqueen_update_addr_count(redqueen_t *self, uint64_t addr)
+{
+ int unused __attribute__((unused));
+ uint32_t value = 0;
+ khiter_t k = kh_get(RQ, self->lookup, addr);
+ if (k != kh_end(self->lookup)) {
+ value = kh_value(self->lookup, k);
+ } else {
+ k = kh_put(RQ, self->lookup, addr, &unused);
+ }
+ value++;
+ kh_value(self->lookup, k) = value;
+ return value & 0xFF000000UL;
+}
+
+void set_rq_instruction(redqueen_t *self, uint64_t addr)
+{
+ if (!redqueen_check_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED)) {
+ redqueen_set_addr_flags(self, addr, CMP_BITMAP_RQ_INSTRUCTION);
+ }
+}
+
+void set_rq_blacklist(redqueen_t *self, uint64_t addr)
+{
+ redqueen_set_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED);
+}
+
+static void insert_hooks_whitelist(redqueen_t *self)
+{
+ for (size_t i = 0; i < self->num_breakpoint_whitelist; i++) {
+ insert_breakpoint(self->cpu, self->breakpoint_whitelist[i], 1);
+ }
+}
+
+static void insert_hooks_bitmap(redqueen_t *self)
+{
+ uint64_t c = 0;
+ uint64_t addr;
+ uint32_t value __attribute__((unused));
+ uint32_t mode = GET_GLOBAL_STATE()->redqueen_instrumentation_mode;
+
+ kh_foreach(self->lookup, addr, value, {
+ if (redqueen_check_addr_flags(self, addr, CMP_BITMAP_BLACKLISTED)) {
+ continue;
+ }
+
+ bool should_hook_rq =
+ (mode == REDQUEEN_LIGHT_INSTRUMENTATION) &&
+ redqueen_check_addr_flags(self, addr, CMP_BITMAP_SHOULD_HOOK_RQ);
+
+ if (should_hook_rq) {
+ insert_breakpoint(self->cpu, addr, 1);
+ c++;
+ }
+ });
+}
+
+void redqueen_insert_hooks(redqueen_t *self)
+{
+ nyx_debug_p(REDQUEEN_PREFIX, "insert hooks");
+ assert(!self->hooks_applied);
+ switch (GET_GLOBAL_STATE()->redqueen_instrumentation_mode) {
+ case (REDQUEEN_LIGHT_INSTRUMENTATION):
+ insert_hooks_bitmap(self);
+ break;
+ case (REDQUEEN_WHITELIST_INSTRUMENTATION):
+ insert_hooks_whitelist(self);
+ break;
+ case (REDQUEEN_NO_INSTRUMENTATION):
+ break;
default:
- abort();
- }
- uint8_t ins_size = 0;
- uint64_t ip = env->eip;
- uint64_t code = ip;
- uint64_t failed_page = 0;
+ assert(false);
+ }
+ self->hooks_applied = 1;
+}
- switch(GET_GLOBAL_STATE()->disassembler_word_width){
- case 64:
- assert(page_cache_disassemble_iter(self->page_cache, &code, insn, &failed_page, mode_64));
+void redqueen_remove_hooks(redqueen_t *self)
+{
+ nyx_debug_p(REDQUEEN_PREFIX, "remove hooks");
+ assert(self->hooks_applied);
+ remove_all_breakpoints(self->cpu);
+
+ for (khiter_t i = kh_begin(self->lookup); i != kh_end(self->lookup); ++i) {
+ if (!kh_exist(self->lookup, i))
+ continue;
+ kh_val(self->lookup, i) &= 0xFF000000UL;
+ }
+ self->hooks_applied = 0;
+ return;
+}
+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;
+ case X86_REG_CS:
+ return env->segs[R_CS].base;
+ case X86_REG_DS:
+ return env->segs[R_DS].base;
+ case X86_REG_SS:
+ return env->segs[R_SS].base;
+ default:
break;
- case 32:
- assert(page_cache_disassemble_iter(self->page_cache, &code, insn, &failed_page, mode_32));
+ }
+ assert(false);
+}
+
+static inline uint64_t sign_extend_from_size(uint64_t value, uint8_t size)
+{
+ switch (size) {
+ case 64:
+ return value;
+ case 32:
+ return ((int32_t)(value) < 0) ? 0xffffffff00000000 | value : value;
+ case 16:
+ return ((int16_t)(value) < 0) ? 0xffffffffffff0000 | value : value;
+ case 8:
+ return ((int8_t)(value) < 0) ? 0xffffffffffffff00 | value : value;
+ }
+ assert(false);
+}
+
+static uint64_t eval_reg(x86_reg reg, uint8_t *size)
+{
+ uint64_t value = 0;
+ CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
+
+ switch (reg) {
+ case X86_REG_RAX:
+ value = env->regs[RAX];
+ *size = 64;
break;
- default:
+ case X86_REG_RCX:
+ value = env->regs[RCX];
+ *size = 64;
+ break;
+ case X86_REG_RDX:
+ value = env->regs[RDX];
+ *size = 64;
+ break;
+ case X86_REG_RBX:
+ value = env->regs[RBX];
+ *size = 64;
+ break;
+ case X86_REG_RSP:
+ value = env->regs[RSP];
+ *size = 64;
+ break;
+ case X86_REG_RBP:
+ value = env->regs[RBP];
+ *size = 64;
+ break;
+ case X86_REG_RSI:
+ value = env->regs[RSI];
+ *size = 64;
+ break;
+ case X86_REG_RDI:
+ value = env->regs[RDI];
+ *size = 64;
+ break;
+ case X86_REG_R8:
+ value = env->regs[R8];
+ *size = 64;
+ break;
+ case X86_REG_R9:
+ value = env->regs[R9];
+ *size = 64;
+ break;
+ case X86_REG_R10:
+ value = env->regs[R10];
+ *size = 64;
+ break;
+ case X86_REG_R11:
+ value = env->regs[R11];
+ *size = 64;
+ break;
+ case X86_REG_R12:
+ value = env->regs[R12];
+ *size = 64;
+ break;
+ case X86_REG_R13:
+ value = env->regs[R13];
+ *size = 64;
+ break;
+ case X86_REG_R14:
+ value = env->regs[R14];
+ *size = 64;
+ break;
+ case X86_REG_R15:
+ value = env->regs[R15];
+ *size = 64;
+ break;
+ case X86_REG_EAX:
+ value = env->regs[RAX] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_ECX:
+ value = env->regs[RCX] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_EDX:
+ value = env->regs[RDX] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_EBX:
+ value = env->regs[RBX] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_ESP:
+ value = env->regs[RSP] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_EBP:
+ value = env->regs[RBP] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_ESI:
+ value = env->regs[RSI] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_EDI:
+ value = env->regs[RDI] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R8D:
+ value = env->regs[R8] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R9D:
+ value = env->regs[R9] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R10D:
+ value = env->regs[R10] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R11D:
+ value = env->regs[R11] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R12D:
+ value = env->regs[R12] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R13D:
+ value = env->regs[R13] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R14D:
+ value = env->regs[R14] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_R15D:
+ value = env->regs[R15] & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_AX:
+ value = env->regs[RAX] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_CX:
+ value = env->regs[RCX] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_DX:
+ value = env->regs[RDX] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_BX:
+ value = env->regs[RBX] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_SP:
+ value = env->regs[RSP] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_BP:
+ value = env->regs[RBP] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_SI:
+ value = env->regs[RSI] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_DI:
+ value = env->regs[RDI] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R8W:
+ value = env->regs[R8] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R9W:
+ value = env->regs[R9] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R10W:
+ value = env->regs[R10] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R11W:
+ value = env->regs[R11] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R12W:
+ value = env->regs[R12] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R13W:
+ value = env->regs[R13] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R14W:
+ value = env->regs[R14] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_R15W:
+ value = env->regs[R15] & 0xffff;
+ *size = 16;
+ break;
+ case X86_REG_AL:
+ value = env->regs[RAX] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_CL:
+ value = env->regs[RCX] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_DL:
+ value = env->regs[RDX] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_BL:
+ value = env->regs[RBX] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_SPL:
+ value = env->regs[RSP] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_BPL:
+ value = env->regs[RBP] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_SIL:
+ value = env->regs[RSI] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_DIL:
+ value = env->regs[RDI] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R8B:
+ value = env->regs[R8] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R9B:
+ value = env->regs[R9] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R10B:
+ value = env->regs[R10] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R11B:
+ value = env->regs[R11] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R12B:
+ value = env->regs[R12] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R13B:
+ value = env->regs[R13] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R14B:
+ value = env->regs[R14] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_R15B:
+ value = env->regs[R15] & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_AH:
+ value = (env->regs[RAX] >> 8) & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_CH:
+ value = (env->regs[RCX] >> 8) & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_DH:
+ value = (env->regs[RDX] >> 8) & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_BH:
+ value = (env->regs[RBX] >> 8) & 0xff;
+ *size = 8;
+ break;
+ case X86_REG_RIP:
+ value = env->eip;
+ *size = 64;
+ break;
+ case X86_REG_EIP:
+ value = env->eip & 0xffffffff;
+ *size = 32;
+ break;
+ case X86_REG_IP:
+ value = env->eip & 0xfffff;
+ *size = 16;
+ break;
+ default:
+ assert(false);
+ }
+ return value;
+}
+
+static uint64_t eval_addr(cs_x86_op *op)
+{
+ uint8_t size = 0;
+ uint64_t base = 0;
+ uint64_t index = 0;
+ uint64_t segment = 0;
+
+ assert(op->type == X86_OP_MEM);
+
+ if (op->mem.base != X86_REG_INVALID) {
+ base = eval_reg(op->mem.base, &size);
+ }
+ if (op->mem.index != X86_REG_INVALID) {
+ index = eval_reg(op->mem.index, &size);
+ }
+
+ if (op->mem.segment != X86_REG_INVALID) {
+ segment = get_segment_register(op->mem.segment);
+ }
+
+ uint64_t addr = segment + base + index * op->mem.scale + op->mem.disp;
+ return addr;
+}
+
+static uint64_t eval_mem(cs_x86_op *op)
+{
+ uint64_t val = 0;
+ assert(op->size == 1 || op->size == 2 || op->size == 4 || op->size == 8);
+ // nyx_debug_p(REDQUEEN_PREFIX, "EVAL MEM FOR OP:");
+
+ /* TODO @ sergej: replace me later */
+ read_virtual_memory(eval_addr(op), (uint8_t *)&val, op->size, qemu_get_cpu(0));
+ return val;
+}
+
+static uint64_t eval(cs_x86_op *op, uint8_t *size)
+{
+ switch ((int)op->type) {
+ case X86_OP_REG:
+ return eval_reg(op->reg, size);
+ case X86_OP_IMM:
+ *size = 0;
+ return op->imm;
+ case X86_OP_MEM:
+ switch (op->size) {
+ case 1:
+ *size = 8;
+ return eval_mem(op) & 0xff;
+ case 2:
+ *size = 16;
+ return eval_mem(op) & 0xffff;
+ case 4:
+ *size = 32;
+ return eval_mem(op) & 0xffffffff;
+ case 8:
+ *size = 64;
+ return eval_mem(op);
+ }
+ }
+
+ /* unreachable, dude! */
+ assert(false);
+ return 0;
+}
+
+static void print_comp_result(uint64_t addr,
+ const char *type,
+ uint64_t val1,
+ uint64_t val2,
+ uint8_t size,
+ bool is_imm)
+{
+ 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);
+ uint64_t mask = 0;
+ switch (size) {
+ case 64:
+ format = " 64\t%016lX-%016lX";
+ mask = 0xffffffffffffffff;
+ break;
+ case 32:
+ format = " 32\t%08X-%08X";
+ mask = 0xffffffff;
+ break;
+ case 16:
+ format = " 16\t%04X-%04X";
+ mask = 0xffff;
+ break;
+ case 8:
+ format = " 8\t%02X-%02X";
+ mask = 0xff;
+ break;
+ default:
+ assert(false);
+ }
+ pos += snprintf(result_buf + pos, 256 - pos, format, val1 & mask, val2 & mask);
+ if (is_imm) {
+ pos += snprintf(result_buf + pos, 256 - pos, " IMM");
+ }
+ pos += snprintf(result_buf + pos, 256 - pos, "\n");
+ write_re_result(result_buf);
+}
+
+static void get_cmp_value(cs_insn *ins, const char *type)
+{
+ uint8_t size_1 = 0;
+ uint8_t size_2 = 0;
+
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
+
+ assert(x86->op_count == 2);
+ cs_x86_op *op1 = &(x86->operands[0]);
+ cs_x86_op *op2 = &(x86->operands[1]);
+
+ uint64_t v1 = eval(op1, &size_1);
+ uint64_t v2 = eval(op2, &size_2);
+
+ if (GET_GLOBAL_STATE()->redqueen_instrumentation_mode ==
+ REDQUEEN_WHITELIST_INSTRUMENTATION ||
+ v1 != v2)
+ {
+ print_comp_result(ins->address, type, v1, v2, (size_1 ? size_1 : size_2),
+ op2->type == X86_OP_IMM);
+ }
+}
+
+static void get_cmp_value_add(cs_insn *ins)
+{
+ uint8_t size_1 = 0;
+ uint8_t size_2 = 0;
+
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
+
+ assert(x86->op_count == 2);
+ cs_x86_op *op1 = &(x86->operands[0]);
+ cs_x86_op *op2 = &(x86->operands[1]);
+
+ uint64_t v1 = eval(op1, &size_1);
+ uint64_t v2 = -sign_extend_from_size(eval(op2, &size_2), size_1);
+
+ if (op2->type != X86_OP_IMM) {
+ return;
+ }
+
+ if (GET_GLOBAL_STATE()->redqueen_instrumentation_mode ==
+ REDQUEEN_WHITELIST_INSTRUMENTATION ||
+ v1 != v2)
+ {
+ bool is_imm = true;
+ print_comp_result(ins->address, "SUB", v1, v2, size_1, is_imm);
+ }
+}
+
+static void get_cmp_value_lea(cs_insn *ins)
+{
+ uint64_t index_val = 0;
+
+ assert(ins);
+ cs_x86 *x86 = &(ins->detail->x86);
+
+ assert(x86->op_count == 2);
+ cs_x86_op *op2 = &(x86->operands[1]);
+
+ assert(op2->type == X86_OP_MEM);
+
+ uint8_t size = 0;
+ if (op2->mem.base != X86_REG_INVALID && op2->mem.index != X86_REG_INVALID) {
+ return;
+ }
+
+ if (op2->mem.base == X86_REG_INVALID && op2->mem.index == X86_REG_INVALID) {
+ return;
+ }
+
+ if (op2->mem.base != X86_REG_INVALID) {
+ index_val = eval_reg(op2->mem.base, &size);
+ }
+
+ if (op2->mem.index != X86_REG_INVALID) {
+ index_val = eval_reg(op2->mem.index, &size);
+ }
+
+ if (GET_GLOBAL_STATE()->redqueen_instrumentation_mode ==
+ REDQUEEN_WHITELIST_INSTRUMENTATION ||
+ index_val != -op2->mem.disp)
+ {
+ bool is_imm = false;
+ print_comp_result(ins->address, "LEA", index_val, -op2->mem.disp,
+ op2->size * 8, is_imm);
+ }
+}
+
+
+static uint64_t limit_to_word_width(uint64_t val)
+{
+ switch (GET_GLOBAL_STATE()->disassembler_word_width) {
+ case 64:
+ return val;
+ case 32:
+ return val & 0xffffffff;
+ default:
+ assert(false);
+ }
+}
+
+static uint64_t word_width_to_bytes(void)
+{
+ switch (GET_GLOBAL_STATE()->disassembler_word_width) {
+ case 64:
+ return 8;
+ case 32:
+ return 4;
+ default:
+ assert(false);
+ }
+}
+
+static uint64_t read_stack(uint64_t word_index)
+{
+ CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
+ uint64_t rsp = env->regs[RSP];
+ rsp = limit_to_word_width(rsp);
+ uint64_t res = 0;
+ uint64_t stack_ptr = rsp + word_index * word_width_to_bytes();
+ /* TODO @ sergej */
+ assert(read_virtual_memory(stack_ptr, (uint8_t *)(&res), 8, qemu_get_cpu(0)));
+ return limit_to_word_width(res);
+}
+
+static void format_strcmp(uint8_t *buf1, uint8_t *buf2)
+{
+ char out_buf[REDQUEEN_MAX_STRCMP_LEN * 4 + 2];
+ char *tmp_hex_buf = &out_buf[0];
+ for (int i = 0; i < REDQUEEN_MAX_STRCMP_LEN; i++) {
+ tmp_hex_buf += sprintf(tmp_hex_buf, "%02X", (uint8_t)buf1[i]);
+ }
+ *tmp_hex_buf++ = '-';
+ for (int i = 0; i < REDQUEEN_MAX_STRCMP_LEN; i++) {
+ tmp_hex_buf += sprintf(tmp_hex_buf, "%02X", (uint8_t)buf2[i]);
+ }
+ char *res = 0;
+ CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
+ uint64_t rip = env->eip;
+ assert(asprintf(&res, "%lx\t\tSTR %d\t%s\n", rip, REDQUEEN_MAX_STRCMP_LEN * 8,
+ out_buf) != -1);
+ write_re_result(res);
+ free(res);
+}
+
+static bool test_strchr(uint64_t arg1, uint64_t arg2)
+{
+ CPUState *cpu = qemu_get_cpu(0);
+
+ /* 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 */
+ 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);
+ buf2[0] = (uint8_t)(arg2);
+ format_strcmp(buf1, buf2);
+ return true;
+}
+
+static bool test_strcmp(uint64_t arg1, uint64_t arg2)
+{
+ CPUState *cpu = qemu_get_cpu(0);
+ if (!is_addr_mapped(arg1, cpu) || !is_addr_mapped(arg2, cpu)) {
+ return false;
+ }
+ // nyx_debug_p(REDQUEEN_PREFIX,"valid ptrs");
+ uint8_t buf1[REDQUEEN_MAX_STRCMP_LEN];
+ uint8_t buf2[REDQUEEN_MAX_STRCMP_LEN];
+ /* 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);
+ return true;
+}
+
+static bool test_strcmp_cdecl(void)
+{
+ uint64_t arg1 = read_stack(0);
+ uint64_t arg2 = read_stack(1);
+ // nyx_debug_p(REDQUEEN_PREFIX, "extract call params cdecl %lx %lx", arg1, arg2);
+ test_strchr(arg1, arg2);
+ return test_strcmp(arg1, arg2);
+}
+
+static bool test_strcmp_fastcall(void)
+{
+ CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
+ uint64_t arg1 = env->regs[RCX]; // rcx
+ uint64_t arg2 = env->regs[RDX]; // rdx
+ // nyx_debug_p(REDQUEEN_PREFIX, "extract call params fastcall %lx %lx", arg1, arg2);
+ test_strchr(arg1, arg2);
+ return test_strcmp(arg1, arg2);
+}
+
+static bool test_strcmp_sys_v(void)
+{
+ if (GET_GLOBAL_STATE()->disassembler_word_width != 64) {
+ return false;
+ }
+ CPUX86State *env = &(X86_CPU(qemu_get_cpu(0)))->env;
+ uint64_t arg1 = env->regs[RDI]; // rdx
+ uint64_t arg2 = env->regs[RSI]; // rsi
+ // nyx_debug_p(REDQUEEN_PREFIX, "extract call params sysv %lx %lx", arg1, arg2);
+ test_strchr(arg1, arg2);
+ return test_strcmp(arg1, arg2);
+}
+
+static void extract_call_params(void)
+{
+ // nyx_debug_p(REDQUEEN_PREFIX, "extract call at %lx", ip);
+ test_strcmp_cdecl();
+ test_strcmp_fastcall();
+ test_strcmp_sys_v();
+}
+
+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");
+ } else if (insn->id == X86_INS_SUB) { // handle original redqueen case
+ get_cmp_value(insn, "SUB");
+ } else if (insn->id == X86_INS_LEA) { // handle original redqueen case
+ get_cmp_value_lea(insn);
+ } else if (insn->id == X86_INS_ADD) { // handle original redqueen case
+ get_cmp_value_add(insn);
+ } else if (insn->id == X86_INS_CALL || insn->id == X86_INS_LCALL) {
+ extract_call_params();
+ }
+}
+
+static uint8_t handle_hook_breakpoint(redqueen_t *self, bool write_data)
+{
+ X86CPU *cpu = X86_CPU(self->cpu);
+ CPUX86State *env = &cpu->env;
+
+ cs_insn *insn = NULL;
+ switch (GET_GLOBAL_STATE()->disassembler_word_width) {
+ case 64:
+ insn = page_cache_cs_malloc(self->page_cache, mode_64);
+ break;
+ case 32:
+ insn = page_cache_cs_malloc(self->page_cache, mode_32);
+ break;
+ default:
+ abort();
+ }
+ uint8_t ins_size = 0;
+ uint64_t ip = env->eip;
+ uint64_t code = ip;
+ uint64_t failed_page = 0;
+
+ switch (GET_GLOBAL_STATE()->disassembler_word_width) {
+ case 64:
+ assert(page_cache_disassemble_iter(self->page_cache, &code, insn,
+ &failed_page, mode_64));
+ break;
+ case 32:
+ assert(page_cache_disassemble_iter(self->page_cache, &code, insn,
+ &failed_page, mode_32));
+ break;
+ default:
abort();
}
- ins_size = insn->size;
+ ins_size = insn->size;
- if(write_data){
- //int mode = self->cpu->redqueen_instrumentation_mode;
+ if (write_data) {
+ // int mode = self->cpu->redqueen_instrumentation_mode;
int mode = GET_GLOBAL_STATE()->redqueen_instrumentation_mode;
- if(mode == REDQUEEN_LIGHT_INSTRUMENTATION || mode == REDQUEEN_WHITELIST_INSTRUMENTATION || mode == REDQUEEN_SE_INSTRUMENTATION){
- handle_hook_redqueen_light(self, ip, insn);
+ if (mode == REDQUEEN_LIGHT_INSTRUMENTATION ||
+ mode == REDQUEEN_WHITELIST_INSTRUMENTATION ||
+ mode == REDQUEEN_SE_INSTRUMENTATION)
+ {
+ handle_hook_redqueen_light(self, ip, insn);
}
- if(mode == REDQUEEN_SE_INSTRUMENTATION){
- assert(false);
+ if (mode == REDQUEEN_SE_INSTRUMENTATION) {
+ assert(false);
}
}
- cs_free(insn, 1);
+ cs_free(insn, 1);
assert(ins_size != 0);
return ins_size;
}
-void handle_hook(redqueen_t* self){
- X86CPU *cpu = X86_CPU(self->cpu);
- CPUX86State *env = &cpu->env;
+void handle_hook(redqueen_t *self)
+{
+ X86CPU *cpu = X86_CPU(self->cpu);
+ CPUX86State *env = &cpu->env;
- if (self->next_rip){
+ if (self->next_rip) {
+ remove_breakpoint(self->cpu, self->next_rip, 1);
- remove_breakpoint(self->cpu, self->next_rip, 1);
+ if (self->last_rip &&
+ redqueen_update_addr_count(self, self->last_rip) < REDQUEEN_TRAP_LIMIT)
+ {
+ insert_breakpoint(self->cpu, self->last_rip, 1);
+ }
- if(self->last_rip && redqueen_update_addr_count(self, self->last_rip) < REDQUEEN_TRAP_LIMIT){
- insert_breakpoint(self->cpu, self->last_rip, 1);
+ kvm_update_guest_debug(self->cpu, 0);
+
+ self->last_rip = 0;
+ self->next_rip = 0;
}
- kvm_update_guest_debug(self->cpu, 0);
+ if (redqueen_check_addr(self, env->eip)) {
+ self->last_rip = env->eip;
+ remove_breakpoint(self->cpu, env->eip, 1);
- self->last_rip = 0;
- self->next_rip = 0;
- }
-
- if(redqueen_check_addr(self, env->eip)){
-
- self->last_rip = env->eip;
- remove_breakpoint(self->cpu, env->eip, 1);
-
- if(self->cpu->pt_enabled && GET_GLOBAL_STATE()->pt_c3_filter == env->cr[3]){
- self->next_rip = handle_hook_breakpoint(self, true);
+ if (self->cpu->pt_enabled && GET_GLOBAL_STATE()->pt_c3_filter == env->cr[3]) {
+ self->next_rip = handle_hook_breakpoint(self, true);
+ } else {
+ self->next_rip = handle_hook_breakpoint(self, true);
+ }
}
- else{
- self->next_rip = handle_hook_breakpoint(self, true);
+}
+
+
+static void _redqueen_update_whitelist(redqueen_t *self)
+{
+ 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_whitelist(redqueen_t* self){
- 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(GET_GLOBAL_STATE()->redqueen_update_blacklist){
- size_t num_addrs = 0;
- uint64_t *addrs;
- parse_address_file(redqueen_workdir.breakpoint_black, &num_addrs, &addrs);
- for(size_t i = 0; i< num_addrs; i++){
- set_rq_blacklist(self, addrs[i]);
+static void _redqueen_update_blacklist(redqueen_t *self)
+{
+ if (GET_GLOBAL_STATE()->redqueen_update_blacklist) {
+ size_t num_addrs = 0;
+ uint64_t *addrs;
+ parse_address_file(redqueen_workdir.breakpoint_black, &num_addrs, &addrs);
+ for (size_t i = 0; i < num_addrs; i++) {
+ set_rq_blacklist(self, addrs[i]);
+ }
+ free(addrs);
}
- free(addrs);
- }
}
-void enable_rq_intercept_mode(redqueen_t* self){
- if(!self->intercept_mode){
- delete_redqueen_files();
- _redqueen_update_whitelist(self);
- _redqueen_update_blacklist(self);
- redqueen_insert_hooks(self);
- self->intercept_mode = true;
- }
+void enable_rq_intercept_mode(redqueen_t *self)
+{
+ if (!self->intercept_mode) {
+ delete_redqueen_files();
+ _redqueen_update_whitelist(self);
+ _redqueen_update_blacklist(self);
+ redqueen_insert_hooks(self);
+ self->intercept_mode = true;
+ }
}
-void disable_rq_intercept_mode(redqueen_t* self){
- if(self->intercept_mode){
- redqueen_remove_hooks(self);
- self->intercept_mode = false;
- }
+void disable_rq_intercept_mode(redqueen_t *self)
+{
+ if (self->intercept_mode) {
+ redqueen_remove_hooks(self);
+ self->intercept_mode = false;
+ }
}
diff --git a/nyx/redqueen.h b/nyx/redqueen.h
index a9881a5787..092b4be740 100644
--- a/nyx/redqueen.h
+++ b/nyx/redqueen.h
@@ -22,100 +22,120 @@ along with QEMU-PT. If not, see .
#pragma once
#include "qemu/osdep.h"
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include "nyx/redqueen_trace.h"
#include "nyx/khash.h"
#include "nyx/page_cache.h"
+#include "nyx/redqueen_trace.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
-//#define RQ_DEBUG
+// #define RQ_DEBUG
#define REDQUEEN_MAX_STRCMP_LEN 64
-#define REDQUEEN_TRAP_LIMIT 16
+#define REDQUEEN_TRAP_LIMIT 16
#define REG64_NUM 16
#define REG32_NUM 16
-//seems we don't want to include rip, since this index is used to acces the qemu cpu structure or something?
-#define REG16_NUM 16
+// seems we don't want to include rip, since this index is used to acces the qemu cpu structure or something?
+#define REG16_NUM 16
#define REG8L_NUM 16
-#define REG8H_NUM 8
+#define REG8H_NUM 8
#define EXTRA_REG_RIP 16
#define EXTRA_REG_NOP 17
-#define REDQUEEN_NO_INSTRUMENTATION 0
-#define REDQUEEN_LIGHT_INSTRUMENTATION 1
-#define REDQUEEN_SE_INSTRUMENTATION 2
+#define REDQUEEN_NO_INSTRUMENTATION 0
+#define REDQUEEN_LIGHT_INSTRUMENTATION 1
+#define REDQUEEN_SE_INSTRUMENTATION 2
#define REDQUEEN_WHITELIST_INSTRUMENTATION 3
-enum reg_types{RAX, RCX, RDX, RBX, RSP, RBP, RSI, RDI, R8, R9, R10, R11, R12, R13, R14, R15};
+enum reg_types {
+ RAX,
+ RCX,
+ RDX,
+ RBX,
+ RSP,
+ RBP,
+ RSI,
+ RDI,
+ R8,
+ R9,
+ R10,
+ R11,
+ R12,
+ R13,
+ R14,
+ R15
+};
-#define CMP_BITMAP_NOP 0x0000000UL
-#define CMP_BITMAP_RQ_INSTRUCTION 0x1000000UL
-#define CMP_BITMAP_SE_INSTRUCTION 0x2000000UL
-#define CMP_BITMAP_BLACKLISTED 0x4000000UL
-#define CMP_BITMAP_TRACE_ENABLED 0x8000000UL
-#define CMP_BITMAP_SHOULD_HOOK_SE (CMP_BITMAP_SE_INSTRUCTION|CMP_BITMAP_TRACE_ENABLED)
-#define CMP_BITMAP_SHOULD_HOOK_RQ (CMP_BITMAP_RQ_INSTRUCTION)
+#define CMP_BITMAP_NOP 0x0000000UL
+#define CMP_BITMAP_RQ_INSTRUCTION 0x1000000UL
+#define CMP_BITMAP_SE_INSTRUCTION 0x2000000UL
+#define CMP_BITMAP_BLACKLISTED 0x4000000UL
+#define CMP_BITMAP_TRACE_ENABLED 0x8000000UL
+#define CMP_BITMAP_SHOULD_HOOK_SE \
+ (CMP_BITMAP_SE_INSTRUCTION | CMP_BITMAP_TRACE_ENABLED)
+#define CMP_BITMAP_SHOULD_HOOK_RQ (CMP_BITMAP_RQ_INSTRUCTION)
KHASH_MAP_INIT_INT64(RQ, uint32_t)
-typedef struct redqueen_s{
- khash_t(RQ) *lookup;
- bool intercept_mode;
- bool singlestep_enabled;
- int hooks_applied;
- CPUState *cpu;
- uint64_t last_rip;
- uint64_t next_rip;
- uint64_t *breakpoint_whitelist;
- uint64_t num_breakpoint_whitelist;
- redqueen_trace_t* trace_state;
- page_cache_t* page_cache;
+typedef struct redqueen_s {
+ khash_t(RQ) * lookup;
+ bool intercept_mode;
+ bool singlestep_enabled;
+ int hooks_applied;
+ CPUState *cpu;
+ uint64_t last_rip;
+ uint64_t next_rip;
+ uint64_t *breakpoint_whitelist;
+ uint64_t num_breakpoint_whitelist;
+ redqueen_trace_t *trace_state;
+ page_cache_t *page_cache;
} redqueen_t;
-typedef struct redqueen_workdir_s{
- char* redqueen_results;
- char* symbolic_results;
- char* pt_trace_results;
- char* redqueen_patches;
- char* breakpoint_white;
- char* breakpoint_black;
- char* target_code_dump;
+typedef struct redqueen_workdir_s {
+ char *redqueen_results;
+ char *symbolic_results;
+ char *pt_trace_results;
+ char *redqueen_patches;
+ char *breakpoint_white;
+ char *breakpoint_black;
+ char *target_code_dump;
} redqueen_workdir_t;
extern redqueen_workdir_t redqueen_workdir;
-void setup_redqueen_workdir(char* workdir);
+void setup_redqueen_workdir(char *workdir);
-redqueen_t* new_rq_state(CPUState *cpu, page_cache_t* page_cache);
-void destroy_rq_state(redqueen_t* self);
+redqueen_t *new_rq_state(CPUState *cpu, page_cache_t *page_cache);
+void destroy_rq_state(redqueen_t *self);
-void set_rq_instruction(redqueen_t* self, uint64_t addr);
-void set_rq_blacklist(redqueen_t* self, uint64_t addr);
+void set_rq_instruction(redqueen_t *self, uint64_t addr);
+void set_rq_blacklist(redqueen_t *self, uint64_t addr);
-void handle_hook(redqueen_t* self);
-void handel_se_hook(redqueen_t* self);
+void handle_hook(redqueen_t *self);
+void handel_se_hook(redqueen_t *self);
-void enable_rq_intercept_mode(redqueen_t* self);
-void disable_rq_intercept_mode(redqueen_t* self);
+void enable_rq_intercept_mode(redqueen_t *self);
+void disable_rq_intercept_mode(redqueen_t *self);
-void set_se_instruction(redqueen_t* self, uint64_t addr);
+void set_se_instruction(redqueen_t *self, uint64_t addr);
-void dump_se_registers(redqueen_t* self);
-void dump_se_memory_access(redqueen_t* self, cs_insn* insn);
-void dump_se_return_access(redqueen_t* self, cs_insn* insn);
-void dump_se_memory_access_at(redqueen_t* self, uint64_t instr_addr, uint64_t mem_addr);
+void dump_se_registers(redqueen_t *self);
+void dump_se_memory_access(redqueen_t *self, cs_insn *insn);
+void dump_se_return_access(redqueen_t *self, cs_insn *insn);
+void dump_se_memory_access_at(redqueen_t *self, uint64_t instr_addr, uint64_t mem_addr);
-void redqueen_insert_hooks(redqueen_t* self);
-void redqueen_remove_hooks(redqueen_t* self);
-
-void redqueen_callback(void* opaque, disassembler_mode_t mode, uint64_t start_addr, uint64_t end_addr);
+void redqueen_insert_hooks(redqueen_t *self);
+void redqueen_remove_hooks(redqueen_t *self);
+void redqueen_callback(void *opaque,
+ disassembler_mode_t mode,
+ uint64_t start_addr,
+ uint64_t end_addr);
diff --git a/nyx/redqueen_patch.c b/nyx/redqueen_patch.c
index 64f4bdea3a..479f9725eb 100644
--- a/nyx/redqueen_patch.c
+++ b/nyx/redqueen_patch.c
@@ -1,27 +1,29 @@
#include "qemu/osdep.h"
#include "redqueen_patch.h"
-#include "redqueen.h"
-#include "patcher.h"
-#include "file_helper.h"
#include "debug.h"
+#include "file_helper.h"
+#include "patcher.h"
+#include "redqueen.h"
/*
* Private Helper Functions Declarations
*/
-void _load_and_set_patches(patcher_t* self);
+void _load_and_set_patches(patcher_t *self);
/*
* Public Functions
*/
-void pt_enable_patches(patcher_t *self){
- _load_and_set_patches(self);
- patcher_apply_all(self);
+void pt_enable_patches(patcher_t *self)
+{
+ _load_and_set_patches(self);
+ patcher_apply_all(self);
}
-void pt_disable_patches(patcher_t *self){
- patcher_restore_all(self);
+void pt_disable_patches(patcher_t *self)
+{
+ patcher_restore_all(self);
}
@@ -30,12 +32,13 @@ void pt_disable_patches(patcher_t *self){
*/
-void _load_and_set_patches(patcher_t* self){
- size_t num_addrs = 0;
- uint64_t *addrs = NULL;
- parse_address_file(redqueen_workdir.redqueen_patches, &num_addrs, &addrs);
- if(num_addrs){
- patcher_set_addrs(self, addrs, num_addrs);
- free(addrs);
- }
+void _load_and_set_patches(patcher_t *self)
+{
+ size_t num_addrs = 0;
+ uint64_t *addrs = NULL;
+ parse_address_file(redqueen_workdir.redqueen_patches, &num_addrs, &addrs);
+ if (num_addrs) {
+ patcher_set_addrs(self, addrs, num_addrs);
+ free(addrs);
+ }
}
diff --git a/nyx/redqueen_trace.c b/nyx/redqueen_trace.c
index 48d51305f8..06619ebf99 100644
--- a/nyx/redqueen_trace.c
+++ b/nyx/redqueen_trace.c
@@ -1,42 +1,43 @@
#include "qemu/osdep.h"
-#include
-#include
-#include
#include
+#include
+#include
+#include
-#include "redqueen_trace.h"
#include "redqueen.h"
+#include "redqueen_trace.h"
#include "state/state.h"
/* write full trace of edge transitions rather than sorted list? */
-//#define KAFL_FULL_TRACES
+// #define KAFL_FULL_TRACES
-int trace_fd = 0;
+int trace_fd = 0;
int redqueen_trace_enabled = false;
uint32_t alt_bitmap_size = 0;
-uint8_t* alt_bitmap = NULL;
+uint8_t *alt_bitmap = NULL;
-void alt_bitmap_init(void* ptr, uint32_t size)
+void alt_bitmap_init(void *ptr, uint32_t size)
{
- if (redqueen_trace_enabled) {
- alt_bitmap = (uint8_t*)ptr;
- alt_bitmap_size = size;
- }
+ if (redqueen_trace_enabled) {
+ alt_bitmap = (uint8_t *)ptr;
+ alt_bitmap_size = size;
+ }
}
void alt_bitmap_reset(void)
{
- if (alt_bitmap) {
- memset(alt_bitmap, 0x00, alt_bitmap_size);
- }
+ if (alt_bitmap) {
+ memset(alt_bitmap, 0x00, alt_bitmap_size);
+ }
}
-static inline uint64_t mix_bits(uint64_t v) {
- v ^= (v >> 31);
- v *= 0x7fb5d329728ea185;
- return v;
+static inline uint64_t mix_bits(uint64_t v)
+{
+ v ^= (v >> 31);
+ v *= 0x7fb5d329728ea185;
+ return v;
}
/*
@@ -45,143 +46,162 @@ static inline uint64_t mix_bits(uint64_t v) {
*/
static void alt_bitmap_add(uint64_t from, uint64_t to)
{
- uint64_t transition_value;
+ uint64_t transition_value;
- if (GET_GLOBAL_STATE()->trace_mode) {
- if(alt_bitmap) {
- transition_value = mix_bits(to)^(mix_bits(from)>>1);
- alt_bitmap[transition_value & (alt_bitmap_size-1)]++;
- }
- }
+ if (GET_GLOBAL_STATE()->trace_mode) {
+ if (alt_bitmap) {
+ transition_value = mix_bits(to) ^ (mix_bits(from) >> 1);
+ alt_bitmap[transition_value & (alt_bitmap_size - 1)]++;
+ }
+ }
}
-static int reset_trace_fd(void) {
- if (trace_fd)
- close(trace_fd);
- trace_fd = open(redqueen_workdir.pt_trace_results, O_WRONLY | O_CREAT | O_TRUNC, 0644);
- if (trace_fd < 0) {
- fprintf(stderr, "Failed to initiate trace output: %s\n", strerror(errno));
- assert(0);
- }
- return trace_fd;
+static int reset_trace_fd(void)
+{
+ if (trace_fd)
+ close(trace_fd);
+ trace_fd =
+ open(redqueen_workdir.pt_trace_results, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+ if (trace_fd < 0) {
+ fprintf(stderr, "Failed to initiate trace output: %s\n", strerror(errno));
+ assert(0);
+ }
+ return trace_fd;
}
-void redqueen_trace_init(void) {
- redqueen_trace_enabled = true;
+void redqueen_trace_init(void)
+{
+ redqueen_trace_enabled = true;
}
-redqueen_trace_t* redqueen_trace_new(void){
- redqueen_trace_t* self = malloc(sizeof(redqueen_trace_t));
- self->lookup = kh_init(RQ_TRACE);
- self->num_ordered_transitions = 0;
- self->max_ordered_transitions = INIT_NUM_OF_STORED_TRANSITIONS;
- self->ordered_transitions = malloc(INIT_NUM_OF_STORED_TRANSITIONS*sizeof(uint128_t));
- return self;
+redqueen_trace_t *redqueen_trace_new(void)
+{
+ redqueen_trace_t *self = malloc(sizeof(redqueen_trace_t));
+ self->lookup = kh_init(RQ_TRACE);
+ self->num_ordered_transitions = 0;
+ self->max_ordered_transitions = INIT_NUM_OF_STORED_TRANSITIONS;
+ self->ordered_transitions =
+ malloc(INIT_NUM_OF_STORED_TRANSITIONS * sizeof(uint128_t));
+ return self;
}
-void redqueen_trace_free(redqueen_trace_t* self){
- kh_destroy(RQ_TRACE, self->lookup);
- free(self->ordered_transitions);
- free(self);
+void redqueen_trace_free(redqueen_trace_t *self)
+{
+ kh_destroy(RQ_TRACE, self->lookup);
+ free(self->ordered_transitions);
+ free(self);
}
-void redqueen_trace_register_transition(redqueen_trace_t* self, disassembler_mode_t mode, uint64_t from, uint64_t to){
- khiter_t k;
- int ret;
- uint64_t exit_ip = 0xffffffffffffffff;
+void redqueen_trace_register_transition(redqueen_trace_t *self,
+ disassembler_mode_t mode,
+ uint64_t from,
+ uint64_t to)
+{
+ khiter_t k;
+ int ret;
+ uint64_t exit_ip = 0xffffffffffffffff;
- if (from != exit_ip && to != exit_ip)
- alt_bitmap_add(from, to);
+ if (from != exit_ip && to != exit_ip)
+ alt_bitmap_add(from, to);
#ifdef KAFL_FULL_TRACES
- assert(trace_fd >= 0);
- dprintf(trace_fd, "%lx,%lx\n", from, to);
- return;
+ assert(trace_fd >= 0);
+ dprintf(trace_fd, "%lx,%lx\n", from, to);
+ return;
#endif
- uint128_t key = (((uint128_t)from)<<64) | ((uint128_t)to);
- k = kh_get(RQ_TRACE, self->lookup, key);
- if(k != kh_end(self->lookup)){
- kh_value(self->lookup, k) += 1;
- } else{
- k = kh_put(RQ_TRACE, self->lookup, key, &ret);
- kh_value(self->lookup, k) = 1;
- self->ordered_transitions[self->num_ordered_transitions] = key;
- self->num_ordered_transitions++;
- assert(self->num_ordered_transitions < self->max_ordered_transitions);
- }
-}
+ uint128_t key = (((uint128_t)from) << 64) | ((uint128_t)to);
+ k = kh_get(RQ_TRACE, self->lookup, key);
+ if (k != kh_end(self->lookup)) {
+ kh_value(self->lookup, k) += 1;
+ } else {
+ k = kh_put(RQ_TRACE, self->lookup, key, &ret);
+ kh_value(self->lookup, k) = 1;
+ self->ordered_transitions[self->num_ordered_transitions] = key;
+ self->num_ordered_transitions++;
+ assert(self->num_ordered_transitions < self->max_ordered_transitions);
+ }
+}
-static void redqueen_trace_write(void){
+static void redqueen_trace_write(void)
+{
#ifdef KAFL_FULL_TRACES
- return;
+ return;
#endif
- redqueen_trace_t *self = GET_GLOBAL_STATE()->redqueen_state->trace_state;
- assert(trace_fd >= 0);
- for(size_t i = 0; i < self->num_ordered_transitions; i++){
- khiter_t k;
- uint128_t key = self->ordered_transitions[i];
- k = kh_get(RQ_TRACE, self->lookup, key);
- assert(k != kh_end(self->lookup));
- dprintf(trace_fd, "%lx,%lx,%lx\n", (uint64_t)(key>>64), (uint64_t)key, kh_value(self->lookup, k) );
- }
+ redqueen_trace_t *self = GET_GLOBAL_STATE()->redqueen_state->trace_state;
+ assert(trace_fd >= 0);
+ for (size_t i = 0; i < self->num_ordered_transitions; i++) {
+ khiter_t k;
+ uint128_t key = self->ordered_transitions[i];
+ k = kh_get(RQ_TRACE, self->lookup, key);
+ assert(k != kh_end(self->lookup));
+ dprintf(trace_fd, "%lx,%lx,%lx\n", (uint64_t)(key >> 64), (uint64_t)key,
+ kh_value(self->lookup, k));
+ }
}
-static void redqueen_state_reset(void){
- redqueen_trace_t *self = GET_GLOBAL_STATE()->redqueen_state->trace_state;
- kh_destroy(RQ_TRACE, self->lookup);
- self->lookup = kh_init(RQ_TRACE);
- self->num_ordered_transitions = 0;
+static void redqueen_state_reset(void)
+{
+ redqueen_trace_t *self = GET_GLOBAL_STATE()->redqueen_state->trace_state;
+ kh_destroy(RQ_TRACE, self->lookup);
+ self->lookup = kh_init(RQ_TRACE);
+ self->num_ordered_transitions = 0;
}
-void redqueen_trace_reset(void){
- if (redqueen_trace_enabled) {
- redqueen_state_reset();
- reset_trace_fd();
- }
+void redqueen_trace_reset(void)
+{
+ if (redqueen_trace_enabled) {
+ redqueen_state_reset();
+ reset_trace_fd();
+ }
}
-void redqueen_trace_flush(void){
- if (redqueen_trace_enabled) {
- redqueen_trace_write();
- if (trace_fd)
- fsync(trace_fd);
- }
+void redqueen_trace_flush(void)
+{
+ if (redqueen_trace_enabled) {
+ redqueen_trace_write();
+ if (trace_fd)
+ fsync(trace_fd);
+ }
}
-void redqueen_set_trace_mode(void){
- if (redqueen_trace_enabled) {
- libxdc_enable_tracing(GET_GLOBAL_STATE()->decoder);
- libxdc_register_edge_callback(GET_GLOBAL_STATE()->decoder,
- (void (*)(void*, disassembler_mode_t, uint64_t, uint64_t))&redqueen_trace_register_transition,
- GET_GLOBAL_STATE()->redqueen_state->trace_state);
- }
+void redqueen_set_trace_mode(void)
+{
+ if (redqueen_trace_enabled) {
+ libxdc_enable_tracing(GET_GLOBAL_STATE()->decoder);
+ libxdc_register_edge_callback(GET_GLOBAL_STATE()->decoder,
+ (void (*)(void *, disassembler_mode_t,
+ uint64_t, uint64_t)) &
+ redqueen_trace_register_transition,
+ GET_GLOBAL_STATE()->redqueen_state->trace_state);
+ }
}
-void redqueen_unset_trace_mode(void){
- if (redqueen_trace_enabled) {
- libxdc_disable_tracing(GET_GLOBAL_STATE()->decoder);
- }
+void redqueen_unset_trace_mode(void)
+{
+ if (redqueen_trace_enabled) {
+ libxdc_disable_tracing(GET_GLOBAL_STATE()->decoder);
+ }
}
#ifdef DEBUG_MAIN
-int main(int argc, char** argv){
+int main(int argc, char **argv)
+{
+ redqueen_trace_t *rq_obj = redqueen_trace_new();
- redqueen_trace_t* rq_obj = redqueen_trace_new();
+ reset_trace_fd();
- reset_trace_fd();
+ for (uint64_t j = 0; j < 0x5; j++) {
+ redqueen_trace_register_transition(rq_obj, 0xBADF, 0xC0FFEE);
+ redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE);
+ for (uint64_t i = 0; i < 0x10000; i++) {
+ redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE);
+ }
+ redqueen_trace_write(rq_obj, STDOUT_FILENO);
+ redqueen_trace_reset();
+ }
- for (uint64_t j = 0; j < 0x5; j++){
- redqueen_trace_register_transition(rq_obj, 0xBADF, 0xC0FFEE);
- redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE);
- for (uint64_t i = 0; i < 0x10000; i++){
- redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE);
- }
- redqueen_trace_write(rq_obj, STDOUT_FILENO);
- redqueen_trace_reset();
- }
-
- redqueen_trace_free(rq_obj);
- return 0;
+ redqueen_trace_free(rq_obj);
+ return 0;
}
#endif
diff --git a/nyx/redqueen_trace.h b/nyx/redqueen_trace.h
index 1f527814aa..50f0ca502d 100644
--- a/nyx/redqueen_trace.h
+++ b/nyx/redqueen_trace.h
@@ -1,9 +1,9 @@
#pragma once
+#include
+#include
#include
#include
-#include
-#include
#include "qemu/osdep.h"
@@ -11,7 +11,7 @@
#include
typedef unsigned __int128 uint128_t;
-typedef uint128_t khint128_t;
+typedef uint128_t khint128_t;
#define INIT_NUM_OF_STORED_TRANSITIONS 0xfffff
@@ -20,8 +20,9 @@ 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
*/
@@ -32,27 +33,31 @@ typedef uint128_t khint128_t;
@param name Name of the hash table [symbol]
@param khval_t Type of values [type]
*/
-#define KHASH_MAP_INIT_INT128(name, khval_t) \
- KHASH_INIT(name, khint128_t, khval_t, 1, kh_int128_hash_func, kh_int128_hash_equal)
+#define KHASH_MAP_INIT_INT128(name, khval_t) \
+ KHASH_INIT(name, khint128_t, khval_t, 1, kh_int128_hash_func, \
+ kh_int128_hash_equal)
KHASH_MAP_INIT_INT128(RQ_TRACE, uint64_t)
#define INIT_TRACE_IP 0xFFFFFFFFFFFFFFFFULL
-typedef struct redqueen_trace_s{
- khash_t(RQ_TRACE) *lookup;
- size_t num_ordered_transitions;
- size_t max_ordered_transitions;
- uint128_t* ordered_transitions;
+typedef struct redqueen_trace_s {
+ khash_t(RQ_TRACE) * lookup;
+ size_t num_ordered_transitions;
+ size_t max_ordered_transitions;
+ uint128_t *ordered_transitions;
} redqueen_trace_t;
/* libxdc outputs no bitmap in trace mode */
void alt_bitmap_reset(void);
-void alt_bitmap_init(void* ptr, uint32_t size);
+void alt_bitmap_init(void *ptr, uint32_t size);
-redqueen_trace_t* redqueen_trace_new(void);
-void redqueen_trace_free(redqueen_trace_t* self);
-void redqueen_trace_register_transition(redqueen_trace_t* self, disassembler_mode_t mode, uint64_t from, uint64_t to);
+redqueen_trace_t *redqueen_trace_new(void);
+void redqueen_trace_free(redqueen_trace_t *self);
+void redqueen_trace_register_transition(redqueen_trace_t *self,
+ disassembler_mode_t mode,
+ uint64_t from,
+ uint64_t to);
void redqueen_trace_init(void);
void redqueen_set_trace_mode(void);
diff --git a/nyx/sharedir.c b/nyx/sharedir.c
index 91a1491b78..49cd40924a 100644
--- a/nyx/sharedir.c
+++ b/nyx/sharedir.c
@@ -11,166 +11,171 @@
#include "nyx/debug.h"
#include "sharedir.h"
-//#define SHAREDIR_DEBUG
+// #define SHAREDIR_DEBUG
-sharedir_t* sharedir_new(void){
- sharedir_t* self = malloc(sizeof(sharedir_t));
- self->dir = NULL;
- self->lookup = kh_init(SHAREDIR_LOOKUP);
- self->last_file_f = NULL;
- self->last_file_obj_ptr = NULL;
- return self;
+sharedir_t *sharedir_new(void)
+{
+ sharedir_t *self = malloc(sizeof(sharedir_t));
+ self->dir = NULL;
+ self->lookup = kh_init(SHAREDIR_LOOKUP);
+ self->last_file_f = NULL;
+ self->last_file_obj_ptr = NULL;
+ return self;
}
-void sharedir_set_dir(sharedir_t* self, const char* dir){
- assert(!self->dir);
- assert(asprintf(&self->dir, "%s", dir) != -1);
+void sharedir_set_dir(sharedir_t *self, const char *dir)
+{
+ assert(!self->dir);
+ assert(asprintf(&self->dir, "%s", dir) != -1);
}
-static bool file_exits(const char* file){
- struct stat sb;
- return (stat (file, &sb) == 0);
+static bool file_exits(const char *file)
+{
+ struct stat sb;
+ return (stat(file, &sb) == 0);
}
-static time_t get_file_mod_time(char *file){
+static time_t get_file_mod_time(char *file)
+{
struct stat attr;
stat(file, &attr);
return attr.st_mtime;
}
-static size_t get_file_size(const char* file){
- struct stat st;
- stat(file, &st);
- return st.st_size;
+static size_t get_file_size(const char *file)
+{
+ struct stat st;
+ stat(file, &st);
+ return st.st_size;
}
-static char* sharedir_scan(sharedir_t* self, const char* file){
+static char *sharedir_scan(sharedir_t *self, const char *file)
+{
+ /*
+ * Agent is not under our control, but lets roughly constrain
+ * it to anything stored in or linked from sharedir
+ */
+ chdir(self->dir);
+ char *real_path = realpath(file, NULL);
- /*
- * Agent is not under our control, but lets roughly constrain
- * it to anything stored in or linked from sharedir
- */
- chdir(self->dir);
- char* real_path = realpath(file, NULL);
-
- if (file[0] != '/' && !strstr(file, "/../") &&
- real_path && file_exits(real_path)) {
- return real_path;
- }
-
- free(real_path);
- return NULL;
-}
-
-static sharedir_file_t* sharedir_get_object(sharedir_t* self, const char* file){
- khiter_t k;
- int ret;
- sharedir_file_t* obj = NULL;
-
- k = kh_get(SHAREDIR_LOOKUP, self->lookup, file);
-
- if(k != kh_end(self->lookup)){
- /* file already exists in our hash map */
- obj = kh_value(self->lookup, k);
-
- /* check if file still exists */
- assert(file_exits(obj->path));
-
- /* check if mod time matches */
- assert(get_file_mod_time(obj->path) == obj->mod_time);
-
- /* check if file size matches */
- assert(get_file_size(obj->path) == obj->size);
-
- return obj;
- }
- else{
- /* nope ! */
- char* realpath = sharedir_scan(self, file);
- struct stat sb;
- if(realpath != NULL){
- if (stat(realpath, &sb) == 0 && S_ISDIR(sb.st_mode)){
- return NULL; // is dir
- }
- obj = malloc(sizeof(sharedir_file_t));
- memset(obj, 0x0, sizeof(sharedir_file_t));
- assert(asprintf(&obj->file, "%s", basename(realpath)) != -1);
- obj->path = realpath;
- obj->size = get_file_size(obj->path);
- obj->bytes_left = (uint64_t) obj->size;
- 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);
- kh_value(self->lookup, k) = obj;
-
- return obj;
+ if (file[0] != '/' && !strstr(file, "/../") && real_path && file_exits(real_path))
+ {
+ return real_path;
}
- /* file not found */
+ free(real_path);
return NULL;
- }
}
-static FILE* get_file_ptr(sharedir_t* self, sharedir_file_t* obj){
- if(obj == self->last_file_obj_ptr && self->last_file_f){
- return self->last_file_f;
- }
+static sharedir_file_t *sharedir_get_object(sharedir_t *self, const char *file)
+{
+ khiter_t k;
+ int ret;
+ sharedir_file_t *obj = NULL;
- if(self->last_file_f){
- fclose(self->last_file_f);
- }
+ k = kh_get(SHAREDIR_LOOKUP, self->lookup, file);
- FILE* f = fopen(obj->path, "r");
- self->last_file_f = f;
- self->last_file_obj_ptr = obj;
- return f;
+ if (k != kh_end(self->lookup)) {
+ /* file already exists in our hash map */
+ obj = kh_value(self->lookup, k);
+
+ /* check if file still exists */
+ assert(file_exits(obj->path));
+
+ /* check if mod time matches */
+ assert(get_file_mod_time(obj->path) == obj->mod_time);
+
+ /* check if file size matches */
+ assert(get_file_size(obj->path) == obj->size);
+
+ return obj;
+ } else {
+ /* nope ! */
+ char *realpath = sharedir_scan(self, file);
+ struct stat sb;
+ if (realpath != NULL) {
+ if (stat(realpath, &sb) == 0 && S_ISDIR(sb.st_mode)) {
+ return NULL; // is dir
+ }
+ obj = malloc(sizeof(sharedir_file_t));
+ memset(obj, 0x0, sizeof(sharedir_file_t));
+ assert(asprintf(&obj->file, "%s", basename(realpath)) != -1);
+ obj->path = realpath;
+ obj->size = get_file_size(obj->path);
+ obj->bytes_left = (uint64_t)obj->size;
+ 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);
+ kh_value(self->lookup, k) = obj;
+
+ return obj;
+ }
+
+ /* file not found */
+ return NULL;
+ }
}
-uint64_t sharedir_request_file(sharedir_t* self, const char* file, uint8_t* page_buffer){
- if(!self->dir){
- fprintf(stderr, "WARNING: New file request received, but no share dir configured! [FILE: %s]\n", file);
- return 0xFFFFFFFFFFFFFFFFUL;
- }
+static FILE *get_file_ptr(sharedir_t *self, sharedir_file_t *obj)
+{
+ if (obj == self->last_file_obj_ptr && self->last_file_f) {
+ return self->last_file_f;
+ }
- FILE* f = NULL;
+ if (self->last_file_f) {
+ fclose(self->last_file_f);
+ }
- sharedir_file_t* obj = sharedir_get_object(self, file);
- if(obj != NULL){
+ FILE *f = fopen(obj->path, "r");
+ self->last_file_f = f;
+ self->last_file_obj_ptr = obj;
+ return f;
+}
+
+uint64_t sharedir_request_file(sharedir_t *self, const char *file, uint8_t *page_buffer)
+{
+ if (!self->dir) {
+ fprintf(stderr, "WARNING: New file request received, but no share dir configured! [FILE: %s]\n",
+ file);
+ return 0xFFFFFFFFFFFFFFFFUL;
+ }
+
+ FILE *f = NULL;
+
+ sharedir_file_t *obj = sharedir_get_object(self, file);
+ if (obj != NULL) {
#ifdef SHAREDIR_DEBUG
- printf("sharedir_get_object->file: %s\n", obj->file);
- printf("sharedir_get_object->path: %s\n", obj->path);
- printf("sharedir_get_object->size: %ld\n", obj->size);
- printf("sharedir_get_object->bytes_left: %ld\n", obj->bytes_left);
+ printf("sharedir_get_object->file: %s\n", obj->file);
+ printf("sharedir_get_object->path: %s\n", obj->path);
+ printf("sharedir_get_object->size: %ld\n", obj->size);
+ printf("sharedir_get_object->bytes_left: %ld\n", obj->bytes_left);
#endif
- if(obj->bytes_left >= 0x1000){
- f = get_file_ptr(self, obj);
- fseek(f, obj->size-obj->bytes_left, SEEK_SET);
- assert(fread(page_buffer, 1, 0x1000, f) == 0x1000);
- obj->bytes_left -= 0x1000;
- return 0x1000;
- }
- else {
- if (obj->bytes_left != 0){
- f = get_file_ptr(self, obj);
- fseek(f, obj->size-obj->bytes_left, SEEK_SET);
- assert(fread(page_buffer, 1, obj->bytes_left, f) == obj->bytes_left);
+ if (obj->bytes_left >= 0x1000) {
+ f = get_file_ptr(self, obj);
+ fseek(f, obj->size - obj->bytes_left, SEEK_SET);
+ assert(fread(page_buffer, 1, 0x1000, f) == 0x1000);
+ obj->bytes_left -= 0x1000;
+ return 0x1000;
+ } else {
+ if (obj->bytes_left != 0) {
+ f = get_file_ptr(self, obj);
+ fseek(f, obj->size - obj->bytes_left, SEEK_SET);
+ assert(fread(page_buffer, 1, obj->bytes_left, f) == obj->bytes_left);
- uint64_t ret_value = obj->bytes_left;
- obj->bytes_left = 0;
+ uint64_t ret_value = obj->bytes_left;
+ obj->bytes_left = 0;
- return ret_value;
- }
- else {
- obj->bytes_left = (uint_fast64_t)obj->size;
- return 0;
- }
+ return ret_value;
+ } else {
+ obj->bytes_left = (uint_fast64_t)obj->size;
+ return 0;
+ }
+ }
+ } else {
+ nyx_error("Warning: No such file in sharedir: %s\n", file);
+ return 0xFFFFFFFFFFFFFFFFUL;
}
- }
- else{
- nyx_error("Warning: No such file in sharedir: %s\n", file);
- return 0xFFFFFFFFFFFFFFFFUL;
- }
}
diff --git a/nyx/sharedir.h b/nyx/sharedir.h
index 7ced681329..77b2de1268 100644
--- a/nyx/sharedir.h
+++ b/nyx/sharedir.h
@@ -1,26 +1,26 @@
#pragma once
-#include
-#include
#include "khash.h"
+#include
+#include
-typedef struct sharedir_file_s{
- char* file;
- char* path;
- size_t size;
- uint64_t bytes_left;
- time_t mod_time;
+typedef struct sharedir_file_s {
+ char *file;
+ char *path;
+ size_t size;
+ uint64_t bytes_left;
+ time_t mod_time;
} sharedir_file_t;
-KHASH_MAP_INIT_STR(SHAREDIR_LOOKUP, sharedir_file_t*)
+KHASH_MAP_INIT_STR(SHAREDIR_LOOKUP, sharedir_file_t *)
-typedef struct sharedir_s{
- char* dir;
- khash_t(SHAREDIR_LOOKUP) *lookup;
- FILE* last_file_f;
- sharedir_file_t* last_file_obj_ptr;
+typedef struct sharedir_s {
+ char *dir;
+ khash_t(SHAREDIR_LOOKUP) * lookup;
+ FILE *last_file_f;
+ sharedir_file_t *last_file_obj_ptr;
} sharedir_t;
-sharedir_t* sharedir_new(void);
-void sharedir_set_dir(sharedir_t* self, const char* dir);
-uint64_t sharedir_request_file(sharedir_t* self, const char* file, uint8_t* page_buffer);
+sharedir_t *sharedir_new(void);
+void sharedir_set_dir(sharedir_t *self, const char *dir);
+uint64_t sharedir_request_file(sharedir_t *self, const char *file, uint8_t *page_buffer);
diff --git a/nyx/snapshot/block/block_cow.c b/nyx/snapshot/block/block_cow.c
index 7fb0652df2..18ea59d63e 100644
--- a/nyx/snapshot/block/block_cow.c
+++ b/nyx/snapshot/block/block_cow.c
@@ -1,515 +1,614 @@
#include "qemu/osdep.h"
#include
-#include
#include
+#include
-#include "nyx/snapshot/block/block_cow.h"
#include "sysemu/block-backend.h"
-#include "nyx/state/state.h"
#include "nyx/debug.h"
+#include "nyx/snapshot/block/block_cow.h"
+#include "nyx/state/state.h"
-//#define COW_CACHE_DEBUG
-//#define COW_CACHE_VERBOSE
+// #define COW_CACHE_DEBUG
+// #define COW_CACHE_VERBOSE
-#define CHUNK_SIZE 0x1000
-//0x200
+#define CHUNK_SIZE 0x1000
+// 0x200
#define PAGE_MASK 0xFFFFFFFFFFFFF000
-uint64_t global_cow_primary_size = COW_CACHE_PRIMARY_MINIMUM_SIZE;
-bool global_cow_primary_size_adjustable = true;
+uint64_t global_cow_primary_size = COW_CACHE_PRIMARY_MINIMUM_SIZE;
+bool global_cow_primary_size_adjustable = true;
-void set_global_cow_cache_primary_size(uint64_t new_size){
- if (global_cow_primary_size_adjustable && new_size > COW_CACHE_PRIMARY_MINIMUM_SIZE && (new_size & 0xFFF) == 0){
- global_cow_primary_size = new_size;
- global_cow_primary_size_adjustable = false;
- }
+void set_global_cow_cache_primary_size(uint64_t new_size)
+{
+ if (global_cow_primary_size_adjustable &&
+ new_size > COW_CACHE_PRIMARY_MINIMUM_SIZE && (new_size & 0xFFF) == 0)
+ {
+ global_cow_primary_size = new_size;
+ global_cow_primary_size_adjustable = false;
+ }
}
-static inline uint64_t get_global_cow_cache_primary_size(void){
- return global_cow_primary_size;
+static inline uint64_t get_global_cow_cache_primary_size(void)
+{
+ return global_cow_primary_size;
}
-cow_cache_t* cow_cache_new(const char* filename){
+cow_cache_t *cow_cache_new(const char *filename)
+{
+ cow_cache_t *self = malloc(sizeof(cow_cache_t));
+ self->lookup_primary = kh_init(COW_CACHE);
+ self->lookup_secondary = kh_init(COW_CACHE);
+ self->lookup_secondary_tmp = kh_init(COW_CACHE);
- cow_cache_t* self = malloc(sizeof(cow_cache_t));
- self->lookup_primary = kh_init(COW_CACHE);
- self->lookup_secondary = kh_init(COW_CACHE);
- self->lookup_secondary_tmp = kh_init(COW_CACHE);
+ 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);
- 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);
+ 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);
- 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);
+ self->data_secondary_tmp = mmap(NULL, COW_CACHE_SECONDARY_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
+ assert(self->data_secondary_tmp != MAP_FAILED);
- self->data_secondary_tmp = mmap(NULL, COW_CACHE_SECONDARY_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, 0, 0);
- assert(self->data_secondary_tmp != MAP_FAILED);
+ self->filename = strdup(basename(filename));
+ self->offset_primary = 0;
+ self->offset_secondary = 0;
+ self->offset_secondary_tmp = 0;
- self->filename = strdup(basename(filename));
- self->offset_primary = 0;
- self->offset_secondary = 0;
- self->offset_secondary_tmp = 0;
-
- if(getenv("NYX_DISABLE_BLOCK_COW")){
- fprintf(stderr, "WARNING: Nyx block COW layer disabled for %s (** write operations are not cached **)\n", filename);
- self->enabled = false;
- }
- else{
- self->enabled = true;
- }
- self->enabled_fuzz = false;
- self->enabled_fuzz_tmp = false;
+ if (getenv("NYX_DISABLE_BLOCK_COW")) {
+ fprintf(stderr,
+ "WARNING: Nyx block COW layer disabled for %s (** write operations "
+ "are not cached **)\n",
+ filename);
+ self->enabled = false;
+ } else {
+ self->enabled = true;
+ }
+ self->enabled_fuzz = false;
+ self->enabled_fuzz_tmp = false;
#ifdef DEBUG_COW_LAYER
- self->read_calls = 0;
- self->write_calls = 0;
- self->read_calls_tmp = 0;
- self->write_calls_tmp = 0;
+ self->read_calls = 0;
+ self->write_calls = 0;
+ self->read_calls_tmp = 0;
+ self->write_calls_tmp = 0;
#endif
- return self;
+ return self;
}
-static char* gen_file_name(cow_cache_t* self, const char* filename_prefix, const char* filename_postfix){
- char* tmp1;
- char* tmp2;
+static char *gen_file_name(cow_cache_t *self,
+ const char *filename_prefix,
+ const char *filename_postfix)
+{
+ char *tmp1;
+ char *tmp2;
- assert(asprintf(&tmp2, "%s", self->filename) != -1);
+ assert(asprintf(&tmp2, "%s", self->filename) != -1);
- for(int i = 0; i < strlen(tmp2); i++){
- if(tmp2[i] == '/'){
- tmp2[i] = '_';
- }
- }
+ for (int i = 0; i < strlen(tmp2); i++) {
+ if (tmp2[i] == '/') {
+ tmp2[i] = '_';
+ }
+ }
- assert(asprintf(&tmp1, "%s_%s.%s", filename_prefix, tmp2, filename_postfix) != -1);
- free(tmp2);
+ assert(asprintf(&tmp1, "%s_%s.%s", filename_prefix, tmp2, filename_postfix) != -1);
+ free(tmp2);
- return tmp1;
+ return tmp1;
}
-void read_primary_buffer(cow_cache_t* self, const char* filename_prefix, bool switch_mode){
- assert(!self->enabled_fuzz);
- global_cow_primary_size_adjustable = false;
+void read_primary_buffer(cow_cache_t *self, const char *filename_prefix, bool switch_mode)
+{
+ assert(!self->enabled_fuzz);
+ global_cow_primary_size_adjustable = false;
- char* tmp1;
- char* tmp2;
+ char *tmp1;
+ char *tmp2;
- tmp1 = gen_file_name(self, filename_prefix, "khash");
- tmp2 = gen_file_name(self, filename_prefix, "pcow");
+ tmp1 = gen_file_name(self, filename_prefix, "khash");
+ tmp2 = gen_file_name(self, filename_prefix, "pcow");
- kh_destroy(COW_CACHE, self->lookup_primary);
+ kh_destroy(COW_CACHE, self->lookup_primary);
- struct stat buffer;
- assert(stat (tmp2, &buffer) == 0);
+ struct stat buffer;
+ assert(stat(tmp2, &buffer) == 0);
- if (buffer.st_size > get_global_cow_cache_primary_size()){
- fprintf(stderr, "ERROR: in-memory CoW buffer is too small compared to snapshot file (buffer: 0x%lx / file: 0x%lx)\n", get_global_cow_cache_primary_size(), buffer.st_size);
- exit(1);
- }
+ if (buffer.st_size > get_global_cow_cache_primary_size()) {
+ fprintf(stderr,
+ "ERROR: in-memory CoW buffer is too small compared to snapshot file "
+ "(buffer: 0x%lx / file: 0x%lx)\n",
+ get_global_cow_cache_primary_size(), buffer.st_size);
+ exit(1);
+ }
- if(buffer.st_size){
- self->lookup_primary = kh_load(COW_CACHE, tmp1);
- }
- else {
- self->lookup_primary = kh_init(COW_CACHE);
- }
+ if (buffer.st_size) {
+ self->lookup_primary = kh_load(COW_CACHE, tmp1);
+ } else {
+ self->lookup_primary = kh_init(COW_CACHE);
+ }
- int fd = open(tmp2, O_RDONLY);
-
- if(switch_mode){
- munmap(self->data_primary, self->cow_primary_size);
- self->cow_primary_size = get_global_cow_cache_primary_size();
- self->data_primary = mmap(0, self->cow_primary_size, PROT_READ, MAP_SHARED, fd, 0);
- assert(self->data_primary);
- }
- else{
+ int fd = open(tmp2, O_RDONLY);
- if(get_global_cow_cache_primary_size() != self->cow_primary_size){
- munmap(self->data_primary, self->cow_primary_size);
- self->cow_primary_size = get_global_cow_cache_primary_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);
- }
+ if (switch_mode) {
+ munmap(self->data_primary, self->cow_primary_size);
+ self->cow_primary_size = get_global_cow_cache_primary_size();
+ self->data_primary =
+ mmap(0, self->cow_primary_size, PROT_READ, MAP_SHARED, fd, 0);
+ assert(self->data_primary);
+ } else {
+ if (get_global_cow_cache_primary_size() != self->cow_primary_size) {
+ munmap(self->data_primary, self->cow_primary_size);
+ self->cow_primary_size = get_global_cow_cache_primary_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);
+ }
- void* ptr = mmap(0, COW_CACHE_PRIMARY_MINIMUM_SIZE, PROT_READ , MAP_SHARED, fd, 0);
- assert(ptr);
- memcpy(self->data_primary, ptr, buffer.st_size);
- munmap(ptr, COW_CACHE_PRIMARY_MINIMUM_SIZE);
- }
- close(fd);
+ void *ptr =
+ mmap(0, COW_CACHE_PRIMARY_MINIMUM_SIZE, PROT_READ, MAP_SHARED, fd, 0);
+ assert(ptr);
+ memcpy(self->data_primary, ptr, buffer.st_size);
+ munmap(ptr, COW_CACHE_PRIMARY_MINIMUM_SIZE);
+ }
+ close(fd);
- self->offset_primary = buffer.st_size;
+ self->offset_primary = buffer.st_size;
- if(switch_mode){
- switch_to_fuzz_mode(self);
- }
+ if (switch_mode) {
+ switch_to_fuzz_mode(self);
+ }
- free(tmp1);
- free(tmp2);
+ free(tmp1);
+ free(tmp2);
}
-void dump_primary_buffer(cow_cache_t* self, const char* filename_prefix){
- assert(self->enabled_fuzz);
+void dump_primary_buffer(cow_cache_t *self, const char *filename_prefix)
+{
+ assert(self->enabled_fuzz);
- char* tmp1;
- char* tmp2;
+ char *tmp1;
+ char *tmp2;
- tmp1 = gen_file_name(self, filename_prefix, "khash");
- tmp2 = gen_file_name(self, filename_prefix, "pcow");
+ tmp1 = gen_file_name(self, filename_prefix, "khash");
+ tmp2 = gen_file_name(self, filename_prefix, "pcow");
- if(self->offset_primary){
- kh_write(COW_CACHE, self->lookup_primary, tmp1);
- }
- else{
- fclose(fopen(tmp1, "wb"));
- }
+ if (self->offset_primary) {
+ kh_write(COW_CACHE, self->lookup_primary, tmp1);
+ } else {
+ fclose(fopen(tmp1, "wb"));
+ }
- FILE *fp = fopen(tmp2, "wb");
- if(fp == NULL) {
- fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp2);
- assert(false);
- }
+ FILE *fp = fopen(tmp2, "wb");
+ if (fp == NULL) {
+ fprintf(stderr, "[%s] Could not open file %s.\n", __func__, tmp2);
+ assert(false);
+ }
- if(self->offset_primary){
- fwrite(self->data_primary, CHUNK_SIZE, self->offset_primary/CHUNK_SIZE, fp);
- }
+ if (self->offset_primary) {
+ fwrite(self->data_primary, CHUNK_SIZE, self->offset_primary / CHUNK_SIZE, fp);
+ }
- fclose(fp);
+ fclose(fp);
- free(tmp1);
- free(tmp2);
+ free(tmp1);
+ free(tmp2);
}
-void cow_cache_reset(cow_cache_t* self){
- if(!self->enabled_fuzz)
- return;
- /* TODO */
- assert(self->enabled_fuzz);
-
- if(self->enabled_fuzz){
+void cow_cache_reset(cow_cache_t *self)
+{
+ if (!self->enabled_fuzz)
+ return;
+ /* TODO */
+ assert(self->enabled_fuzz);
+ if (self->enabled_fuzz) {
#ifdef DEBUG_COW_LAYER
- printf("%s: read_calls =>\t%ld\n", __func__, self->read_calls);
- printf("%s: write_calls =>\t%ld\n", __func__, self->write_calls);
- printf("%s: read_calls_tmp =>\t%ld\n", __func__, self->read_calls_tmp);
- printf("%s: write_calls_tmp =>\t%ld\n", __func__, self->write_calls_tmp);
-#endif
-
- if(!self->enabled_fuzz_tmp){
- self->offset_secondary = 0;
- kh_clear(COW_CACHE, self->lookup_secondary);
-
-#ifdef DEBUG_COW_LAYER
- self->read_calls = 0;
- self->write_calls = 0;
+ printf("%s: read_calls =>\t%ld\n", __func__, self->read_calls);
+ printf("%s: write_calls =>\t%ld\n", __func__, self->write_calls);
+ printf("%s: read_calls_tmp =>\t%ld\n", __func__, self->read_calls_tmp);
+ printf("%s: write_calls_tmp =>\t%ld\n", __func__, self->write_calls_tmp);
#endif
- }
- else {
- self->offset_secondary_tmp = 0;
- kh_clear(COW_CACHE, self->lookup_secondary_tmp);
+
+ if (!self->enabled_fuzz_tmp) {
+ self->offset_secondary = 0;
+ kh_clear(COW_CACHE, self->lookup_secondary);
#ifdef DEBUG_COW_LAYER
- printf("CLEAR lookup_secondary_tmp\n");
- self->read_calls_tmp = 0;
- self->write_calls_tmp = 0;
+ self->read_calls = 0;
+ self->write_calls = 0;
#endif
- }
- }
+ } else {
+ self->offset_secondary_tmp = 0;
+ kh_clear(COW_CACHE, self->lookup_secondary_tmp);
+
+#ifdef DEBUG_COW_LAYER
+ printf("CLEAR lookup_secondary_tmp\n");
+ self->read_calls_tmp = 0;
+ self->write_calls_tmp = 0;
+#endif
+ }
+ }
}
-void cow_cache_enable_tmp_mode(cow_cache_t* self){
- assert(self->enabled_fuzz);
- self->enabled_fuzz_tmp = true;
+void cow_cache_enable_tmp_mode(cow_cache_t *self)
+{
+ assert(self->enabled_fuzz);
+ self->enabled_fuzz_tmp = true;
}
-void cow_cache_disable_tmp_mode(cow_cache_t* self){
- assert(self->enabled_fuzz);
- assert(self->enabled_fuzz_tmp);
- cow_cache_reset(self);
- self->enabled_fuzz_tmp = false;
+void cow_cache_disable_tmp_mode(cow_cache_t *self)
+{
+ assert(self->enabled_fuzz);
+ assert(self->enabled_fuzz_tmp);
+ cow_cache_reset(self);
+ self->enabled_fuzz_tmp = false;
}
-void cow_cache_enable(cow_cache_t* self){
- cow_cache_reset(self);
- self->enabled = true;
+void cow_cache_enable(cow_cache_t *self)
+{
+ cow_cache_reset(self);
+ self->enabled = true;
}
-void cow_cache_disable(cow_cache_t* self){
- cow_cache_reset(self);
- self->enabled = false;
+void cow_cache_disable(cow_cache_t *self)
+{
+ cow_cache_reset(self);
+ self->enabled = false;
}
typedef struct BlkRwCo {
- BlockBackend *blk;
- int64_t offset;
- QEMUIOVector *qiov;
- int ret;
+ BlockBackend *blk;
+ int64_t offset;
+ QEMUIOVector *qiov;
+ int ret;
BdrvRequestFlags flags;
} BlkRwCo;
typedef struct BlkAioEmAIOCB {
BlockAIOCB common;
- BlkRwCo rwco;
- int bytes;
- bool has_returned;
+ BlkRwCo rwco;
+ int bytes;
+ bool has_returned;
} BlkAioEmAIOCB;
extern void blk_aio_write_entry(void *opaque);
-extern int blk_check_byte_request(BlockBackend *blk, int64_t offset, size_t size);
+extern int blk_check_byte_request(BlockBackend *blk, int64_t offset, size_t size);
extern void blk_aio_complete(BlkAioEmAIOCB *acb);
/* read from primary buffer */
-static inline void read_from_primary_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){
- khiter_t k;
+static inline void read_from_primary_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)
+{
+ khiter_t k;
- k = kh_get(COW_CACHE, self->lookup_primary, offset_addr);
- if(k != kh_end(self->lookup_primary)){
- #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
- qemu_iovec_from_buf(qiov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
- }
- return;
+ k = kh_get(COW_CACHE, self->lookup_primary, offset_addr);
+ if (k != kh_end(self->lookup_primary)) {
+#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
+ qemu_iovec_from_buf(qiov, iov_offset,
+ self->data_primary + kh_value(self->lookup_primary, k),
+ CHUNK_SIZE);
+ }
+ return;
}
/* try to read from secondary buffer
* read from primary buffer if the data is not available yet */
-static inline void read_from_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){
- /* read from L2 TMP buffer */
- khiter_t k;
- if(self->enabled_fuzz_tmp){
- k = kh_get(COW_CACHE, self->lookup_secondary_tmp, offset_addr);
- if(k != kh_end(self->lookup_secondary_tmp)){
- #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
- qemu_iovec_from_buf(qiov, iov_offset, self->data_secondary_tmp + kh_value(self->lookup_secondary_tmp, k), CHUNK_SIZE);
- return;
- }
- }
+static inline void read_from_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)
+{
+ /* read from L2 TMP buffer */
+ khiter_t k;
+ if (self->enabled_fuzz_tmp) {
+ k = kh_get(COW_CACHE, self->lookup_secondary_tmp, offset_addr);
+ if (k != kh_end(self->lookup_secondary_tmp)) {
+#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
+ qemu_iovec_from_buf(qiov, iov_offset,
+ self->data_secondary_tmp +
+ kh_value(self->lookup_secondary_tmp, k),
+ CHUNK_SIZE);
+ return;
+ }
+ }
- /* read from L2 buffer */
- k = kh_get(COW_CACHE, self->lookup_secondary, offset_addr);
- if(k != kh_end(self->lookup_secondary)){
- #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
- qemu_iovec_from_buf(qiov, iov_offset, self->data_secondary + kh_value(self->lookup_secondary, k), CHUNK_SIZE);
- return;
- }
+ /* read from L2 buffer */
+ k = kh_get(COW_CACHE, self->lookup_secondary, offset_addr);
+ if (k != kh_end(self->lookup_secondary)) {
+#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
+ qemu_iovec_from_buf(qiov, iov_offset,
+ self->data_secondary + kh_value(self->lookup_secondary, k),
+ CHUNK_SIZE);
+ return;
+ }
- /* read from L1 buffer */
- k = kh_get(COW_CACHE, self->lookup_primary, offset_addr);
- if(k != kh_end(self->lookup_primary)){
- #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
- qemu_iovec_from_buf(qiov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
- }
+ /* read from L1 buffer */
+ k = kh_get(COW_CACHE, self->lookup_primary, offset_addr);
+ if (k != kh_end(self->lookup_primary)) {
+#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
+ qemu_iovec_from_buf(qiov, iov_offset,
+ self->data_primary + kh_value(self->lookup_primary, k),
+ CHUNK_SIZE);
+ }
}
/* read data from cow cache */
-static int cow_cache_read(cow_cache_t* self, BlockBackend *blk, int64_t offset, unsigned int bytes, QEMUIOVector *qiov, BdrvRequestFlags flags){
-
+static int cow_cache_read(cow_cache_t *self,
+ BlockBackend *blk,
+ int64_t offset,
+ unsigned int bytes,
+ QEMUIOVector *qiov,
+ BdrvRequestFlags flags)
+{
#ifdef DEBUG_COW_LAYER
- if(self->enabled_fuzz){
- if(!self->enabled_fuzz_tmp){
- self->read_calls++;
- }
- else{
- self->read_calls_tmp++;
- }
- }
-#endif
- blk_co_preadv(blk, offset, bytes, qiov, flags);
-
- if ((qiov->size%CHUNK_SIZE)){
-#ifdef COW_CACHE_DEBUG
- fprintf(stderr, "%s: FAILED %lx!\n", __func__, qiov->size);
-#endif
- return 0;
+ if (self->enabled_fuzz) {
+ if (!self->enabled_fuzz_tmp) {
+ self->read_calls++;
+ } else {
+ self->read_calls_tmp++;
+ }
}
- assert(!(qiov->size%CHUNK_SIZE));
-
- uint64_t iov_offset = 0;
- for(uint64_t offset_addr = offset; offset_addr < (offset+(qiov->size)); offset_addr+= CHUNK_SIZE){
+#endif
+ blk_co_preadv(blk, offset, bytes, qiov, flags);
- if(self->enabled_fuzz){
- read_from_secondary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags, offset_addr, iov_offset);
- }
- else{
- read_from_primary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags, offset_addr, iov_offset);
- }
+ if ((qiov->size % CHUNK_SIZE)) {
+#ifdef COW_CACHE_DEBUG
+ fprintf(stderr, "%s: FAILED %lx!\n", __func__, qiov->size);
+#endif
+ return 0;
+ }
+ assert(!(qiov->size % CHUNK_SIZE));
- iov_offset+= CHUNK_SIZE;
- }
+ uint64_t iov_offset = 0;
+ for (uint64_t offset_addr = offset; offset_addr < (offset + (qiov->size));
+ offset_addr += CHUNK_SIZE)
+ {
+ if (self->enabled_fuzz) {
+ read_from_secondary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags,
+ offset_addr, iov_offset);
+ } else {
+ read_from_primary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags,
+ offset_addr, iov_offset);
+ }
- return 0;
+ iov_offset += CHUNK_SIZE;
+ }
+
+ return 0;
}
/* write to primary buffer */
-static inline void write_to_primary_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;
- khiter_t k;
+static inline void write_to_primary_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;
+ khiter_t k;
- 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);
- #endif
+ 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);
+#endif
- kh_value(self->lookup_primary, k) = self->offset_primary;
+ kh_value(self->lookup_primary, k) = self->offset_primary;
- self->offset_primary += CHUNK_SIZE;
+ self->offset_primary += CHUNK_SIZE;
- #ifdef COW_CACHE_VERBOSE
- printf("COW CACHE IS 0x%lx BYTES (KB: %ld / MB: %ld / GB: %ld) IN SIZE!\n", self->offset, self->offset >> 10, self->offset >> 20, self->offset >> 30);
- #endif
+#ifdef COW_CACHE_VERBOSE
+ printf("COW CACHE IS 0x%lx BYTES (KB: %ld / MB: %ld / GB: %ld) IN SIZE!\n",
+ self->offset, self->offset >> 10, self->offset >> 20,
+ self->offset >> 30);
+#endif
- /* IN CASE THE BUFFER IS FULL -> ABORT! */
- assert(self->offset_primary < self->cow_primary_size);
- }
+ /* IN CASE THE BUFFER IS FULL -> ABORT! */
+ assert(self->offset_primary < self->cow_primary_size);
+ }
- #ifdef COW_CACHE_DEBUG
- printf("LOAD COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx (%s)\n", offset_addr, iov_offset, kh_value(self->lookup_primary, k), self->filename);
- #endif
+#ifdef COW_CACHE_DEBUG
+ printf("LOAD COW PAGE: ADDR: %lx IOVEC OFFSET: %lx DATA OFFSET: %lx (%s)\n",
+ offset_addr, iov_offset, kh_value(self->lookup_primary, k), self->filename);
+#endif
- /* write to cached page */
- qemu_iovec_to_buf(qiov, iov_offset, self->data_primary + kh_value(self->lookup_primary, k), CHUNK_SIZE);
+ /* write to cached page */
+ qemu_iovec_to_buf(qiov, iov_offset,
+ self->data_primary + kh_value(self->lookup_primary, k),
+ CHUNK_SIZE);
}
-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;
+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;
- if(!self->enabled_fuzz_tmp){
- /* L2 mode */
+ if (!self->enabled_fuzz_tmp) {
+ /* L2 mode */
- /* IN CASE THE BUFFER IS FULL -> ABORT! */
- if(self->offset_secondary >= COW_CACHE_SECONDARY_SIZE){
- GET_GLOBAL_STATE()->cow_cache_full = true;
- abort();
- return;
+ /* IN CASE THE BUFFER IS FULL -> ABORT! */
+ if (self->offset_secondary >= COW_CACHE_SECONDARY_SIZE) {
+ GET_GLOBAL_STATE()->cow_cache_full = true;
+ abort();
+ return;
+ }
+
+ khiter_t k_secondary = kh_get(COW_CACHE, self->lookup_secondary, offset_addr);
+ if (unlikely(k_secondary == kh_end(self->lookup_secondary))) {
+ /* if page is not cached in secondary buffer yet */
+ k_secondary = kh_put(COW_CACHE, self->lookup_secondary, offset_addr, &ret);
+ kh_value(self->lookup_secondary, k_secondary) = self->offset_secondary;
+ self->offset_secondary += CHUNK_SIZE;
+ }
+ /* write to cache */
+ qemu_iovec_to_buf(qiov, iov_offset,
+ self->data_secondary +
+ kh_value(self->lookup_secondary, k_secondary),
+ CHUNK_SIZE);
+ } else {
+ /* L2 TMP mode */
+
+ /* IN CASE THE BUFFER IS FULL -> ABORT! */
+ if (self->offset_secondary_tmp >= COW_CACHE_SECONDARY_SIZE) {
+ GET_GLOBAL_STATE()->cow_cache_full = true;
+ abort();
+ return;
+ }
+
+ khiter_t k_secondary_tmp =
+ kh_get(COW_CACHE, self->lookup_secondary_tmp, offset_addr);
+ if (unlikely(k_secondary_tmp == kh_end(self->lookup_secondary_tmp))) {
+ /* if page is not cached in secondary tmp buffer yet */
+ k_secondary_tmp =
+ kh_put(COW_CACHE, self->lookup_secondary_tmp, offset_addr, &ret);
+ kh_value(self->lookup_secondary_tmp, k_secondary_tmp) =
+ self->offset_secondary_tmp;
+ self->offset_secondary_tmp += CHUNK_SIZE;
+ }
+
+ /* write to cache */
+ qemu_iovec_to_buf(qiov, iov_offset,
+ self->data_secondary_tmp +
+ kh_value(self->lookup_secondary_tmp, k_secondary_tmp),
+ CHUNK_SIZE);
}
-
- khiter_t k_secondary = kh_get(COW_CACHE, self->lookup_secondary, offset_addr);
- if(unlikely(k_secondary == kh_end(self->lookup_secondary))){
- /* if page is not cached in secondary buffer yet */
- k_secondary = kh_put(COW_CACHE, self->lookup_secondary, offset_addr, &ret);
- kh_value(self->lookup_secondary, k_secondary) = self->offset_secondary;
- self->offset_secondary += CHUNK_SIZE;
-
- }
- /* write to cache */
- qemu_iovec_to_buf(qiov, iov_offset, self->data_secondary + kh_value(self->lookup_secondary, k_secondary), CHUNK_SIZE);
- }
- else{
- /* L2 TMP mode */
-
- /* IN CASE THE BUFFER IS FULL -> ABORT! */
- if(self->offset_secondary_tmp >= COW_CACHE_SECONDARY_SIZE){
- GET_GLOBAL_STATE()->cow_cache_full = true;
- abort();
- return;
- }
-
- khiter_t k_secondary_tmp = kh_get(COW_CACHE, self->lookup_secondary_tmp, offset_addr);
- if(unlikely(k_secondary_tmp == kh_end(self->lookup_secondary_tmp))){
- /* if page is not cached in secondary tmp buffer yet */
- k_secondary_tmp = kh_put(COW_CACHE, self->lookup_secondary_tmp, offset_addr, &ret);
- kh_value(self->lookup_secondary_tmp, k_secondary_tmp) = self->offset_secondary_tmp;
- self->offset_secondary_tmp += CHUNK_SIZE;
- }
-
- /* write to cache */
- 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){
-
+static int cow_cache_write(cow_cache_t *self,
+ BlockBackend *blk,
+ int64_t offset,
+ unsigned int bytes,
+ QEMUIOVector *qiov,
+ BdrvRequestFlags flags)
+{
#ifdef DEBUG_COW_LAYER
- if(self->enabled_fuzz){
- if(!self->enabled_fuzz_tmp){
- self->write_calls++;
- }
- else{
- self->write_calls_tmp++;
- }
- }
+ if (self->enabled_fuzz) {
+ if (!self->enabled_fuzz_tmp) {
+ self->write_calls++;
+ } else {
+ self->write_calls_tmp++;
+ }
+ }
#endif
- if ((qiov->size%CHUNK_SIZE)){
+ if ((qiov->size % CHUNK_SIZE)) {
#ifdef COW_CACHE_DEBUG
- fprintf(stderr, "%s: FAILED %lx!\n", __func__, qiov->size);
+ fprintf(stderr, "%s: FAILED %lx!\n", __func__, qiov->size);
#endif
- return 0;
- }
- 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);
- return 0;
- }
- else{
- assert(!(qiov->size%CHUNK_SIZE));
- }
-
- uint64_t iov_offset = 0;
- for(uint64_t offset_addr = offset; offset_addr < (offset+(qiov->size)); offset_addr+= CHUNK_SIZE){
- if(self->enabled_fuzz){
- write_to_secondary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags, offset_addr, iov_offset);
- }
- else{
- write_to_primary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags, offset_addr, iov_offset);
- }
+ return 0;
+ }
+ 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);
+ return 0;
+ } else {
+ assert(!(qiov->size % CHUNK_SIZE));
+ }
- iov_offset+= CHUNK_SIZE;
- }
+ uint64_t iov_offset = 0;
+ for (uint64_t offset_addr = offset; offset_addr < (offset + (qiov->size));
+ offset_addr += CHUNK_SIZE)
+ {
+ if (self->enabled_fuzz) {
+ write_to_secondary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags,
+ offset_addr, iov_offset);
+ } else {
+ write_to_primary_buffer(self, blk, offset, CHUNK_SIZE, qiov, flags,
+ offset_addr, iov_offset);
+ }
- return 0;
+ iov_offset += CHUNK_SIZE;
+ }
+
+ return 0;
}
-void switch_to_fuzz_mode(cow_cache_t* self){
- self->enabled_fuzz = true;
- assert(!mprotect(self->data_primary, self->cow_primary_size, PROT_READ));
- nyx_debug("switching to secondary CoW buffer\n");
+void switch_to_fuzz_mode(cow_cache_t *self)
+{
+ self->enabled_fuzz = true;
+ assert(!mprotect(self->data_primary, self->cow_primary_size, PROT_READ));
+ nyx_debug("switching to secondary CoW buffer\n");
}
-void cow_cache_read_entry(void* opaque){
-
- BlkAioEmAIOCB *acb = opaque;
- BlkRwCo *rwco = &acb->rwco;
+void cow_cache_read_entry(void *opaque)
+{
+ BlkAioEmAIOCB *acb = opaque;
+ BlkRwCo *rwco = &acb->rwco;
#ifdef COW_CACHE_DEBUG
- printf("%s %lx %lx\n", __func__, rwco->offset, acb->bytes);
+ printf("%s %lx %lx\n", __func__, rwco->offset, acb->bytes);
#endif
- rwco->ret = cow_cache_read( *((cow_cache_t**)(rwco->blk)), rwco->blk, rwco->offset, acb->bytes, rwco->qiov, rwco->flags);
+ rwco->ret = cow_cache_read(*((cow_cache_t **)(rwco->blk)), rwco->blk,
+ rwco->offset, acb->bytes, rwco->qiov, rwco->flags);
blk_aio_complete(acb);
}
-void cow_cache_write_entry(void* opaque){
- BlkAioEmAIOCB *acb = opaque;
- BlkRwCo *rwco = &acb->rwco;
+void cow_cache_write_entry(void *opaque)
+{
+ BlkAioEmAIOCB *acb = opaque;
+ BlkRwCo *rwco = &acb->rwco;
#ifdef COW_CACHE_DEBUG
- printf("%s\n", __func__);
+ printf("%s\n", __func__);
#endif
- rwco->ret = cow_cache_write( *((cow_cache_t**)(rwco->blk)), rwco->blk, rwco->offset, acb->bytes, rwco->qiov, rwco->flags);
+ rwco->ret = cow_cache_write(*((cow_cache_t **)(rwco->blk)), rwco->blk,
+ rwco->offset, acb->bytes, rwco->qiov, rwco->flags);
blk_aio_complete(acb);
}
diff --git a/nyx/snapshot/block/block_cow.h b/nyx/snapshot/block/block_cow.h
index 55a65226da..480a082c06 100644
--- a/nyx/snapshot/block/block_cow.h
+++ b/nyx/snapshot/block/block_cow.h
@@ -1,4 +1,4 @@
-#pragma once
+#pragma once
#include
@@ -10,66 +10,68 @@
#include "nyx/khash.h"
#include "nyx/redqueen_trace.h"
-//#define DEBUG_COW_LAYER
+// #define DEBUG_COW_LAYER
-/* Minimum size of CoW buffer that stores data written to
+/* Minimum size of CoW buffer that stores data written to
* the block device between boot time and root snapshot (3GB)
*/
#define COW_CACHE_PRIMARY_MINIMUM_SIZE 0xC0000000
-/* Size of CoW buffer which stores data written to
- * the block device between the root snapshot and the
- * next snapshot restore (3GB). This buffer is allocated
- * twice to store the incremental snapshot delta.
+/* Size of CoW buffer which stores data written to
+ * the block device between the root snapshot and the
+ * next snapshot restore (3GB). This buffer is allocated
+ * twice to store the incremental snapshot delta.
*/
#define COW_CACHE_SECONDARY_SIZE 0xC0000000
KHASH_MAP_INIT_INT64(COW_CACHE, uint64_t)
-typedef struct cow_cache_s{
- khash_t(COW_CACHE) *lookup_primary;
- khash_t(COW_CACHE) *lookup_secondary;
- khash_t(COW_CACHE) *lookup_secondary_tmp;
+typedef struct cow_cache_s {
+ khash_t(COW_CACHE) * lookup_primary;
+ khash_t(COW_CACHE) * lookup_secondary;
+ khash_t(COW_CACHE) * lookup_secondary_tmp;
- void* data_primary;
- void* data_secondary;
- void* data_secondary_tmp;
+ void *data_primary;
+ void *data_secondary;
+ void *data_secondary_tmp;
- uint64_t cow_primary_size;
+ uint64_t cow_primary_size;
- char* filename;
- uint64_t offset_primary;
- uint64_t offset_secondary;
- uint64_t offset_secondary_tmp;
+ char *filename;
+ uint64_t offset_primary;
+ uint64_t offset_secondary;
+ uint64_t offset_secondary_tmp;
- bool enabled;
- bool enabled_fuzz;
- bool enabled_fuzz_tmp;
+ bool enabled;
+ bool enabled_fuzz;
+ bool enabled_fuzz_tmp;
#ifdef DEBUG_COW_LAYER
- uint64_t read_calls;
- uint64_t write_calls;
- uint64_t read_calls_tmp;
- uint64_t write_calls_tmp;
+ uint64_t read_calls;
+ uint64_t write_calls;
+ uint64_t read_calls_tmp;
+ uint64_t write_calls_tmp;
#endif
} cow_cache_t;
-cow_cache_t* cow_cache_new(const char* filename);
-void cow_cache_reset(cow_cache_t* self);
+cow_cache_t *cow_cache_new(const char *filename);
+void cow_cache_reset(cow_cache_t *self);
-void switch_to_fuzz_mode(cow_cache_t* self);
+void switch_to_fuzz_mode(cow_cache_t *self);
-void read_primary_buffer(cow_cache_t* self, const char* filename_prefix, bool switch_mode);
-void dump_primary_buffer(cow_cache_t* self, const char* filename_prefix);
+void read_primary_buffer(cow_cache_t *self,
+ const char *filename_prefix,
+ bool switch_mode);
+void dump_primary_buffer(cow_cache_t *self, const char *filename_prefix);
-void cow_cache_read_entry(void* opaque);
-void cow_cache_write_entry(void* opaque);
+void cow_cache_read_entry(void *opaque);
+void cow_cache_write_entry(void *opaque);
-void cow_cache_enable(cow_cache_t* self);
-void cow_cache_disable(cow_cache_t* self);
+void cow_cache_enable(cow_cache_t *self);
+void cow_cache_disable(cow_cache_t *self);
-void cow_cache_enable_tmp_mode(cow_cache_t* self);
-void cow_cache_disable_tmp_mode(cow_cache_t* self);
+void cow_cache_enable_tmp_mode(cow_cache_t *self);
+void cow_cache_disable_tmp_mode(cow_cache_t *self);
void set_global_cow_cache_primary_size(uint64_t new_size);
diff --git a/nyx/snapshot/block/nyx_block_snapshot.c b/nyx/snapshot/block/nyx_block_snapshot.c
index 9186ec153f..43d1fe8f59 100644
--- a/nyx/snapshot/block/nyx_block_snapshot.c
+++ b/nyx/snapshot/block/nyx_block_snapshot.c
@@ -11,22 +11,22 @@
#include "nyx/snapshot/block/nyx_block_snapshot.h"
#include "nyx/state/state.h"
-typedef struct fast_reload_cow_entry_s{
- uint32_t id;
- char idstr[256];
-} fast_reload_cow_entry_t;
+typedef struct fast_reload_cow_entry_s {
+ uint32_t id;
+ char idstr[256];
+} fast_reload_cow_entry_t;
-nyx_block_t* nyx_block_snapshot_init_from_file(const char* folder, bool pre_snapshot){
-
- nyx_block_t* self = malloc(sizeof(nyx_block_t));
+nyx_block_t *nyx_block_snapshot_init_from_file(const char *folder, bool pre_snapshot)
+{
+ nyx_block_t *self = malloc(sizeof(nyx_block_t));
memset(self, 0, sizeof(nyx_block_t));
- BlockBackend *blk;
+ BlockBackend *blk;
fast_reload_cow_entry_t entry;
- char* tmp1;
- char* tmp2;
+ char *tmp1;
+ char *tmp2;
assert(asprintf(&tmp1, "%s/fs_cache.meta", folder) != -1);
assert(asprintf(&tmp2, "%s/fs_drv", folder) != -1);
@@ -34,29 +34,30 @@ nyx_block_t* nyx_block_snapshot_init_from_file(const char* folder, bool pre_snap
self->cow_cache_array_size = 0;
- FILE* f = fopen (tmp1, "r");
+ FILE *f = fopen(tmp1, "r");
assert(f != NULL);
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
- if(blk && blk->cow_cache){
+ if (blk && blk->cow_cache) {
nyx_debug("%p %s\n", blk->cow_cache, blk->cow_cache->filename);
self->cow_cache_array_size++;
}
}
- uint32_t temp_cow_cache_array_size;
+ uint32_t temp_cow_cache_array_size;
assert(fread(&temp_cow_cache_array_size, sizeof(uint32_t), 1, f) == 1);
nyx_debug("%d vs %x\n", temp_cow_cache_array_size, self->cow_cache_array_size);
assert(self->cow_cache_array_size == temp_cow_cache_array_size);
- self->cow_cache_array = (cow_cache_t**)malloc(sizeof(cow_cache_t*)*self->cow_cache_array_size);
+ self->cow_cache_array =
+ (cow_cache_t **)malloc(sizeof(cow_cache_t *) * self->cow_cache_array_size);
- uint32_t i = 0;
+ uint32_t i = 0;
uint32_t id = 0;
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
- if(blk && blk->cow_cache){
+ if (blk && blk->cow_cache) {
self->cow_cache_array[i++] = blk->cow_cache;
assert(fread(&entry, sizeof(fast_reload_cow_entry_t), 1, f) == 1);
@@ -69,7 +70,7 @@ nyx_block_t* nyx_block_snapshot_init_from_file(const char* folder, bool pre_snap
fclose(f);
- for(i = 0; i < self->cow_cache_array_size; i++){
+ for (i = 0; i < self->cow_cache_array_size; i++) {
read_primary_buffer(self->cow_cache_array[i], tmp2, !pre_snapshot);
}
@@ -78,75 +79,82 @@ nyx_block_t* nyx_block_snapshot_init_from_file(const char* folder, bool pre_snap
return self;
}
-nyx_block_t* nyx_block_snapshot_init(void){
-
- nyx_block_t* self = malloc(sizeof(nyx_block_t));
+nyx_block_t *nyx_block_snapshot_init(void)
+{
+ nyx_block_t *self = malloc(sizeof(nyx_block_t));
memset(self, 0, sizeof(nyx_block_t));
BlockBackend *blk;
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
- if(blk && blk->cow_cache){
+ if (blk && blk->cow_cache) {
nyx_debug("%p %s\n", blk->cow_cache, blk->cow_cache->filename);
self->cow_cache_array_size++;
}
}
- self->cow_cache_array = (cow_cache_t**)malloc(sizeof(cow_cache_t*)*self->cow_cache_array_size);
+ self->cow_cache_array =
+ (cow_cache_t **)malloc(sizeof(cow_cache_t *) * self->cow_cache_array_size);
uint32_t i = 0;
for (blk = blk_next(NULL); blk; blk = blk_next(blk)) {
- if(blk && blk->cow_cache){
+ if (blk && blk->cow_cache) {
self->cow_cache_array[i++] = blk->cow_cache;
}
}
- for(i = 0; i < self->cow_cache_array_size; i++){
+ for (i = 0; i < self->cow_cache_array_size; i++) {
switch_to_fuzz_mode(self->cow_cache_array[i]);
}
return self;
}
-void nyx_block_snapshot_flush(nyx_block_t* self){
+void nyx_block_snapshot_flush(nyx_block_t *self)
+{
GET_GLOBAL_STATE()->cow_cache_full = false;
}
-void nyx_block_snapshot_switch_incremental(nyx_block_t* self){
- for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
+void nyx_block_snapshot_switch_incremental(nyx_block_t *self)
+{
+ for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
cow_cache_enable_tmp_mode(self->cow_cache_array[i]);
}
nyx_block_snapshot_flush(self);
}
-void nyx_block_snapshot_disable_incremental(nyx_block_t* self){
- for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
+void nyx_block_snapshot_disable_incremental(nyx_block_t *self)
+{
+ for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
cow_cache_disable_tmp_mode(self->cow_cache_array[i]);
}
}
-void nyx_block_snapshot_reset(nyx_block_t* self){
- for(uint32_t i = 0; i < self->cow_cache_array_size; i++){
+void nyx_block_snapshot_reset(nyx_block_t *self)
+{
+ for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
cow_cache_reset(self->cow_cache_array[i]);
}
}
-void nyx_block_snapshot_serialize(nyx_block_t* self, const char* snapshot_folder){
+void nyx_block_snapshot_serialize(nyx_block_t *self, const char *snapshot_folder)
+{
fast_reload_cow_entry_t entry;
- char* tmp1;
- char* tmp2;
+ char *tmp1;
+ char *tmp2;
assert(asprintf(&tmp1, "%s/fs_cache.meta", snapshot_folder) != -1);
assert(asprintf(&tmp2, "%s/fs_drv", snapshot_folder) != -1);
- FILE* f = fopen (tmp1, "w");
+ 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++){
+ for (uint32_t i = 0; i < self->cow_cache_array_size; i++) {
entry.id = i;
- strncpy((char*)&entry.idstr, (const char*)self->cow_cache_array[i]->filename, 255);
+ strncpy((char *)&entry.idstr,
+ (const char *)self->cow_cache_array[i]->filename, 255);
fwrite(&entry, sizeof(fast_reload_cow_entry_t), 1, f);
dump_primary_buffer(self->cow_cache_array[i], tmp2);
diff --git a/nyx/snapshot/block/nyx_block_snapshot.h b/nyx/snapshot/block/nyx_block_snapshot.h
index afeb232cb9..caf314b059 100644
--- a/nyx/snapshot/block/nyx_block_snapshot.h
+++ b/nyx/snapshot/block/nyx_block_snapshot.h
@@ -1,21 +1,21 @@
-#pragma once
+#pragma once
-#include
#include "nyx/snapshot/block/block_cow.h"
+#include
-typedef struct nyx_block_s{
- cow_cache_t **cow_cache_array;
- uint32_t cow_cache_array_size;
+typedef struct nyx_block_s {
+ cow_cache_t **cow_cache_array;
+ uint32_t cow_cache_array_size;
-} nyx_block_t;
+} nyx_block_t;
-nyx_block_t* nyx_block_snapshot_init_from_file(const char* folder, bool pre_snapshot);
-nyx_block_t* nyx_block_snapshot_init(void);
-void nyx_block_snapshot_switch_to_incremental(nyx_block_t*);
+nyx_block_t *nyx_block_snapshot_init_from_file(const char *folder, bool pre_snapshot);
+nyx_block_t *nyx_block_snapshot_init(void);
+void nyx_block_snapshot_switch_to_incremental(nyx_block_t *);
-void nyx_block_snapshot_flush(nyx_block_t* self);
-void nyx_block_snapshot_switch_incremental(nyx_block_t* self);
-void nyx_block_snapshot_disable_incremental(nyx_block_t* self);
-void nyx_block_snapshot_reset(nyx_block_t* self);
+void nyx_block_snapshot_flush(nyx_block_t *self);
+void nyx_block_snapshot_switch_incremental(nyx_block_t *self);
+void nyx_block_snapshot_disable_incremental(nyx_block_t *self);
+void nyx_block_snapshot_reset(nyx_block_t *self);
-void nyx_block_snapshot_serialize(nyx_block_t* self, const char* snapshot_folder);
\ No newline at end of file
+void nyx_block_snapshot_serialize(nyx_block_t *self, const char *snapshot_folder);
\ No newline at end of file
diff --git a/nyx/snapshot/devices/nyx_device_state.c b/nyx/snapshot/devices/nyx_device_state.c
index 3fd170eadd..9c72615cc0 100644
--- a/nyx/snapshot/devices/nyx_device_state.c
+++ b/nyx/snapshot/devices/nyx_device_state.c
@@ -29,37 +29,39 @@
#include "nyx/snapshot/devices/state_reallocation.h"
#include "nyx/snapshot/devices/vm_change_state_handlers.h"
-#define STATE_BUFFER 0x8000000 /* up to 128MB */
+#define STATE_BUFFER 0x8000000 /* up to 128MB */
extern void enable_fast_snapshot_rtc(void);
extern void enable_fast_snapshot_kvm_clock(void);
-static void enable_fast_snapshot_mode(void){
+static void enable_fast_snapshot_mode(void)
+{
enable_fast_snapshot_rtc();
enable_fast_snapshot_kvm_clock();
}
extern int kvm_nyx_put_tsc_value(CPUState *cs, uint64_t data);
-static void set_tsc_value(nyx_device_state_t* self, bool tmp_snapshot){
- if(self->incremental_mode){
+static void set_tsc_value(nyx_device_state_t *self, bool tmp_snapshot)
+{
+ if (self->incremental_mode) {
assert(self->tsc_value_incremental);
- assert(kvm_nyx_put_tsc_value(qemu_get_cpu(0), self->tsc_value_incremental) == 0);
- }
- else{
+ assert(kvm_nyx_put_tsc_value(qemu_get_cpu(0), self->tsc_value_incremental) ==
+ 0);
+ } else {
assert(self->tsc_value);
assert(kvm_nyx_put_tsc_value(qemu_get_cpu(0), self->tsc_value) == 0);
}
}
-static void save_tsc_value(nyx_device_state_t* self, bool incremental_mode){
- X86CPU *cpu = X86_CPU(qemu_get_cpu(0));
+static void save_tsc_value(nyx_device_state_t *self, bool incremental_mode)
+{
+ X86CPU *cpu = X86_CPU(qemu_get_cpu(0));
CPUX86State *env = &cpu->env;
- if(incremental_mode){
+ if (incremental_mode) {
self->tsc_value_incremental = env->tsc;
- }
- else{
+ } else {
self->tsc_value = env->tsc;
}
}
@@ -69,28 +71,28 @@ extern int qemu_savevm_state(QEMUFile *f, Error **errp);
/* new savevm routine */
typedef struct SaveStateEntry {
QTAILQ_ENTRY(SaveStateEntry) entry;
- char idstr[256];
- int instance_id;
- int alias_id;
- int version_id;
- int load_version_id;
- int section_id;
- int load_section_id;
- SaveVMHandlers *ops;
+ char idstr[256];
+ int instance_id;
+ int alias_id;
+ int version_id;
+ int load_version_id;
+ int section_id;
+ int load_section_id;
+ SaveVMHandlers *ops;
const VMStateDescription *vmsd;
- void *opaque;
- void *compat;
- int is_ram;
+ void *opaque;
+ void *compat;
+ int is_ram;
} SaveStateEntry;
typedef struct SaveState {
QTAILQ_HEAD(, SaveStateEntry) handlers;
- int global_section_id;
- bool skip_configuration;
- uint32_t len;
+ int global_section_id;
+ bool skip_configuration;
+ uint32_t len;
const char *name;
- uint32_t target_page_bits;
+ uint32_t target_page_bits;
} SaveState;
extern SaveState savevm_state;
@@ -107,20 +109,20 @@ extern void save_section_header(QEMUFile *f, SaveStateEntry *se, uint8_t section
/* skip block ram */
static void fast_qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_only)
{
- QJSON *vmdesc;
- int vmdesc_len;
+ QJSON *vmdesc;
+ int vmdesc_len;
SaveStateEntry *se;
- int ret;
- bool in_postcopy = migration_in_postcopy();
+ int ret;
+ bool in_postcopy = migration_in_postcopy();
cpu_synchronize_all_states();
- QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
- if(strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")){
- if (!se->ops ||
- (in_postcopy && se->ops->save_live_complete_postcopy) ||
+ QTAILQ_FOREACH (se, &savevm_state.handlers, entry) {
+ if (strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")) {
+ if (!se->ops || (in_postcopy && se->ops->save_live_complete_postcopy) ||
(in_postcopy && !iterable_only) ||
- !se->ops->save_live_complete_precopy) {
+ !se->ops->save_live_complete_precopy)
+ {
continue;
}
@@ -148,8 +150,8 @@ static void fast_qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_o
vmdesc = qjson_new();
json_prop_int(vmdesc, "page_size", TARGET_PAGE_SIZE);
json_start_array(vmdesc, "devices");
- QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
- if(strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")){
+ QTAILQ_FOREACH (se, &savevm_state.handlers, entry) {
+ if (strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")) {
if ((!se->ops || !se->ops->save_state) && !se->vmsd) {
continue;
}
@@ -189,12 +191,13 @@ static void fast_qemu_savevm_state_complete_precopy(QEMUFile *f, bool iterable_o
}
-static int fast_qemu_savevm_state_iterate(QEMUFile *f, bool postcopy) {
+static int fast_qemu_savevm_state_iterate(QEMUFile *f, bool postcopy)
+{
SaveStateEntry *se;
- int ret = 1;
+ int ret = 1;
- QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
- if(strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")){
+ QTAILQ_FOREACH (se, &savevm_state.handlers, entry) {
+ if (strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")) {
if (!se->ops || !se->ops->save_live_iterate) {
continue;
}
@@ -236,12 +239,13 @@ static int fast_qemu_savevm_state_iterate(QEMUFile *f, bool postcopy) {
return ret;
}
-static void fast_qemu_savevm_state_setup(QEMUFile *f){
+static void fast_qemu_savevm_state_setup(QEMUFile *f)
+{
SaveStateEntry *se;
- int ret;
+ int ret;
- QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
- if(strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")){
+ QTAILQ_FOREACH (se, &savevm_state.handlers, entry) {
+ if (strcmp(se->idstr, "ram") && strcmp(se->idstr, "block")) {
if (!se->ops || !se->ops->save_setup) {
continue;
}
@@ -263,7 +267,8 @@ static void fast_qemu_savevm_state_setup(QEMUFile *f){
}
-static int fast_qemu_savevm_state(QEMUFile *f, Error **errp) {
+static int fast_qemu_savevm_state(QEMUFile *f, Error **errp)
+{
qemu_savevm_state_header(f);
fast_qemu_savevm_state_setup(f);
@@ -278,84 +283,99 @@ static int fast_qemu_savevm_state(QEMUFile *f, Error **errp) {
}
/* QEMUFile RAM Emulation */
-static ssize_t fast_savevm_writev_buffer(void *opaque, struct iovec *iov, int iovcnt, int64_t pos){
+static ssize_t fast_savevm_writev_buffer(void *opaque,
+ struct iovec *iov,
+ int iovcnt,
+ int64_t pos)
+{
ssize_t retval = 0;
- for(uint32_t i = 0; i < iovcnt; i++){
- memcpy((void*)(((struct fast_savevm_opaque_t*)(opaque))->buf + ((struct fast_savevm_opaque_t*)(opaque))->pos), iov[i].iov_base, iov[i].iov_len);
- ((struct fast_savevm_opaque_t*)(opaque))->pos += iov[i].iov_len;
+ for (uint32_t i = 0; i < iovcnt; i++) {
+ memcpy((void *)(((struct fast_savevm_opaque_t *)(opaque))->buf +
+ ((struct fast_savevm_opaque_t *)(opaque))->pos),
+ iov[i].iov_base, iov[i].iov_len);
+ ((struct fast_savevm_opaque_t *)(opaque))->pos += iov[i].iov_len;
retval += iov[i].iov_len;
- }
+ }
return retval;
}
-static int fast_savevm_fclose_save_to_buffer(void *opaque){
- memcpy(((struct fast_savevm_opaque_t*)(opaque))->output_buffer, ((struct fast_savevm_opaque_t*)(opaque))->buf, ((struct fast_savevm_opaque_t*)(opaque))->pos);
- *((struct fast_savevm_opaque_t*)(opaque))->output_buffer_size = ((struct fast_savevm_opaque_t*)(opaque))->pos;
- //printf("DUMPED: %d\n", *((struct fast_savevm_opaque_t*)(opaque))->output_buffer_size);
+static int fast_savevm_fclose_save_to_buffer(void *opaque)
+{
+ memcpy(((struct fast_savevm_opaque_t *)(opaque))->output_buffer,
+ ((struct fast_savevm_opaque_t *)(opaque))->buf,
+ ((struct fast_savevm_opaque_t *)(opaque))->pos);
+ *((struct fast_savevm_opaque_t *)(opaque))->output_buffer_size =
+ ((struct fast_savevm_opaque_t *)(opaque))->pos;
+ // printf("DUMPED: %d\n", *((struct fast_savevm_opaque_t*)(opaque))->output_buffer_size);
return 0;
}
-static int fast_loadvm_fclose(void *opaque){
+static int fast_loadvm_fclose(void *opaque)
+{
return 0;
}
-static ssize_t fast_loadvm_get_buffer(void *opaque, uint8_t *buf, int64_t pos, size_t size){
- memcpy(buf, (void*)(((struct fast_savevm_opaque_t*)(opaque))->buf + pos), size);
+static ssize_t fast_loadvm_get_buffer(void *opaque, uint8_t *buf, int64_t pos, size_t size)
+{
+ memcpy(buf, (void *)(((struct fast_savevm_opaque_t *)(opaque))->buf + pos), size);
return size;
}
static const QEMUFileOps fast_loadvm_ops = {
- .get_buffer = (QEMUFileGetBufferFunc*)fast_loadvm_get_buffer,
- .close = (QEMUFileCloseFunc*)fast_loadvm_fclose
+ .get_buffer = (QEMUFileGetBufferFunc *)fast_loadvm_get_buffer,
+ .close = (QEMUFileCloseFunc *)fast_loadvm_fclose
};
static const QEMUFileOps fast_savevm_ops_to_buffer = {
- .writev_buffer = (QEMUFileWritevBufferFunc*)fast_savevm_writev_buffer,
- .close = (QEMUFileCloseFunc*)fast_savevm_fclose_save_to_buffer
+ .writev_buffer = (QEMUFileWritevBufferFunc *)fast_savevm_writev_buffer,
+ .close = (QEMUFileCloseFunc *)fast_savevm_fclose_save_to_buffer
};
-nyx_device_state_t* nyx_device_state_init_from_snapshot(const char* snapshot_folder, bool pre_snapshot){
- nyx_device_state_t* self = malloc(sizeof(nyx_device_state_t));
+nyx_device_state_t *nyx_device_state_init_from_snapshot(const char *snapshot_folder,
+ bool pre_snapshot)
+{
+ nyx_device_state_t *self = malloc(sizeof(nyx_device_state_t));
memset(self, 0, sizeof(nyx_device_state_t));
- self->state_buf = malloc(STATE_BUFFER);
+ self->state_buf = malloc(STATE_BUFFER);
self->state_buf_size = 0;
- char* qemu_state_file;
- assert(asprintf(&qemu_state_file, "%s/fast_snapshot.qemu_state", snapshot_folder) != -1);
+ char *qemu_state_file;
+ assert(asprintf(&qemu_state_file, "%s/fast_snapshot.qemu_state",
+ snapshot_folder) != -1);
struct fast_savevm_opaque_t fast_savevm_opaque;
- FILE* f;
+ FILE *f;
uint8_t ret = global_state_store();
assert(!ret);
- struct stat buffer;
- assert(stat (qemu_state_file, &buffer) == 0);
+ struct stat buffer;
+ assert(stat(qemu_state_file, &buffer) == 0);
- void* state_buf2 = malloc(STATE_BUFFER);
+ void *state_buf2 = malloc(STATE_BUFFER);
f = fopen(qemu_state_file, "r");
assert(fread(state_buf2, buffer.st_size, 1, f) == 1);
fclose(f);
fast_savevm_opaque.buf = state_buf2;
- fast_savevm_opaque.f = NULL;
+ fast_savevm_opaque.f = NULL;
fast_savevm_opaque.pos = 0;
- QEMUFile* file_dump = qemu_fopen_ops(&fast_savevm_opaque, &fast_loadvm_ops);
+ QEMUFile *file_dump = qemu_fopen_ops(&fast_savevm_opaque, &fast_loadvm_ops);
qemu_devices_reset();
qemu_loadvm_state(file_dump);
-
- if(!pre_snapshot){
+
+ if (!pre_snapshot) {
self->qemu_state = state_reallocation_new(file_dump);
}
free(state_buf2);
- if(!pre_snapshot){
+ if (!pre_snapshot) {
enable_fast_snapshot_mode();
save_tsc_value(self, false);
}
@@ -369,36 +389,36 @@ nyx_device_state_t* nyx_device_state_init_from_snapshot(const char* snapshot_fol
* backed by RAM. state_reallocation_new() then uses this file to build an
* optimized sequence of snapshot restore operations.
*/
-nyx_device_state_t* nyx_device_state_init(void){
-
- nyx_device_state_t* self = malloc(sizeof(nyx_device_state_t));
+nyx_device_state_t *nyx_device_state_init(void)
+{
+ nyx_device_state_t *self = malloc(sizeof(nyx_device_state_t));
memset(self, 0, sizeof(nyx_device_state_t));
- self->state_buf = malloc(STATE_BUFFER);
+ self->state_buf = malloc(STATE_BUFFER);
self->state_buf_size = 0;
- Error *local_err = NULL;
+ Error *local_err = NULL;
struct fast_savevm_opaque_t fast_savevm_opaque, fast_loadvm_opaque;
- void* tmp_buf = malloc(1024*1024*16);
+ void *tmp_buf = malloc(1024 * 1024 * 16);
- fast_savevm_opaque.output_buffer = self->state_buf;
+ fast_savevm_opaque.output_buffer = self->state_buf;
fast_savevm_opaque.output_buffer_size = &self->state_buf_size;
fast_savevm_opaque.buf = tmp_buf;
- fast_savevm_opaque.f = NULL;
+ fast_savevm_opaque.f = NULL;
fast_savevm_opaque.pos = 0;
uint8_t ret = global_state_store();
assert(!ret);
- QEMUFile* f = qemu_fopen_ops(&fast_savevm_opaque, &fast_savevm_ops_to_buffer);
- ret = fast_qemu_savevm_state(f, &local_err);
+ QEMUFile *f = qemu_fopen_ops(&fast_savevm_opaque, &fast_savevm_ops_to_buffer);
+ ret = fast_qemu_savevm_state(f, &local_err);
fast_loadvm_opaque.buf = tmp_buf;
- fast_loadvm_opaque.f = NULL;
+ fast_loadvm_opaque.f = NULL;
fast_loadvm_opaque.pos = 0;
- QEMUFile* file_dump = qemu_fopen_ops(&fast_loadvm_opaque, &fast_loadvm_ops);
+ QEMUFile *file_dump = qemu_fopen_ops(&fast_loadvm_opaque, &fast_loadvm_ops);
self->qemu_state = state_reallocation_new(file_dump);
qemu_fclose(file_dump);
@@ -411,41 +431,49 @@ nyx_device_state_t* nyx_device_state_init(void){
return self;
}
-void nyx_device_state_switch_incremental(nyx_device_state_t* self){
+void nyx_device_state_switch_incremental(nyx_device_state_t *self)
+{
self->incremental_mode = true;
fdl_fast_create_tmp(self->qemu_state);
fdl_fast_enable_tmp(self->qemu_state);
}
-void nyx_device_state_disable_incremental(nyx_device_state_t* self){
+void nyx_device_state_disable_incremental(nyx_device_state_t *self)
+{
fdl_fast_disable_tmp(self->qemu_state);
self->incremental_mode = false;
}
-void nyx_device_state_restore(nyx_device_state_t* self){
+void nyx_device_state_restore(nyx_device_state_t *self)
+{
fdl_fast_reload(self->qemu_state);
call_fast_change_handlers();
}
-void nyx_device_state_post_restore(nyx_device_state_t* self){
+void nyx_device_state_post_restore(nyx_device_state_t *self)
+{
set_tsc_value(self, self->incremental_mode);
}
-void nyx_device_state_save_tsc(nyx_device_state_t* self){
+void nyx_device_state_save_tsc(nyx_device_state_t *self)
+{
save_tsc_value(self, false);
}
-void nyx_device_state_save_tsc_incremental(nyx_device_state_t* self){
+void nyx_device_state_save_tsc_incremental(nyx_device_state_t *self)
+{
save_tsc_value(self, true);
}
-void nyx_device_state_serialize(nyx_device_state_t* self, const char* snapshot_folder){
- char* tmp;
+void nyx_device_state_serialize(nyx_device_state_t *self, const char *snapshot_folder)
+{
+ char *tmp;
assert(asprintf(&tmp, "%s/fast_snapshot.qemu_state", snapshot_folder) != -1);
- FILE* f_qemu_state = fopen(tmp, "w+b");
- assert(fwrite(self->state_buf, 1, self->state_buf_size, f_qemu_state) == self->state_buf_size);
+ FILE *f_qemu_state = fopen(tmp, "w+b");
+ assert(fwrite(self->state_buf, 1, self->state_buf_size, f_qemu_state) ==
+ self->state_buf_size);
fclose(f_qemu_state);
}
diff --git a/nyx/snapshot/devices/nyx_device_state.h b/nyx/snapshot/devices/nyx_device_state.h
index 666330567d..1bce35a89f 100644
--- a/nyx/snapshot/devices/nyx_device_state.h
+++ b/nyx/snapshot/devices/nyx_device_state.h
@@ -1,33 +1,34 @@
-#pragma once
+#pragma once
-#include
-#include
#include "nyx/snapshot/devices/state_reallocation.h"
+#include
+#include
-typedef struct nyx_device_state_s{
- state_reallocation_t* qemu_state;
+typedef struct nyx_device_state_s {
+ state_reallocation_t *qemu_state;
- uint64_t tsc_value;
- uint64_t tsc_value_incremental;
+ uint64_t tsc_value;
+ uint64_t tsc_value_incremental;
- bool incremental_mode;
+ bool incremental_mode;
- void* state_buf; /* QEMU's serialized state */
- uint32_t state_buf_size;
+ void *state_buf; /* QEMU's serialized state */
+ uint32_t state_buf_size;
-} nyx_device_state_t;
+} nyx_device_state_t;
-nyx_device_state_t* nyx_device_state_init(void);
-nyx_device_state_t* nyx_device_state_init_from_snapshot(const char* snapshot_folder, bool pre_snapshot);
+nyx_device_state_t *nyx_device_state_init(void);
+nyx_device_state_t *nyx_device_state_init_from_snapshot(const char *snapshot_folder,
+ bool pre_snapshot);
-void nyx_device_state_restore(nyx_device_state_t* self);
-void nyx_device_state_post_restore(nyx_device_state_t* self);
+void nyx_device_state_restore(nyx_device_state_t *self);
+void nyx_device_state_post_restore(nyx_device_state_t *self);
-void nyx_device_state_switch_incremental(nyx_device_state_t* self);
-void nyx_device_state_disable_incremental(nyx_device_state_t* self);
+void nyx_device_state_switch_incremental(nyx_device_state_t *self);
+void nyx_device_state_disable_incremental(nyx_device_state_t *self);
-void nyx_device_state_save_tsc(nyx_device_state_t* self);
-void nyx_device_state_save_tsc_incremental(nyx_device_state_t* self);
+void nyx_device_state_save_tsc(nyx_device_state_t *self);
+void nyx_device_state_save_tsc_incremental(nyx_device_state_t *self);
-void nyx_device_state_serialize(nyx_device_state_t* self, const char* snapshot_folder);
+void nyx_device_state_serialize(nyx_device_state_t *self, const char *snapshot_folder);
diff --git a/nyx/snapshot/devices/state_reallocation.c b/nyx/snapshot/devices/state_reallocation.c
index 9a1a17b7b0..e1636cf63d 100644
--- a/nyx/snapshot/devices/state_reallocation.c
+++ b/nyx/snapshot/devices/state_reallocation.c
@@ -33,59 +33,59 @@ along with QEMU-PT. If not, see .
#include "nyx/snapshot/devices/nyx_device_state.h"
#include "nyx/snapshot/devices/state_reallocation.h"
-//#define VERBOSE_DEBUG
+// #define VERBOSE_DEBUG
-#define QEMU_VM_SUBSECTION 0x05
+#define QEMU_VM_SUBSECTION 0x05
typedef struct CompatEntry {
char idstr[256];
- int instance_id;
+ int instance_id;
} CompatEntry;
typedef struct SaveStateEntry {
QTAILQ_ENTRY(SaveStateEntry) entry;
- char idstr[256];
- int instance_id;
- int alias_id;
- int version_id;
- int load_version_id;
- int section_id;
- int load_section_id;
- SaveVMHandlers *ops;
+ char idstr[256];
+ int instance_id;
+ int alias_id;
+ int version_id;
+ int load_version_id;
+ int section_id;
+ int load_section_id;
+ SaveVMHandlers *ops;
const VMStateDescription *vmsd;
- CompatEntry *opaque;
- CompatEntry *compat;
- int is_ram;
+ CompatEntry *opaque;
+ CompatEntry *compat;
+ int is_ram;
} SaveStateEntry;
struct LoadStateEntry {
QLIST_ENTRY(LoadStateEntry) entry;
SaveStateEntry *se;
- int section_id;
- int version_id;
+ int section_id;
+ int version_id;
};
typedef struct SaveState {
QTAILQ_HEAD(, SaveStateEntry) handlers;
- int global_section_id;
- bool skip_configuration;
- uint32_t len;
+ int global_section_id;
+ bool skip_configuration;
+ uint32_t len;
const char *name;
- uint32_t target_page_bits;
+ uint32_t target_page_bits;
} SaveState;
-extern void* vmstate_configuration;
+extern void *vmstate_configuration;
extern SaveState savevm_state;
-extern int vmstate_n_elems(void *opaque, VMStateField *field);
-extern int vmstate_size(void *opaque, VMStateField *field);
+extern int vmstate_n_elems(void *opaque, VMStateField *field);
+extern int vmstate_size(void *opaque, VMStateField *field);
extern void vmstate_handle_alloc(void *ptr, VMStateField *field, void *opaque);
-extern int vmstate_load(QEMUFile *f, SaveStateEntry *se);
+extern int vmstate_load(QEMUFile *f, SaveStateEntry *se);
-static void fast_timer_get(void* data, size_t size, void* opaque)
+static void fast_timer_get(void *data, size_t size, void *opaque)
{
- QEMUTimer *ts = (QEMUTimer*) opaque;
- uint64_t expire_time = *((uint64_t*)data);
+ QEMUTimer *ts = (QEMUTimer *)opaque;
+ uint64_t expire_time = *((uint64_t *)data);
if (expire_time != -1) {
timer_mod_ns(ts, expire_time);
} else {
@@ -97,17 +97,17 @@ static SaveStateEntry *fdl_find_se(const char *idstr, int instance_id)
{
SaveStateEntry *se;
- QTAILQ_FOREACH(se, &savevm_state.handlers, entry) {
+ QTAILQ_FOREACH (se, &savevm_state.handlers, entry) {
if (!strcmp(se->idstr, idstr) &&
- (instance_id == se->instance_id ||
- instance_id == se->alias_id)){
+ (instance_id == se->instance_id || instance_id == se->alias_id))
+ {
return se;
}
/* Migrating from an older version? */
if (strstr(se->idstr, idstr) && se->compat) {
if (!strcmp(se->compat->idstr, idstr) &&
- (instance_id == se->compat->instance_id ||
- instance_id == se->alias_id)){
+ (instance_id == se->compat->instance_id || instance_id == se->alias_id))
+ {
return se;
}
}
@@ -115,10 +115,16 @@ static SaveStateEntry *fdl_find_se(const char *idstr, int instance_id)
return NULL;
}
-static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const VMStateDescription *vmsd, void *opaque, int version_id, uintptr_t* 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);
-static inline VMStateDescription* fdl_vmstate_get_subsection(VMStateDescription **sub, char *idstr)
+static inline VMStateDescription *fdl_vmstate_get_subsection(VMStateDescription **sub,
+ char *idstr)
{
while (sub && *sub && (*sub)->needed) {
if (strcmp(idstr, (*sub)->name) == 0) {
@@ -129,12 +135,15 @@ static inline VMStateDescription* fdl_vmstate_get_subsection(VMStateDescription
return NULL;
}
-static int fdl_vmstate_subsection_load(state_reallocation_t* self, QEMUFile *f, const VMStateDescription *vmsd, void *opaque)
+static int fdl_vmstate_subsection_load(state_reallocation_t *self,
+ QEMUFile *f,
+ const VMStateDescription *vmsd,
+ void *opaque)
{
while (qemu_peek_byte(f, 0) == QEMU_VM_SUBSECTION) {
- char idstr[256], *idstr_ret;
- int ret;
- uint8_t version_id, len, size;
+ char idstr[256], *idstr_ret;
+ int ret;
+ uint8_t version_id, len, size;
const VMStateDescription *sub_vmsd;
len = qemu_peek_byte(f, 1);
@@ -153,12 +162,13 @@ static int fdl_vmstate_subsection_load(state_reallocation_t* self, QEMUFile *f,
/* it doesn't have a valid subsection name */
return 0;
}
- sub_vmsd = fdl_vmstate_get_subsection((VMStateDescription **)vmsd->subsections, idstr);
+ sub_vmsd = fdl_vmstate_get_subsection((VMStateDescription **)vmsd->subsections,
+ idstr);
if (sub_vmsd == NULL) {
return -ENOENT;
}
- qemu_file_skip(f, 1); /* subsection */
- qemu_file_skip(f, 1); /* len */
+ qemu_file_skip(f, 1); /* subsection */
+ qemu_file_skip(f, 1); /* len */
qemu_file_skip(f, len); /* idstr */
version_id = qemu_get_be32(f);
@@ -172,47 +182,47 @@ static int fdl_vmstate_subsection_load(state_reallocation_t* self, QEMUFile *f,
}
uint32_t post_counter = 0;
-void* post_fptr_array[256];
+void *post_fptr_array[256];
uint32_t post_version_id_array[256];
-void* post_opaque_array[256];
+void *post_opaque_array[256];
-
-
-
-static void add_post_fptr(state_reallocation_t* self, void* fptr, uint32_t version_id, void* opaque, const char* name){
-
- if(!self){
+static void add_post_fptr(state_reallocation_t *self,
+ void *fptr,
+ uint32_t version_id,
+ void *opaque,
+ const char *name)
+{
+ if (!self) {
return;
}
- if(!strcmp("I440FX", name)){
+ if (!strcmp("I440FX", name)) {
return;
}
-
-
- if(1){
- /*
- if( !strcmp("cpu_common", name) ||
- !strcmp("cpu/nested_state", name) ||
- !strcmp("cpu", name) ||
- //!strcmp("kvm-tpr-opt", name) ||
- !strcmp("globalstate", name) ||
- !strcmp("serial", name) ||
+ if (1) {
+ /*
+ if( !strcmp("cpu_common", name) ||
+ !strcmp("cpu/nested_state", name) ||
+ !strcmp("cpu", name) ||
+ //!strcmp("kvm-tpr-opt", name) ||
- !strcmp("i8259", name) ||
- !strcmp("i8254", name) ||
+ !strcmp("globalstate", name) ||
+ !strcmp("serial", name) ||
- !strcmp("apic", name) ||
- //!strcmp("vga", name) ||
- //!strcmp("ide", name) ||
- //!strcmp("ide_drive", name) ||
- !strcmp("ioapic", name)){
- */
+ !strcmp("i8259", name) ||
+ !strcmp("i8254", name) ||
- /*
+ !strcmp("apic", name) ||
+ //!strcmp("vga", name) ||
+ //!strcmp("ide", name) ||
+ //!strcmp("ide_drive", name) ||
+ !strcmp("ioapic", name)){
+ */
+
+ /*
--> cpu_common
--> cpu/nested_state
--> cpu
@@ -246,292 +256,321 @@ static void add_post_fptr(state_reallocation_t* self, void* fptr, uint32_t versi
--> piix4_pm
--> globalstate
*/
-
- //fprintf(stderr, "--> %s\n", name);
- self->fptr[self->fast_state_fptr_pos] = fptr;
- self->opaque[self->fast_state_fptr_pos] = opaque;
+ // fprintf(stderr, "--> %s\n", name);
+
+ self->fptr[self->fast_state_fptr_pos] = fptr;
+ self->opaque[self->fast_state_fptr_pos] = opaque;
self->version[self->fast_state_fptr_pos] = version_id;
self->fast_state_fptr_pos++;
- if(self->fast_state_fptr_pos >= self->fast_state_fptr_size){
+ if (self->fast_state_fptr_pos >= self->fast_state_fptr_size) {
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*));
- self->version = realloc(self->version, self->fast_state_fptr_size * sizeof(uint32_t));
+ self->fptr =
+ realloc(self->fptr, self->fast_state_fptr_size * sizeof(void *));
+ self->opaque =
+ realloc(self->opaque, self->fast_state_fptr_size * sizeof(void *));
+ self->version =
+ realloc(self->version, self->fast_state_fptr_size * sizeof(uint32_t));
}
}
}
-extern void fast_get_pci_config_device(void* data, size_t size, void* opaque);
-void fast_get_pci_irq_state(void* data, size_t size, void* opaque);
+extern void fast_get_pci_config_device(void *data, size_t size, void *opaque);
+void fast_get_pci_irq_state(void *data, size_t size, void *opaque);
-//void fast_virtio_device_get(void* data, size_t size, void* opaque);
+// void fast_virtio_device_get(void* data, size_t size, void* opaque);
int virtio_device_get(QEMUFile *f, void *opaque, size_t size, const VMStateField *field);
-static int fast_loadvm_fclose(void *opaque){
+static int fast_loadvm_fclose(void *opaque)
+{
return 0;
}
-static ssize_t fast_loadvm_get_buffer(void *opaque, uint8_t *buf, int64_t pos, size_t size){
- assert(pos < ((struct fast_savevm_opaque_t*)(opaque))->buflen);
- memcpy(buf, (void*)(((struct fast_savevm_opaque_t*)(opaque))->buf + pos), size);
+static ssize_t fast_loadvm_get_buffer(void *opaque, uint8_t *buf, int64_t pos, size_t size)
+{
+ assert(pos < ((struct fast_savevm_opaque_t *)(opaque))->buflen);
+ memcpy(buf, (void *)(((struct fast_savevm_opaque_t *)(opaque))->buf + pos), size);
return size;
}
static const QEMUFileOps fast_loadvm_ops = {
- .get_buffer = (QEMUFileGetBufferFunc*)fast_loadvm_get_buffer,
- .close = (QEMUFileCloseFunc*)fast_loadvm_fclose
+ .get_buffer = (QEMUFileGetBufferFunc *)fast_loadvm_get_buffer,
+ .close = (QEMUFileCloseFunc *)fast_loadvm_fclose
};
/* use opaque data to bootstrap virtio restore from QEMUFile */
-static void fast_virtio_device_get(void* data, size_t size, void* opaque)
+static void fast_virtio_device_get(void *data, size_t size, void *opaque)
{
struct fast_savevm_opaque_t fast_loadvm_opaque = {
- .buf = data,
- .buflen = size,
- .f = NULL,
- .pos = 0,
- };
- QEMUFile* f = qemu_fopen_ops(&fast_loadvm_opaque, &fast_loadvm_ops);
+ .buf = data,
+ .buflen = size,
+ .f = NULL,
+ .pos = 0,
+ };
+ QEMUFile *f = qemu_fopen_ops(&fast_loadvm_opaque, &fast_loadvm_ops);
- virtio_device_get(f, opaque, size, NULL);
+ virtio_device_get(f, opaque, size, NULL);
}
-static void add_get(state_reallocation_t* self, void* fptr, void* opaque, size_t size, void* field, QEMUFile* f, const char* name){
- if(!self){
+static void add_get(state_reallocation_t *self,
+ void *fptr,
+ void *opaque,
+ size_t size,
+ void *field,
+ QEMUFile *f,
+ const char *name)
+{
+ if (!self) {
return;
}
- void (*handler)(void* , size_t, void*) = NULL;
- uint8_t* data = NULL;
+ void (*handler)(void *, size_t, void *) = NULL;
+ uint8_t *data = NULL;
- if(!strcmp(name, "timer")){
- nyx_debug("SKPPING: %ld\n", size*-1);
+ if (!strcmp(name, "timer")) {
+ nyx_debug("SKPPING: %ld\n", size * -1);
qemu_file_skip(f, size * -1);
- handler = fast_timer_get;
- data = malloc(sizeof(uint64_t));
- *((uint64_t*)data) = qemu_get_be64(f);
+ handler = fast_timer_get;
+ data = malloc(sizeof(uint64_t));
+ *((uint64_t *)data) = qemu_get_be64(f);
}
-
- else if(!strcmp(name, "pci irq state")){
+
+ else if (!strcmp(name, "pci irq state"))
+ {
qemu_file_skip(f, size * -1);
handler = fast_get_pci_irq_state;
- data = malloc(sizeof(uint8_t)*size);
+ data = malloc(sizeof(uint8_t) * size);
- ((uint32_t*)data)[0] = qemu_get_be32(f);
- ((uint32_t*)data)[1] = qemu_get_be32(f);
- ((uint32_t*)data)[2] = qemu_get_be32(f);
- ((uint32_t*)data)[3] = qemu_get_be32(f);
- }
- else if(!strcmp(name, "pci config")){
+ ((uint32_t *)data)[0] = qemu_get_be32(f);
+ ((uint32_t *)data)[1] = qemu_get_be32(f);
+ ((uint32_t *)data)[2] = qemu_get_be32(f);
+ ((uint32_t *)data)[3] = qemu_get_be32(f);
+ } else if (!strcmp(name, "pci config")) {
qemu_file_skip(f, size * -1);
handler = fast_get_pci_config_device;
- data = malloc(sizeof(uint8_t)*size);
- qemu_get_buffer(f, (uint8_t*)data, size);
- }
- else if(!strcmp(name, "virtio")){
+ data = malloc(sizeof(uint8_t) * size);
+ qemu_get_buffer(f, (uint8_t *)data, size);
+ } else if (!strcmp(name, "virtio")) {
qemu_file_skip(f, size * -1);
handler = fast_virtio_device_get;
- data = malloc(sizeof(uint8_t)*size);
- qemu_get_buffer(f, (uint8_t*)data, size);
- }
- else{
+ data = malloc(sizeof(uint8_t) * size);
+ qemu_get_buffer(f, (uint8_t *)data, size);
+ } else {
fprintf(stderr, "WARNING: NOT IMPLEMENTED FAST GET ROUTINE for %s\n", name);
abort();
return;
}
- // will be called by pre-/post-save or pre-post-load?
- // will be processed by fdl_fast_reload()
- self->get_fptr[self->fast_state_get_fptr_pos] = handler;
+ // will be called by pre-/post-save or pre-post-load?
+ // will be processed by fdl_fast_reload()
+ self->get_fptr[self->fast_state_get_fptr_pos] = handler;
self->get_opaque[self->fast_state_get_fptr_pos] = opaque;
- self->get_size[self->fast_state_get_fptr_pos] = size;
- self->get_data[self->fast_state_get_fptr_pos] = data;
+ self->get_size[self->fast_state_get_fptr_pos] = size;
+ self->get_data[self->fast_state_get_fptr_pos] = data;
self->fast_state_get_fptr_pos++;
- if(self->fast_state_get_fptr_pos >= self->fast_state_get_fptr_size){
+ if (self->fast_state_get_fptr_pos >= self->fast_state_get_fptr_size) {
nyx_debug("RESIZE %s\n", __func__);
self->fast_state_get_fptr_size += REALLOC_SIZE;
- self->get_fptr = realloc(self->get_fptr, self->fast_state_get_fptr_size * sizeof(void*));
- self->get_opaque = realloc(self->get_opaque, self->fast_state_get_fptr_size * sizeof(void*));
- self->get_size = realloc(self->get_size, self->fast_state_get_fptr_size * sizeof(size_t));
- self->get_data = realloc(self->get_data, self->fast_state_get_fptr_size * sizeof(void*));
+ self->get_fptr =
+ realloc(self->get_fptr, self->fast_state_get_fptr_size * sizeof(void *));
+ self->get_opaque = realloc(self->get_opaque,
+ self->fast_state_get_fptr_size * sizeof(void *));
+ self->get_size =
+ realloc(self->get_size, self->fast_state_get_fptr_size * sizeof(size_t));
+ self->get_data =
+ realloc(self->get_data, self->fast_state_get_fptr_size * sizeof(void *));
}
-
}
-static void add_mblock(state_reallocation_t* self, char* foo, const char* bar, size_t offset, uint64_t start, uint64_t size){
-
- if(!self){
+static void add_mblock(state_reallocation_t *self,
+ char *foo,
+ const char *bar,
+ size_t offset,
+ uint64_t start,
+ uint64_t size)
+{
+ if (!self) {
return;
}
- if(self->fast_state_pos && (uint64_t)(self->ptr[self->fast_state_pos-1]+self->size[self->fast_state_pos-1]) == start){
- void* new = (void*)(self->pre_alloc_block+self->pre_alloc_block_offset);
+ if (self->fast_state_pos &&
+ (uint64_t)(self->ptr[self->fast_state_pos - 1] +
+ self->size[self->fast_state_pos - 1]) == start)
+ {
+ void *new = (void *)(self->pre_alloc_block + self->pre_alloc_block_offset);
self->pre_alloc_block_offset += size;
- memcpy(new, (void*)start, size);
+ memcpy(new, (void *)start, size);
- self->size[self->fast_state_pos-1] = size + self->size[self->fast_state_pos-1];
- }
- else{
- self->ptr[self->fast_state_pos] = (void*)start;
- self->copy[self->fast_state_pos] = (void*)(self->pre_alloc_block+self->pre_alloc_block_offset);
+ self->size[self->fast_state_pos - 1] =
+ size + self->size[self->fast_state_pos - 1];
+ } else {
+ self->ptr[self->fast_state_pos] = (void *)start;
+ self->copy[self->fast_state_pos] =
+ (void *)(self->pre_alloc_block + self->pre_alloc_block_offset);
self->pre_alloc_block_offset += size;
- memcpy(self->copy[self->fast_state_pos], (void*)start, size);
+ memcpy(self->copy[self->fast_state_pos], (void *)start, size);
self->size[self->fast_state_pos] = size;
self->fast_state_pos++;
- if(self->fast_state_pos >= self->fast_state_size){
+ if (self->fast_state_pos >= self->fast_state_size) {
self->fast_state_size += REALLOC_SIZE;
- self->ptr = realloc(self->ptr, self->fast_state_size * sizeof(void*));
- self->copy = realloc(self->copy, self->fast_state_size * sizeof(void*));
+ self->ptr = realloc(self->ptr, self->fast_state_size * sizeof(void *));
+ self->copy = realloc(self->copy, self->fast_state_size * sizeof(void *));
self->size = realloc(self->size, self->fast_state_size * sizeof(size_t));
}
}
}
-static inline int get_handler(state_reallocation_t* self, QEMUFile* f, void* curr_elem, size_t size, VMStateField *field, char* vmsd_name){
-
+static inline int get_handler(state_reallocation_t *self,
+ QEMUFile *f,
+ void *curr_elem,
+ size_t size,
+ VMStateField *field,
+ char *vmsd_name)
+{
int ret;
- //printf("%s\n", vmsd_name);
+ // printf("%s\n", vmsd_name);
ret = field->info->get(f, curr_elem, size, field);
- if (!strcmp(field->info->name, "bool")){
+ if (!strcmp(field->info->name, "bool")) {
assert(size == 1);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 1);
- }
- else if(!strcmp(field->info->name, "int8")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 1);
+ } else if (!strcmp(field->info->name, "int8")) {
assert(size == 1);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 1);
- }
- else if(!strcmp(field->info->name, "int16")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 1);
+ } else if (!strcmp(field->info->name, "int16")) {
assert(size == 2);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 2);
- }
- else if(!strcmp(field->info->name, "int32")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 2);
+ } else if (!strcmp(field->info->name, "int32")) {
assert(size == 4);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 4);
- }
- else if(!strcmp(field->info->name, "int32 equal")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 4);
+ } else if (!strcmp(field->info->name, "int32 equal")) {
assert(size == 4);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 4);
- }
- else if(!strcmp(field->info->name, "int32 le")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 4);
+ } else if (!strcmp(field->info->name, "int32 le")) {
assert(size == 4);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 4);
- }
- else if(!strcmp(field->info->name, "int64")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 4);
+ } else if (!strcmp(field->info->name, "int64")) {
assert(size == 8);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
- }
- else if(!strcmp(field->info->name, "uint8")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 8);
+ } else if (!strcmp(field->info->name, "uint8")) {
assert(size == 1);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 1);
- }
- else if(!strcmp(field->info->name, "uint16")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 1);
+ } else if (!strcmp(field->info->name, "uint16")) {
assert(size == 2);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 2);
- }
- else if(!strcmp(field->info->name, "uint32")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 2);
+ } else if (!strcmp(field->info->name, "uint32")) {
assert(size == 4);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 4);
- }
- else if(!strcmp(field->info->name, "uint32 equal")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 4);
+ } else if (!strcmp(field->info->name, "uint32 equal")) {
assert(size == 4);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 4);
- }
- else if(!strcmp(field->info->name, "uint64")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 4);
+ } else if (!strcmp(field->info->name, "uint64")) {
assert(size == 8);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
- }
- else if(!strcmp(field->info->name, "int64 equal")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 8);
+ } else if (!strcmp(field->info->name, "int64 equal")) {
assert(size == 8);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
- }
- else if(!strcmp(field->info->name, "uint8 equal")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 8);
+ } else if (!strcmp(field->info->name, "uint8 equal")) {
assert(size == 1);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 1);
- }
- else if(!strcmp(field->info->name, "uint16 equal")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 1);
+ } else if (!strcmp(field->info->name, "uint16 equal")) {
assert(size == 16);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 2);
- }
- else if(!strcmp(field->info->name, "float64")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 2);
+ } else if (!strcmp(field->info->name, "float64")) {
assert(size == 64);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
- }
- else if(!strcmp(field->info->name, "CPU_Double_U")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 8);
+ } else if (!strcmp(field->info->name, "CPU_Double_U")) {
assert(0);
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, 8);
- }
- else if(!strcmp(field->info->name, "buffer")){
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, size);
- }
- else if(!strcmp(field->info->name, "unused_buffer")){
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ 8);
+ } else if (!strcmp(field->info->name, "buffer")) {
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ size);
+ } else if (!strcmp(field->info->name, "unused_buffer")) {
/* save nothing */
- }
- else if(!strcmp(field->info->name, "tmp")){
- add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem, size);
+ } else if (!strcmp(field->info->name, "tmp")) {
+ add_mblock(self, vmsd_name, field->name, field->offset, (uint64_t)curr_elem,
+ size);
/* save nothing */
- }
- else if(!strcmp(field->info->name, "bitmap")){
+ } else if (!strcmp(field->info->name, "bitmap")) {
assert(0);
- }
- else if(!strcmp(field->info->name, "qtailq")){
+ } else if (!strcmp(field->info->name, "qtailq")) {
assert(0);
- }
- else if(!strcmp(field->info->name, "timer")){
- add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
- }
- else if(!strcmp(field->info->name, "fpreg")){
+ } else if (!strcmp(field->info->name, "timer")) {
+ add_get(self, (void *)field->info->get, curr_elem, size, (void *)field, f,
+ field->info->name);
+ } else if (!strcmp(field->info->name, "fpreg")) {
nyx_debug("type: %s (size: %lx)\n", field->info->name, size);
assert(0);
- add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
- }
- else if(!strcmp(field->info->name, "pci config")){
- 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")){
- 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);
- }
- else{
- fprintf(stderr, "[QEMU-PT] %s: WARNING no handler for %s, type %s, size %lx!\n",
- __func__, vmsd_name, 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 config")) {
+ 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")) {
+ 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);
+ } 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;
+ return ret;
}
/* 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)
+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
VMStateField *field = (VMStateField *)vmsd->fields;
- int ret = 0;
+ int ret = 0;
uint64_t total_size = 0;
if (version_id > vmsd->version_id) {
return -EINVAL;
}
- if (version_id < vmsd->minimum_version_id) {
+ if (version_id < vmsd->minimum_version_id) {
#ifdef VERBOSE_DEBUG
printf("OLD LOAD\n");
-#endif
+#endif
- if (vmsd->load_state_old &&
- version_id >= vmsd->minimum_version_id_old) {
+ if (vmsd->load_state_old && version_id >= vmsd->minimum_version_id_old) {
fprintf(stderr, "OLDSTATE\n");
assert(0);
ret = vmsd->load_state_old(f, opaque, version_id);
@@ -541,29 +580,28 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
}
if (vmsd->pre_load) {
#ifdef VERBOSE_DEBUG
- printf("\tPRELOAD Function\n");
+ printf("\tPRELOAD Function\n");
#endif
/* TODO ADD PRE FPTR FOR SERIAL */
- //fprintf(stderr, "PRELOAD RUN: %s\n", vmsd->name);
- //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);
}
while (field->name) {
#ifdef VERBOSE_DEBUG
printf("Field: %s %s %s\n", __func__, vmsd->name, field->name);
#endif
- if ((field->field_exists &&
- field->field_exists(opaque, version_id)) ||
- (!field->field_exists &&
- field->version_id <= version_id)) {
+ if ((field->field_exists && field->field_exists(opaque, version_id)) ||
+ (!field->field_exists && field->version_id <= version_id))
+ {
void *first_elem = opaque + field->offset;
- int i, n_elems = vmstate_n_elems(opaque, field);
- int size = vmstate_size(opaque, field);
+ int i, n_elems = vmstate_n_elems(opaque, field);
+ int size = vmstate_size(opaque, field);
#ifdef VERBOSE_DEBUG
printf("-----------------> vmstate_handle_alloc\n");
#endif
- //fprintf(stderr, "-----------------> vmstate_handle_alloc\n");
+ // fprintf(stderr, "-----------------> vmstate_handle_alloc\n");
vmstate_handle_alloc(first_elem, field, opaque);
if (field->flags & VMS_POINTER) {
#ifdef VERBOSE_DEBUG
@@ -576,57 +614,67 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
}
for (i = 0; i < n_elems; i++) {
- uint64_t* tmp_opaque_ptr = 0;
+ uint64_t *tmp_opaque_ptr = 0;
total_size += size;
void *curr_elem = first_elem + size * i;
if (field->flags & VMS_ARRAY_OF_POINTER) {
#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);
- //hexDump((void*)field->name, curr_elem, size);
+ 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);
+ // hexDump((void*)field->name, curr_elem, size);
#endif
tmp_opaque_ptr = curr_elem;
- curr_elem = *(void **)curr_elem;
- add_mblock(self, (char*)vmsd->name, (const char*)field->name, field->offset, (uint64_t)(curr_elem), (uint64_t)(size));
+ curr_elem = *(void **)curr_elem;
+ add_mblock(self, (char *)vmsd->name, (const char *)field->name,
+ field->offset, (uint64_t)(curr_elem), (uint64_t)(size));
#ifdef VERBOSE_DEBUG
- //hexDump((void*)field->name, curr_elem, size);
+ // hexDump((void*)field->name, curr_elem, size);
#endif
}
if (!curr_elem && size) {
- // if null pointer check placeholder and do not follow
+ // if null pointer check placeholder and do not follow
assert(field->flags & VMS_ARRAY_OF_POINTER);
#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);
- //hexDump((void*)field->name, curr_elem, size);
+ 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);
+ // hexDump((void*)field->name, curr_elem, size);
#endif
nyx_debug("*** vmstate_info_nullptr.get ***\n");
ret = vmstate_info_nullptr.get(f, curr_elem, size, NULL);
- add_mblock(self, (char*)vmsd->name, (const char*)field->name, field->offset, (uint64_t)(curr_elem), (uint64_t)(size));
+ add_mblock(self, (char *)vmsd->name, (const char *)field->name,
+ field->offset, (uint64_t)(curr_elem), (uint64_t)(size));
#ifdef VERBOSE_DEBUG
- //hexDump((void*)field->name, curr_elem, size);
+ // hexDump((void*)field->name, curr_elem, size);
#endif
} else if (field->flags & VMS_STRUCT) {
- //printf("Field-Offset 0x%lx-0x%lx\n", field->offset + (opaque-base_opaque), field->offset+(size*n_elems) + (opaque-base_opaque));
+ // printf("Field-Offset 0x%lx-0x%lx\n", field->offset + (opaque-base_opaque),
+ // field->offset+(size*n_elems) + (opaque-base_opaque));
#ifdef VERBOSE_DEBUG
- printf("=VMS_STRUCT= %lx %x\n", *((uint64_t*)curr_elem), size);
- //hexDump((void*)field->name, curr_elem, size);
+ printf("=VMS_STRUCT= %lx %x\n", *((uint64_t *)curr_elem), size);
+ // hexDump((void*)field->name, curr_elem, size);
#endif
/* FIXME */
- ret = fdl_vmstate_load_state(self, f, field->vmsd, curr_elem, field->vmsd->version_id, tmp_opaque_ptr);
+ 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);
+ // hexDump((void*)field->name, curr_elem, size);
#endif
} else {
-
-
- ret = get_handler(self, f, curr_elem, size, field, (char*)vmsd->name);
+ ret = get_handler(self, f, curr_elem, size, field,
+ (char *)vmsd->name);
}
if (ret >= 0) {
ret = qemu_file_get_error(f);
@@ -639,9 +687,8 @@ static int fdl_vmstate_load_state(state_reallocation_t* self, QEMUFile *f, const
} else if (field->flags & VMS_MUST_EXIST) {
nyx_debug("Input validation failed: %s/%s", vmsd->name, field->name);
return -1;
- }
- else {
- //printf("Field does not exist...\n");
+ } else {
+ // printf("Field does not exist...\n");
}
field++;
}
@@ -667,22 +714,29 @@ 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)
+static int fdl_vmstate_load(state_reallocation_t *self,
+ QEMUFile *f,
+ SaveStateEntry *se,
+ int version_id)
{
- if (!se->vmsd) { /* Old style */
+ if (!se->vmsd) { /* Old style */
return se->ops->load_state(f, se->opaque, version_id);
}
-
+
uintptr_t *t = (uintptr_t *)&(se->opaque);
- return fdl_vmstate_load_state(self, f, se->vmsd, se->opaque, version_id, (uintptr_t *)t);
+ 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;
+static int fdl_enumerate_section(state_reallocation_t *self,
+ QEMUFile *f,
+ MigrationIncomingState *mis)
+{
+ uint32_t instance_id, version_id, section_id;
SaveStateEntry *se;
char idstr[256];
- int ret;
+ int ret;
/* Read section start */
section_id = qemu_get_be32(f);
@@ -691,7 +745,7 @@ static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, Migrat
return -EINVAL;
}
instance_id = qemu_get_be32(f);
- version_id = qemu_get_be32(f);
+ version_id = qemu_get_be32(f);
/* Find savevm section */
se = fdl_find_se(idstr, instance_id);
@@ -702,65 +756,68 @@ static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, Migrat
/* Validate version */
if (version_id > se->version_id) {
- printf("savevm: unsupported version %d for '%s' v%d", version_id, idstr, se->version_id);
+ printf("savevm: unsupported version %d for '%s' v%d", version_id, idstr,
+ se->version_id);
return -EINVAL;
}
se->load_version_id = version_id;
se->load_section_id = section_id;
-
- if(se->vmsd && ((strcmp("tiMer", (const char*)(VMStateDescription *)(se->vmsd)->name))
- /*
- && (strcmp("cpu_common", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("cpu", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("kvm-tpr-opt", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("apic", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("kvmclock", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("fw_cfg", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("PCIBUS", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("I440FX", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("PIIX3", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("i8259", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("ioapic", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("vga", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("hpet", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("mc146818rtc", (VMStateDescription *)(se->vmsd)->name))
+ if (se->vmsd &&
+ ((strcmp("tiMer", (const char *)(VMStateDescription *)(se->vmsd)->name))
+ /*
+ && (strcmp("cpu_common", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("cpu", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("kvm-tpr-opt", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("apic", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("kvmclock", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("fw_cfg", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("PCIBUS", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("I440FX", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("i8254", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("pcspk", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("dma", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("serial", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("parallel_isa", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("fdc", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("ps2kbd", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("ps2mouse", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("PIIX3", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("i8259", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("ioapic", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("vga", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("hpet", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("mc146818rtc", (VMStateDescription *)(se->vmsd)->name))
+
+ && (strcmp("i8254", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("pcspk", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("dma", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("serial", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("parallel_isa", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("fdc", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("ps2kbd", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("ps2mouse", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("pckbd", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("vmmouse", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("port92", (VMStateDescription *)(se->vmsd)->name))
- */
- //&& (strcmp("e1000", (VMStateDescription *)(se->vmsd)->name))
- /*
- && (strcmp("ide", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("i2c_bus", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("pckbd", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("vmmouse", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("port92", (VMStateDescription *)(se->vmsd)->name))
+ */
+ //&& (strcmp("e1000", (VMStateDescription *)(se->vmsd)->name))
+ /*
+ && (strcmp("ide", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("i2c_bus", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("piix4_pm", (VMStateDescription *)(se->vmsd)->name))
- && (strcmp("acpi_build", (VMStateDescription *)(se->vmsd)->name))
- */
+ && (strcmp("piix4_pm", (VMStateDescription *)(se->vmsd)->name))
+ && (strcmp("acpi_build", (VMStateDescription *)(se->vmsd)->name))
+ */
- )){
+ ))
+ {
ret = fdl_vmstate_load(self, f, se, version_id);
- }
- else{
- nyx_debug("---------------------------------\nVMSD2: %p\n", (void*)se->vmsd);
+ } else {
+ nyx_debug("---------------------------------\nVMSD2: %p\n", (void *)se->vmsd);
ret = vmstate_load(f, se);
}
-
+
if (ret < 0) {
- printf("error while loading state for instance 0x%x of device '%s'", instance_id, idstr);
+ printf("error while loading state for instance 0x%x of device '%s'",
+ instance_id, idstr);
return ret;
}
@@ -770,10 +827,11 @@ static int fdl_enumerate_section(state_reallocation_t* self, QEMUFile *f, Migrat
return 0;
}
-static void fdl_enumerate_global_states(state_reallocation_t* self, QEMUFile *f){
- ((struct QEMUFile_tmp*)f)->pos = 0;
- ((struct QEMUFile_tmp*)f)->buf_index = 0;
- ((struct QEMUFile_tmp*)f)->buf_size = 0;
+static void fdl_enumerate_global_states(state_reallocation_t *self, QEMUFile *f)
+{
+ ((struct QEMUFile_tmp *)f)->pos = 0;
+ ((struct QEMUFile_tmp *)f)->buf_index = 0;
+ ((struct QEMUFile_tmp *)f)->buf_size = 0;
uint8_t section_type;
@@ -784,120 +842,126 @@ static void fdl_enumerate_global_states(state_reallocation_t* self, QEMUFile *f)
qemu_get_byte(f);
/* migration state */
- vmstate_load_state(f, (VMStateDescription*) &vmstate_configuration, (void*)&savevm_state, 0);
+ vmstate_load_state(f, (VMStateDescription *)&vmstate_configuration,
+ (void *)&savevm_state, 0);
while ((section_type = qemu_get_byte(f)) != QEMU_VM_EOF) {
switch (section_type) {
- case QEMU_VM_SECTION_START:
- case QEMU_VM_SECTION_FULL:
- fdl_enumerate_section(self, f, mis);
- break;
- default:
- /* oops */
- nyx_error("==> ERROR: unkown section_type: %x\n", section_type);
- //abort();
- break;
- }
+ case QEMU_VM_SECTION_START:
+ case QEMU_VM_SECTION_FULL:
+ fdl_enumerate_section(self, f, mis);
+ break;
+ default:
+ /* oops */
+ nyx_error("==> ERROR: unkown section_type: %x\n", section_type);
+ // abort();
+ break;
+ }
}
}
-state_reallocation_t* state_reallocation_new(QEMUFile *f){
- state_reallocation_t* self = malloc(sizeof(state_reallocation_t));
- self->fast_state_pos = 0;
- self->fast_state_size = REALLOC_SIZE;
- self->ptr = malloc(sizeof(void*) * REALLOC_SIZE);
- self->copy = malloc(sizeof(void*) * REALLOC_SIZE);
- self->size = malloc(sizeof(size_t) * REALLOC_SIZE);
+state_reallocation_t *state_reallocation_new(QEMUFile *f)
+{
+ state_reallocation_t *self = malloc(sizeof(state_reallocation_t));
+ self->fast_state_pos = 0;
+ self->fast_state_size = REALLOC_SIZE;
+ self->ptr = malloc(sizeof(void *) * REALLOC_SIZE);
+ self->copy = malloc(sizeof(void *) * REALLOC_SIZE);
+ self->size = malloc(sizeof(size_t) * REALLOC_SIZE);
- self->fast_state_fptr_pos = 0;
+ self->fast_state_fptr_pos = 0;
self->fast_state_fptr_size = REALLOC_SIZE;
- self->fptr = malloc(sizeof(void*) * REALLOC_SIZE);
- self->opaque = malloc(sizeof(void*) * REALLOC_SIZE);
+ self->fptr = malloc(sizeof(void *) * REALLOC_SIZE);
+ self->opaque = malloc(sizeof(void *) * REALLOC_SIZE);
self->version = malloc(sizeof(uint32_t) * REALLOC_SIZE);
- self->fast_state_get_fptr_pos = 0;
+ self->fast_state_get_fptr_pos = 0;
self->fast_state_get_fptr_size = REALLOC_SIZE;
- self->get_fptr = malloc(sizeof(void*) * REALLOC_SIZE);
- self->get_opaque = malloc(sizeof(void*) * REALLOC_SIZE);
- self->get_size = malloc(sizeof(size_t) * REALLOC_SIZE);
- self->get_data = malloc(sizeof(void*) * REALLOC_SIZE);
+ self->get_fptr = malloc(sizeof(void *) * REALLOC_SIZE);
+ self->get_opaque = malloc(sizeof(void *) * REALLOC_SIZE);
+ self->get_size = malloc(sizeof(size_t) * REALLOC_SIZE);
+ self->get_data = malloc(sizeof(void *) * REALLOC_SIZE);
- self->pre_alloc_block = (uint32_t*)mmap(NULL, PRE_ALLOC_BLOCK_SIZE, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
- assert(self->pre_alloc_block != (void *) -1);
+ self->pre_alloc_block = (uint32_t *)mmap(NULL, PRE_ALLOC_BLOCK_SIZE,
+ PROT_READ | PROT_WRITE,
+ MAP_ANONYMOUS | MAP_PRIVATE, 0, 0);
+ assert(self->pre_alloc_block != (void *)-1);
self->pre_alloc_block_offset = 0;
- self->tmp_snapshot.enabled = false;
+ self->tmp_snapshot.enabled = false;
self->tmp_snapshot.fast_state_size = 0;
// actually enumerate the devices here
fdl_enumerate_global_states(self, f);
- self->tmp_snapshot.copy = malloc(sizeof(void*) * self->fast_state_pos);
+ self->tmp_snapshot.copy = malloc(sizeof(void *) * self->fast_state_pos);
self->tmp_snapshot.fast_state_size = self->fast_state_pos;
- for(uint32_t i = 0; i < self->fast_state_pos; i++){
+ for (uint32_t i = 0; i < self->fast_state_pos; i++) {
self->tmp_snapshot.copy[i] = malloc(self->size[i]);
}
return self;
}
-void fdl_fast_reload(state_reallocation_t* self){
-
- for(uint32_t i = 0; i < self->fast_state_fptr_pos; i++){
- if((self->version[i]) == 1337){
+void fdl_fast_reload(state_reallocation_t *self)
+{
+ for (uint32_t i = 0; i < self->fast_state_fptr_pos; i++) {
+ if ((self->version[i]) == 1337) {
((int (*)(void *opaque))self->fptr[i])(self->opaque[i]);
}
}
- if(!self->tmp_snapshot.enabled){
- for(uint32_t i = 0; i < self->fast_state_pos; i++){
+ if (!self->tmp_snapshot.enabled) {
+ for (uint32_t i = 0; i < self->fast_state_pos; i++) {
memcpy(self->ptr[i], self->copy[i], self->size[i]);
}
- }
- else{
- for(uint32_t i = 0; i < self->fast_state_pos; i++){
+ } else {
+ for (uint32_t i = 0; i < self->fast_state_pos; i++) {
memcpy(self->ptr[i], self->tmp_snapshot.copy[i], self->size[i]);
}
}
-
- for(uint32_t i = 0; i < self->fast_state_fptr_pos; i++){
- if((self->version[i]) != 1337){
- ((int (*)(void *opaque, int version_id))self->fptr[i])(self->opaque[i], self->version[i]);
+
+ for (uint32_t i = 0; i < self->fast_state_fptr_pos; i++) {
+ if ((self->version[i]) != 1337) {
+ ((int (*)(void *opaque, int version_id))self->fptr[i])(self->opaque[i],
+ self->version[i]);
}
}
}
-void fdl_fast_create_tmp(state_reallocation_t* self){
- for(uint32_t i = 0; i < self->fast_state_fptr_pos; i++){
- if((self->version[i]) == 1337){
+void fdl_fast_create_tmp(state_reallocation_t *self)
+{
+ for (uint32_t i = 0; i < self->fast_state_fptr_pos; i++) {
+ if ((self->version[i]) == 1337) {
((int (*)(void *opaque))self->fptr[i])(self->opaque[i]);
- }
- else{
+ } else {
//((int (*)(void *opaque, int version_id))self->fptr[i])(self->opaque[i], self->version[i]);
}
}
-
- for(uint32_t i = 0; i < self->fast_state_pos; i++){
- memcpy(self->tmp_snapshot.copy[i], self->ptr[i], self->size[i]);
- }
-
- for(uint32_t i = 0; i < self->fast_state_fptr_pos; i++){
- if((self->version[i]) == 1337){
+ for (uint32_t i = 0; i < self->fast_state_pos; i++) {
+ memcpy(self->tmp_snapshot.copy[i], self->ptr[i], self->size[i]);
+ }
+
+
+ for (uint32_t i = 0; i < self->fast_state_fptr_pos; i++) {
+ if ((self->version[i]) == 1337) {
//((int (*)(void *opaque))self->fptr[i])(self->opaque[i]);
- }
- else{
- ((int (*)(void *opaque, int version_id))self->fptr[i])(self->opaque[i], self->version[i]);
+ } else {
+ ((int (*)(void *opaque, int version_id))self->fptr[i])(self->opaque[i],
+ self->version[i]);
}
}
}
-void fdl_fast_enable_tmp(state_reallocation_t* self){
+void fdl_fast_enable_tmp(state_reallocation_t *self)
+{
self->tmp_snapshot.enabled = true;
}
-void fdl_fast_disable_tmp(state_reallocation_t* self){
+void fdl_fast_disable_tmp(state_reallocation_t *self)
+{
self->tmp_snapshot.enabled = false;
}
diff --git a/nyx/snapshot/devices/state_reallocation.h b/nyx/snapshot/devices/state_reallocation.h
index dc53ee8cdc..e155c1feb6 100644
--- a/nyx/snapshot/devices/state_reallocation.h
+++ b/nyx/snapshot/devices/state_reallocation.h
@@ -21,8 +21,8 @@ along with QEMU-PT. If not, see .
#pragma once
#include "qemu/osdep.h"
-#include "monitor/monitor.h"
#include "migration/migration.h"
+#include "monitor/monitor.h"
#include "nyx/khash.h"
#define IO_BUF_SIZE 32768
@@ -35,68 +35,68 @@ struct QEMUFile_tmp {
int64_t bytes_xfer;
int64_t xfer_limit;
- int64_t pos; // buffer start on write, end on read
+ int64_t pos; // buffer start on write, end on read
volatile int buf_index;
- int buf_size; // 0 when writing
- uint8_t buf[IO_BUF_SIZE];
+ int buf_size; // 0 when writing
+ uint8_t buf[IO_BUF_SIZE];
};
-struct fast_savevm_opaque_t{
- FILE* f;
- uint8_t* buf;
- size_t buflen;
- uint64_t pos;
- void* output_buffer;
- uint32_t* output_buffer_size;
+struct fast_savevm_opaque_t {
+ FILE *f;
+ uint8_t *buf;
+ size_t buflen;
+ uint64_t pos;
+ void *output_buffer;
+ uint32_t *output_buffer_size;
};
#define REALLOC_SIZE 0x8000
#define PRE_ALLOC_BLOCK_SIZE 0x8000000 /* 128 MB */
-typedef struct state_reallocation_tmp_s{
- void **copy;
- uint32_t fast_state_size;
- bool enabled;
+typedef struct state_reallocation_tmp_s {
+ void **copy;
+ uint32_t fast_state_size;
+ bool enabled;
} state_reallocation_tmp_t;
-typedef struct state_reallocation_s{
- void **ptr;
- void **copy;
+typedef struct state_reallocation_s {
+ void **ptr;
+ void **copy;
size_t *size;
- uint32_t fast_state_size;
+ uint32_t fast_state_size;
uint32_t fast_state_pos;
- void **fptr;
- void **opaque;
+ void **fptr;
+ void **opaque;
uint32_t *version;
-
- uint32_t fast_state_fptr_size;
+
+ uint32_t fast_state_fptr_size;
uint32_t fast_state_fptr_pos;
- void **get_fptr;
- void **get_opaque;
+ void **get_fptr;
+ void **get_opaque;
size_t *get_size;
- void **get_data;
+ void **get_data;
- uint32_t fast_state_get_fptr_size;
+ uint32_t fast_state_get_fptr_size;
uint32_t fast_state_get_fptr_pos;
/* prevents heap fragmentation and additional 2GB mem usage */
- void* pre_alloc_block;
+ void *pre_alloc_block;
uint32_t pre_alloc_block_offset;
state_reallocation_tmp_t tmp_snapshot;
} state_reallocation_t;
-state_reallocation_t* state_reallocation_new(QEMUFile *f);
+state_reallocation_t *state_reallocation_new(QEMUFile *f);
-void fdl_fast_reload(state_reallocation_t* self);
+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);
+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);
diff --git a/nyx/snapshot/devices/vm_change_state_handlers.c b/nyx/snapshot/devices/vm_change_state_handlers.c
index 40dcdaeb1a..f2d5fed595 100644
--- a/nyx/snapshot/devices/vm_change_state_handlers.c
+++ b/nyx/snapshot/devices/vm_change_state_handlers.c
@@ -1,23 +1,24 @@
-#include
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
#include "nyx/snapshot/devices/vm_change_state_handlers.h"
+#include
-VMChangeStateHandler* change_kvm_clock_handler = NULL;
-VMChangeStateHandler* change_kvm_pit_handler = NULL;
-VMChangeStateHandler* change_cpu_handler = NULL;
-void* change_kvm_clock_opaque = NULL;
-void* change_kvm_pit_opaque = NULL;
-void* change_cpu_opaque = NULL;
+VMChangeStateHandler *change_kvm_clock_handler = NULL;
+VMChangeStateHandler *change_kvm_pit_handler = NULL;
+VMChangeStateHandler *change_cpu_handler = NULL;
+void *change_kvm_clock_opaque = NULL;
+void *change_kvm_pit_opaque = NULL;
+void *change_cpu_opaque = NULL;
-VMChangeStateHandler* change_ide_core_handler = NULL;
-uint8_t change_ide_core_opaque_num = 0;
-void* change_ide_core_opaque[32] = {NULL};
+VMChangeStateHandler *change_ide_core_handler = NULL;
+uint8_t change_ide_core_opaque_num = 0;
+void *change_ide_core_opaque[32] = { NULL };
-void call_fast_change_handlers(void){
+void call_fast_change_handlers(void)
+{
assert(change_kvm_clock_handler && change_kvm_pit_handler && change_cpu_handler);
change_kvm_clock_handler(change_kvm_clock_opaque, 1, RUN_STATE_RUNNING);
@@ -25,35 +26,36 @@ void call_fast_change_handlers(void){
change_cpu_handler(change_cpu_opaque, 1, RUN_STATE_RUNNING);
return;
-
+
/* TODO: check if necessary */
- if(change_ide_core_handler){
- for(uint8_t i = 0; i < change_ide_core_opaque_num; i++){
+ 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);
}
}
}
-void add_fast_reload_change_handler(VMChangeStateHandler *cb, void *opaque, int id){
- switch(id){
- case RELOAD_HANDLER_KVM_CLOCK:
- change_kvm_clock_handler = cb;
- change_kvm_clock_opaque = opaque;
- return;
- case RELOAD_HANDLER_KVM_PIT:
- change_kvm_pit_handler = cb;
- change_kvm_pit_opaque = opaque;
- return;
- case RELOAD_HANDLER_KVM_CPU:
- change_cpu_handler = cb;
- change_cpu_opaque = opaque;
- return;
- case RELOAD_HANDLER_IDE_CORE:
- change_ide_core_handler = cb;
- change_ide_core_opaque[change_ide_core_opaque_num] = opaque;
- change_ide_core_opaque_num++;
- return;
- default:
- abort();
+void add_fast_reload_change_handler(VMChangeStateHandler *cb, void *opaque, int id)
+{
+ switch (id) {
+ case RELOAD_HANDLER_KVM_CLOCK:
+ change_kvm_clock_handler = cb;
+ change_kvm_clock_opaque = opaque;
+ return;
+ case RELOAD_HANDLER_KVM_PIT:
+ change_kvm_pit_handler = cb;
+ change_kvm_pit_opaque = opaque;
+ return;
+ case RELOAD_HANDLER_KVM_CPU:
+ change_cpu_handler = cb;
+ change_cpu_opaque = opaque;
+ return;
+ case RELOAD_HANDLER_IDE_CORE:
+ change_ide_core_handler = cb;
+ change_ide_core_opaque[change_ide_core_opaque_num] = opaque;
+ change_ide_core_opaque_num++;
+ return;
+ default:
+ abort();
}
}
diff --git a/nyx/snapshot/devices/vm_change_state_handlers.h b/nyx/snapshot/devices/vm_change_state_handlers.h
index 88692e6ee3..ca468c1425 100644
--- a/nyx/snapshot/devices/vm_change_state_handlers.h
+++ b/nyx/snapshot/devices/vm_change_state_handlers.h
@@ -1,13 +1,13 @@
-#pragma once
+#pragma once
-#include
-#include
#include "sysemu/runstate.h"
+#include
+#include
#define RELOAD_HANDLER_KVM_CLOCK 0
-#define RELOAD_HANDLER_KVM_PIT 1
-#define RELOAD_HANDLER_KVM_CPU 2
-#define RELOAD_HANDLER_IDE_CORE 3
+#define RELOAD_HANDLER_KVM_PIT 1
+#define RELOAD_HANDLER_KVM_CPU 2
+#define RELOAD_HANDLER_IDE_CORE 3
void call_fast_change_handlers(void);
void add_fast_reload_change_handler(VMChangeStateHandler *cb, void *opaque, int id);
diff --git a/nyx/snapshot/helper.c b/nyx/snapshot/helper.c
index 714b10da51..c45f740724 100644
--- a/nyx/snapshot/helper.c
+++ b/nyx/snapshot/helper.c
@@ -1,31 +1,32 @@
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/cpus.h"
#include "qemu/main-loop.h"
+#include "sysemu/cpus.h"
+#include "sysemu/sysemu.h"
-#include "qemu/bitmap.h"
#include "exec/ram_addr.h"
-#include "qemu/rcu_queue.h"
#include "migration/migration.h"
+#include "qemu/bitmap.h"
+#include "qemu/rcu_queue.h"
#include "nyx/memory_access.h"
-#include "nyx/snapshot/helper.h"
#include "nyx/fast_vm_reload.h"
+#include "nyx/snapshot/helper.h"
-//#define DEBUG_NYX_SNAPSHOT_HELPER
+// #define DEBUG_NYX_SNAPSHOT_HELPER
-uint64_t get_ram_size(void){
- RAMBlock *block;
- uint64_t guest_ram_size = 0;
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
- guest_ram_size += block->used_length;
+uint64_t get_ram_size(void)
+{
+ RAMBlock *block;
+ uint64_t guest_ram_size = 0;
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
+ guest_ram_size += block->used_length;
#ifdef DEBUG_NYX_SNAPSHOT_HELPER
- printf("Block: %s (%lx)\n", block->idstr, block->used_length);
+ printf("Block: %s (%lx)\n", block->idstr, block->used_length);
#endif
- }
+ }
#ifdef DEBUG_NYX_SNAPSHOT_HELPER
- printf("%s - guest_ram_size: %lx\n", __func__, guest_ram_size);
+ printf("%s - guest_ram_size: %lx\n", __func__, guest_ram_size);
#endif
- return guest_ram_size;
+ return guest_ram_size;
}
diff --git a/nyx/snapshot/helper.h b/nyx/snapshot/helper.h
index cb5b7340b0..9fe2e40181 100644
--- a/nyx/snapshot/helper.h
+++ b/nyx/snapshot/helper.h
@@ -1,4 +1,4 @@
-#pragma once
+#pragma once
#include
@@ -6,8 +6,8 @@
#define PAGE_SIZE qemu_real_host_page_size
#endif
-#define BITMAP_SIZE(x) ((x/PAGE_SIZE)/8)
-#define DIRTY_STACK_SIZE(x) ((x/PAGE_SIZE)*sizeof(uint64_t))
+#define BITMAP_SIZE(x) ((x / PAGE_SIZE) / 8)
+#define DIRTY_STACK_SIZE(x) ((x / PAGE_SIZE) * sizeof(uint64_t))
uint64_t get_ram_size(void);
diff --git a/nyx/snapshot/memory/backend/nyx_debug.c b/nyx/snapshot/memory/backend/nyx_debug.c
index 3d7efbffc2..43e75bc459 100644
--- a/nyx/snapshot/memory/backend/nyx_debug.c
+++ b/nyx/snapshot/memory/backend/nyx_debug.c
@@ -1,115 +1,139 @@
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
#include "exec/ram_addr.h"
-#include "qemu/rcu_queue.h"
#include "migration/migration.h"
+#include "qemu/rcu_queue.h"
#include "nyx/memory_access.h"
-#include "nyx/snapshot/memory/backend/nyx_debug.h"
#include "nyx/fast_vm_reload.h"
+#include "nyx/snapshot/memory/backend/nyx_debug.h"
/* init operation */
-void nyx_snapshot_debug_pre_init(void){
- /* TODO */
+void nyx_snapshot_debug_pre_init(void)
+{
+ /* TODO */
}
/* init operation */
-void nyx_snapshot_debug_init(fast_reload_t* self){
- /* TODO */
+void nyx_snapshot_debug_init(fast_reload_t *self)
+{
+ /* TODO */
}
/* enable operation */
-void nyx_snapshot_debug_enable(fast_reload_t* self){
- /* TODO */
+void nyx_snapshot_debug_enable(fast_reload_t *self)
+{
+ /* TODO */
}
/* restore operation */
-uint32_t nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose){
- uint32_t num_dirty_pages = 0;
+uint32_t nyx_snapshot_debug_restore(shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist,
+ bool verbose)
+{
+ uint32_t num_dirty_pages = 0;
- void* current_region = NULL;
- int counter = 0;
- for(uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++){
-
- if(shadow_memory_state->incremental_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 addr = 0; addr < shadow_memory_state->ram_regions[i].size; addr+=0x1000){
-
- void* host_addr = shadow_memory_state->ram_regions[i].host_region_ptr + addr;
- void* snapshot_addr = current_region + addr;
- uint64_t physical_addr = addr + shadow_memory_state->ram_regions[i].base;
-
- /* check first if the page is dirty (this is super slow, but quite useful for debugging) */
- if(memcmp(host_addr, snapshot_addr, TARGET_PAGE_SIZE)){
- /* check if page is not on the block list */
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == false){
- //fprintf(stderr, "(2) DIRTY: 0x%lx (NUM: %d - OFFSET: 0x%lx)\n", physical_addr, i, addr);
-
- if(verbose){
- printf("%s -> (phys: 0x%lx) %p <-- %p [%d]\n", __func__, physical_addr, host_addr, snapshot_addr, shadow_memory_state->incremental_enabled);
- counter++;
- }
-
- memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
- num_dirty_pages++;
+ void *current_region = NULL;
+ int counter = 0;
+ for (uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++) {
+ if (shadow_memory_state->incremental_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 addr = 0; addr < shadow_memory_state->ram_regions[i].size;
+ addr += 0x1000)
+ {
+ void *host_addr =
+ shadow_memory_state->ram_regions[i].host_region_ptr + addr;
+ void *snapshot_addr = current_region + addr;
+ uint64_t physical_addr = addr + shadow_memory_state->ram_regions[i].base;
+
+ /* check first if the page is dirty (this is super slow, but quite useful for debugging) */
+ if (memcmp(host_addr, snapshot_addr, TARGET_PAGE_SIZE)) {
+ /* check if page is not on the block list */
+ if (snapshot_page_blocklist_check_phys_addr(blocklist,
+ physical_addr) == false)
+ {
+ // fprintf(stderr, "(2) DIRTY: 0x%lx (NUM: %d - OFFSET: 0x%lx)\n", physical_addr, i, addr);
+
+ if (verbose) {
+ printf("%s -> (phys: 0x%lx) %p <-- %p [%d]\n", __func__,
+ physical_addr, host_addr, snapshot_addr,
+ shadow_memory_state->incremental_enabled);
+ counter++;
+ }
+
+ memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
+ num_dirty_pages++;
+ }
+ }
}
- }
}
- }
-
- if(verbose){
- printf("TOTAL: %d\n", counter);
- }
- return num_dirty_pages;
+
+ if (verbose) {
+ printf("TOTAL: %d\n", counter);
+ }
+ return num_dirty_pages;
}
-void nyx_snapshot_debug_save_root_pages(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose){
- void* current_region = NULL;
+void nyx_snapshot_debug_save_root_pages(shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist,
+ bool verbose)
+{
+ void *current_region = NULL;
- for(uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++){
-
- if(shadow_memory_state->incremental_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 addr = 0; addr < shadow_memory_state->ram_regions[i].size; addr+=0x1000){
-
- void* host_addr = shadow_memory_state->ram_regions[i].host_region_ptr + addr;
- void* snapshot_addr = current_region + addr;
- uint64_t physical_addr = addr + shadow_memory_state->ram_regions[i].base;
- void* incremental_addr = shadow_memory_state->ram_regions[i].incremental_region_ptr + addr;
-
- /* check first if the page is dirty (this is super slow, but quite useful for debugging) */
- if(memcmp(host_addr, snapshot_addr, TARGET_PAGE_SIZE)){
- /* check if page is not on the block list */
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == false){
- //fprintf(stderr, "(2) DIRTY: 0x%lx (NUM: %d - OFFSET: 0x%lx)\n", physical_addr, i, addr);
-
- if(verbose && !shadow_memory_is_root_page_tracked(shadow_memory_state, addr, i)){
- printf("%s -> %p <-- %p [%d]\n", __func__, host_addr, snapshot_addr, shadow_memory_state->incremental_enabled);
- }
-
- shadow_memory_track_dirty_root_pages(shadow_memory_state, addr, i);
- memcpy(incremental_addr, host_addr, TARGET_PAGE_SIZE);
+ for (uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++) {
+ if (shadow_memory_state->incremental_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 addr = 0; addr < shadow_memory_state->ram_regions[i].size;
+ addr += 0x1000)
+ {
+ void *host_addr =
+ shadow_memory_state->ram_regions[i].host_region_ptr + addr;
+ void *snapshot_addr = current_region + addr;
+ uint64_t physical_addr = addr + shadow_memory_state->ram_regions[i].base;
+ void *incremental_addr =
+ shadow_memory_state->ram_regions[i].incremental_region_ptr + addr;
+
+ /* check first if the page is dirty (this is super slow, but quite useful for debugging) */
+ if (memcmp(host_addr, snapshot_addr, TARGET_PAGE_SIZE)) {
+ /* check if page is not on the block list */
+ if (snapshot_page_blocklist_check_phys_addr(blocklist,
+ physical_addr) == false)
+ {
+ // fprintf(stderr, "(2) DIRTY: 0x%lx (NUM: %d - OFFSET: 0x%lx)\n", physical_addr, i, addr);
+
+ if (verbose &&
+ !shadow_memory_is_root_page_tracked(shadow_memory_state,
+ addr, i))
+ {
+ printf("%s -> %p <-- %p [%d]\n", __func__, host_addr,
+ snapshot_addr,
+ shadow_memory_state->incremental_enabled);
+ }
+
+ shadow_memory_track_dirty_root_pages(shadow_memory_state, addr, i);
+ memcpy(incremental_addr, host_addr, TARGET_PAGE_SIZE);
+ }
+ }
}
- }
}
- }
}
/* set operation */
-void nyx_snapshot_debug_set(fast_reload_t* self){
- /* TODO */
+void nyx_snapshot_debug_set(fast_reload_t *self)
+{
+ /* TODO */
}
\ No newline at end of file
diff --git a/nyx/snapshot/memory/backend/nyx_debug.h b/nyx/snapshot/memory/backend/nyx_debug.h
index 676deb7690..9a80f8bcb5 100644
--- a/nyx/snapshot/memory/backend/nyx_debug.h
+++ b/nyx/snapshot/memory/backend/nyx_debug.h
@@ -1,11 +1,15 @@
-#pragma once
+#pragma once
-#include
#include "nyx/fast_vm_reload.h"
+#include
-void nyx_snapshot_debug_pre_init(void);
-void nyx_snapshot_debug_init(fast_reload_t* self);
-void nyx_snapshot_debug_enable(fast_reload_t* self);
-uint32_t nyx_snapshot_debug_restore(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose);
-void nyx_snapshot_debug_set(fast_reload_t* self);
-void nyx_snapshot_debug_save_root_pages(shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, bool verbose);
+void nyx_snapshot_debug_pre_init(void);
+void nyx_snapshot_debug_init(fast_reload_t *self);
+void nyx_snapshot_debug_enable(fast_reload_t *self);
+uint32_t nyx_snapshot_debug_restore(shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist,
+ bool verbose);
+void nyx_snapshot_debug_set(fast_reload_t *self);
+void nyx_snapshot_debug_save_root_pages(shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist,
+ bool verbose);
diff --git a/nyx/snapshot/memory/backend/nyx_dirty_ring.c b/nyx/snapshot/memory/backend/nyx_dirty_ring.c
index 920eabb674..8930cfc58b 100644
--- a/nyx/snapshot/memory/backend/nyx_dirty_ring.c
+++ b/nyx/snapshot/memory/backend/nyx_dirty_ring.c
@@ -2,8 +2,8 @@
#include "qemu/osdep.h"
#include
-#include "nyx/snapshot/memory/backend/nyx_dirty_ring.h"
#include "nyx/snapshot/helper.h"
+#include "nyx/snapshot/memory/backend/nyx_dirty_ring.h"
#include "sysemu/kvm.h"
#include "sysemu/kvm_int.h"
@@ -13,329 +13,399 @@
#define FAST_IN_RANGE(address, start, end) (address < end && address >= start)
/* dirty ring specific defines */
-#define KVM_DIRTY_LOG_PAGE_OFFSET 64
-#define KVM_EXIT_DIRTY_RING_FULL 31
-#define KVM_RESET_DIRTY_RINGS _IO(KVMIO, 0xc7)
-#define KVM_CAP_DIRTY_LOG_RING 192
+#define KVM_DIRTY_LOG_PAGE_OFFSET 64
+#define KVM_EXIT_DIRTY_RING_FULL 31
+#define KVM_RESET_DIRTY_RINGS _IO(KVMIO, 0xc7)
+#define KVM_CAP_DIRTY_LOG_RING 192
/* global vars */
-int dirty_ring_size = 0;
-int dirty_ring_max_size_global = 0;
-struct kvm_dirty_gfn *kvm_dirty_gfns = NULL; /* dirty ring mmap ptr */
-uint32_t kvm_dirty_gfns_index = 0;
-uint32_t kvm_dirty_gfns_index_mask = 0;
+int dirty_ring_size = 0;
+int dirty_ring_max_size_global = 0;
+struct kvm_dirty_gfn *kvm_dirty_gfns = NULL; /* dirty ring mmap ptr */
+uint32_t kvm_dirty_gfns_index = 0;
+uint32_t kvm_dirty_gfns_index_mask = 0;
-static int vm_enable_dirty_ring(int vm_fd, uint32_t ring_size){
- struct kvm_enable_cap cap = { 0 };
+static int vm_enable_dirty_ring(int vm_fd, uint32_t ring_size)
+{
+ struct kvm_enable_cap cap = { 0 };
- cap.cap = KVM_CAP_DIRTY_LOG_RING;
- cap.args[0] = ring_size;
+ cap.cap = KVM_CAP_DIRTY_LOG_RING;
+ cap.args[0] = ring_size;
- int ret = ioctl(vm_fd, KVM_ENABLE_CAP, &cap);
- if(ret != 0){
- printf("[QEMU-Nyx] Error: KVM_ENABLE_CAP ioctl failed\n");
- }
-
- return ring_size;
-}
-
-static int check_dirty_ring_size(int kvm_fd, int vm_fd){
- int ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
- if(ret < 0 ){
- printf("[QEMU-Nyx] Error: KVM_CAP_DIRTY_LOG_RING failed (dirty ring not supported?)\n");
- exit(1);
- }
-
- printf("[QEMU-Nyx] Max Dirty Ring Size -> %d (Entries: %d)\n", ret, ret/(int)sizeof(struct kvm_dirty_gfn));
-
- uint64_t dirty_ring_max_size = ret; //kvm_dirty_ring_size * sizeof(struct kvm_dirty_gfn);
-
- /* DIRTY RING -> 1MB in size results in 256M trackable memory */
- ret = vm_enable_dirty_ring(vm_fd, dirty_ring_max_size);
-
- if(ret < 0 ){
- printf("[QEMU-Nyx] Error: Enabling dirty ring (size: %ld) failed\n", dirty_ring_max_size);
- exit(1);
- }
-
- dirty_ring_max_size_global = dirty_ring_max_size;
- return ret;
-}
-
-static void allocate_dirty_ring(int kvm_vcpu, int vm_fd){
- assert(dirty_ring_size);
-
- if (dirty_ring_size) {
- kvm_dirty_gfns = mmap(NULL, dirty_ring_size, PROT_READ | PROT_WRITE, MAP_SHARED, kvm_vcpu, PAGE_SIZE * KVM_DIRTY_LOG_PAGE_OFFSET);
- if (kvm_dirty_gfns == MAP_FAILED) {
- printf("[QEMU-Nyx] Error: Dirty ring mmap failed!\n");
- exit(1);
+ int ret = ioctl(vm_fd, KVM_ENABLE_CAP, &cap);
+ if (ret != 0) {
+ printf("[QEMU-Nyx] Error: KVM_ENABLE_CAP ioctl failed\n");
}
- }
- printf("[QEMU-Nyx] Dirty ring mmap region located at %p\n", kvm_dirty_gfns);
- int ret = ioctl(vm_fd, KVM_RESET_DIRTY_RINGS, 0);
- assert(ret == 0);
+ return ring_size;
+}
+
+static int check_dirty_ring_size(int kvm_fd, int vm_fd)
+{
+ int ret = ioctl(kvm_fd, KVM_CHECK_EXTENSION, KVM_CAP_DIRTY_LOG_RING);
+ if (ret < 0) {
+ printf("[QEMU-Nyx] Error: KVM_CAP_DIRTY_LOG_RING failed (dirty ring not "
+ "supported?)\n");
+ exit(1);
+ }
+
+ printf("[QEMU-Nyx] Max Dirty Ring Size -> %d (Entries: %d)\n", ret,
+ ret / (int)sizeof(struct kvm_dirty_gfn));
+
+ uint64_t dirty_ring_max_size =
+ ret; // kvm_dirty_ring_size * sizeof(struct kvm_dirty_gfn);
+
+ /* DIRTY RING -> 1MB in size results in 256M trackable memory */
+ ret = vm_enable_dirty_ring(vm_fd, dirty_ring_max_size);
+
+ if (ret < 0) {
+ printf("[QEMU-Nyx] Error: Enabling dirty ring (size: %ld) failed\n",
+ dirty_ring_max_size);
+ exit(1);
+ }
+
+ dirty_ring_max_size_global = dirty_ring_max_size;
+ return ret;
+}
+
+static void allocate_dirty_ring(int kvm_vcpu, int vm_fd)
+{
+ assert(dirty_ring_size);
+
+ if (dirty_ring_size) {
+ kvm_dirty_gfns = mmap(NULL, dirty_ring_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, kvm_vcpu,
+ PAGE_SIZE * KVM_DIRTY_LOG_PAGE_OFFSET);
+ if (kvm_dirty_gfns == MAP_FAILED) {
+ printf("[QEMU-Nyx] Error: Dirty ring mmap failed!\n");
+ exit(1);
+ }
+ }
+ printf("[QEMU-Nyx] Dirty ring mmap region located at %p\n", kvm_dirty_gfns);
+
+ int ret = ioctl(vm_fd, KVM_RESET_DIRTY_RINGS, 0);
+ assert(ret == 0);
}
/* pre_init operation */
-void nyx_dirty_ring_early_init(int kvm_fd, int vm_fd){
- dirty_ring_size = check_dirty_ring_size(kvm_fd, vm_fd);
+void nyx_dirty_ring_early_init(int kvm_fd, int vm_fd)
+{
+ dirty_ring_size = check_dirty_ring_size(kvm_fd, vm_fd);
}
-void nyx_dirty_ring_pre_init(int kvm_fd, int vm_fd){
- allocate_dirty_ring(kvm_fd, vm_fd);
-
- kvm_dirty_gfns_index = 0;
- kvm_dirty_gfns_index_mask = ((dirty_ring_max_size_global/sizeof(struct kvm_dirty_gfn)) - 1);
+void nyx_dirty_ring_pre_init(int kvm_fd, int vm_fd)
+{
+ allocate_dirty_ring(kvm_fd, vm_fd);
+ kvm_dirty_gfns_index = 0;
+ kvm_dirty_gfns_index_mask =
+ ((dirty_ring_max_size_global / sizeof(struct kvm_dirty_gfn)) - 1);
}
-static inline void dirty_ring_collect(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, uint64_t slot, uint64_t gfn){
+static inline void dirty_ring_collect(nyx_dirty_ring_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist,
+ uint64_t slot,
+ uint64_t gfn)
+{
+ /* sanity check */
+ assert((slot & 0xFFFF0000) == 0);
- /* sanity check */
- assert((slot&0xFFFF0000) == 0);
+ slot_t *kvm_region_slot = &self->kvm_region_slots[slot & 0xFFFF];
- slot_t* kvm_region_slot = &self->kvm_region_slots[slot&0xFFFF];
-
- if(test_and_set_bit(gfn, (void*)kvm_region_slot->bitmap) == false){
-
- kvm_region_slot->stack[kvm_region_slot->stack_ptr] = gfn;
- kvm_region_slot->stack_ptr++;
- }
+ if (test_and_set_bit(gfn, (void *)kvm_region_slot->bitmap) == false) {
+ kvm_region_slot->stack[kvm_region_slot->stack_ptr] = gfn;
+ kvm_region_slot->stack_ptr++;
+ }
}
-static void dirty_ring_flush_and_collect(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist, int vm_fd){
- struct kvm_dirty_gfn *entry = NULL;
- int cleared = 0;
+static void dirty_ring_flush_and_collect(nyx_dirty_ring_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist,
+ int vm_fd)
+{
+ struct kvm_dirty_gfn *entry = NULL;
+ int cleared = 0;
- while(true){
+ while (true) {
+ entry = &kvm_dirty_gfns[kvm_dirty_gfns_index & kvm_dirty_gfns_index_mask];
- entry = &kvm_dirty_gfns[kvm_dirty_gfns_index & kvm_dirty_gfns_index_mask];
+ if ((entry->flags & 0x3) == 0) {
+ break;
+ }
- if((entry->flags & 0x3) == 0){
- break;
- }
+ if ((entry->flags & 0x1) == 1) {
+ dirty_ring_collect(self, shadow_memory_state, blocklist, entry->slot,
+ entry->offset);
+ cleared++;
+ entry->flags |= 0x2; // reset dirty entry
+ } else {
+ printf("[QEMU-Nyx] [%p] kvm_dirty_gfn -> flags: %d slot: %d offset: %lx "
+ "{ERROR}\n",
+ entry, entry->flags, entry->slot, entry->offset);
+ fflush(stdout);
+ exit(1);
+ }
- if((entry->flags & 0x1) == 1){
- dirty_ring_collect(self, shadow_memory_state, blocklist, entry->slot, entry->offset);
- cleared++;
- entry->flags |= 0x2; // reset dirty entry
- }
- else{
- printf("[QEMU-Nyx] [%p] kvm_dirty_gfn -> flags: %d slot: %d offset: %lx {ERROR}\n", entry, entry->flags, entry->slot, entry->offset);
- fflush(stdout);
- exit(1);
- }
+ kvm_dirty_gfns_index++;
+ }
- kvm_dirty_gfns_index++;
- }
-
- int ret = ioctl(vm_fd, KVM_RESET_DIRTY_RINGS, 0);
- assert(ret == cleared);
+ int ret = ioctl(vm_fd, KVM_RESET_DIRTY_RINGS, 0);
+ assert(ret == cleared);
}
-static void dirty_ring_flush(int vm_fd){
- struct kvm_dirty_gfn *entry = NULL;
- int cleared = 0;
+static void dirty_ring_flush(int vm_fd)
+{
+ struct kvm_dirty_gfn *entry = NULL;
+ int cleared = 0;
- while(true){
+ while (true) {
+ entry = &kvm_dirty_gfns[kvm_dirty_gfns_index & kvm_dirty_gfns_index_mask];
- entry = &kvm_dirty_gfns[kvm_dirty_gfns_index & kvm_dirty_gfns_index_mask];
+ if ((entry->flags & 0x3) == 0) {
+ break;
+ }
- if((entry->flags & 0x3) == 0){
- break;
- }
+ if ((entry->flags & 0x1) == 1) {
+ cleared++;
+ entry->flags |= 0x2; // reset dirty entry
+ } else {
+ printf("[QEMU-Nyx] [%p] kvm_dirty_gfn -> flags: %d slot: %d offset: %lx "
+ "{ERROR}\n",
+ entry, entry->flags, entry->slot, entry->offset);
+ fflush(stdout);
+ exit(1);
+ }
- if((entry->flags & 0x1) == 1){
- cleared++;
- entry->flags |= 0x2; // reset dirty entry
- }
- else{
- printf("[QEMU-Nyx] [%p] kvm_dirty_gfn -> flags: %d slot: %d offset: %lx {ERROR}\n", entry, entry->flags, entry->slot, entry->offset);
- fflush(stdout);
- exit(1);
- }
+ kvm_dirty_gfns_index++;
+ }
- kvm_dirty_gfns_index++;
- }
-
- int ret = ioctl(vm_fd, KVM_RESET_DIRTY_RINGS, 0);
- assert(ret == cleared);
+ int ret = ioctl(vm_fd, KVM_RESET_DIRTY_RINGS, 0);
+ assert(ret == cleared);
}
/* init operation */
-nyx_dirty_ring_t* nyx_dirty_ring_init(shadow_memory_t* shadow_memory){
- nyx_dirty_ring_t* self = malloc(sizeof(nyx_dirty_ring_t));
- memset(self, 0, sizeof(nyx_dirty_ring_t));
+nyx_dirty_ring_t *nyx_dirty_ring_init(shadow_memory_t *shadow_memory)
+{
+ nyx_dirty_ring_t *self = malloc(sizeof(nyx_dirty_ring_t));
+ memset(self, 0, sizeof(nyx_dirty_ring_t));
- assert(kvm_state);
+ assert(kvm_state);
- KVMMemoryListener *kml = kvm_get_kml(0);
- KVMSlot *mem;
+ KVMMemoryListener *kml = kvm_get_kml(0);
+ KVMSlot *mem;
- for (int i = 0; i < kvm_get_max_memslots(); i++) {
- mem = &kml->slots[i];
+ for (int i = 0; i < kvm_get_max_memslots(); i++) {
+ mem = &kml->slots[i];
- if(mem->start_addr == 0 && mem->memory_size == 0){
- break;
- }
+ if (mem->start_addr == 0 && mem->memory_size == 0) {
+ break;
+ }
- self->kvm_region_slots_num++;
- }
+ self->kvm_region_slots_num++;
+ }
- self->kvm_region_slots = malloc(sizeof(slot_t) * self->kvm_region_slots_num);
- memset(self->kvm_region_slots, 0, sizeof(slot_t) * self->kvm_region_slots_num);
+ self->kvm_region_slots = malloc(sizeof(slot_t) * self->kvm_region_slots_num);
+ memset(self->kvm_region_slots, 0, sizeof(slot_t) * self->kvm_region_slots_num);
- for (int i = 0; i < kvm_get_max_memslots(); i++) {
- mem = &kml->slots[i];
+ for (int i = 0; i < kvm_get_max_memslots(); i++) {
+ mem = &kml->slots[i];
- if(mem->start_addr == 0 && mem->memory_size == 0){
- break;
- }
+ if (mem->start_addr == 0 && mem->memory_size == 0) {
+ break;
+ }
- self->kvm_region_slots[i].enabled = (mem->flags&KVM_MEM_READONLY) == 0;
- self->kvm_region_slots[i].bitmap = malloc(BITMAP_SIZE(mem->memory_size));
- self->kvm_region_slots[i].stack = malloc(DIRTY_STACK_SIZE(mem->memory_size));
+ self->kvm_region_slots[i].enabled = (mem->flags & KVM_MEM_READONLY) == 0;
+ self->kvm_region_slots[i].bitmap = malloc(BITMAP_SIZE(mem->memory_size));
+ self->kvm_region_slots[i].stack = malloc(DIRTY_STACK_SIZE(mem->memory_size));
- memset(self->kvm_region_slots[i].bitmap, 0, BITMAP_SIZE(mem->memory_size));
- memset(self->kvm_region_slots[i].stack, 0, DIRTY_STACK_SIZE(mem->memory_size));
+ memset(self->kvm_region_slots[i].bitmap, 0, BITMAP_SIZE(mem->memory_size));
+ memset(self->kvm_region_slots[i].stack, 0, DIRTY_STACK_SIZE(mem->memory_size));
- self->kvm_region_slots[i].bitmap_size = BITMAP_SIZE(mem->memory_size);
+ self->kvm_region_slots[i].bitmap_size = BITMAP_SIZE(mem->memory_size);
- self->kvm_region_slots[i].stack_ptr = 0;
+ self->kvm_region_slots[i].stack_ptr = 0;
- if(self->kvm_region_slots[i].enabled){
- bool ram_region_found = false;
- for(int j = 0; j < shadow_memory->ram_regions_num; j++){
+ if (self->kvm_region_slots[i].enabled) {
+ bool ram_region_found = false;
+ for (int j = 0; j < shadow_memory->ram_regions_num; j++) {
+ if (FAST_IN_RANGE(mem->start_addr, shadow_memory->ram_regions[j].base,
+ (shadow_memory->ram_regions[j].base +
+ shadow_memory->ram_regions[j].size)))
+ {
+ assert(FAST_IN_RANGE((mem->start_addr + mem->memory_size - 1),
+ shadow_memory->ram_regions[j].base,
+ (shadow_memory->ram_regions[j].base +
+ shadow_memory->ram_regions[j].size)));
- if(FAST_IN_RANGE(mem->start_addr, shadow_memory->ram_regions[j].base, (shadow_memory->ram_regions[j].base+shadow_memory->ram_regions[j].size))){
- assert(FAST_IN_RANGE((mem->start_addr+mem->memory_size-1), shadow_memory->ram_regions[j].base, (shadow_memory->ram_regions[j].base+shadow_memory->ram_regions[j].size)));
-
- self->kvm_region_slots[i].region_id = j;
- self->kvm_region_slots[i].region_offset = mem->start_addr - shadow_memory->ram_regions[j].base;
- ram_region_found = true;
- break;
- }
- }
- assert(ram_region_found);
- }
- }
+ self->kvm_region_slots[i].region_id = j;
+ self->kvm_region_slots[i].region_offset =
+ mem->start_addr - shadow_memory->ram_regions[j].base;
+ ram_region_found = true;
+ break;
+ }
+ }
+ assert(ram_region_found);
+ }
+ }
#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);
- printf("[%d].stack = %p\n", i, self->kvm_region_slots[i].stack);
- printf("[%d].stack_ptr = %ld\n", i, self->kvm_region_slots[i].stack_ptr);
- if(self->kvm_region_slots[i].enabled){
- printf("[%d].region_id = %d\n", i, self->kvm_region_slots[i].region_id);
- printf("[%d].region_offset = 0x%lx\n", i, self->kvm_region_slots[i].region_offset);
- }
- else{
- printf("[%d].region_id = -\n", i);
- printf("[%d].region_offset = -\n", i);
- }
- }
+ 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);
+ printf("[%d].stack = %p\n", i, self->kvm_region_slots[i].stack);
+ printf("[%d].stack_ptr = %ld\n", i, self->kvm_region_slots[i].stack_ptr);
+ if (self->kvm_region_slots[i].enabled) {
+ printf("[%d].region_id = %d\n", i,
+ self->kvm_region_slots[i].region_id);
+ printf("[%d].region_offset = 0x%lx\n", i,
+ self->kvm_region_slots[i].region_offset);
+ } else {
+ printf("[%d].region_id = -\n", i);
+ printf("[%d].region_offset = -\n", i);
+ }
+ }
#endif
- dirty_ring_flush(kvm_get_vm_fd(kvm_state));
- return self;
+ dirty_ring_flush(kvm_get_vm_fd(kvm_state));
+ return self;
}
-static uint32_t restore_memory(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
- uint32_t num_dirty_pages = 0;
- void* host_addr = NULL;
- void* snapshot_addr = NULL;
- uint64_t physical_addr = 0;
- uint64_t gfn = 0;
- uint64_t entry_offset_addr = 0;
+static uint32_t restore_memory(nyx_dirty_ring_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist)
+{
+ uint32_t num_dirty_pages = 0;
+ void *host_addr = NULL;
+ void *snapshot_addr = NULL;
+ uint64_t physical_addr = 0;
+ uint64_t gfn = 0;
+ uint64_t entry_offset_addr = 0;
- for(uint8_t j = 0; j < self->kvm_region_slots_num; j++){
- slot_t* kvm_region_slot = &self->kvm_region_slots[j];
- if(kvm_region_slot->enabled && kvm_region_slot->stack_ptr){
- for(uint64_t i = 0; i < kvm_region_slot->stack_ptr; i++){
- gfn = kvm_region_slot->stack[i];
+ for (uint8_t j = 0; j < self->kvm_region_slots_num; j++) {
+ slot_t *kvm_region_slot = &self->kvm_region_slots[j];
+ if (kvm_region_slot->enabled && kvm_region_slot->stack_ptr) {
+ for (uint64_t i = 0; i < kvm_region_slot->stack_ptr; i++) {
+ gfn = kvm_region_slot->stack[i];
- entry_offset_addr = kvm_region_slot->region_offset + (gfn<<12);
+ entry_offset_addr = kvm_region_slot->region_offset + (gfn << 12);
- physical_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].base + entry_offset_addr;
+ physical_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id].base +
+ entry_offset_addr;
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
- continue;
- }
+ if (snapshot_page_blocklist_check_phys_addr(blocklist,
+ physical_addr) == true)
+ {
+ continue;
+ }
- host_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].host_region_ptr + entry_offset_addr;
-
- if(shadow_memory_state->incremental_enabled){
- snapshot_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].incremental_region_ptr + entry_offset_addr;
- }
- else{
- snapshot_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].snapshot_region_ptr + entry_offset_addr;
- }
+ host_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id]
+ .host_region_ptr +
+ entry_offset_addr;
- memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
+ if (shadow_memory_state->incremental_enabled) {
+ snapshot_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id]
+ .incremental_region_ptr +
+ entry_offset_addr;
+ } else {
+ snapshot_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id]
+ .snapshot_region_ptr +
+ entry_offset_addr;
+ }
- clear_bit(gfn, (void*)kvm_region_slot->bitmap);
- num_dirty_pages++;
- }
- kvm_region_slot->stack_ptr = 0;
- }
- }
- return num_dirty_pages;
+ memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
+
+ clear_bit(gfn, (void *)kvm_region_slot->bitmap);
+ num_dirty_pages++;
+ }
+ kvm_region_slot->stack_ptr = 0;
+ }
+ }
+ return num_dirty_pages;
}
-static void save_root_pages(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
- void* host_addr = NULL;
- void* incremental_addr = NULL;
- uint64_t physical_addr = 0;
- uint64_t gfn = 0;
- uint64_t entry_offset_addr = 0;
+static void save_root_pages(nyx_dirty_ring_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist)
+{
+ void *host_addr = NULL;
+ void *incremental_addr = NULL;
+ uint64_t physical_addr = 0;
+ uint64_t gfn = 0;
+ uint64_t entry_offset_addr = 0;
- for(uint8_t j = 0; j < self->kvm_region_slots_num; j++){
- slot_t* kvm_region_slot = &self->kvm_region_slots[j];
- if(kvm_region_slot->enabled && kvm_region_slot->stack_ptr){
- for(uint64_t i = 0; i < kvm_region_slot->stack_ptr; i++){
- gfn = kvm_region_slot->stack[i];
+ for (uint8_t j = 0; j < self->kvm_region_slots_num; j++) {
+ slot_t *kvm_region_slot = &self->kvm_region_slots[j];
+ if (kvm_region_slot->enabled && kvm_region_slot->stack_ptr) {
+ for (uint64_t i = 0; i < kvm_region_slot->stack_ptr; i++) {
+ gfn = kvm_region_slot->stack[i];
- entry_offset_addr = kvm_region_slot->region_offset + (gfn<<12);
+ entry_offset_addr = kvm_region_slot->region_offset + (gfn << 12);
- physical_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].base + entry_offset_addr;
+ physical_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id].base +
+ entry_offset_addr;
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
- continue;
- }
+ if (snapshot_page_blocklist_check_phys_addr(blocklist,
+ physical_addr) == true)
+ {
+ continue;
+ }
- host_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].host_region_ptr + entry_offset_addr;
- incremental_addr = shadow_memory_state->ram_regions[kvm_region_slot->region_id].incremental_region_ptr + entry_offset_addr;
+ host_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id]
+ .host_region_ptr +
+ entry_offset_addr;
+ incremental_addr =
+ shadow_memory_state->ram_regions[kvm_region_slot->region_id]
+ .incremental_region_ptr +
+ entry_offset_addr;
- shadow_memory_track_dirty_root_pages(shadow_memory_state, entry_offset_addr, kvm_region_slot->region_id);
- memcpy(incremental_addr, host_addr, TARGET_PAGE_SIZE);
+ shadow_memory_track_dirty_root_pages(shadow_memory_state,
+ entry_offset_addr,
+ kvm_region_slot->region_id);
+ memcpy(incremental_addr, host_addr, TARGET_PAGE_SIZE);
- clear_bit(gfn, (void*)kvm_region_slot->bitmap);
- }
- kvm_region_slot->stack_ptr = 0;
- }
- }
+ clear_bit(gfn, (void *)kvm_region_slot->bitmap);
+ }
+ kvm_region_slot->stack_ptr = 0;
+ }
+ }
}
-uint32_t nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
- dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist, kvm_get_vm_fd(kvm_state));
- return restore_memory(self, shadow_memory_state, blocklist);
+uint32_t nyx_snapshot_nyx_dirty_ring_restore(nyx_dirty_ring_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist)
+{
+ dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist,
+ kvm_get_vm_fd(kvm_state));
+ return restore_memory(self, shadow_memory_state, 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){
-
- dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist, kvm_get_vm_fd(kvm_state));
- save_root_pages(self, shadow_memory_state, 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)
+{
+ dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist,
+ kvm_get_vm_fd(kvm_state));
+ save_root_pages(self, shadow_memory_state, blocklist);
}
-void nyx_snapshot_nyx_dirty_ring_flush(void){
- dirty_ring_flush(kvm_get_vm_fd(kvm_state));
+void nyx_snapshot_nyx_dirty_ring_flush(void)
+{
+ dirty_ring_flush(kvm_get_vm_fd(kvm_state));
}
-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){
- dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist, kvm_get_vm_fd(kvm_state));
+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)
+{
+ dirty_ring_flush_and_collect(self, shadow_memory_state, blocklist,
+ kvm_get_vm_fd(kvm_state));
}
diff --git a/nyx/snapshot/memory/backend/nyx_dirty_ring.h b/nyx/snapshot/memory/backend/nyx_dirty_ring.h
index 431cf0e611..bfe777846f 100644
--- a/nyx/snapshot/memory/backend/nyx_dirty_ring.h
+++ b/nyx/snapshot/memory/backend/nyx_dirty_ring.h
@@ -1,30 +1,30 @@
-#pragma once
+#pragma once
-#include
#include "nyx/snapshot/memory/block_list.h"
#include "nyx/snapshot/memory/shadow_memory.h"
+#include
struct kvm_dirty_gfn {
- uint32_t flags;
- uint32_t slot;
- uint64_t offset;
+ uint32_t flags;
+ uint32_t slot;
+ uint64_t offset;
};
-typedef struct slot_s{
- bool enabled; /* set if slot is not marked as read-only */
+typedef struct slot_s {
+ bool enabled; /* set if slot is not marked as read-only */
- uint8_t region_id; /* shadow_memory region id */
- uint64_t region_offset; /* shadow_memory region offset*/
+ uint8_t region_id; /* shadow_memory region id */
+ uint64_t region_offset; /* shadow_memory region offset*/
- void* bitmap;
+ void *bitmap;
- uint64_t bitmap_size; // remove me later
- uint64_t* stack;
- uint64_t stack_ptr;
+ uint64_t bitmap_size; // remove me later
+ uint64_t *stack;
+ uint64_t stack_ptr;
} slot_t;
-typedef struct nyx_dirty_ring_s{
- slot_t* kvm_region_slots;
+typedef struct nyx_dirty_ring_s {
+ slot_t *kvm_region_slots;
uint8_t kvm_region_slots_num;
} nyx_dirty_ring_t;
@@ -35,12 +35,18 @@ void nyx_dirty_ring_early_init(int kvm_fd, int vm_fd);
/* must be called right after KVM_CREATE_VCPU */
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);
+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);
+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_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);
+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);
diff --git a/nyx/snapshot/memory/backend/nyx_fdl.c b/nyx/snapshot/memory/backend/nyx_fdl.c
index b048fa020c..b9f11fb105 100644
--- a/nyx/snapshot/memory/backend/nyx_fdl.c
+++ b/nyx/snapshot/memory/backend/nyx_fdl.c
@@ -1,10 +1,10 @@
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
#include "exec/ram_addr.h"
-#include "qemu/rcu_queue.h"
#include "migration/migration.h"
+#include "qemu/rcu_queue.h"
#include "nyx/memory_access.h"
@@ -16,39 +16,41 @@
#include "nyx/snapshot/memory/nyx_fdl_user.h"
/* debug option for the FDL constructor */
-//#define DEBUG_VMX_FDL_ALLOC
+// #define DEBUG_VMX_FDL_ALLOC
/* additional output to debug the FDL restore operation */
-//#define SHOW_NUM_DIRTY_PAGES
+// #define SHOW_NUM_DIRTY_PAGES
/* option to include restore of VRAM memory */
-//#define RESET_VRAM
-//#define DEBUG_FDL_VRAM
-
-nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
+// #define RESET_VRAM
+// #define DEBUG_FDL_VRAM
+nyx_fdl_t *nyx_fdl_init(shadow_memory_t *shadow_memory)
+{
static bool fdl_created = false;
/* 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));
+ nyx_fdl_t *self = malloc(sizeof(nyx_fdl_t));
memset(self, 0, sizeof(nyx_fdl_t));
- int ret;
- CPUState* cpu = qemu_get_cpu(0);
+ int ret;
+ CPUState *cpu = qemu_get_cpu(0);
kvm_cpu_synchronize_state(cpu);
- struct fdl_conf configuration;
+ struct fdl_conf configuration;
assert(kvm_state);
self->vmx_fdl_fd = kvm_vm_ioctl(kvm_state, KVM_VMX_FDL_SETUP_FD, (unsigned long)0);
configuration.num = 0;
- for(uint8_t i = 0; i < shadow_memory->ram_regions_num; i++){
- configuration.areas[configuration.num].base_address = shadow_memory->ram_regions[i].base;
- configuration.areas[configuration.num].size = shadow_memory->ram_regions[i].size;
+ for (uint8_t i = 0; i < shadow_memory->ram_regions_num; i++) {
+ 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++;
}
@@ -58,19 +60,24 @@ nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
#ifdef DEBUG_VMX_FDL_ALLOC
printf("KVM_VMX_FDL_SET: %d\n", ret);
printf("configuration.mmap_size = 0x%lx\n", configuration.mmap_size);
- for(uint8_t i = 0; i < configuration.num; i++){
- printf("configuration.areas[%d].mmap_bitmap_offset = 0x%lx\n", i, configuration.areas[i].mmap_bitmap_offset);
- printf("configuration.areas[%d].mmap_stack_offset = 0x%lx\n", i, configuration.areas[i].mmap_stack_offset);
+ for (uint8_t i = 0; i < configuration.num; i++) {
+ printf("configuration.areas[%d].mmap_bitmap_offset = 0x%lx\n", i,
+ configuration.areas[i].mmap_bitmap_offset);
+ printf("configuration.areas[%d].mmap_stack_offset = 0x%lx\n", i,
+ configuration.areas[i].mmap_stack_offset);
}
#endif
- self->vmx_fdl_mmap = mmap(NULL, configuration.mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, self->vmx_fdl_fd, 0);
+ self->vmx_fdl_mmap = mmap(NULL, configuration.mmap_size, PROT_READ | PROT_WRITE,
+ MAP_SHARED, self->vmx_fdl_fd, 0);
- assert(self->vmx_fdl_mmap != (void*)0xFFFFFFFFFFFFFFFF);
+ assert(self->vmx_fdl_mmap != (void *)0xFFFFFFFFFFFFFFFF);
- for(uint8_t i = 0; i < configuration.num; i++){
- self->entry[i].stack = self->vmx_fdl_mmap + configuration.areas[i].mmap_stack_offset;
- self->entry[i].bitmap = self->vmx_fdl_mmap + configuration.areas[i].mmap_bitmap_offset;
+ for (uint8_t i = 0; i < configuration.num; i++) {
+ self->entry[i].stack =
+ self->vmx_fdl_mmap + configuration.areas[i].mmap_stack_offset;
+ self->entry[i].bitmap =
+ self->vmx_fdl_mmap + configuration.areas[i].mmap_bitmap_offset;
#ifdef DEBUG_VMX_FDL_ALLOC
printf("fdl_stacks[%d] -> %p\n", i, self->entry[i].stack);
@@ -84,9 +91,9 @@ nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
memset(&result, 0, sizeof(struct fdl_result));
ret = ioctl(self->vmx_fdl_fd, KVM_VMX_FDL_GET_INDEX, &result);
-#ifdef DEBUG_VMX_FDL_ALLOC
+#ifdef DEBUG_VMX_FDL_ALLOC
printf("result: %d\n", result.num);
- for(uint8_t i = 0; i < result.num; i++){
+ for (uint8_t i = 0; i < result.num; i++) {
printf("result.values[%d]: %ld\n", i, result.values[i]);
}
#endif
@@ -95,99 +102,110 @@ nyx_fdl_t* nyx_fdl_init(shadow_memory_t* shadow_memory){
}
/* 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 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;
+ 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);
+ // nyx_snapshot_nyx_fdl_unset_blocklisted_pages(self, shadow_memory_state, blocklist);
- for(uint8_t i = 0; i < result.num; i++){
+ 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);
+ printf("Kernel -> [%d] %ld \t%ldKB\n", i, result.values[i],
+ (0x1000 * result.values[i]) >> 0x10);
#endif
- if(shadow_memory_state->incremental_enabled){
- current_region = shadow_memory_state->ram_regions[i].incremental_region_ptr;
- }
- else{
+ if (shadow_memory_state->incremental_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++){
-
+ for (uint64_t j = 0; j < result.values[i]; j++) {
uint64_t physical_addr = self->entry[i].stack[j];
- uint64_t entry_offset_addr = physical_addr - shadow_memory_state->ram_regions[i].base;
+ 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;
-
+ void *host_addr = shadow_memory_state->ram_regions[i].host_region_ptr +
+ entry_offset_addr;
+ void *snapshot_addr = current_region + entry_offset_addr;
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
+
+ if (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);
+ if (!is_black_listed_addr(self, entry_offset_addr)) {
+ printf("WARNING: %s: -> %lx is not blacklisted\n", __func__,
+ entry_offset_addr);
abort();
}
#endif
- continue; // blacklisted page
+ continue; // blacklisted page
}
- clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap);
+ clear_bit(entry_offset_addr >> 12, (void *)self->entry[i].bitmap);
memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
num_dirty_pages++;
}
-
}
#ifdef RESET_VRAM
- //nyx_snapshot_nyx_fdl_restore_vram(self, shadow_memory_state);
+ // nyx_snapshot_nyx_fdl_restore_vram(self, shadow_memory_state);
#endif
return num_dirty_pages;
}
-void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
+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);
- for(uint8_t i = 0; i < result.num; i++){
+ 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);
+ 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++){
-
+ for (uint64_t j = 0; j < result.values[i]; j++) {
uint64_t physical_addr = self->entry[i].stack[j];
- uint64_t entry_offset_addr = physical_addr - shadow_memory_state->ram_regions[i].base;
+ 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* incremental_addr = shadow_memory_state->ram_regions[i].incremental_region_ptr + entry_offset_addr;
-
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
+ 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;
+
+ if (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);
+ if (!is_black_listed_addr(self, entry_offset_addr)) {
+ printf("WARNING: %s: -> %lx is not blacklisted\n", __func__,
+ entry_offset_addr);
abort();
}
#endif
continue; // skip blacklisted page
}
- clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap);
- shadow_memory_track_dirty_root_pages(shadow_memory_state, entry_offset_addr, i);
+ clear_bit(entry_offset_addr >> 12, (void *)self->entry[i].bitmap);
+ shadow_memory_track_dirty_root_pages(shadow_memory_state,
+ entry_offset_addr, i);
memcpy(incremental_addr, host_addr, TARGET_PAGE_SIZE);
}
-
}
}
-
-
-
-
-
diff --git a/nyx/snapshot/memory/backend/nyx_fdl.h b/nyx/snapshot/memory/backend/nyx_fdl.h
index 3346c3e465..8b0afdc48f 100644
--- a/nyx/snapshot/memory/backend/nyx_fdl.h
+++ b/nyx/snapshot/memory/backend/nyx_fdl.h
@@ -1,61 +1,65 @@
-#pragma once
+#pragma once
#include
#include "nyx/snapshot/memory/block_list.h"
#include "nyx/snapshot/memory/shadow_memory.h"
-#define STATE_BUFFER 0x8000000 /* up to 128MB */
+#define STATE_BUFFER 0x8000000 /* up to 128MB */
#define USER_FDL_SLOTS 0x400000 /* fix this later */
-#define KVM_VMX_FDL_SETUP_FD _IO(KVMIO, 0xe5)
-#define KVM_VMX_FDL_SET _IOW(KVMIO, 0xe6, __u64)
-#define KVM_VMX_FDL_FLUSH _IO(KVMIO, 0xe7)
-#define KVM_VMX_FDL_GET_INDEX _IOR(KVMIO, 0xe8, __u64)
+#define KVM_VMX_FDL_SETUP_FD _IO(KVMIO, 0xe5)
+#define KVM_VMX_FDL_SET _IOW(KVMIO, 0xe6, __u64)
+#define KVM_VMX_FDL_FLUSH _IO(KVMIO, 0xe7)
+#define KVM_VMX_FDL_GET_INDEX _IOR(KVMIO, 0xe8, __u64)
#define FAST_IN_RANGE(address, start, end) (address < end && address >= start)
#define FDL_MAX_AREAS 8
-struct fdl_area{
- uint64_t base_address;
- uint64_t size;
- uint64_t mmap_bitmap_offset;
- uint64_t mmap_stack_offset;
+struct fdl_area {
+ uint64_t base_address;
+ uint64_t size;
+ uint64_t mmap_bitmap_offset;
+ uint64_t mmap_stack_offset;
uint64_t mmap_bitmap_size;
- uint64_t mmap_stack_size;
+ uint64_t mmap_stack_size;
};
-struct fdl_conf{
- uint8_t num;
- uint64_t mmap_size;
- struct fdl_area areas[FDL_MAX_AREAS];
+struct fdl_conf {
+ uint8_t num;
+ uint64_t mmap_size;
+ struct fdl_area areas[FDL_MAX_AREAS];
};
-struct fdl_result{
- uint8_t num;
- uint64_t values[FDL_MAX_AREAS];
+struct fdl_result {
+ uint8_t num;
+ uint64_t values[FDL_MAX_AREAS];
};
-typedef struct nyx_fdl_s{
+typedef struct nyx_fdl_s {
/* vmx_fdl file descriptor */
int vmx_fdl_fd;
/* mmap mapping of fdl data -> might be useful for destructor */
- void* vmx_fdl_mmap;
+ void *vmx_fdl_mmap;
struct {
- uint64_t* stack;
- uint8_t* bitmap;
- }entry[FDL_MAX_AREAS];
+ uint64_t *stack;
+ uint8_t *bitmap;
+ } entry[FDL_MAX_AREAS];
uint8_t num;
-
-}nyx_fdl_t;
-nyx_fdl_t* nyx_fdl_init(shadow_memory_t* self);
-uint32_t nyx_snapshot_nyx_fdl_restore(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
+} nyx_fdl_t;
-void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist);
+nyx_fdl_t *nyx_fdl_init(shadow_memory_t *self);
+uint32_t nyx_snapshot_nyx_fdl_restore(nyx_fdl_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist);
+
+void nyx_snapshot_nyx_fdl_save_root_pages(nyx_fdl_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist);
diff --git a/nyx/snapshot/memory/block_list.c b/nyx/snapshot/memory/block_list.c
index 448b65e922..9abfbb5e1f 100644
--- a/nyx/snapshot/memory/block_list.c
+++ b/nyx/snapshot/memory/block_list.c
@@ -1,68 +1,72 @@
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
#include "exec/ram_addr.h"
-#include "qemu/rcu_queue.h"
#include "migration/migration.h"
+#include "qemu/rcu_queue.h"
#include "nyx/memory_access.h"
-#include "nyx/snapshot/memory/block_list.h"
#include "nyx/snapshot/helper.h"
+#include "nyx/snapshot/memory/block_list.h"
#include "nyx/snapshot/memory/shadow_memory.h"
#define REALLOC_SIZE 0x8000
-//#define DEBUG_NYX_SNAPSHOT_PAGE_BLOCKLIST
+// #define DEBUG_NYX_SNAPSHOT_PAGE_BLOCKLIST
-snapshot_page_blocklist_t* snapshot_page_blocklist_init(void){
+snapshot_page_blocklist_t *snapshot_page_blocklist_init(void)
+{
+ snapshot_page_blocklist_t *self = malloc(sizeof(snapshot_page_blocklist_t));
- snapshot_page_blocklist_t* self = malloc(sizeof(snapshot_page_blocklist_t));
+ uint64_t ram_size = get_ram_size();
+ self->phys_area_size = ram_size <= MEM_SPLIT_START ?
+ ram_size :
+ ram_size + (MEM_SPLIT_END - MEM_SPLIT_START);
- uint64_t ram_size = get_ram_size();
- self->phys_area_size = ram_size <= MEM_SPLIT_START ? ram_size : ram_size + (MEM_SPLIT_END-MEM_SPLIT_START);
+ self->phys_bitmap = malloc(BITMAP_SIZE(self->phys_area_size));
+ memset(self->phys_bitmap, 0x0, BITMAP_SIZE(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));
+ if (ram_size > MEM_SPLIT_START) {
+ memset(self->phys_bitmap + BITMAP_SIZE(MEM_SPLIT_START), 0xff,
+ BITMAP_SIZE((MEM_SPLIT_END - MEM_SPLIT_START)));
+ }
- if(ram_size > MEM_SPLIT_START){
- memset(self->phys_bitmap+BITMAP_SIZE(MEM_SPLIT_START), 0xff, BITMAP_SIZE((MEM_SPLIT_END-MEM_SPLIT_START)));
- }
+ self->pages_num = 0;
+ self->pages_size = REALLOC_SIZE;
+ self->pages = malloc(sizeof(uint64_t) * REALLOC_SIZE);
- self->pages_num = 0;
- self->pages_size = REALLOC_SIZE;
- self->pages = malloc(sizeof(uint64_t) * REALLOC_SIZE);
-
- return self;
+ return self;
}
-void snapshot_page_blocklist_add(snapshot_page_blocklist_t* self, uint64_t phys_addr){
- if(phys_addr == -1){
- fprintf(stderr, "ERROR %s: phys_addr=%lx\n", __func__, phys_addr);
- return;
- }
- assert(self != NULL);
+void snapshot_page_blocklist_add(snapshot_page_blocklist_t *self, uint64_t phys_addr)
+{
+ if (phys_addr == -1) {
+ fprintf(stderr, "ERROR %s: phys_addr=%lx\n", __func__, phys_addr);
+ return;
+ }
+ assert(self != NULL);
- assert(phys_addr < self->phys_area_size);
+ assert(phys_addr < self->phys_area_size);
- if(self->pages_num <= self->pages_size){
- self->pages_size += REALLOC_SIZE;
- self->pages = realloc(self->pages, sizeof(uint64_t) * self->pages_size);
- }
+ if (self->pages_num <= self->pages_size) {
+ self->pages_size += REALLOC_SIZE;
+ self->pages = realloc(self->pages, sizeof(uint64_t) * self->pages_size);
+ }
- self->pages[self->pages_num] = phys_addr;
- self->pages_num++;
+ self->pages[self->pages_num] = phys_addr;
+ self->pages_num++;
- /* check if bit is empty */
- assert(test_bit(phys_addr>>12, (const unsigned long *)self->phys_bitmap) == 0);
+ /* check if bit is empty */
+ assert(test_bit(phys_addr >> 12, (const unsigned long *)self->phys_bitmap) == 0);
- /* set bit for lookup */
- set_bit(phys_addr>>12, (unsigned long *)self->phys_bitmap);
+ /* set bit for lookup */
+ set_bit(phys_addr >> 12, (unsigned long *)self->phys_bitmap);
#ifdef DEBUG_NYX_SNAPSHOT_PAGE_BLOCKLIST
- printf("%s: %lx\n", __func__, phys_addr);
+ printf("%s: %lx\n", __func__, phys_addr);
#endif
}
diff --git a/nyx/snapshot/memory/block_list.h b/nyx/snapshot/memory/block_list.h
index acc7e30577..0f67b171e8 100644
--- a/nyx/snapshot/memory/block_list.h
+++ b/nyx/snapshot/memory/block_list.h
@@ -1,32 +1,34 @@
-#pragma once
+#pragma once
-#include
-#include
#include "nyx/snapshot/memory/shadow_memory.h"
+#include
+#include
-typedef struct snapshot_page_blocklist_s{
+typedef struct snapshot_page_blocklist_s {
+ /* total number of blocklisted page frames */
+ uint64_t pages_num;
- /* total number of blocklisted page frames */
- uint64_t pages_num;
+ /* lookup array */
+ uint64_t *pages;
- /* lookup array */
- uint64_t* pages;
+ /* current size of our array */
+ uint64_t pages_size;
- /* current size of our array */
- uint64_t pages_size;
+ /* lookup bitmap of guest's physical memory layout (PCI-area between 3GB-4GB is set by default) */
+ uint8_t *phys_bitmap;
- /* lookup bitmap of guest's physical memory layout (PCI-area between 3GB-4GB is set by default) */
- uint8_t* phys_bitmap;
+ /* area of guest's physical memory (including RAM + PCI-hole) */
+ uint64_t phys_area_size;
+} snapshot_page_blocklist_t;
- /* area of guest's physical memory (including RAM + PCI-hole) */
- uint64_t phys_area_size;
-}snapshot_page_blocklist_t;
-
-void snapshot_page_blocklist_add(snapshot_page_blocklist_t* self, uint64_t phys_addr);
+void snapshot_page_blocklist_add(snapshot_page_blocklist_t *self, uint64_t phys_addr);
/* returns true if phys_addr is on the blocklis */
-static inline bool snapshot_page_blocklist_check_phys_addr(snapshot_page_blocklist_t* self, uint64_t phys_addr){
- return phys_addr < self->phys_area_size && test_bit(phys_addr>>12, (const unsigned long *)self->phys_bitmap) != 0;
+static inline bool snapshot_page_blocklist_check_phys_addr(
+ snapshot_page_blocklist_t *self, uint64_t phys_addr)
+{
+ return phys_addr < self->phys_area_size &&
+ test_bit(phys_addr >> 12, (const unsigned long *)self->phys_bitmap) != 0;
}
-snapshot_page_blocklist_t* snapshot_page_blocklist_init(void);
+snapshot_page_blocklist_t *snapshot_page_blocklist_init(void);
diff --git a/nyx/snapshot/memory/nyx_fdl_user.c b/nyx/snapshot/memory/nyx_fdl_user.c
index 68ee0af228..2f721c9338 100644
--- a/nyx/snapshot/memory/nyx_fdl_user.c
+++ b/nyx/snapshot/memory/nyx_fdl_user.c
@@ -1,6 +1,6 @@
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
#include "exec/ram_addr.h"
#include "migration/migration.h"
@@ -11,144 +11,200 @@
#include
#include "nyx/snapshot/helper.h"
-#include "nyx/snapshot/memory/shadow_memory.h"
#include "nyx/snapshot/memory/nyx_fdl_user.h"
+#include "nyx/snapshot/memory/shadow_memory.h"
/* debug option */
-//#define DEBUG_USER_FDL
+// #define DEBUG_USER_FDL
/* init operation */
-nyx_fdl_user_t* nyx_fdl_user_init(shadow_memory_t* shadow_memory_state){
-
- nyx_fdl_user_t* self = malloc(sizeof(nyx_fdl_user_t));
+nyx_fdl_user_t *nyx_fdl_user_init(shadow_memory_t *shadow_memory_state)
+{
+ nyx_fdl_user_t *self = malloc(sizeof(nyx_fdl_user_t));
memset(self, 0, sizeof(nyx_fdl_user_t));
/* get rid of that? */
self->num = shadow_memory_state->ram_regions_num;
- for(uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++){
- 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));
+ for (uint8_t i = 0; i < shadow_memory_state->ram_regions_num; i++) {
+ 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));
}
return self;
}
/* enable operation */
-void nyx_fdl_user_enable(nyx_fdl_user_t* self){
+void nyx_fdl_user_enable(nyx_fdl_user_t *self)
+{
assert(self);
self->enabled = true;
}
-static void nyx_snapshot_user_fdl_reset(nyx_fdl_user_t* self){
- if(self){
- for(uint8_t i = 0; i < self->num; i++){
+static void nyx_snapshot_user_fdl_reset(nyx_fdl_user_t *self)
+{
+ if (self) {
+ for (uint8_t i = 0; i < self->num; i++) {
self->entry[i].pos = 0;
}
}
}
/* reset operation */
-uint32_t nyx_snapshot_user_fdl_restore(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state, snapshot_page_blocklist_t* blocklist){
+uint32_t nyx_snapshot_user_fdl_restore(nyx_fdl_user_t *self,
+ shadow_memory_t *shadow_memory_state,
+ snapshot_page_blocklist_t *blocklist)
+{
uint32_t num_dirty_pages = 0;
- if(self){
-
- void* current_region = NULL;
+ if (self) {
+ void *current_region = NULL;
- for(uint8_t i = 0; i < self->num; i++){
+ for (uint8_t i = 0; i < self->num; i++) {
#ifdef DEBUG_USER_FDL
- printf("User -> [%d] %ld \t%ldKB\n", i, self->entry[i].pos, (0x1000*self->entry[i].pos)>>0x10);
+ printf("User -> [%d] %ld \t%ldKB\n", i, self->entry[i].pos,
+ (0x1000 * self->entry[i].pos) >> 0x10);
#endif
- if(shadow_memory_state->incremental_enabled){
- current_region = shadow_memory_state->ram_regions[i].incremental_region_ptr;
- }
- else{
- current_region = shadow_memory_state->ram_regions[i].snapshot_region_ptr;
+ if (shadow_memory_state->incremental_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 < self->entry[i].pos; j++){
+ for (uint64_t j = 0; j < self->entry[i].pos; j++) {
uint64_t physical_addr = self->entry[i].stack[j];
- uint64_t entry_offset_addr = physical_addr - shadow_memory_state->ram_regions[i].base;
+ 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;
+ void *host_addr = shadow_memory_state->ram_regions[i].host_region_ptr +
+ entry_offset_addr;
+ void *snapshot_addr = current_region + entry_offset_addr;
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
+ if (snapshot_page_blocklist_check_phys_addr(blocklist,
+ physical_addr) == true)
+ {
continue;
}
#ifdef DEBUG_USER_FDL
printf("%s -> %p <-- %p\n", __func__, host_addr, snapshot_addr);
#endif
- clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap);
+ clear_bit(entry_offset_addr >> 12, (void *)self->entry[i].bitmap);
memcpy(host_addr, snapshot_addr, TARGET_PAGE_SIZE);
num_dirty_pages++;
}
-
}
-
}
nyx_snapshot_user_fdl_reset(self);
return num_dirty_pages;
}
-/* set operation (mark pf as dirty) */
-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){
- if(length < 0x1000){
+/* set operation (mark pf as dirty) */
+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)
+{
+ if (length < 0x1000) {
length = 0x1000;
}
- if(self && self->enabled && length >= 0x1000){
-
- uint8_t ram_area = 0xff;
+ if (self && self->enabled && length >= 0x1000) {
+ uint8_t ram_area = 0xff;
/* optimize this? */
addr = ram_offset_to_address(addr);
- switch(MAX_REGIONS-shadow_memory_state->ram_regions_num){
- case 0:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[7].base, shadow_memory_state->ram_regions[7].base+(shadow_memory_state->ram_regions[7].size-1)) ? 7 : ram_area;
- case 1:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[6].base, shadow_memory_state->ram_regions[6].base+(shadow_memory_state->ram_regions[6].size-1)) ? 6 : ram_area;
- case 2:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[5].base, shadow_memory_state->ram_regions[5].base+(shadow_memory_state->ram_regions[5].size-1)) ? 5 : ram_area;
- case 3:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[4].base, shadow_memory_state->ram_regions[4].base+(shadow_memory_state->ram_regions[4].size-1)) ? 4 : ram_area;
- case 4:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[3].base, shadow_memory_state->ram_regions[3].base+(shadow_memory_state->ram_regions[3].size-1)) ? 3 : ram_area;
- case 5:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[2].base, shadow_memory_state->ram_regions[2].base+(shadow_memory_state->ram_regions[2].size-1)) ? 2 : ram_area;
- case 6:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[1].base, shadow_memory_state->ram_regions[1].base+(shadow_memory_state->ram_regions[1].size-1)) ? 1 : ram_area;
- case 7:
- ram_area = FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[0].base, shadow_memory_state->ram_regions[0].base+(shadow_memory_state->ram_regions[0].size-1)) ? 0 : ram_area;
- default:
- break;
- }
+ switch (MAX_REGIONS - shadow_memory_state->ram_regions_num) {
+ case 0:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[7].base,
+ shadow_memory_state->ram_regions[7].base +
+ (shadow_memory_state->ram_regions[7].size - 1)) ?
+ 7 :
+ ram_area;
+ case 1:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[6].base,
+ shadow_memory_state->ram_regions[6].base +
+ (shadow_memory_state->ram_regions[6].size - 1)) ?
+ 6 :
+ ram_area;
+ case 2:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[5].base,
+ shadow_memory_state->ram_regions[5].base +
+ (shadow_memory_state->ram_regions[5].size - 1)) ?
+ 5 :
+ ram_area;
+ case 3:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[4].base,
+ shadow_memory_state->ram_regions[4].base +
+ (shadow_memory_state->ram_regions[4].size - 1)) ?
+ 4 :
+ ram_area;
+ case 4:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[3].base,
+ shadow_memory_state->ram_regions[3].base +
+ (shadow_memory_state->ram_regions[3].size - 1)) ?
+ 3 :
+ ram_area;
+ case 5:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[2].base,
+ shadow_memory_state->ram_regions[2].base +
+ (shadow_memory_state->ram_regions[2].size - 1)) ?
+ 2 :
+ ram_area;
+ case 6:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[1].base,
+ shadow_memory_state->ram_regions[1].base +
+ (shadow_memory_state->ram_regions[1].size - 1)) ?
+ 1 :
+ ram_area;
+ case 7:
+ ram_area =
+ FAST_IN_RANGE(addr, shadow_memory_state->ram_regions[0].base,
+ shadow_memory_state->ram_regions[0].base +
+ (shadow_memory_state->ram_regions[0].size - 1)) ?
+ 0 :
+ ram_area;
+ default:
+ break;
+ }
- if(ram_area == 0xff){
- printf("ERROR: %s %lx [%d]\n", __func__, addr, ram_area);
+ if (ram_area == 0xff) {
+ printf("ERROR: %s %lx [%d]\n", __func__, addr, ram_area);
abort();
- return;
- }
+ return;
+ }
- for(uint64_t offset = 0; offset < length; offset+=0x1000){
+ for (uint64_t offset = 0; offset < length; offset += 0x1000) {
+ uint64_t current_addr = (addr + offset) & 0xFFFFFFFFFFFFF000;
- uint64_t current_addr = (addr+offset) & 0xFFFFFFFFFFFFF000;
-
- long pfn = (long) ((current_addr-shadow_memory_state->ram_regions[ram_area].base)>>12);
+ long pfn = (long)((current_addr -
+ shadow_memory_state->ram_regions[ram_area].base) >>
+ 12);
assert(self->entry[ram_area].bitmap);
/* 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);
+ if (!test_bit(pfn, (const unsigned long *)self->entry[ram_area].bitmap)) {
+ set_bit(pfn, (unsigned long *)self->entry[ram_area].bitmap);
- self->entry[ram_area].stack[self->entry[ram_area].pos] = current_addr & 0xFFFFFFFFFFFFF000;
+ self->entry[ram_area].stack[self->entry[ram_area].pos] =
+ current_addr & 0xFFFFFFFFFFFFF000;
self->entry[ram_area].pos++;
#ifdef DEBUG_USER_FDL
@@ -159,21 +215,30 @@ void nyx_fdl_user_set(nyx_fdl_user_t* self, shadow_memory_t* shadow_memory_state
}
}
-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){
-
- for(uint8_t i = 0; i < self->num; i++){
+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)
+{
+ for (uint8_t i = 0; i < self->num; i++) {
#ifdef DEBUG_USER_FDL
- printf("User -> [%d] %ld \t%ldKB\n", i, self->entry[i].pos, (0x1000*self->entry[i].pos)>>0x10);
+ printf("User -> [%d] %ld \t%ldKB\n", i, self->entry[i].pos,
+ (0x1000 * self->entry[i].pos) >> 0x10);
#endif
- for(uint64_t j = 0; j < self->entry[i].pos; j++){
+ for (uint64_t j = 0; j < self->entry[i].pos; j++) {
uint64_t physical_addr = self->entry[i].stack[j];
- uint64_t entry_offset_addr = physical_addr - shadow_memory_state->ram_regions[i].base;
+ 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* incremental_addr = shadow_memory_state->ram_regions[i].incremental_region_ptr + entry_offset_addr;
-
- if(snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) == true){
+ 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;
+
+ if (snapshot_page_blocklist_check_phys_addr(blocklist, physical_addr) ==
+ true)
+ {
printf("%s: 0x%lx is dirty\n", __func__, physical_addr);
continue;
}
@@ -181,10 +246,10 @@ void nyx_snapshot_nyx_fdl_user_save_root_pages(nyx_fdl_user_t* self, shadow_memo
printf("%s -> %p <-- %p\n", __func__, incremental_addr, host_addr);
#endif
- clear_bit(entry_offset_addr>>12, (void*)self->entry[i].bitmap);
- shadow_memory_track_dirty_root_pages(shadow_memory_state, entry_offset_addr, i);
+ clear_bit(entry_offset_addr >> 12, (void *)self->entry[i].bitmap);
+ shadow_memory_track_dirty_root_pages(shadow_memory_state,
+ entry_offset_addr, i);
memcpy(incremental_addr, host_addr, TARGET_PAGE_SIZE);
-
}
}
diff --git a/nyx/snapshot/memory/nyx_fdl_user.h b/nyx/snapshot/memory/nyx_fdl_user.h
index c59eba1055..5c31006282 100644
--- a/nyx/snapshot/memory/nyx_fdl_user.h
+++ b/nyx/snapshot/memory/nyx_fdl_user.h
@@ -1,30 +1,38 @@
-#pragma once
+#pragma once
-#include
#include "nyx/snapshot/helper.h"
+#include "nyx/snapshot/memory/backend/nyx_fdl.h"
#include "nyx/snapshot/memory/block_list.h"
#include "nyx/snapshot/memory/shadow_memory.h"
-#include "nyx/snapshot/memory/backend/nyx_fdl.h"
+#include
#define MAX_REGIONS 8 /* don't */
-typedef struct nyx_fdl_user_s{
+typedef struct nyx_fdl_user_s {
struct {
- uint64_t* stack;
- uint8_t* bitmap;
- uint64_t pos;
- }entry[MAX_REGIONS];
+ uint64_t *stack;
+ uint8_t *bitmap;
+ uint64_t pos;
+ } entry[MAX_REGIONS];
uint8_t num;
- bool enabled;
-}nyx_fdl_user_t;
+ bool enabled;
+} nyx_fdl_user_t;
-nyx_fdl_user_t* nyx_fdl_user_init(shadow_memory_t* shadow_memory_state);
+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_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);
+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);
+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);
+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);
diff --git a/nyx/snapshot/memory/shadow_memory.c b/nyx/snapshot/memory/shadow_memory.c
index a3dfca402c..bf55ab77da 100644
--- a/nyx/snapshot/memory/shadow_memory.c
+++ b/nyx/snapshot/memory/shadow_memory.c
@@ -1,194 +1,219 @@
#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
#include "qemu/main-loop.h"
+#include "sysemu/sysemu.h"
#include "exec/ram_addr.h"
-#include "qemu/rcu_queue.h"
#include "migration/migration.h"
+#include "qemu/rcu_queue.h"
#include "nyx/debug.h"
#include "nyx/memory_access.h"
-#include "nyx/snapshot/memory/shadow_memory.h"
#include "nyx/snapshot/helper.h"
+#include "nyx/snapshot/memory/shadow_memory.h"
-typedef struct fast_reload_dump_head_s{
- uint32_t shadow_memory_regions;
- uint32_t ram_region_index; // remove
-} fast_reload_dump_head_t;
+typedef struct fast_reload_dump_head_s {
+ uint32_t shadow_memory_regions;
+ uint32_t ram_region_index; // remove
+} fast_reload_dump_head_t;
-typedef struct fast_reload_dump_entry_s{
- uint64_t shadow_memory_offset;
- char idstr[256];
-} fast_reload_dump_entry_t;
+typedef struct fast_reload_dump_entry_s {
+ uint64_t shadow_memory_offset;
+ char idstr[256];
+} fast_reload_dump_entry_t;
-static void shadow_memory_set_incremental_ptrs(shadow_memory_t* self){
- for(uint8_t i = 0; i < self->ram_regions_num; i++){
- self->ram_regions[i].incremental_region_ptr = self->incremental_ptr + self->ram_regions[i].offset;
+static void shadow_memory_set_incremental_ptrs(shadow_memory_t *self)
+{
+ for (uint8_t i = 0; i < self->ram_regions_num; i++) {
+ self->ram_regions[i].incremental_region_ptr =
+ self->incremental_ptr + self->ram_regions[i].offset;
}
}
-static void shadow_memory_pre_alloc_incremental(shadow_memory_t* self){
- self->incremental_ptr = mmap(0, self->memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, self->snapshot_ptr_fd, 0);
+static void shadow_memory_pre_alloc_incremental(shadow_memory_t *self)
+{
+ self->incremental_ptr = mmap(0, self->memory_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, self->snapshot_ptr_fd, 0);
shadow_memory_set_incremental_ptrs(self);
}
-static void shadow_memory_init_generic(shadow_memory_t* self){
- self->root_track_pages_num = 0;
+static void shadow_memory_init_generic(shadow_memory_t *self)
+{
+ self->root_track_pages_num = 0;
self->root_track_pages_size = 32 << 10;
- self->root_track_pages_stack = malloc(sizeof(uint64_t)*self->root_track_pages_size);
+ self->root_track_pages_stack =
+ malloc(sizeof(uint64_t) * self->root_track_pages_size);
shadow_memory_pre_alloc_incremental(self);
self->incremental_enabled = false;
}
-shadow_memory_t* shadow_memory_init(void){
-
+shadow_memory_t *shadow_memory_init(void)
+{
RAMBlock *block;
- RAMBlock* block_array[10];
- void* snapshot_ptr_offset_array[10];
+ RAMBlock *block_array[10];
+ void *snapshot_ptr_offset_array[10];
- shadow_memory_t* self = malloc(sizeof(shadow_memory_t));
+ shadow_memory_t *self = malloc(sizeof(shadow_memory_t));
memset(self, 0x0, sizeof(shadow_memory_t));
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
self->memory_size += block->used_length;
}
- self->snapshot_ptr_fd = memfd_create("in_memory_root_snapshot", MFD_CLOEXEC | MFD_ALLOW_SEALING);
+ self->snapshot_ptr_fd =
+ memfd_create("in_memory_root_snapshot", MFD_CLOEXEC | MFD_ALLOW_SEALING);
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);
+ fcntl(self->snapshot_ptr_fd, F_ADD_SEALS,
+ F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL);
- self->snapshot_ptr = mmap(NULL, self->memory_size, PROT_READ | PROT_WRITE , MAP_SHARED , self->snapshot_ptr_fd, 0);
+ 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);
- nyx_debug_p(RELOAD_PREFIX, "Allocating Memory (%p) Size: %lx", self->snapshot_ptr, self->memory_size);
+ nyx_debug_p(RELOAD_PREFIX, "Allocating Memory (%p) Size: %lx",
+ self->snapshot_ptr, self->memory_size);
-
- uint64_t offset = 0;
- uint8_t i = 0;
- 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);
+ uint64_t offset = 0;
+ uint8_t i = 0;
+ 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);
block_array[i] = block;
- memcpy(self->snapshot_ptr+offset, block->host, block->used_length);
- snapshot_ptr_offset_array[i++] = self->snapshot_ptr+offset;
+ memcpy(self->snapshot_ptr + offset, block->host, block->used_length);
+ snapshot_ptr_offset_array[i++] = self->snapshot_ptr + offset;
offset += block->used_length;
regions_num++;
- }
+ }
- for(uint8_t i = 0; i < regions_num; i++){
+ for (uint8_t i = 0; i < regions_num; i++) {
block = block_array[i];
- if(!block->mr->readonly){
-
- if(self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START){
-
+ if (!block->mr->readonly) {
+ if (self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START) {
self->ram_regions[self->ram_regions_num].ram_region = i;
self->ram_regions[self->ram_regions_num].base = block->mr->addr;
self->ram_regions[self->ram_regions_num].size = MEM_SPLIT_START;
- self->ram_regions[self->ram_regions_num].offset = snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
+ self->ram_regions[self->ram_regions_num].offset =
+ snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
- self->ram_regions[self->ram_regions_num].snapshot_region_ptr = self->snapshot_ptr+self->ram_regions[self->ram_regions_num].offset;
- 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);
+ self->ram_regions[self->ram_regions_num].snapshot_region_ptr =
+ self->snapshot_ptr +
+ self->ram_regions[self->ram_regions_num].offset;
+ 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);
strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
self->ram_regions_num++;
self->ram_regions[self->ram_regions_num].ram_region = i;
- self->ram_regions[self->ram_regions_num].base = MEM_SPLIT_END;
- 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 = 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);
- strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
- }
- else{
- self->ram_regions[self->ram_regions_num].ram_region = i;
- self->ram_regions[self->ram_regions_num].base = block->mr->addr;
- self->ram_regions[self->ram_regions_num].size = block->used_length;
- self->ram_regions[self->ram_regions_num].offset = snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
- self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
- self->ram_regions[self->ram_regions_num].snapshot_region_ptr = self->snapshot_ptr+self->ram_regions[self->ram_regions_num].offset;
- 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);
- strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
- }
-
- self->ram_regions_num++;
- }
- }
-
-
-
- shadow_memory_init_generic(self);
- return self;
+ self->ram_regions[self->ram_regions_num].base =
+MEM_SPLIT_END
+;
+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 =
+ 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);
+strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
+}
+else {
+ self->ram_regions[self->ram_regions_num].ram_region = i;
+ self->ram_regions[self->ram_regions_num].base = block->mr->addr;
+ self->ram_regions[self->ram_regions_num].size = block->used_length;
+ self->ram_regions[self->ram_regions_num].offset =
+ snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
+ self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
+ self->ram_regions[self->ram_regions_num].snapshot_region_ptr =
+ self->snapshot_ptr + self->ram_regions[self->ram_regions_num].offset;
+ 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);
+ strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
}
-shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, bool pre_snapshot){
-
- RAMBlock *block;
- RAMBlock* block_array[10];
- void* snapshot_ptr_offset_array[10];
+self->ram_regions_num++;
+}
+}
- shadow_memory_t* self = malloc(sizeof(shadow_memory_t));
+
+shadow_memory_init_generic(self);
+return self;
+}
+
+shadow_memory_t *shadow_memory_init_from_snapshot(const char *snapshot_folder,
+ bool pre_snapshot)
+{
+ RAMBlock *block;
+ RAMBlock *block_array[10];
+ void *snapshot_ptr_offset_array[10];
+
+ shadow_memory_t *self = malloc(sizeof(shadow_memory_t));
memset(self, 0x0, sizeof(shadow_memory_t));
/* count total memory size */
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
self->memory_size += block->used_length;
}
/* count number of ram regions */
- QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
- if(!block->mr->readonly){
- if(self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START){
+ QLIST_FOREACH_RCU (block, &ram_list.blocks, next) {
+ if (!block->mr->readonly) {
+ if (self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START) {
self->ram_regions_num++;
}
self->ram_regions_num++;
}
}
- char* path_meta;
- char* path_dump;
+ char *path_meta;
+ char *path_dump;
assert(asprintf(&path_meta, "%s/fast_snapshot.mem_meta", snapshot_folder) != -1);
assert(asprintf(&path_dump, "%s/fast_snapshot.mem_dump", snapshot_folder) != -1);
- fast_reload_dump_head_t head;
+ fast_reload_dump_head_t head;
- FILE* file_mem_meta = fopen (path_meta, "r");
+ 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){
- nyx_error("Error: self->ram_regions_num (%d) != head.shadow_memory_regions (%d)\n", self->ram_regions_num, head.shadow_memory_regions);
+ if (self->ram_regions_num != head.shadow_memory_regions) {
+ nyx_error(
+ "Error: self->ram_regions_num (%d) != head.shadow_memory_regions (%d)\n",
+ self->ram_regions_num, head.shadow_memory_regions);
exit(1);
}
- //printf("LOAD -> self->ram_regions_num: %d\n", self->ram_regions_num);
+ // printf("LOAD -> self->ram_regions_num: %d\n", self->ram_regions_num);
- FILE* file_mem_dump = fopen (path_dump, "r");
+ FILE *file_mem_dump = fopen(path_dump, "r");
assert(file_mem_dump != NULL);
fseek(file_mem_dump, 0L, SEEK_END);
uint64_t file_mem_dump_size = ftell(file_mem_dump);
- nyx_debug("guest_ram_size == ftell(f) => 0x%lx vs 0x%lx (%s)\n", self->memory_size, file_mem_dump_size, path_dump);
+ nyx_debug("guest_ram_size == ftell(f) => 0x%lx vs 0x%lx (%s)\n",
+ self->memory_size, file_mem_dump_size, path_dump);
- #define VGA_SIZE (16<<20)
+#define VGA_SIZE (16 << 20)
- if(self->memory_size != file_mem_dump_size){
- if (file_mem_dump_size >= VGA_SIZE){
- nyx_error("ERROR: guest size should be %ld MB - set it to %ld MB\n", (file_mem_dump_size-VGA_SIZE)>>20, (self->memory_size-VGA_SIZE)>>20);
+ if (self->memory_size != file_mem_dump_size) {
+ if (file_mem_dump_size >= VGA_SIZE) {
+ nyx_error("ERROR: guest size should be %ld MB - set it to %ld MB\n",
+ (file_mem_dump_size - VGA_SIZE) >> 20,
+ (self->memory_size - VGA_SIZE) >> 20);
exit(1);
- }
- else{
- nyx_error("ERROR: guest size: %ld bytes\n", file_mem_dump_size);
+ } else {
+ nyx_error("ERROR: guest size: %ld bytes\n", file_mem_dump_size);
exit(1);
}
}
@@ -197,116 +222,137 @@ shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, b
fclose(file_mem_dump);
self->snapshot_ptr_fd = open(path_dump, O_RDONLY);
- self->snapshot_ptr = mmap(0, self->memory_size, PROT_READ, MAP_SHARED, self->snapshot_ptr_fd, 0);
+ self->snapshot_ptr =
+ mmap(0, self->memory_size, PROT_READ, MAP_SHARED, self->snapshot_ptr_fd, 0);
- assert(self->snapshot_ptr != (void*)-1);
+ assert(self->snapshot_ptr != (void *)-1);
madvise(self->snapshot_ptr, self->memory_size, MADV_MERGEABLE);
- uint64_t offset = 0;
- uint8_t i = 0;
- 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);
+ uint64_t offset = 0;
+ uint8_t i = 0;
+ 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);
- block_array[i] = block;
- snapshot_ptr_offset_array[i++] = self->snapshot_ptr+offset;
+ block_array[i] = block;
+ snapshot_ptr_offset_array[i++] = self->snapshot_ptr + offset;
offset += block->used_length;
regions_num++;
}
self->ram_regions_num = 0;
- for(uint8_t i = 0; i < regions_num; i++){
+ for (uint8_t i = 0; i < regions_num; i++) {
block = block_array[i];
- if(!block->mr->readonly){
-
- if(self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START){
-
+ if (!block->mr->readonly) {
+ if (self->ram_regions_num == 0 && block->used_length >= MEM_SPLIT_START) {
self->ram_regions[self->ram_regions_num].ram_region = i;
self->ram_regions[self->ram_regions_num].base = block->mr->addr;
self->ram_regions[self->ram_regions_num].size = MEM_SPLIT_START;
- self->ram_regions[self->ram_regions_num].offset = snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
+ self->ram_regions[self->ram_regions_num].offset =
+ snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
- self->ram_regions[self->ram_regions_num].snapshot_region_ptr = self->snapshot_ptr+self->ram_regions[self->ram_regions_num].offset;
- 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);
+ self->ram_regions[self->ram_regions_num].snapshot_region_ptr =
+ self->snapshot_ptr +
+ self->ram_regions[self->ram_regions_num].offset;
+ 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);
strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
self->ram_regions_num++;
self->ram_regions[self->ram_regions_num].ram_region = i;
- self->ram_regions[self->ram_regions_num].base = MEM_SPLIT_END;
- 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 = 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);
- strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
- }
- else{
- self->ram_regions[self->ram_regions_num].ram_region = i;
- self->ram_regions[self->ram_regions_num].base = block->mr->addr;
- self->ram_regions[self->ram_regions_num].size = block->used_length;
- self->ram_regions[self->ram_regions_num].offset = snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
- self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
- self->ram_regions[self->ram_regions_num].snapshot_region_ptr = self->snapshot_ptr+self->ram_regions[self->ram_regions_num].offset;
- 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);
- strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
- }
+ self->ram_regions[self->ram_regions_num].base =
+MEM_SPLIT_END
+;
+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 =
+ 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);
+strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
+}
+else {
+ self->ram_regions[self->ram_regions_num].ram_region = i;
+ self->ram_regions[self->ram_regions_num].base = block->mr->addr;
+ self->ram_regions[self->ram_regions_num].size = block->used_length;
+ self->ram_regions[self->ram_regions_num].offset =
+ snapshot_ptr_offset_array[i] - snapshot_ptr_offset_array[0];
+ self->ram_regions[self->ram_regions_num].host_region_ptr = block->host;
+ self->ram_regions[self->ram_regions_num].snapshot_region_ptr =
+ self->snapshot_ptr + self->ram_regions[self->ram_regions_num].offset;
+ 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);
+ strcpy(self->ram_regions[self->ram_regions_num].idstr, block->idstr);
+}
- self->ram_regions_num++;
- }
- }
+self->ram_regions_num++;
+}
+}
#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);
- }
+/* 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);
- }
+/* 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;
+shadow_memory_init_generic(self);
+return self;
}
-void shadow_memory_prepare_incremental(shadow_memory_t* self){
+void shadow_memory_prepare_incremental(shadow_memory_t *self)
+{
static int count = 0;
- if(count >= RESTORE_RATE){
+ if (count >= RESTORE_RATE) {
count = 0;
munmap(self->incremental_ptr, self->memory_size);
- self->incremental_ptr = mmap(0, self->memory_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, self->snapshot_ptr_fd, 0);
- shadow_memory_set_incremental_ptrs(self);
+ self->incremental_ptr = mmap(0, self->memory_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, self->snapshot_ptr_fd, 0);
+ shadow_memory_set_incremental_ptrs(self);
}
count++;
}
-void shadow_memory_switch_snapshot(shadow_memory_t* self, bool incremental){
+void shadow_memory_switch_snapshot(shadow_memory_t *self, bool incremental)
+{
self->incremental_enabled = incremental;
}
-void shadow_memory_restore_memory(shadow_memory_t* self){
+void shadow_memory_restore_memory(shadow_memory_t *self)
+{
rcu_read_lock();
- uint8_t slot = 0;
+ uint8_t slot = 0;
uint64_t addr = 0;
- for(uint64_t i = 0; i < self->root_track_pages_num; i++){
+ for (uint64_t i = 0; i < self->root_track_pages_num; i++) {
addr = self->root_track_pages_stack[i] & 0xFFFFFFFFFFFFF000;
slot = self->root_track_pages_stack[i] & 0xFFF;
- memcpy(self->ram_regions[slot].host_region_ptr+addr, self->ram_regions[slot].snapshot_region_ptr+addr, TARGET_PAGE_SIZE);
- memcpy(self->ram_regions[slot].incremental_region_ptr+addr, self->ram_regions[slot].snapshot_region_ptr+addr, TARGET_PAGE_SIZE);
+ memcpy(self->ram_regions[slot].host_region_ptr + addr,
+ self->ram_regions[slot].snapshot_region_ptr + addr, TARGET_PAGE_SIZE);
+ memcpy(self->ram_regions[slot].incremental_region_ptr + addr,
+ self->ram_regions[slot].snapshot_region_ptr + addr, TARGET_PAGE_SIZE);
}
self->root_track_pages_num = 0;
@@ -315,38 +361,42 @@ void shadow_memory_restore_memory(shadow_memory_t* self){
/* only used in debug mode -> no need to be fast */
-bool shadow_memory_is_root_page_tracked(shadow_memory_t* self, uint64_t address, uint8_t slot){
+bool shadow_memory_is_root_page_tracked(shadow_memory_t *self,
+ uint64_t address,
+ uint8_t slot)
+{
uint64_t value = (address & 0xFFFFFFFFFFFFF000) | slot;
-
- for(uint64_t i = 0; i < self->root_track_pages_num; i++){
- if(self->root_track_pages_stack[i] == value){
+
+ for (uint64_t i = 0; i < self->root_track_pages_num; i++) {
+ if (self->root_track_pages_stack[i] == value) {
return true;
}
}
return false;
}
-void shadow_memory_serialize(shadow_memory_t* self, const char* snapshot_folder){
- char* tmp1;
- char* tmp2;
+void shadow_memory_serialize(shadow_memory_t *self, const char *snapshot_folder)
+{
+ char *tmp1;
+ char *tmp2;
assert(asprintf(&tmp1, "%s/fast_snapshot.mem_meta", snapshot_folder) != -1);
assert(asprintf(&tmp2, "%s/fast_snapshot.mem_dump", snapshot_folder) != -1);
- FILE* file_mem_meta = fopen(tmp1, "w+b");
- FILE* file_mem_data = fopen(tmp2, "w+b");
+ FILE *file_mem_meta = fopen(tmp1, "w+b");
+ FILE *file_mem_data = fopen(tmp2, "w+b");
- fast_reload_dump_head_t head;
+ fast_reload_dump_head_t head;
fast_reload_dump_entry_t entry;
head.shadow_memory_regions = self->ram_regions_num;
- head.ram_region_index = 0; /* due to legacy reasons */
+ head.ram_region_index = 0; /* due to legacy reasons */
fwrite(&head, sizeof(fast_reload_dump_head_t), 1, file_mem_meta);
- for (uint64_t i = 0; i < self->ram_regions_num; i++){
+ for (uint64_t i = 0; i < self->ram_regions_num; i++) {
memset(&entry, 0x0, sizeof(fast_reload_dump_entry_t));
entry.shadow_memory_offset = (uint64_t)self->ram_regions[i].offset;
- strncpy((char*)&entry.idstr, (const char*)self->ram_regions[i].idstr, 255);
+ strncpy((char *)&entry.idstr, (const char *)self->ram_regions[i].idstr, 255);
fwrite(&entry, sizeof(fast_reload_dump_entry_t), 1, file_mem_meta);
}
@@ -356,43 +406,57 @@ void shadow_memory_serialize(shadow_memory_t* self, const char* snapshot_folder)
fclose(file_mem_data);
}
-static bool shadow_memory_read_page_frame(shadow_memory_t* self, uint64_t address, void* ptr, uint16_t offset, uint16_t size){
+static bool shadow_memory_read_page_frame(shadow_memory_t *self,
+ uint64_t address,
+ void *ptr,
+ uint16_t offset,
+ uint16_t size)
+{
assert((offset + size) <= 0x1000);
- for(uint8_t i = 0; i < self->ram_regions_num; i++){
- if(address >= self->ram_regions[i].base && address < (self->ram_regions[i].base + self->ram_regions[i].size)){
- void* snapshot_ptr = self->ram_regions[i].snapshot_region_ptr + (address-self->ram_regions[i].base);
- memcpy(ptr, snapshot_ptr+offset, size);
+ for (uint8_t i = 0; i < self->ram_regions_num; i++) {
+ if (address >= self->ram_regions[i].base &&
+ address < (self->ram_regions[i].base + self->ram_regions[i].size))
+ {
+ void *snapshot_ptr = self->ram_regions[i].snapshot_region_ptr +
+ (address - self->ram_regions[i].base);
+ memcpy(ptr, snapshot_ptr + offset, size);
return true;
}
}
return false;
}
-bool shadow_memory_read_physical_memory(shadow_memory_t* self, uint64_t address, void* ptr, size_t size){
-
- size_t bytes_left = size;
- size_t copy_bytes = 0;
+bool shadow_memory_read_physical_memory(shadow_memory_t *self,
+ uint64_t address,
+ void *ptr,
+ size_t size)
+{
+ size_t bytes_left = size;
+ size_t copy_bytes = 0;
uint64_t current_address = address;
- uint64_t offset = 0;
+ uint64_t offset = 0;
while (bytes_left != 0) {
-
/* full page */
- if ((current_address & 0xFFF) == 0){
+ if ((current_address & 0xFFF) == 0) {
copy_bytes = 0x1000;
}
/* partial page (starting at an offset) */
- else {
+ else
+ {
copy_bytes = 0x1000 - (current_address & 0xFFF);
}
-
+
/* partial page */
- if (bytes_left < copy_bytes){
+ if (bytes_left < copy_bytes) {
copy_bytes = bytes_left;
}
- if (shadow_memory_read_page_frame(self, current_address & ~0xFFFULL, ptr + offset, current_address & 0xFFFULL, copy_bytes) == false){
+ if (shadow_memory_read_page_frame(self, current_address & ~0xFFFULL,
+ ptr + offset, current_address & 0xFFFULL,
+ copy_bytes) == false)
+ {
return false;
}
current_address += copy_bytes;
diff --git a/nyx/snapshot/memory/shadow_memory.h b/nyx/snapshot/memory/shadow_memory.h
index a71626b62c..7ace5cfd81 100644
--- a/nyx/snapshot/memory/shadow_memory.h
+++ b/nyx/snapshot/memory/shadow_memory.h
@@ -1,90 +1,101 @@
-#pragma once
+#pragma once
-#include
#include "nyx/snapshot/devices/state_reallocation.h"
+#include
/* munmap & mmap incremental snapshot area after RESTORE_RATE restores to avoid high memory pressure */
#define RESTORE_RATE 2000
-typedef struct ram_region_s{
+typedef struct ram_region_s {
+ /* simple numeric identifier
+ * (can be the same for multiple regions if the memory is
+ * actually splitted across different bases in the guest's memory
+ * but related to the same mapping)
+ */
+ uint8_t ram_region;
- /* simple numeric identifier
- * (can be the same for multiple regions if the memory is
- * actually splitted across different bases in the guest's memory
- * but related to the same mapping)
- */
- uint8_t ram_region;
+ /* base in the guest's physical address space */
+ uint64_t base;
- /* base in the guest's physical address space */
- uint64_t base;
+ /* size of this region */
+ uint64_t size;
- /* size of this region */
- uint64_t size;
+ /* mmap offset of this region (does not apply to the actual guest's memory) */
+ uint64_t offset;
- /* mmap offset of this region (does not apply to the actual guest's memory) */
- uint64_t offset;
+ /* pointer to the actual mmap region used by KVM */
+ void *host_region_ptr;
- /* pointer to the actual mmap region used by KVM */
- void* host_region_ptr;
+ /* pointer to the snapshot mmap + offset */
+ void *snapshot_region_ptr;
- /* pointer to the snapshot mmap + offset */
- void* snapshot_region_ptr;
+ /* pointer to the incremental CoW mmap + offset */
+ void *incremental_region_ptr;
- /* pointer to the incremental CoW mmap + offset */
- void* incremental_region_ptr;
-
- char* idstr;
+ char *idstr;
} ram_region_t;
-typedef struct shadow_memory_s{
- /* snapshot memory backup */
- void* snapshot_ptr;
+typedef struct shadow_memory_s {
+ /* snapshot memory backup */
+ void *snapshot_ptr;
- /* snapshot memory backup memfd */
- int snapshot_ptr_fd;
+ /* snapshot memory backup memfd */
+ int snapshot_ptr_fd;
- /* incremental memory backup */
- void* incremental_ptr;
+ /* incremental memory backup */
+ void *incremental_ptr;
- //fast_reload_tmp_snapshot_t tmp_snapshot;
+ // fast_reload_tmp_snapshot_t tmp_snapshot;
- /* total memory size */
- uint64_t memory_size;
+ /* total memory size */
+ uint64_t memory_size;
- /* keep this */
- ram_region_t ram_regions[10];
- uint8_t ram_regions_num;
+ /* keep this */
+ ram_region_t ram_regions[10];
+ uint8_t ram_regions_num;
- /* additional dirty stack to restore root snapshot */
- uint64_t root_track_pages_num;
- uint64_t root_track_pages_size;
- uint64_t* root_track_pages_stack;
+ /* additional dirty stack to restore root snapshot */
+ uint64_t root_track_pages_num;
+ uint64_t root_track_pages_size;
+ uint64_t *root_track_pages_stack;
- bool incremental_enabled;
-}shadow_memory_t;
+ bool incremental_enabled;
+} shadow_memory_t;
-shadow_memory_t* shadow_memory_init(void);
-shadow_memory_t* shadow_memory_init_from_snapshot(const char* snapshot_folder, bool pre_snapshot);
+shadow_memory_t *shadow_memory_init(void);
+shadow_memory_t *shadow_memory_init_from_snapshot(const char *snapshot_folder,
+ bool pre_snapshot);
-void shadow_memory_prepare_incremental(shadow_memory_t* self);
-void shadow_memory_switch_snapshot(shadow_memory_t* self, bool incremental);
+void shadow_memory_prepare_incremental(shadow_memory_t *self);
+void shadow_memory_switch_snapshot(shadow_memory_t *self, bool incremental);
-void shadow_memory_restore_memory(shadow_memory_t* self);
+void shadow_memory_restore_memory(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;
- self->root_track_pages_stack = realloc(self->root_track_pages_stack, self->root_track_pages_size*sizeof(uint64_t));
+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;
+ self->root_track_pages_stack =
+ realloc(self->root_track_pages_stack,
+ self->root_track_pages_size * sizeof(uint64_t));
}
- self->root_track_pages_stack[self->root_track_pages_num] = (address & 0xFFFFFFFFFFFFF000) | slot;
+ self->root_track_pages_stack[self->root_track_pages_num] =
+ (address & 0xFFFFFFFFFFFFF000) | slot;
self->root_track_pages_num++;
}
-bool shadow_memory_is_root_page_tracked(shadow_memory_t* self, uint64_t address, uint8_t slot);
+bool shadow_memory_is_root_page_tracked(shadow_memory_t *self,
+ uint64_t address,
+ uint8_t slot);
-void shadow_memory_serialize(shadow_memory_t* self, const char* snapshot_folder);
+void shadow_memory_serialize(shadow_memory_t *self, const char *snapshot_folder);
-bool shadow_memory_read_physical_memory(shadow_memory_t* self, uint64_t address, void* ptr, size_t size);
+bool shadow_memory_read_physical_memory(shadow_memory_t *self,
+ uint64_t address,
+ void *ptr,
+ size_t size);
diff --git a/nyx/state/snapshot_state.c b/nyx/state/snapshot_state.c
index 8d61960aa3..14d7800f18 100644
--- a/nyx/state/snapshot_state.c
+++ b/nyx/state/snapshot_state.c
@@ -3,140 +3,152 @@
#include "sysemu/cpus.h"
#include "nyx/state/snapshot_state.h"
#include "nyx/debug.h"
-#include "nyx/state/state.h"
#include "nyx/memory_access.h"
-#include
+#include "nyx/state/state.h"
#include
+#include
-void serialize_state(const char* filename_prefix, bool is_pre_snapshot){
- nyx_trace();
+void serialize_state(const char *filename_prefix, bool is_pre_snapshot)
+{
+ nyx_trace();
- char* tmp;
+ char *tmp;
- assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1);
+ assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1);
- FILE *fp = fopen(tmp, "wb");
- if(fp == NULL) {
+ FILE *fp = fopen(tmp, "wb");
+ if (fp == NULL) {
nyx_error("[%s] Could not open file %s.\n", __func__, tmp);
assert(false);
}
- serialized_state_header_t header = {0};
+ serialized_state_header_t header = { 0 };
- header.magic = NYX_SERIALIZED_STATE_MAGIC;
+ header.magic = NYX_SERIALIZED_STATE_MAGIC;
header.version = NYX_SERIALIZED_STATE_VERSION;
- if (is_pre_snapshot){
+ if (is_pre_snapshot) {
header.type = NYX_SERIALIZED_TYPE_PRE_SNAPSHOT;
fwrite(&header, sizeof(serialized_state_header_t), 1, fp);
- }
- else{
+ } else {
header.type = NYX_SERIALIZED_TYPE_ROOT_SNAPSHOT;
fwrite(&header, sizeof(serialized_state_header_t), 1, fp);
- qemu_nyx_state_t* nyx_global_state = GET_GLOBAL_STATE();
- serialized_state_root_snapshot_t root_snapshot = {0};
+ qemu_nyx_state_t *nyx_global_state = GET_GLOBAL_STATE();
+ serialized_state_root_snapshot_t root_snapshot = { 0 };
- for (uint8_t i = 0; i < 4; i++){
- root_snapshot.pt_ip_filter_configured[i] = nyx_global_state->pt_ip_filter_configured[i];
+ for (uint8_t i = 0; i < 4; i++) {
+ root_snapshot.pt_ip_filter_configured[i] =
+ nyx_global_state->pt_ip_filter_configured[i];
root_snapshot.pt_ip_filter_a[i] = nyx_global_state->pt_ip_filter_a[i];
root_snapshot.pt_ip_filter_b[i] = nyx_global_state->pt_ip_filter_b[i];
}
root_snapshot.parent_cr3 = nyx_global_state->parent_cr3;
- root_snapshot.disassembler_word_width = nyx_global_state->disassembler_word_width;
+ root_snapshot.disassembler_word_width =
+ nyx_global_state->disassembler_word_width;
root_snapshot.fast_reload_pre_image = nyx_global_state->fast_reload_pre_image;
- root_snapshot.mem_mode = nyx_global_state->mem_mode;
- root_snapshot.pt_trace_mode =nyx_global_state->pt_trace_mode;
+ root_snapshot.mem_mode = nyx_global_state->mem_mode;
+ root_snapshot.pt_trace_mode = nyx_global_state->pt_trace_mode;
root_snapshot.input_buffer_vaddr = nyx_global_state->payload_buffer;
root_snapshot.protect_input_buffer = nyx_global_state->protect_payload_buffer;
-
+
root_snapshot.input_buffer_size = nyx_global_state->input_buffer_size;
root_snapshot.cap_timeout_detection = nyx_global_state->cap_timeout_detection;
root_snapshot.cap_only_reload_mode = nyx_global_state->cap_only_reload_mode;
- root_snapshot.cap_compile_time_tracing = nyx_global_state->cap_compile_time_tracing;
+ root_snapshot.cap_compile_time_tracing =
+ nyx_global_state->cap_compile_time_tracing;
root_snapshot.cap_ijon_tracing = nyx_global_state->cap_ijon_tracing;
- root_snapshot.cap_cr3 = nyx_global_state->cap_cr3;
- root_snapshot.cap_compile_time_tracing_buffer_vaddr = nyx_global_state->cap_compile_time_tracing_buffer_vaddr;
- root_snapshot.cap_ijon_tracing_buffer_vaddr = nyx_global_state->cap_ijon_tracing_buffer_vaddr;
- root_snapshot.cap_coverage_bitmap_size = nyx_global_state->cap_coverage_bitmap_size;
+ root_snapshot.cap_cr3 = nyx_global_state->cap_cr3;
+ root_snapshot.cap_compile_time_tracing_buffer_vaddr =
+ nyx_global_state->cap_compile_time_tracing_buffer_vaddr;
+ root_snapshot.cap_ijon_tracing_buffer_vaddr =
+ nyx_global_state->cap_ijon_tracing_buffer_vaddr;
+ root_snapshot.cap_coverage_bitmap_size =
+ nyx_global_state->cap_coverage_bitmap_size;
fwrite(&root_snapshot, sizeof(serialized_state_root_snapshot_t), 1, fp);
-
}
-
+
fclose(fp);
- free(tmp);
+ free(tmp);
}
-void deserialize_state(const char* filename_prefix){
- nyx_trace();
+void deserialize_state(const char *filename_prefix)
+{
+ nyx_trace();
- char* tmp;
+ char *tmp;
- assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1);
+ assert(asprintf(&tmp, "%s/global.state", filename_prefix) != -1);
- FILE *fp = fopen(tmp, "rb");
- if(fp == NULL) {
+ FILE *fp = fopen(tmp, "rb");
+ if (fp == NULL) {
nyx_debug("[%s] Could not open file %s.\n", __func__, tmp);
assert(false);
}
- serialized_state_header_t header = {0};
+ serialized_state_header_t header = { 0 };
assert(fread(&header, sizeof(serialized_state_header_t), 1, fp) == 1);
assert(header.magic == NYX_SERIALIZED_STATE_MAGIC);
assert(header.version == NYX_SERIALIZED_STATE_VERSION);
- if(header.type == NYX_SERIALIZED_TYPE_PRE_SNAPSHOT){
+ if (header.type == NYX_SERIALIZED_TYPE_PRE_SNAPSHOT) {
/* we're done here */
- }
- else if (header.type == NYX_SERIALIZED_TYPE_ROOT_SNAPSHOT){
- qemu_nyx_state_t* nyx_global_state = GET_GLOBAL_STATE();
- serialized_state_root_snapshot_t root_snapshot = {0};
- assert(fread(&root_snapshot, sizeof(serialized_state_root_snapshot_t), 1, fp) == 1);
+ } else if (header.type == NYX_SERIALIZED_TYPE_ROOT_SNAPSHOT) {
+ qemu_nyx_state_t *nyx_global_state = GET_GLOBAL_STATE();
+ serialized_state_root_snapshot_t root_snapshot = { 0 };
+ assert(fread(&root_snapshot, sizeof(serialized_state_root_snapshot_t), 1,
+ fp) == 1);
- for (uint8_t i = 0; i < 4; i++){
- nyx_global_state->pt_ip_filter_configured[i] = root_snapshot.pt_ip_filter_configured[i];
+ for (uint8_t i = 0; i < 4; i++) {
+ nyx_global_state->pt_ip_filter_configured[i] =
+ root_snapshot.pt_ip_filter_configured[i];
nyx_global_state->pt_ip_filter_a[i] = root_snapshot.pt_ip_filter_a[i];
nyx_global_state->pt_ip_filter_b[i] = root_snapshot.pt_ip_filter_b[i];
}
nyx_global_state->parent_cr3 = root_snapshot.parent_cr3;
- nyx_global_state->disassembler_word_width = root_snapshot.disassembler_word_width;
+ nyx_global_state->disassembler_word_width =
+ root_snapshot.disassembler_word_width;
nyx_global_state->fast_reload_pre_image = root_snapshot.fast_reload_pre_image;
- nyx_global_state->mem_mode = root_snapshot.mem_mode;
- nyx_global_state->pt_trace_mode =root_snapshot.pt_trace_mode;
+ nyx_global_state->mem_mode = root_snapshot.mem_mode;
+ nyx_global_state->pt_trace_mode = root_snapshot.pt_trace_mode;
nyx_global_state->payload_buffer = root_snapshot.input_buffer_vaddr;
nyx_global_state->protect_payload_buffer = root_snapshot.protect_input_buffer;
-
+
nyx_global_state->input_buffer_size = root_snapshot.input_buffer_size;
nyx_global_state->cap_timeout_detection = root_snapshot.cap_timeout_detection;
nyx_global_state->cap_only_reload_mode = root_snapshot.cap_only_reload_mode;
- nyx_global_state->cap_compile_time_tracing = root_snapshot.cap_compile_time_tracing;
+ nyx_global_state->cap_compile_time_tracing =
+ root_snapshot.cap_compile_time_tracing;
nyx_global_state->cap_ijon_tracing = root_snapshot.cap_ijon_tracing;
- nyx_global_state->cap_cr3 = root_snapshot.cap_cr3;
- nyx_global_state->cap_compile_time_tracing_buffer_vaddr = root_snapshot.cap_compile_time_tracing_buffer_vaddr;
- nyx_global_state->cap_ijon_tracing_buffer_vaddr = root_snapshot.cap_ijon_tracing_buffer_vaddr;
- nyx_global_state->cap_coverage_bitmap_size = root_snapshot.cap_coverage_bitmap_size;
+ nyx_global_state->cap_cr3 = root_snapshot.cap_cr3;
+ nyx_global_state->cap_compile_time_tracing_buffer_vaddr =
+ root_snapshot.cap_compile_time_tracing_buffer_vaddr;
+ nyx_global_state->cap_ijon_tracing_buffer_vaddr =
+ root_snapshot.cap_ijon_tracing_buffer_vaddr;
+ nyx_global_state->cap_coverage_bitmap_size =
+ root_snapshot.cap_coverage_bitmap_size;
assert(apply_capabilities(qemu_get_cpu(0)));
- remap_payload_buffer(nyx_global_state->payload_buffer, ((CPUState *)qemu_get_cpu(0)) );
+ remap_payload_buffer(nyx_global_state->payload_buffer,
+ ((CPUState *)qemu_get_cpu(0)));
/* makes sure that we are allowed to enter the fuzzing loop */
- nyx_global_state->get_host_config_done = true;
+ nyx_global_state->get_host_config_done = true;
nyx_global_state->set_agent_config_done = true;
- }
- else{
+ } else {
fprintf(stderr, "[QEMU-Nyx]: this feature is currently missing\n");
abort();
}
fclose(fp);
- free(tmp);
+ free(tmp);
}
diff --git a/nyx/state/snapshot_state.h b/nyx/state/snapshot_state.h
index cfeb103bae..fa9491795f 100644
--- a/nyx/state/snapshot_state.h
+++ b/nyx/state/snapshot_state.h
@@ -3,12 +3,12 @@
#include
#include
-#define NYX_SERIALIZED_STATE_MAGIC 0x58594E
-#define NYX_SERIALIZED_STATE_VERSION 1
+#define NYX_SERIALIZED_STATE_MAGIC 0x58594E
+#define NYX_SERIALIZED_STATE_VERSION 1
-#define NYX_SERIALIZED_TYPE_PRE_SNAPSHOT 0
-#define NYX_SERIALIZED_TYPE_ROOT_SNAPSHOT 1
-#define NYX_SERIALIZED_TYPE_NESTED_SNAPSHOT 2
+#define NYX_SERIALIZED_TYPE_PRE_SNAPSHOT 0
+#define NYX_SERIALIZED_TYPE_ROOT_SNAPSHOT 1
+#define NYX_SERIALIZED_TYPE_NESTED_SNAPSHOT 2
typedef struct serialized_state_header_s {
uint32_t magic;
@@ -17,24 +17,24 @@ typedef struct serialized_state_header_s {
} serialized_state_header_t;
typedef struct serialized_state_root_snapshot_s {
- bool pt_ip_filter_configured[4];
+ bool pt_ip_filter_configured[4];
uint64_t pt_ip_filter_a[4];
uint64_t pt_ip_filter_b[4];
uint64_t parent_cr3;
- uint8_t disassembler_word_width;
- bool fast_reload_pre_image;
- uint8_t mem_mode;
- bool pt_trace_mode;
+ uint8_t disassembler_word_width;
+ bool fast_reload_pre_image;
+ uint8_t mem_mode;
+ bool pt_trace_mode;
uint64_t input_buffer_vaddr;
- bool protect_input_buffer;
+ bool protect_input_buffer;
uint32_t input_buffer_size;
- uint8_t cap_timeout_detection;
- uint8_t cap_only_reload_mode;
- uint8_t cap_compile_time_tracing;
- uint8_t cap_ijon_tracing;
- uint64_t cap_cr3;
+ uint8_t cap_timeout_detection;
+ uint8_t cap_only_reload_mode;
+ uint8_t cap_compile_time_tracing;
+ uint8_t cap_ijon_tracing;
+ uint64_t cap_cr3;
uint64_t cap_compile_time_tracing_buffer_vaddr;
uint64_t cap_ijon_tracing_buffer_vaddr;
uint64_t cap_coverage_bitmap_size;
@@ -42,6 +42,5 @@ typedef struct serialized_state_root_snapshot_s {
} serialized_state_root_snapshot_t;
-
-void serialize_state(const char* filename_prefix, bool is_pre_snapshot);
-void deserialize_state(const char* filename_prefix);
+void serialize_state(const char *filename_prefix, bool is_pre_snapshot);
+void deserialize_state(const char *filename_prefix);
diff --git a/nyx/state/state.c b/nyx/state/state.c
index 22680898e3..b7e736cd16 100644
--- a/nyx/state/state.c
+++ b/nyx/state/state.c
@@ -24,23 +24,24 @@ along with QEMU-PT. If not, see .
#include
#include
-#include "nyx/state/state.h"
-#include "nyx/debug.h"
-#include "nyx/memory_access.h"
#include "sysemu/kvm.h"
#include "nyx/auxiliary_buffer.h"
-#include "nyx/sharedir.h"
+#include "nyx/debug.h"
#include "nyx/fast_vm_reload_sync.h"
#include "nyx/helpers.h"
+#include "nyx/memory_access.h"
+#include "nyx/sharedir.h"
+#include "nyx/state/state.h"
-//#define STATE_VERBOSE
+// #define STATE_VERBOSE
/* global singleton */
qemu_nyx_state_t global_state;
#define LIBXDC_RELEASE_VERSION_REQUIRED 2
-void state_init_global(void){
+void state_init_global(void)
+{
#ifdef STATE_VERBOSE
fprintf(stderr, "--> %s <--\n", __func__);
#endif
@@ -50,194 +51,213 @@ void state_init_global(void){
global_state.nyx_fdl = false;
global_state.workdir_path = NULL;
- global_state.worker_id = 0xffff;
+ global_state.worker_id = 0xffff;
- global_state.fast_reload_enabled = false;
- global_state.fast_reload_mode = false;
- global_state.fast_reload_path = NULL;
- global_state.fast_reload_pre_path = NULL;
+ global_state.fast_reload_enabled = false;
+ global_state.fast_reload_mode = false;
+ global_state.fast_reload_path = NULL;
+ global_state.fast_reload_pre_path = NULL;
global_state.fast_reload_pre_image = false;
global_state.fast_reload_snapshot = fast_reload_new();
- global_state.reload_state = init_fast_vm_reload_sync();
+ global_state.reload_state = init_fast_vm_reload_sync();
global_state.decoder = NULL;
global_state.page_cache = NULL;
- global_state.redqueen_enable_pending = false;
- global_state.redqueen_disable_pending = false;
+ global_state.redqueen_enable_pending = false;
+ global_state.redqueen_disable_pending = false;
global_state.redqueen_instrumentation_mode = 0;
- global_state.redqueen_update_blacklist = false;
- global_state.patches_enable_pending = false;
- global_state.patches_disable_pending = false;
- global_state.redqueen_state = NULL;
+ global_state.redqueen_update_blacklist = false;
+ global_state.patches_enable_pending = false;
+ global_state.patches_disable_pending = false;
+ global_state.redqueen_state = NULL;
- for(uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++){
+ for (uint8_t i = 0; i < INTEL_PT_MAX_RANGES; i++) {
global_state.pt_ip_filter_configured[i] = false;
- global_state.pt_ip_filter_enabled[i] = false;
- global_state.pt_ip_filter_a[i] = 0x0;
- global_state.pt_ip_filter_b[i] = 0x0;
+ global_state.pt_ip_filter_enabled[i] = false;
+ global_state.pt_ip_filter_a[i] = 0x0;
+ global_state.pt_ip_filter_b[i] = 0x0;
}
global_state.pt_c3_filter = 0;
-
- global_state.parent_cr3 = 0;
- global_state.disassembler_word_width = 64;
- global_state.nested = false;
- global_state.payload_buffer = 0;
- global_state.nested_payload_pages = NULL;
+
+ global_state.parent_cr3 = 0;
+ global_state.disassembler_word_width = 64;
+ global_state.nested = false;
+ global_state.payload_buffer = 0;
+ global_state.nested_payload_pages = NULL;
global_state.nested_payload_pages_num = 0;
- global_state.protect_payload_buffer = 0;
- global_state.discard_tmp_snapshot = 0;
- global_state.mem_mode = mm_unkown;
+ global_state.protect_payload_buffer = 0;
+ global_state.discard_tmp_snapshot = 0;
+ global_state.mem_mode = mm_unkown;
init_timeout_detector(&(global_state.timeout_detector));
- global_state.in_fuzzing_mode = false;
- global_state.in_reload_mode = true;
- global_state.starved = false;
- global_state.trace_mode = false;
+ global_state.in_fuzzing_mode = false;
+ global_state.in_reload_mode = true;
+ global_state.starved = false;
+ global_state.trace_mode = false;
global_state.shutdown_requested = false;
- global_state.cow_cache_full = false;
+ global_state.cow_cache_full = false;
global_state.auxilary_buffer = NULL;
memset(&global_state.shadow_config, 0x0, sizeof(auxilary_buffer_config_t));
- global_state.decoder_page_fault = false;
+ global_state.decoder_page_fault = false;
global_state.decoder_page_fault_addr = 0x0;
- global_state.dump_page = false;
+ global_state.dump_page = false;
global_state.dump_page_addr = 0x0;
global_state.in_redqueen_reload_mode = false;
-
- global_state.pt_trace_mode = true;
+
+ global_state.pt_trace_mode = true;
global_state.pt_trace_mode_force = false;
global_state.num_dirty_pages = 0;
-
- global_state.get_host_config_done = false;
+
+ global_state.get_host_config_done = false;
global_state.set_agent_config_done = false;
global_state.sharedir = sharedir_new();
- global_state.shared_bitmap_fd = 0;
- global_state.shared_bitmap_size = 0;
+ global_state.shared_bitmap_fd = 0;
+ global_state.shared_bitmap_size = 0;
global_state.shared_bitmap_real_size = 0;
- global_state.shared_bitmap_ptr = NULL;
+ global_state.shared_bitmap_ptr = NULL;
- global_state.shared_payload_buffer_fd = 0;
+ global_state.shared_payload_buffer_fd = 0;
global_state.shared_payload_buffer_size = 0;
- global_state.shared_ijon_bitmap_fd = 0;
+ global_state.shared_ijon_bitmap_fd = 0;
global_state.shared_ijon_bitmap_size = 0;
- global_state.shared_ijon_bitmap_ptr = NULL;
+ global_state.shared_ijon_bitmap_ptr = NULL;
global_state.pt_trace_size = 0;
- global_state.bb_coverage = 0;
+ global_state.bb_coverage = 0;
- global_state.cap_timeout_detection = 0;
- global_state.cap_only_reload_mode = 0;
- global_state.cap_compile_time_tracing = 0;
- global_state.cap_ijon_tracing = 0;
- global_state.cap_cr3 = 0;
+ global_state.cap_timeout_detection = 0;
+ global_state.cap_only_reload_mode = 0;
+ global_state.cap_compile_time_tracing = 0;
+ global_state.cap_ijon_tracing = 0;
+ global_state.cap_cr3 = 0;
global_state.cap_compile_time_tracing_buffer_vaddr = 0;
- global_state.cap_ijon_tracing_buffer_vaddr = 0;
+ global_state.cap_ijon_tracing_buffer_vaddr = 0;
QTAILQ_INIT(&global_state.redqueen_breakpoints);
}
-fast_reload_t* get_fast_reload_snapshot(void){
+fast_reload_t *get_fast_reload_snapshot(void)
+{
return global_state.fast_reload_snapshot;
}
-void set_fast_reload_mode(bool mode){
+void set_fast_reload_mode(bool mode)
+{
global_state.fast_reload_mode = mode;
}
-void set_fast_reload_path(const char* path){
+void set_fast_reload_path(const char *path)
+{
assert(global_state.fast_reload_path == NULL);
- global_state.fast_reload_path = malloc(strlen(path)+1);
+ global_state.fast_reload_path = malloc(strlen(path) + 1);
strcpy(global_state.fast_reload_path, path);
}
-void set_fast_reload_pre_path(const char* path){
+void set_fast_reload_pre_path(const char *path)
+{
assert(global_state.fast_reload_pre_path == NULL);
- global_state.fast_reload_pre_path = malloc(strlen(path)+1);
+ global_state.fast_reload_pre_path = malloc(strlen(path) + 1);
strcpy(global_state.fast_reload_pre_path, path);
}
-void set_fast_reload_pre_image(void){
+void set_fast_reload_pre_image(void)
+{
assert(global_state.fast_reload_pre_path != NULL);
global_state.fast_reload_pre_image = true;
}
-void enable_fast_reloads(void){
+void enable_fast_reloads(void)
+{
assert(global_state.fast_reload_path != NULL);
global_state.fast_reload_enabled = true;
}
-void init_page_cache(char* path){
+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);
}
-page_cache_t* get_page_cache(void){
+page_cache_t *get_page_cache(void)
+{
assert(global_state.page_cache);
return global_state.page_cache;
}
-void init_redqueen_state(void){
- global_state.redqueen_state = new_rq_state((CPUState *)qemu_get_cpu(0), get_page_cache());
+void init_redqueen_state(void)
+{
+ global_state.redqueen_state =
+ new_rq_state((CPUState *)qemu_get_cpu(0), get_page_cache());
}
-redqueen_t* get_redqueen_state(void){
+redqueen_t *get_redqueen_state(void)
+{
assert(global_state.redqueen_state != NULL);
return global_state.redqueen_state;
}
-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);
+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);
- ptr = mmap(0, AUX_BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (ptr == MAP_FAILED) {
- fprintf(stderr, "aux buffer allocation failed!\n");
- return (void*)-1;
- }
- return ptr;
+ 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);
+ ptr = mmap(0, AUX_BUFFER_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
+ if (ptr == MAP_FAILED) {
+ fprintf(stderr, "aux buffer allocation failed!\n");
+ return (void *)-1;
+ }
+ return ptr;
}
-void init_aux_buffer(const char* filename){
- global_state.auxilary_buffer = (auxilary_buffer_t*)alloc_auxiliary_buffer(filename);
+void init_aux_buffer(const char *filename)
+{
+ global_state.auxilary_buffer =
+ (auxilary_buffer_t *)alloc_auxiliary_buffer(filename);
init_auxiliary_buffer(global_state.auxilary_buffer);
}
-void set_payload_buffer(uint64_t payload_buffer){
+void set_payload_buffer(uint64_t payload_buffer)
+{
assert(global_state.payload_buffer == 0 && global_state.nested == false);
global_state.payload_buffer = payload_buffer;
- global_state.nested = false;
+ global_state.nested = false;
}
-void set_payload_pages(uint64_t* payload_pages, uint32_t pages){
- assert(global_state.nested_payload_pages == NULL && global_state.nested_payload_pages_num == 0);
- global_state.nested_payload_pages = (uint64_t*)malloc(sizeof(uint64_t)*pages);
+void set_payload_pages(uint64_t *payload_pages, uint32_t pages)
+{
+ assert(global_state.nested_payload_pages == NULL &&
+ global_state.nested_payload_pages_num == 0);
+ global_state.nested_payload_pages = (uint64_t *)malloc(sizeof(uint64_t) * pages);
global_state.nested_payload_pages_num = pages;
- memcpy(global_state.nested_payload_pages, payload_pages, sizeof(uint64_t)*pages);
+ memcpy(global_state.nested_payload_pages, payload_pages, sizeof(uint64_t) * pages);
global_state.nested = true;
}
-void set_workdir_path(char* workdir){
+void set_workdir_path(char *workdir)
+{
assert(workdir && !global_state.workdir_path);
- assert(asprintf(&global_state.workdir_path, "%s", workdir) != -1);
+ assert(asprintf(&global_state.workdir_path, "%s", workdir) != -1);
}
diff --git a/nyx/state/state.h b/nyx/state/state.h
index e434c30724..08513325a5 100644
--- a/nyx/state/state.h
+++ b/nyx/state/state.h
@@ -21,109 +21,109 @@ along with QEMU-PT. If not, see .
#pragma once
+#include "nyx/auxiliary_buffer.h"
+#include "nyx/fast_vm_reload.h"
+#include "nyx/fast_vm_reload_sync.h"
+#include "nyx/page_cache.h"
#include "nyx/redqueen.h"
#include "nyx/redqueen_patch.h"
-#include "nyx/fast_vm_reload.h"
-#include "nyx/page_cache.h"
-#include "nyx/synchronization.h"
-#include "nyx/auxiliary_buffer.h"
#include "nyx/sharedir.h"
-#include "nyx/fast_vm_reload_sync.h"
+#include "nyx/synchronization.h"
#include "nyx/types.h"
#include
-#define INTEL_PT_MAX_RANGES 4
-
-typedef struct qemu_nyx_state_s{
+#define INTEL_PT_MAX_RANGES 4
+typedef struct qemu_nyx_state_s {
/* set if FDL backend is used (required to perform some additional runtime tests) */
bool nyx_fdl;
- char* workdir_path;
+ char *workdir_path;
uint32_t worker_id;
/* FAST VM RELOAD */
- bool fast_reload_enabled;
- bool fast_reload_mode;
- char* fast_reload_path;
- char* fast_reload_pre_path;
- bool fast_reload_pre_image;
- fast_reload_t* fast_reload_snapshot;
- fast_vm_reload_sync_t* reload_state;
+ bool fast_reload_enabled;
+ bool fast_reload_mode;
+ char *fast_reload_path;
+ char *fast_reload_pre_path;
+ bool fast_reload_pre_image;
+ fast_reload_t *fast_reload_snapshot;
+ fast_vm_reload_sync_t *reload_state;
/* PAGE CACHE */
- page_cache_t* page_cache;
+ page_cache_t *page_cache;
/* Decoder */
- libxdc_t* decoder;
+ libxdc_t *decoder;
/* REDQUEEN */
- bool redqueen_enable_pending;
- bool redqueen_disable_pending;
- int redqueen_instrumentation_mode;
- bool redqueen_update_blacklist;
- bool patches_enable_pending;
- bool patches_disable_pending;
- redqueen_t* redqueen_state;
+ bool redqueen_enable_pending;
+ bool redqueen_disable_pending;
+ int redqueen_instrumentation_mode;
+ bool redqueen_update_blacklist;
+ bool patches_enable_pending;
+ bool patches_disable_pending;
+ redqueen_t *redqueen_state;
/* Intel PT Options (not migratable) */
- uint64_t pt_c3_filter;
+ uint64_t pt_c3_filter;
volatile bool pt_ip_filter_enabled[4];
bool pt_trace_mode; // enabled by default; disabled if compile-time tracing is implemented by agent
- /* disabled by default; enable to force usage of PT tracing
- * (useful for targets that use compile-time tracing and redqueen at the same time (which obviously relies on PT traces))
- * This mode is usually enabled by the fuzzing logic by enabling trace mode.
- * *** THIS FEATURES IS STILL EXPERIMENTAL ***
+ /* disabled by default; enable to force usage of PT tracing
+ * (useful for targets that use compile-time tracing and redqueen at the same
+ * time (which obviously relies on PT traces)) This mode is usually enabled by
+ * the fuzzing logic by enabling trace mode.
+ * *** THIS FEATURES IS STILL EXPERIMENTAL ***
* */
- bool pt_trace_mode_force;
+ bool pt_trace_mode_force;
- uint32_t pt_trace_size; // trace size counter
- uint32_t bb_coverage; // trace size counter
+ uint32_t pt_trace_size; // trace size counter
+ uint32_t bb_coverage; // trace size counter
/* mmap Options (not migratable) */
- int shared_bitmap_fd;
- uint32_t shared_bitmap_size; /* size of the shared memory file */
- uint32_t shared_bitmap_real_size; /* actual size of the bitmap */
- void* shared_bitmap_ptr;
+ int shared_bitmap_fd;
+ uint32_t shared_bitmap_size; /* size of the shared memory file */
+ uint32_t shared_bitmap_real_size; /* actual size of the bitmap */
+ void *shared_bitmap_ptr;
- int shared_payload_buffer_fd;
+ int shared_payload_buffer_fd;
uint32_t shared_payload_buffer_size;
- int shared_ijon_bitmap_fd;
+ int shared_ijon_bitmap_fd;
uint32_t shared_ijon_bitmap_size;
- void* shared_ijon_bitmap_ptr;
+ void *shared_ijon_bitmap_ptr;
/* Intel PT Options (migratable) */
- bool pt_ip_filter_configured[4];
+ bool pt_ip_filter_configured[4];
uint64_t pt_ip_filter_a[4];
uint64_t pt_ip_filter_b[4];
/* OPTIONS (MIGRATABLE VIA FAST SNAPSHOTS) */
- uint64_t parent_cr3;
- uint8_t disassembler_word_width;
- bool nested;
- uint64_t payload_buffer;
- uint32_t nested_payload_pages_num;
- uint64_t* nested_payload_pages;
- bool protect_payload_buffer;
- bool discard_tmp_snapshot;
- mem_mode_t mem_mode;
- uint32_t input_buffer_size;
+ uint64_t parent_cr3;
+ uint8_t disassembler_word_width;
+ bool nested;
+ uint64_t payload_buffer;
+ uint32_t nested_payload_pages_num;
+ uint64_t *nested_payload_pages;
+ bool protect_payload_buffer;
+ bool discard_tmp_snapshot;
+ mem_mode_t mem_mode;
+ uint32_t input_buffer_size;
/* NON MIGRATABLE OPTION */
timeout_detector_t timeout_detector;
- bool decoder_page_fault;
+ bool decoder_page_fault;
uint64_t decoder_page_fault_addr;
- bool dump_page;
+ bool dump_page;
uint64_t dump_page_addr;
bool in_fuzzing_mode;
- bool in_reload_mode;
+ bool in_reload_mode;
bool starved;
bool trace_mode;
@@ -138,18 +138,18 @@ typedef struct qemu_nyx_state_s{
bool set_agent_config_done;
/* capabilites */
- uint8_t cap_timeout_detection;
- uint8_t cap_only_reload_mode;
- uint8_t cap_compile_time_tracing;
- uint8_t cap_ijon_tracing;
- uint64_t cap_cr3;
+ uint8_t cap_timeout_detection;
+ uint8_t cap_only_reload_mode;
+ uint8_t cap_compile_time_tracing;
+ uint8_t cap_ijon_tracing;
+ uint64_t cap_cr3;
uint64_t cap_compile_time_tracing_buffer_vaddr;
uint64_t cap_ijon_tracing_buffer_vaddr;
uint64_t cap_coverage_bitmap_size;
- auxilary_buffer_t* auxilary_buffer;
+ auxilary_buffer_t *auxilary_buffer;
auxilary_buffer_config_t shadow_config;
- sharedir_t* sharedir;
+ sharedir_t *sharedir;
QTAILQ_HEAD(, kvm_sw_breakpoint) redqueen_breakpoints;
} qemu_nyx_state_t;
@@ -158,27 +158,27 @@ extern qemu_nyx_state_t global_state;
#define GET_GLOBAL_STATE() (&global_state)
-void state_init_global(void);
-fast_reload_t* get_fast_reload_snapshot(void);
-void set_fast_reload_mode(bool mode);
-void set_fast_reload_path(const char* path);
-void set_fast_reload_pre_image(void);
+void state_init_global(void);
+fast_reload_t *get_fast_reload_snapshot(void);
+void set_fast_reload_mode(bool mode);
+void set_fast_reload_path(const char *path);
+void set_fast_reload_pre_image(void);
void enable_fast_reloads(void);
/* Page Cache */
-void init_page_cache(char* path);
-page_cache_t* get_page_cache(void);
+void init_page_cache(char *path);
+page_cache_t *get_page_cache(void);
void init_redqueen_state(void);
-redqueen_t* get_redqueen_state(void);
+redqueen_t *get_redqueen_state(void);
-void init_aux_buffer(const char* filename);
-void set_fast_reload_pre_path(const char* path);
+void init_aux_buffer(const char *filename);
+void set_fast_reload_pre_path(const char *path);
void set_payload_buffer(uint64_t payload_buffer);
-void set_payload_pages(uint64_t* payload_pages, uint32_t pages);
+void set_payload_pages(uint64_t *payload_pages, uint32_t pages);
-void set_workdir_path(char* workdir);
+void set_workdir_path(char *workdir);
diff --git a/nyx/synchronization.c b/nyx/synchronization.c
index e5c23df787..77d222c56d 100644
--- a/nyx/synchronization.c
+++ b/nyx/synchronization.c
@@ -1,409 +1,442 @@
+#include "qemu/osdep.h"
+#include "qemu/main-loop.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
+#include "qemu-common.h"
#include "nyx/synchronization.h"
+#include "nyx/debug.h"
+#include "nyx/fast_vm_reload.h"
+#include "nyx/file_helper.h"
+#include "nyx/helpers.h"
#include "nyx/hypercall/hypercall.h"
#include "nyx/interface.h"
-#include "nyx/fast_vm_reload.h"
-#include "qemu-common.h"
-#include "qemu/osdep.h"
-#include "sysemu/sysemu.h"
-#include "sysemu/kvm.h"
-#include "nyx/debug.h"
#include "nyx/state/state.h"
-#include
#include
-#include "qemu/main-loop.h"
-#include "nyx/helpers.h"
-#include "nyx/file_helper.h"
+#include
#include "pt.h"
-pthread_mutex_t synchronization_lock_mutex = PTHREAD_MUTEX_INITIALIZER;
-pthread_cond_t synchronization_lock_condition = PTHREAD_COND_INITIALIZER;
+pthread_mutex_t synchronization_lock_mutex = PTHREAD_MUTEX_INITIALIZER;
+pthread_cond_t synchronization_lock_condition = PTHREAD_COND_INITIALIZER;
pthread_mutex_t synchronization_disable_pt_mutex = PTHREAD_MUTEX_INITIALIZER;
-volatile bool synchronization_reload_pending = false;
+volatile bool synchronization_reload_pending = false;
volatile bool synchronization_kvm_loop_waiting = false;
/* SIGALRM based timeout detection */
-//#define DEBUG_TIMEOUT_DETECTOR
+// #define DEBUG_TIMEOUT_DETECTOR
-void init_timeout_detector(timeout_detector_t* timer){
- timer->kvm_tid = 0;
- timer->detection_enabled = false;
+void init_timeout_detector(timeout_detector_t *timer)
+{
+ timer->kvm_tid = 0;
+ timer->detection_enabled = false;
- timer->config.tv_sec = 0;
- timer->config.tv_usec = 0;
-
- timer->alarm.it_interval.tv_sec = 0;
- timer->alarm.it_interval.tv_usec = 0;
- timer->alarm.it_value.tv_sec = 0;
- timer->alarm.it_value.tv_usec = 0;
+ timer->config.tv_sec = 0;
+ timer->config.tv_usec = 0;
+ timer->alarm.it_interval.tv_sec = 0;
+ timer->alarm.it_interval.tv_usec = 0;
+ timer->alarm.it_value.tv_sec = 0;
+ timer->alarm.it_value.tv_usec = 0;
}
-static void sigalarm_handler(int signum) {
- /* ensure that SIGALARM is ALWAYS handled by kvm thread */
- assert(GET_GLOBAL_STATE()->timeout_detector.kvm_tid == syscall(SYS_gettid));
+static void sigalarm_handler(int signum)
+{
+ /* ensure that SIGALARM is ALWAYS handled by kvm thread */
+ assert(GET_GLOBAL_STATE()->timeout_detector.kvm_tid == syscall(SYS_gettid));
#ifdef DEBUG_TIMEOUT_DETECTOR
- fprintf(stderr, "Handled! %d %ld\n", signum, syscall(SYS_gettid));
+ fprintf(stderr, "Handled! %d %ld\n", signum, syscall(SYS_gettid));
#endif
}
-void install_timeout_detector(timeout_detector_t* timer){
- timer->kvm_tid = syscall(SYS_gettid);
- if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
- fprintf(stderr, "%s failed!\n", __func__);
- assert(false);
- }
+void install_timeout_detector(timeout_detector_t *timer)
+{
+ timer->kvm_tid = syscall(SYS_gettid);
+ if (signal(SIGALRM, sigalarm_handler) == SIG_ERR) {
+ fprintf(stderr, "%s failed!\n", __func__);
+ assert(false);
+ }
#ifdef DEBUG_TIMEOUT_DETECTOR
- fprintf(stderr, "SIGALRM HANDLER INSTALLED! tid=%ld\n", syscall(SYS_gettid));
+ fprintf(stderr, "SIGALRM HANDLER INSTALLED! tid=%ld\n", syscall(SYS_gettid));
#endif
}
-void reset_timeout_detector(timeout_detector_t* timer){
-#ifdef DEBUG_TIMEOUT_DETECTOR
- fprintf(stderr, "%s!\n", __func__);
-#endif
-
- if (timer->config.tv_sec || timer->config.tv_usec) {
- timer->alarm.it_value.tv_sec = timer->config.tv_sec;
- timer->alarm.it_value.tv_usec = timer->config.tv_usec;
- timer->detection_enabled = true;
- } else {
- timer->detection_enabled = false;
- }
-}
-
-void update_itimer(timeout_detector_t* timer, uint8_t sec, uint32_t usec)
+void reset_timeout_detector(timeout_detector_t *timer)
{
#ifdef DEBUG_TIMEOUT_DETECTOR
- //fprintf(stderr, "%s: %x %x\n", __func__, sec, usec);
+ fprintf(stderr, "%s!\n", __func__);
#endif
- if (sec || usec) {
- timer->config.tv_sec = (time_t)sec;
- timer->config.tv_usec = (suseconds_t)usec;
- timer->detection_enabled = true;
- } else {
- timer->detection_enabled = false;
- }
+ if (timer->config.tv_sec || timer->config.tv_usec) {
+ timer->alarm.it_value.tv_sec = timer->config.tv_sec;
+ timer->alarm.it_value.tv_usec = timer->config.tv_usec;
+ timer->detection_enabled = true;
+ } else {
+ timer->detection_enabled = false;
+ }
}
-void arm_sigprof_timer(timeout_detector_t* timer){
+void update_itimer(timeout_detector_t *timer, uint8_t sec, uint32_t usec)
+{
#ifdef DEBUG_TIMEOUT_DETECTOR
- fprintf(stderr, "%s (%ld %ld)\n", __func__, timer->alarm.it_value.tv_sec, timer->alarm.it_value.tv_usec);
+ // fprintf(stderr, "%s: %x %x\n", __func__, sec, usec);
#endif
- if (timer->detection_enabled) {
- if (timer->alarm.it_value.tv_usec == 0 && timer->alarm.it_value.tv_sec == 0) {
- 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);
- }
- assert(setitimer(ITIMER_REAL, &timer->alarm, NULL) == 0);
- }
+ if (sec || usec) {
+ timer->config.tv_sec = (time_t)sec;
+ timer->config.tv_usec = (suseconds_t)usec;
+ timer->detection_enabled = true;
+ } else {
+ timer->detection_enabled = false;
+ }
}
-bool disarm_sigprof_timer(timeout_detector_t* timer){
-
+void arm_sigprof_timer(timeout_detector_t *timer)
+{
#ifdef DEBUG_TIMEOUT_DETECTOR
- fprintf(stderr, "%s (%ld %ld)\n", __func__, timer->alarm.it_value.tv_sec, timer->alarm.it_value.tv_usec);
+ fprintf(stderr, "%s (%ld %ld)\n", __func__, timer->alarm.it_value.tv_sec,
+ timer->alarm.it_value.tv_usec);
#endif
- if (timer->detection_enabled) {
- struct itimerval disable = {0};
- assert(setitimer(ITIMER_REAL, &disable, &timer->alarm) == 0);
- assert(timer->alarm.it_interval.tv_usec == 0);
-
- if (timer->alarm.it_value.tv_usec == 0 && timer->alarm.it_value.tv_sec == 0) {
- reset_timeout_detector(timer);
- return true;
- }
- }
- return false;
+ if (timer->detection_enabled) {
+ if (timer->alarm.it_value.tv_usec == 0 && timer->alarm.it_value.tv_sec == 0) {
+ 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);
+ }
+ assert(setitimer(ITIMER_REAL, &timer->alarm, NULL) == 0);
+ }
}
-void block_signals(void){
- sigset_t set;
+bool disarm_sigprof_timer(timeout_detector_t *timer)
+{
+#ifdef DEBUG_TIMEOUT_DETECTOR
+ fprintf(stderr, "%s (%ld %ld)\n", __func__, timer->alarm.it_value.tv_sec,
+ timer->alarm.it_value.tv_usec);
+#endif
- sigemptyset(&set);
- sigaddset(&set, SIGALRM);
- sigaddset(&set, SIGABRT);
- sigaddset(&set, SIGSEGV);
- pthread_sigmask(SIG_BLOCK, &set, NULL);
- //fprintf(stderr, "%s!\n", __func__);
+ if (timer->detection_enabled) {
+ struct itimerval disable = { 0 };
+ assert(setitimer(ITIMER_REAL, &disable, &timer->alarm) == 0);
+ assert(timer->alarm.it_interval.tv_usec == 0);
+ if (timer->alarm.it_value.tv_usec == 0 && timer->alarm.it_value.tv_sec == 0) {
+ reset_timeout_detector(timer);
+ return true;
+ }
+ }
+ return false;
}
-void unblock_signals(void){
- sigset_t set;
+void block_signals(void)
+{
+ sigset_t set;
- sigemptyset(&set);
- sigaddset(&set, SIGABRT);
- sigaddset(&set, SIGSEGV);
- sigaddset(&set, SIGALRM);
- sigprocmask(SIG_UNBLOCK, &set, NULL);
+ sigemptyset(&set);
+ sigaddset(&set, SIGALRM);
+ sigaddset(&set, SIGABRT);
+ sigaddset(&set, SIGSEGV);
+ pthread_sigmask(SIG_BLOCK, &set, NULL);
+ // fprintf(stderr, "%s!\n", __func__);
+}
+
+void unblock_signals(void)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ sigaddset(&set, SIGABRT);
+ sigaddset(&set, SIGSEGV);
+ sigaddset(&set, SIGALRM);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
}
/* -------------------- */
-static inline void handle_tmp_snapshot_state(void){
- if(GET_GLOBAL_STATE()->discard_tmp_snapshot){
- if(fast_reload_tmp_created(get_fast_reload_snapshot())){
- qemu_mutex_lock_iothread();
- fast_reload_discard_tmp_snapshot(get_fast_reload_snapshot()); /* bye bye */
- qemu_mutex_unlock_iothread();
- //fprintf(stderr, "======= SNAPSHOT REMOVED! =======\n");
- }
- GET_GLOBAL_STATE()->discard_tmp_snapshot = false;
- set_tmp_snapshot_created(GET_GLOBAL_STATE()->auxilary_buffer, 0);
- }
+static inline void handle_tmp_snapshot_state(void)
+{
+ if (GET_GLOBAL_STATE()->discard_tmp_snapshot) {
+ if (fast_reload_tmp_created(get_fast_reload_snapshot())) {
+ qemu_mutex_lock_iothread();
+ fast_reload_discard_tmp_snapshot(get_fast_reload_snapshot()); /* bye bye */
+ qemu_mutex_unlock_iothread();
+ // fprintf(stderr, "======= SNAPSHOT REMOVED! =======\n");
+ }
+ GET_GLOBAL_STATE()->discard_tmp_snapshot = false;
+ set_tmp_snapshot_created(GET_GLOBAL_STATE()->auxilary_buffer, 0);
+ }
}
-static inline bool synchronization_check_page_not_found(void){
- bool failure = false;
+static inline bool synchronization_check_page_not_found(void)
+{
+ bool failure = false;
- /* a page is missing in the current execution */
- if(GET_GLOBAL_STATE()->decoder_page_fault){
- set_page_not_found_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, GET_GLOBAL_STATE()->decoder_page_fault_addr);
- GET_GLOBAL_STATE()->decoder_page_fault = false;
- GET_GLOBAL_STATE()->decoder_page_fault_addr = 0;
- failure = true;
- }
+ /* a page is missing in the current execution */
+ if (GET_GLOBAL_STATE()->decoder_page_fault) {
+ set_page_not_found_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ GET_GLOBAL_STATE()->decoder_page_fault_addr);
+ GET_GLOBAL_STATE()->decoder_page_fault = false;
+ GET_GLOBAL_STATE()->decoder_page_fault_addr = 0;
+ failure = true;
+ }
- /* page was dumped during this execution */
- if(GET_GLOBAL_STATE()->dump_page){
- kvm_remove_all_breakpoints(qemu_get_cpu(0));
- kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
- kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_MTF);
- reset_page_not_found_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- failure = true;
- }
+ /* page was dumped during this execution */
+ if (GET_GLOBAL_STATE()->dump_page) {
+ kvm_remove_all_breakpoints(qemu_get_cpu(0));
+ kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
+ kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_MTF);
+ reset_page_not_found_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
+ failure = true;
+ }
- return failure;
+ return failure;
}
-void synchronization_unlock(void){
- //fprintf(stderr, "%s\n", __func__);
+void synchronization_unlock(void)
+{
+ // fprintf(stderr, "%s\n", __func__);
- pthread_mutex_lock(&synchronization_lock_mutex);
- pthread_cond_signal(&synchronization_lock_condition);
- pthread_mutex_unlock(&synchronization_lock_mutex);
+ pthread_mutex_lock(&synchronization_lock_mutex);
+ pthread_cond_signal(&synchronization_lock_condition);
+ pthread_mutex_unlock(&synchronization_lock_mutex);
}
-uint64_t run_counter = 0;
-bool in_fuzzing_loop = false;
+uint64_t run_counter = 0;
+bool in_fuzzing_loop = false;
-void synchronization_lock_hprintf(void){
- pthread_mutex_lock(&synchronization_lock_mutex);
- interface_send_char(NYX_INTERFACE_PING);
+void synchronization_lock_hprintf(void)
+{
+ pthread_mutex_lock(&synchronization_lock_mutex);
+ interface_send_char(NYX_INTERFACE_PING);
- pthread_cond_wait(&synchronization_lock_condition, &synchronization_lock_mutex);
- pthread_mutex_unlock(&synchronization_lock_mutex);
+ pthread_cond_wait(&synchronization_lock_condition, &synchronization_lock_mutex);
+ pthread_mutex_unlock(&synchronization_lock_mutex);
}
-void synchronization_lock(void){
+void synchronization_lock(void)
+{
+ timeout_detector_t timer = GET_GLOBAL_STATE()->timeout_detector;
+ pthread_mutex_lock(&synchronization_lock_mutex);
+ run_counter++;
- timeout_detector_t timer = GET_GLOBAL_STATE()->timeout_detector;
- pthread_mutex_lock(&synchronization_lock_mutex);
- run_counter++;
+ if (qemu_get_cpu(0)->intel_pt_run_trashed) {
+ set_pt_overflow_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
+ }
- if(qemu_get_cpu(0)->intel_pt_run_trashed){
- set_pt_overflow_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- }
+ long runtime_sec = timer.config.tv_sec - timer.alarm.it_value.tv_sec;
+ long runtime_usec = timer.config.tv_usec - timer.alarm.it_value.tv_usec;
- long runtime_sec = timer.config.tv_sec - timer.alarm.it_value.tv_sec;
- long runtime_usec = timer.config.tv_usec - timer.alarm.it_value.tv_usec;
+ if (runtime_usec < 0) {
+ if (runtime_sec < 1) {
+ fprintf(stderr, "Error: negative payload runtime?!\n");
+ }
+ runtime_sec -= 1;
+ runtime_usec = timer.config.tv_usec - timer.alarm.it_value.tv_usec + 1000000;
+ }
+ set_exec_done_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ runtime_sec, runtime_usec,
+ GET_GLOBAL_STATE()->num_dirty_pages);
- if (runtime_usec < 0) {
- if (runtime_sec < 1) {
- fprintf(stderr, "Error: negative payload runtime?!\n");
- }
- runtime_sec -= 1;
- runtime_usec = timer.config.tv_usec - timer.alarm.it_value.tv_usec + 1000000;
- }
- set_exec_done_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
- runtime_sec, runtime_usec,
- GET_GLOBAL_STATE()->num_dirty_pages);
+ if (synchronization_check_page_not_found()) {
+ set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 0);
+ }
- if(synchronization_check_page_not_found()){
- set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 0);
- }
+ if (GET_GLOBAL_STATE()->dump_page) {
+ GET_GLOBAL_STATE()->dump_page = false;
+ GET_GLOBAL_STATE()->dump_page_addr = 0x0;
+ kvm_remove_all_breakpoints(qemu_get_cpu(0));
+ kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
+ }
- if(GET_GLOBAL_STATE()->dump_page){
- GET_GLOBAL_STATE()->dump_page = false;
- GET_GLOBAL_STATE()->dump_page_addr = 0x0;
- kvm_remove_all_breakpoints(qemu_get_cpu(0));
- kvm_vcpu_ioctl(qemu_get_cpu(0), KVM_VMX_PT_DISABLE_PAGE_DUMP_CR3);
- }
+ if (unlikely(GET_GLOBAL_STATE()->in_redqueen_reload_mode)) {
+ fsync_redqueen_files();
+ }
- if(unlikely(GET_GLOBAL_STATE()->in_redqueen_reload_mode)) {
- fsync_redqueen_files();
- }
+ if (unlikely(GET_GLOBAL_STATE()->trace_mode)) {
+ redqueen_trace_flush();
+ }
- if (unlikely(GET_GLOBAL_STATE()->trace_mode)) {
- redqueen_trace_flush();
- }
+ interface_send_char(NYX_INTERFACE_PING);
- interface_send_char(NYX_INTERFACE_PING);
+ pthread_cond_wait(&synchronization_lock_condition, &synchronization_lock_mutex);
+ pthread_mutex_unlock(&synchronization_lock_mutex);
- pthread_cond_wait(&synchronization_lock_condition, &synchronization_lock_mutex);
- pthread_mutex_unlock(&synchronization_lock_mutex);
+ check_auxiliary_config_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ &GET_GLOBAL_STATE()->shadow_config);
- check_auxiliary_config_buffer(GET_GLOBAL_STATE()->auxilary_buffer, &GET_GLOBAL_STATE()->shadow_config);
+ 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);
- 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;
+ GET_GLOBAL_STATE()->pt_trace_size = 0;
}
-static void perform_reload(void){
- if(fast_reload_root_created(get_fast_reload_snapshot())){
- qemu_mutex_lock_iothread();
- fast_reload_restore(get_fast_reload_snapshot());
- qemu_mutex_unlock_iothread();
- set_reload_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- set_result_dirty_pages(GET_GLOBAL_STATE()->auxilary_buffer, get_dirty_page_num(get_fast_reload_snapshot()));
- }
- else{
- fprintf(stderr, "WARNING: Root snapshot is not available yet!\n");
- }
+static void perform_reload(void)
+{
+ if (fast_reload_root_created(get_fast_reload_snapshot())) {
+ qemu_mutex_lock_iothread();
+ fast_reload_restore(get_fast_reload_snapshot());
+ qemu_mutex_unlock_iothread();
+ set_reload_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
+ set_result_dirty_pages(GET_GLOBAL_STATE()->auxilary_buffer,
+ get_dirty_page_num(get_fast_reload_snapshot()));
+ } else {
+ fprintf(stderr, "WARNING: Root snapshot is not available yet!\n");
+ }
}
-void synchronization_lock_crash_found(void){
- if(!in_fuzzing_loop && GET_GLOBAL_STATE()->in_fuzzing_mode){
- fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP] at %lx\n", getpid(), run_counter, __func__, get_rip(qemu_get_cpu(0)));
- //abort();
- }
+void synchronization_lock_crash_found(void)
+{
+ if (!in_fuzzing_loop && GET_GLOBAL_STATE()->in_fuzzing_mode) {
+ fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP] at %lx\n", getpid(),
+ run_counter, __func__, get_rip(qemu_get_cpu(0)));
+ // abort();
+ }
- pt_disable(qemu_get_cpu(0), false);
+ pt_disable(qemu_get_cpu(0), false);
- handle_tmp_snapshot_state();
+ handle_tmp_snapshot_state();
- set_crash_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
-
- perform_reload();
+ set_crash_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- in_fuzzing_loop = false;
+ perform_reload();
+
+ in_fuzzing_loop = false;
}
-void synchronization_lock_asan_found(void){
- 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);
- }
+void synchronization_lock_asan_found(void)
+{
+ 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);
+ }
- pt_disable(qemu_get_cpu(0), false);
+ pt_disable(qemu_get_cpu(0), false);
- handle_tmp_snapshot_state();
+ handle_tmp_snapshot_state();
- set_asan_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
-
- perform_reload();
+ set_asan_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- in_fuzzing_loop = false;
+ perform_reload();
+
+ in_fuzzing_loop = false;
}
-void synchronization_lock_timeout_found(void){
-
- //fprintf(stderr, "<%d>\t%s\n", getpid(), __func__);
+void synchronization_lock_timeout_found(void)
+{
+ // fprintf(stderr, "<%d>\t%s\n", getpid(), __func__);
- 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);
- }
+ 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);
+ }
- pt_disable(qemu_get_cpu(0), false);
+ pt_disable(qemu_get_cpu(0), false);
- handle_tmp_snapshot_state();
+ handle_tmp_snapshot_state();
- set_timeout_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
+ set_timeout_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- perform_reload();
+ perform_reload();
- in_fuzzing_loop = false;
+ in_fuzzing_loop = false;
}
-void synchronization_lock_shutdown_detected(void){
- 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);
- }
+void synchronization_lock_shutdown_detected(void)
+{
+ 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);
+ }
- pt_disable(qemu_get_cpu(0), false);
+ pt_disable(qemu_get_cpu(0), false);
- handle_tmp_snapshot_state();
+ handle_tmp_snapshot_state();
- perform_reload();
+ perform_reload();
- in_fuzzing_loop = false;
+ in_fuzzing_loop = false;
}
-void synchronization_payload_buffer_write_detected(void){
- static char reason[1024];
+void synchronization_payload_buffer_write_detected(void)
+{
+ static char reason[1024];
- if(!in_fuzzing_loop){
- fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP]\n", getpid(), run_counter, __func__);
- }
-
- pt_disable(qemu_get_cpu(0), false);
+ if (!in_fuzzing_loop) {
+ fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP]\n", getpid(),
+ run_counter, __func__);
+ }
- handle_tmp_snapshot_state();
+ pt_disable(qemu_get_cpu(0), false);
- int bytes = snprintf(reason, 1024, "Payload buffer write attempt at RIP: %lx\n", get_rip(qemu_get_cpu(0)));
- set_payload_buffer_write_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, reason, bytes);
- set_reload_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
+ handle_tmp_snapshot_state();
- perform_reload();
+ int bytes = snprintf(reason, 1024, "Payload buffer write attempt at RIP: %lx\n",
+ get_rip(qemu_get_cpu(0)));
+ set_payload_buffer_write_reason_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ reason, bytes);
+ set_reload_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
- in_fuzzing_loop = false;
+ perform_reload();
+
+ in_fuzzing_loop = false;
}
-void synchronization_cow_full_detected(void){
- if(!in_fuzzing_loop){
- fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP]\n", getpid(), run_counter, __func__);
- }
+void synchronization_cow_full_detected(void)
+{
+ if (!in_fuzzing_loop) {
+ fprintf(stderr, "<%d-%ld>\t%s [NOT IN FUZZING LOOP]\n", getpid(),
+ run_counter, __func__);
+ }
- pt_disable(qemu_get_cpu(0), false);
+ pt_disable(qemu_get_cpu(0), false);
- handle_tmp_snapshot_state();
+ handle_tmp_snapshot_state();
- perform_reload();
+ perform_reload();
- in_fuzzing_loop = false;
+ in_fuzzing_loop = false;
}
-void synchronization_disable_pt(CPUState *cpu){
- // 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);
- }
+void synchronization_disable_pt(CPUState *cpu)
+{
+ // 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);
+ }
- pt_disable(qemu_get_cpu(0), false);
+ pt_disable(qemu_get_cpu(0), false);
- handle_tmp_snapshot_state();
+ handle_tmp_snapshot_state();
- if(GET_GLOBAL_STATE()->in_reload_mode || GET_GLOBAL_STATE()->in_redqueen_reload_mode || GET_GLOBAL_STATE()->dump_page || fast_reload_tmp_created(get_fast_reload_snapshot())){
- perform_reload();
- }
+ if (GET_GLOBAL_STATE()->in_reload_mode ||
+ GET_GLOBAL_STATE()->in_redqueen_reload_mode || GET_GLOBAL_STATE()->dump_page ||
+ fast_reload_tmp_created(get_fast_reload_snapshot()))
+ {
+ perform_reload();
+ }
- 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);
+ 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;
+ in_fuzzing_loop = false;
}
-void synchronization_enter_fuzzing_loop(CPUState *cpu){
- if (pt_enable(cpu, false) == 0){
- cpu->pt_enabled = true;
- }
- in_fuzzing_loop = true;
+void synchronization_enter_fuzzing_loop(CPUState *cpu)
+{
+ if (pt_enable(cpu, false) == 0) {
+ cpu->pt_enabled = true;
+ }
+ in_fuzzing_loop = true;
- reset_timeout_detector(&(GET_GLOBAL_STATE()->timeout_detector));
+ reset_timeout_detector(&(GET_GLOBAL_STATE()->timeout_detector));
}
-
diff --git a/nyx/synchronization.h b/nyx/synchronization.h
index bbae0407bc..48bea7b4c8 100644
--- a/nyx/synchronization.h
+++ b/nyx/synchronization.h
@@ -6,19 +6,19 @@
#include
typedef struct timeout_detector_s {
- int kvm_tid;
- volatile bool detection_enabled;
+ int kvm_tid;
+ volatile bool detection_enabled;
- struct timeval config;
- struct itimerval alarm;
+ struct timeval config;
+ struct itimerval alarm;
} timeout_detector_t;
-void init_timeout_detector(timeout_detector_t* timeout_detector);
-void install_timeout_detector(timeout_detector_t* timeout_detector);
-void reset_timeout_detector(timeout_detector_t* timeout_detector);
-void arm_sigprof_timer(timeout_detector_t* timeout_detector);
-bool disarm_sigprof_timer(timeout_detector_t* timeout_detector);
-void update_itimer(timeout_detector_t* timeout_detector, uint8_t sec, uint32_t usec);
+void init_timeout_detector(timeout_detector_t *timeout_detector);
+void install_timeout_detector(timeout_detector_t *timeout_detector);
+void reset_timeout_detector(timeout_detector_t *timeout_detector);
+void arm_sigprof_timer(timeout_detector_t *timeout_detector);
+bool disarm_sigprof_timer(timeout_detector_t *timeout_detector);
+void update_itimer(timeout_detector_t *timeout_detector, uint8_t sec, uint32_t usec);
void block_signals(void);
void unblock_signals(void);
diff --git a/nyx/trace_dump.c b/nyx/trace_dump.c
index 1dfc731011..09736ac394 100644
--- a/nyx/trace_dump.c
+++ b/nyx/trace_dump.c
@@ -1,9 +1,9 @@
#include "qemu/osdep.h"
-#include
-#include
-#include
#include
+#include
+#include
+#include
#include "nyx/debug.h"
#include "nyx/state/state.h"
@@ -12,57 +12,61 @@
/* dump PT trace as returned from HW */
char *pt_trace_dump_filename;
-bool pt_dump_initialized = false;
-bool pt_dump_enabled = false;
+bool pt_dump_initialized = false;
+bool pt_dump_enabled = false;
-void pt_trace_dump_enable(bool enable){
- if (pt_dump_initialized)
- pt_dump_enabled = enable;
-}
-
-void pt_trace_dump_init(char* filename)
+void pt_trace_dump_enable(bool enable)
{
- int test_fd;
-
- nyx_debug("Enable pt trace dump at %s", filename);
- pt_dump_initialized = true;
-
- test_fd = open(filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
- if (test_fd < 0)
- fprintf(stderr, "Error accessing pt_dump output path %s: %s", pt_trace_dump_filename, strerror(errno));
- assert(test_fd >= 0);
-
- pt_trace_dump_filename = strdup(filename);
- assert(pt_trace_dump_filename);
+ if (pt_dump_initialized)
+ pt_dump_enabled = enable;
}
-void pt_truncate_pt_dump_file(void) {
- int fd;
+void pt_trace_dump_init(char *filename)
+{
+ int test_fd;
- if (!pt_dump_enabled)
- return;
+ nyx_debug("Enable pt trace dump at %s", filename);
+ pt_dump_initialized = true;
- fd = open(pt_trace_dump_filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
- if (fd < 0) {
- fprintf(stderr, "Error truncating %s: %s\n", pt_trace_dump_filename, strerror(errno));
- assert(0);
- }
- close(fd);
+ test_fd = open(filename, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (test_fd < 0)
+ fprintf(stderr, "Error accessing pt_dump output path %s: %s",
+ pt_trace_dump_filename, strerror(errno));
+ assert(test_fd >= 0);
+
+ pt_trace_dump_filename = strdup(filename);
+ assert(pt_trace_dump_filename);
+}
+
+void pt_truncate_pt_dump_file(void)
+{
+ int fd;
+
+ if (!pt_dump_enabled)
+ return;
+
+ fd = open(pt_trace_dump_filename, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+ if (fd < 0) {
+ fprintf(stderr, "Error truncating %s: %s\n", pt_trace_dump_filename,
+ strerror(errno));
+ assert(0);
+ }
+ close(fd);
}
void pt_write_pt_dump_file(uint8_t *data, size_t bytes)
{
- int fd;
+ int fd;
- if (!pt_dump_enabled)
- return;
+ if (!pt_dump_enabled)
+ return;
- fd = open(pt_trace_dump_filename, O_APPEND|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);
- }
+ fd = open(pt_trace_dump_filename, O_APPEND | 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);
+ }
assert(bytes == write(fd, data, bytes));
- close(fd);
+ close(fd);
}
-
diff --git a/nyx/trace_dump.h b/nyx/trace_dump.h
index 110550e06d..0f5689b2bc 100644
--- a/nyx/trace_dump.h
+++ b/nyx/trace_dump.h
@@ -2,7 +2,7 @@
#include
-void pt_trace_dump_init(char* filename);
+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);
void pt_truncate_pt_dump_file(void);
diff --git a/nyx/types.h b/nyx/types.h
index 7c15f8ee72..6c331b182e 100644
--- a/nyx/types.h
+++ b/nyx/types.h
@@ -1,12 +1,12 @@
#pragma once
-enum mem_mode {
+enum mem_mode {
mm_unkown,
- mm_32_protected, /* 32 Bit / No MMU */
- mm_32_paging, /* 32 Bit / L3 Paging */
- mm_32_pae, /* 32 Bit / PAE Paging */
- mm_64_l4_paging, /* 64 Bit / L4 Paging */
- mm_64_l5_paging, /* 32 Bit / L5 Paging */
+ mm_32_protected, /* 32 Bit / No MMU */
+ mm_32_paging, /* 32 Bit / L3 Paging */
+ mm_32_pae, /* 32 Bit / PAE Paging */
+ mm_64_l4_paging, /* 64 Bit / L4 Paging */
+ mm_64_l5_paging, /* 32 Bit / L5 Paging */
};
typedef uint8_t mem_mode_t;
diff --git a/vl.c b/vl.c
index 7f1178a64a..aefbd3c7a1 100644
--- a/vl.c
+++ b/vl.c
@@ -137,12 +137,12 @@ int main(int argc, char **argv)
#ifdef QEMU_NYX
// clang-format on
#include "nyx/debug.h"
-#include "nyx/pt.h"
-#include "nyx/hypercall/hypercall.h"
-#include "nyx/synchronization.h"
#include "nyx/fast_vm_reload.h"
-#include "nyx/state/state.h"
#include "nyx/fast_vm_reload_sync.h"
+#include "nyx/hypercall/hypercall.h"
+#include "nyx/pt.h"
+#include "nyx/state/state.h"
+#include "nyx/synchronization.h"
// clang-format off
#endif
@@ -257,26 +257,23 @@ static struct {
#ifdef QEMU_NYX
// clang-format on
static QemuOptsList qemu_fast_vm_reloads_opts = {
- .name = "fast_vm_reload-opts",
+ .name = "fast_vm_reload-opts",
.implied_opt_name = "order",
- .head = QTAILQ_HEAD_INITIALIZER(qemu_fast_vm_reloads_opts.head),
- .merge_lists = true,
- .desc = {
- {
- .name = "path",
- .type = QEMU_OPT_STRING,
- },{
- .name = "load",
- .type = QEMU_OPT_BOOL,
- },{
- .name = "pre_path",
- .type = QEMU_OPT_STRING,
- },{
- .name = "skip_serialization",
- .type = QEMU_OPT_BOOL,
- },
- { }
- },
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_fast_vm_reloads_opts.head),
+ .merge_lists = true,
+ .desc = {{
+.name = "path",
+.type = QEMU_OPT_STRING,
+}, {
+ .name = "load",
+ .type = QEMU_OPT_BOOL,
+ }, {
+ .name = "pre_path",
+ .type = QEMU_OPT_STRING,
+ }, {
+ .name = "skip_serialization",
+ .type = QEMU_OPT_BOOL,
+ }, {}},
};
// clang-format off
#endif
@@ -1481,7 +1478,7 @@ void vm_state_notify(int running, RunState state)
#ifdef QEMU_NYX
// clang-format on
-char* loadvm_global = NULL;
+char *loadvm_global = NULL;
// clang-format off
#endif
@@ -1660,8 +1657,8 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
void qemu_system_reset_request(ShutdownCause reason)
{
#ifdef QEMU_NYX
-// clang-format on
- if(GET_GLOBAL_STATE()->in_fuzzing_mode){
+ // clang-format on
+ if (GET_GLOBAL_STATE()->in_fuzzing_mode) {
nyx_trace();
GET_GLOBAL_STATE()->shutdown_requested = true;
return;
@@ -1872,8 +1869,8 @@ static bool main_loop_should_exit(void)
}
if (qemu_vmstop_requested(&r)) {
#ifdef QEMU_NYX
-// clang-format on
- if(check_if_relood_request_exists_post(GET_GLOBAL_STATE()->reload_state)){
+ // clang-format on
+ if (check_if_relood_request_exists_post(GET_GLOBAL_STATE()->reload_state)) {
return false;
}
// clang-format off
@@ -1902,9 +1899,9 @@ static void main_loop(void)
static void version(void)
{
#ifdef QEMU_NYX
-// clang-format on
- printf("QEMU-PT emulator version " QEMU_VERSION QEMU_PKGVERSION " (kAFL)\n"
- QEMU_COPYRIGHT "\n");
+ // clang-format on
+ printf("QEMU-PT emulator version " QEMU_VERSION QEMU_PKGVERSION
+ " (kAFL)\n" QEMU_COPYRIGHT "\n");
// clang-format off
#else
printf("QEMU emulator version " QEMU_FULL_VERSION "\n"
@@ -2809,17 +2806,17 @@ static bool object_create_delayed(const char *type, QemuOpts *opts)
#ifdef QEMU_NYX
// clang-format on
-static bool verifiy_snapshot_folder(const char* folder){
+static bool verifiy_snapshot_folder(const char *folder)
+{
struct stat s;
- if(!folder){
+ if (!folder) {
return false;
}
- if(-1 != stat(folder, &s)) {
- if(S_ISDIR(s.st_mode)) {
+ if (-1 != stat(folder, &s)) {
+ if (S_ISDIR(s.st_mode)) {
return true;
- }
- else{
+ } else {
error_report("fast_vm_reload: path is not a folder");
exit(1);
}
@@ -2943,7 +2940,7 @@ int main(int argc, char **argv, char **envp)
{
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
bool fast_vm_reload = false;
state_init_global();
const char *fast_vm_reload_opt_arg = NULL;
@@ -3011,7 +3008,7 @@ int main(int argc, char **argv, char **envp)
qemu_add_opts(&qemu_nic_opts);
qemu_add_opts(&qemu_net_opts);
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
qemu_add_opts(&qemu_fast_vm_reloads_opts);
// clang-format off
#endif
@@ -3103,7 +3100,7 @@ int main(int argc, char **argv, char **envp)
}
switch(popt->index) {
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
case QEMU_OPTION_fast_vm_reload:
opts = qemu_opts_parse_noisily(qemu_find_opts("fast_vm_reload-opts"),
optarg, true);
@@ -3111,7 +3108,7 @@ int main(int argc, char **argv, char **envp)
exit(1);
}
fast_vm_reload_opt_arg = optarg;
- fast_vm_reload = true;
+ fast_vm_reload = true;
break;
// clang-format off
#endif
@@ -3571,8 +3568,8 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_loadvm:
loadvm = optarg;
#ifdef QEMU_NYX
-// clang-format on
- loadvm_global = (char*)optarg;
+ // clang-format on
+ loadvm_global = (char *)optarg;
// clang-format off
#endif
break;
@@ -4015,7 +4012,7 @@ int main(int argc, char **argv, char **envp)
}
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
block_signals();
// clang-format off
#endif
@@ -4590,99 +4587,109 @@ int main(int argc, char **argv, char **envp)
register_global_state();
#ifdef QEMU_NYX
-// clang-format on
+ // clang-format on
fast_reload_init(GET_GLOBAL_STATE()->fast_reload_snapshot);
- if (fast_vm_reload){
-
- if(getenv("NYX_DISABLE_BLOCK_COW")){
- nyx_error("Nyx block COW cache layer cannot be disabled while using fast snapshots\n");
+ if (fast_vm_reload) {
+ if (getenv("NYX_DISABLE_BLOCK_COW")) {
+ nyx_error("Nyx block COW cache layer cannot be disabled while using "
+ "fast snapshots\n");
exit(1);
}
- QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("fast_vm_reload-opts"), fast_vm_reload_opt_arg, true);
- const char* snapshot_path = qemu_opt_get(opts, "path");
- const char* pre_snapshot_path = qemu_opt_get(opts, "pre_path");
+ QemuOpts *opts =
+ qemu_opts_parse_noisily(qemu_find_opts("fast_vm_reload-opts"),
+ fast_vm_reload_opt_arg, true);
+ const char *snapshot_path = qemu_opt_get(opts, "path");
+ const char *pre_snapshot_path = qemu_opt_get(opts, "pre_path");
- /*
-
- valid arguments:
+ /*
+
+ valid arguments:
// create root snapshot to path (load pre_snapshot first)
-> path=foo,pre_path=bar,load=off // ALLOWED
// create root snapshot im memory (load pre_snapshot first)
-> pre_path=bar,load=off,skip_serialization // ALLOWED
// create root snapshot to path
-> path=foo,load=off // ALLOWED
- // load root snapshot from path
+ // load root snapshot from path
-> path=foo,load=on // ALLOWED
// create pre snapshot to pre_path
-> pre_path=bar,load=off // ALLOWED
- invalid arguments:
+ invalid arguments:
-> load=off // ALLOWED but useless
-> path=foo,pre_path=bar,load=on // INVALID
-> pre_path=bar,load=on // INVALID
-> load=on // INVALID
*/
- bool snapshot_used = verifiy_snapshot_folder(snapshot_path);
- bool pre_snapshot_used = verifiy_snapshot_folder(pre_snapshot_path);
- bool load_mode = qemu_opt_get_bool(opts, "load", false);
+ bool snapshot_used = verifiy_snapshot_folder(snapshot_path);
+ bool pre_snapshot_used = verifiy_snapshot_folder(pre_snapshot_path);
+ bool load_mode = qemu_opt_get_bool(opts, "load", false);
bool skip_serialization = qemu_opt_get_bool(opts, "skip_serialization", false);
- if((snapshot_used || load_mode || skip_serialization) && getenv("NYX_DISABLE_DIRTY_RING")){
- error_report("NYX_DISABLE_DIRTY_RING is only allowed during pre-snapshot creation\n");
+ if ((snapshot_used || load_mode || skip_serialization) &&
+ getenv("NYX_DISABLE_DIRTY_RING"))
+ {
+ error_report("NYX_DISABLE_DIRTY_RING is only allowed during "
+ "pre-snapshot creation\n");
exit(1);
}
- if((pre_snapshot_used && !snapshot_used && !load_mode) && !getenv("NYX_DISABLE_DIRTY_RING")){
- error_report("NYX_DISABLE_DIRTY_RING is required during pre-snapshot creation\n");
+ if ((pre_snapshot_used && !snapshot_used && !load_mode) &&
+ !getenv("NYX_DISABLE_DIRTY_RING"))
+ {
+ error_report(
+ "NYX_DISABLE_DIRTY_RING is required during pre-snapshot creation\n");
exit(1);
}
- if(pre_snapshot_used && load_mode){
+ if (pre_snapshot_used && load_mode) {
error_report("invalid argument (pre_snapshot_used && load_mode)!\n");
exit(1);
}
- if((!snapshot_used && !pre_snapshot_used) && load_mode){
- error_report("invalid argument ((!pre_snapshot_used && !pre_snapshot_used) && load_mode)!\n");
+ if ((!snapshot_used && !pre_snapshot_used) && load_mode) {
+ error_report("invalid argument ((!pre_snapshot_used && "
+ "!pre_snapshot_used) && load_mode)!\n");
exit(1);
}
- if(pre_snapshot_used && snapshot_used){
+ if (pre_snapshot_used && snapshot_used) {
nyx_printf("[Qemu-Nyx]: loading pre image to start fuzzing...\n");
set_fast_reload_mode(false);
set_fast_reload_path(snapshot_path);
- if(!skip_serialization){
+ if (!skip_serialization) {
enable_fast_reloads();
}
- fast_reload_create_from_file_pre_image(get_fast_reload_snapshot(), pre_snapshot_path, false);
+ fast_reload_create_from_file_pre_image(get_fast_reload_snapshot(),
+ pre_snapshot_path, false);
fast_reload_destroy(get_fast_reload_snapshot());
GET_GLOBAL_STATE()->fast_reload_snapshot = fast_reload_new();
fast_reload_init(GET_GLOBAL_STATE()->fast_reload_snapshot);
- }
- else{
- if(pre_snapshot_used){
+ } else {
+ if (pre_snapshot_used) {
nyx_printf("[Qemu-Nyx]: preparing to create pre image...\n");
set_fast_reload_pre_path(pre_snapshot_path);
set_fast_reload_pre_image();
- }
- else if(snapshot_used){
+ } else if (snapshot_used) {
set_fast_reload_path(snapshot_path);
- if(!skip_serialization){
+ if (!skip_serialization) {
enable_fast_reloads();
}
- if (load_mode){
+ if (load_mode) {
set_fast_reload_mode(true);
- nyx_printf("[Qemu-Nyx]: waiting for snapshot to start fuzzing...\n");
- fast_reload_create_from_file(get_fast_reload_snapshot(), snapshot_path, false);
- //cpu_synchronize_all_post_reset();
- set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 3);
+ nyx_printf(
+ "[Qemu-Nyx]: waiting for snapshot to start fuzzing...\n");
+ fast_reload_create_from_file(get_fast_reload_snapshot(),
+ snapshot_path, false);
+ // cpu_synchronize_all_post_reset();
+ set_state_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer,
+ 3);
skip_init();
- //GET_GLOBAL_STATE()->pt_trace_mode = false;
- }
- else{
+ // GET_GLOBAL_STATE()->pt_trace_mode = false;
+ } else {
nyx_printf("[Qemu-Nyx]: Booting VM to start fuzzing...\n");
set_fast_reload_mode(false);
}