Merge pull request #4 from il-steffen/staging-upstream-3

various improvements
This commit is contained in:
Sergej Schumilo 2022-02-22 23:26:27 +01:00 committed by GitHub
commit 0f8447d93a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 624 additions and 285 deletions

View File

@ -2562,18 +2562,23 @@ int kvm_cpu_exec(CPUState *cpu)
ret = EXCP_INTERRUPT; ret = EXCP_INTERRUPT;
break; break;
case KVM_EXIT_SHUTDOWN: case KVM_EXIT_SHUTDOWN:
DPRINTF("shutdown\n");
#ifndef QEMU_NYX #ifndef QEMU_NYX
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
ret = EXCP_INTERRUPT; ret = EXCP_INTERRUPT;
#else #else
fprintf(stderr, "ATTEMPT TO SHUTDOWN MACHINE (KVM_EXIT_SHUTDOWN)!\n");
if(GET_GLOBAL_STATE()->in_fuzzing_mode){ 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 */ /* 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]); handle_hypercall_kafl_release(run, cpu, (uint64_t)run->hypercall.args[0]);
ret = 0; ret = 0;
} #else
else{ debug_fprintf(stderr "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{
qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
ret = EXCP_INTERRUPT; ret = EXCP_INTERRUPT;
} }
@ -2684,8 +2689,17 @@ int kvm_cpu_exec(CPUState *cpu)
#ifndef QEMU_NYX #ifndef QEMU_NYX
DPRINTF("kvm_arch_handle_exit\n"); DPRINTF("kvm_arch_handle_exit\n");
#else #else
printf("kvm_arch_handle_exit => %d\n", run->exit_reason); #define CONFIG_UNKNOWN_ERROR_IS_PANIC
assert(false); #ifndef CONFIG_UNKNOWN_ERROR_IS_PANIC
fprintf(stderr, "Unknown exit code (%d) => ABORT\n", run->exit_reason);
ret = kvm_arch_handle_exit(cpu, run);
assert(ret == 0);
#else
debug_fprintf("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]);
#endif
#endif #endif
ret = kvm_arch_handle_exit(cpu, run); ret = kvm_arch_handle_exit(cpu, run);
break; break;

View File

@ -45,7 +45,8 @@ compile_libraries (){
echo "[!] compiling libxdc..." echo "[!] compiling libxdc..."
cd libxdc cd libxdc
CFLAGS="-I../capstone_v4/include/" V=1 make libxdc.a git checkout 641de7539e99f7faf5c8e8f1c8a4b37a9df52a5f
sudo make install
cd .. cd ..
echo "[!] libxdc is ready!" echo "[!] libxdc is ready!"
} }

View File

@ -533,3 +533,20 @@ static void pc_q35_2_4_machine_options(MachineClass *m)
DEFINE_Q35_MACHINE(v2_4, "pc-q35-2.4", NULL, DEFINE_Q35_MACHINE(v2_4, "pc-q35-2.4", NULL,
pc_q35_2_4_machine_options); pc_q35_2_4_machine_options);
#ifdef QEMU_NYX
static void pc_kAFL64_vmx_v1_0_machine_options(MachineClass *m)
{
pc_q35_4_2_machine_options(m);
m->alias = "kAFL64";
//m->is_default = 1;
m->desc = "kAFL64 PC (Q35 + ICH9, 2009)";
}
static void kAFL64_init(MachineState *machine)
{
pc_q35_init(machine);
}
DEFINE_PC_MACHINE(v1, "kAFL64-Q35", kAFL64_init, pc_kAFL64_vmx_v1_0_machine_options);
#endif

View File

@ -479,6 +479,7 @@ static void ich9_lpc_rcba_update(ICH9LPCState *lpc, uint32_t rcba_old)
if (rcba_old & ICH9_LPC_RCBA_EN) { if (rcba_old & ICH9_LPC_RCBA_EN) {
memory_region_del_subregion(get_system_memory(), &lpc->rcrb_mem); memory_region_del_subregion(get_system_memory(), &lpc->rcrb_mem);
} }
// Nyx snapshot reload fails here if ICH9_LPC_RCBA_EN=1
if (rcba & ICH9_LPC_RCBA_EN) { if (rcba & ICH9_LPC_RCBA_EN) {
memory_region_add_subregion_overlap(get_system_memory(), memory_region_add_subregion_overlap(get_system_memory(),
rcba & ICH9_LPC_RCBA_BA_MASK, rcba & ICH9_LPC_RCBA_BA_MASK,

View File

@ -2807,7 +2807,9 @@ static int virtio_device_put(QEMUFile *f, void *opaque, size_t size,
} }
/* A wrapper for use as a VMState .get function */ /* A wrapper for use as a VMState .get function */
static int virtio_device_get(QEMUFile *f, void *opaque, size_t size, int virtio_device_get(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field);
int virtio_device_get(QEMUFile *f, void *opaque, size_t size,
const VMStateField *field) const VMStateField *field)
{ {
VirtIODevice *vdev = VIRTIO_DEVICE(opaque); VirtIODevice *vdev = VIRTIO_DEVICE(opaque);

View File

@ -177,7 +177,12 @@ typedef struct ICH9LPCState {
#define ICH9_LPC_RCBA 0xf0 #define ICH9_LPC_RCBA 0xf0
#define ICH9_LPC_RCBA_BA_MASK Q35_MASK(32, 31, 14) #define ICH9_LPC_RCBA_BA_MASK Q35_MASK(32, 31, 14)
#ifdef QEMU_NYX
// Nyx snapshot restore fails on this
#define ICH9_LPC_RCBA_EN 0x0
#else
#define ICH9_LPC_RCBA_EN 0x1 #define ICH9_LPC_RCBA_EN 0x1
#endif
#define ICH9_LPC_RCBA_DEFAULT 0x0 #define ICH9_LPC_RCBA_DEFAULT 0x0
#define ICH9_LPC_PIC_NUM_PINS 16 #define ICH9_LPC_PIC_NUM_PINS 16

View File

@ -7,6 +7,7 @@ synchronization.o \
page_cache.o \ page_cache.o \
kvm_nested.o \ kvm_nested.o \
debug.o \ debug.o \
trace_dump.o \
auxiliary_buffer.o \ auxiliary_buffer.o \
mmh3.o \ mmh3.o \
nested_hypercalls.o \ nested_hypercalls.o \

View File

@ -25,6 +25,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include <stdbool.h> #include <stdbool.h>
#include "nyx/state/state.h" #include "nyx/state/state.h"
#include "nyx/debug.h" #include "nyx/debug.h"
#include "nyx/trace_dump.h"
/* experimental feature (currently broken) /* experimental feature (currently broken)
* enabled via trace mode * enabled via trace mode
@ -103,7 +104,9 @@ void check_auxiliary_config_buffer(auxilary_buffer_t* auxilary_buffer, auxilary_
#ifdef SUPPORT_COMPILE_TIME_REDQUEEN #ifdef SUPPORT_COMPILE_TIME_REDQUEEN
GET_GLOBAL_STATE()->pt_trace_mode_force = true; GET_GLOBAL_STATE()->pt_trace_mode_force = true;
#endif #endif
redqueen_set_trace_mode(GET_GLOBAL_STATE()->redqueen_state); GET_GLOBAL_STATE()->trace_mode = true;
redqueen_set_trace_mode();
pt_trace_dump_enable(true);
} }
} }
else { else {
@ -112,7 +115,9 @@ void check_auxiliary_config_buffer(auxilary_buffer_t* auxilary_buffer, auxilary_
#ifdef SUPPORT_COMPILE_TIME_REDQUEEN #ifdef SUPPORT_COMPILE_TIME_REDQUEEN
GET_GLOBAL_STATE()->pt_trace_mode_force = false; GET_GLOBAL_STATE()->pt_trace_mode_force = false;
#endif #endif
redqueen_unset_trace_mode(GET_GLOBAL_STATE()->redqueen_state); GET_GLOBAL_STATE()->trace_mode = false;
redqueen_unset_trace_mode();
pt_trace_dump_enable(false);
} }
} }
@ -166,6 +171,10 @@ void set_crash_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_crash); 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){ void set_timeout_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer){
VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_timeout); VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_timeout);
} }
@ -225,7 +234,12 @@ 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_success_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer, uint8_t success){
VOLATILE_WRITE_8(auxilary_buffer->result.exec_result_code, rc_success); //should 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){ void set_payload_buffer_write_reason_auxiliary_buffer(auxilary_buffer_t* auxilary_buffer, char* msg, uint32_t len){
@ -259,4 +273,4 @@ void set_result_bb_coverage(auxilary_buffer_t* auxilary_buffer, uint32_t value){
if (value != auxilary_buffer->result.bb_coverage){ if (value != auxilary_buffer->result.bb_coverage){
VOLATILE_WRITE_32(auxilary_buffer->result.bb_coverage, value); VOLATILE_WRITE_32(auxilary_buffer->result.bb_coverage, value);
} }
} }

View File

@ -44,6 +44,8 @@ enum nyx_result_codes {
rc_timeout = 3, rc_timeout = 3,
rc_input_buffer_write = 4, rc_input_buffer_write = 4,
rc_aborted = 5, rc_aborted = 5,
rc_sanitizer = 6,
rc_starved = 7,
}; };
typedef struct auxilary_buffer_header_s{ typedef struct auxilary_buffer_header_s{
@ -72,7 +74,7 @@ typedef struct auxilary_buffer_config_s{
/* trigger to enable / disable different QEMU-PT modes */ /* trigger to enable / disable different QEMU-PT modes */
uint8_t redqueen_mode; uint8_t redqueen_mode;
uint8_t trace_mode; uint8_t trace_mode; /* dump decoded edge transitions to file */
uint8_t reload_mode; uint8_t reload_mode;
uint8_t verbose_level; uint8_t verbose_level;
@ -149,6 +151,7 @@ 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 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_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_timeout_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
void set_reload_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_pt_overflow_auxiliary_result_buffer(auxilary_buffer_t* auxilary_buffer);
@ -173,4 +176,4 @@ 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);

View File

@ -56,7 +56,6 @@ void parse_address_file(char* path, size_t* num_addrs, uint64_t** addrs){
int re_fd = 0; int re_fd = 0;
int se_fd = 0; int se_fd = 0;
int trace_fd = 0;
void write_re_result(char* buf){ void write_re_result(char* buf){
int unused __attribute__((unused)); int unused __attribute__((unused));
@ -65,20 +64,7 @@ void write_re_result(char* buf){
unused = write(re_fd, buf, strlen(buf)); unused = write(re_fd, buf, strlen(buf));
} }
void write_trace_result(redqueen_trace_t* trace_state){ void fsync_redqueen_files(void){
//int fd;
int unused __attribute__((unused));
if (!trace_fd)
trace_fd = open(redqueen_workdir.pt_trace_results, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
redqueen_trace_write_file(trace_state, trace_fd);
//unused = write(trace_fd, buf, strlen(buf));
//close(fd);
}
void fsync_all_traces(void){
if (!trace_fd){
fsync(trace_fd);
}
if (!se_fd){ if (!se_fd){
fsync(se_fd); fsync(se_fd);
} }
@ -96,13 +82,6 @@ void write_se_result(char* buf){
//close(fd); //close(fd);
} }
void delete_trace_files(void){
int unused __attribute__((unused));
if (!trace_fd)
trace_fd = open(redqueen_workdir.pt_trace_results, O_WRONLY | O_CREAT | O_APPEND, S_IRWXU);
unused = ftruncate(trace_fd, 0);
}
void delete_redqueen_files(void){ void delete_redqueen_files(void){
int unused __attribute__((unused)); int unused __attribute__((unused));
if (!re_fd) if (!re_fd)

View File

@ -1,7 +1,8 @@
#include <stdio.h> #include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "redqueen_trace.h"
#pragma once
//doesn't take ownership of path, num_addrs or addrs //doesn't take ownership of path, num_addrs or addrs
void parse_address_file(char* path, size_t* num_addrs, uint64_t** addrs); void parse_address_file(char* path, size_t* num_addrs, uint64_t** addrs);
@ -12,14 +13,9 @@ void write_re_result(char* buf);
//doesn't take ownership of buf //doesn't take ownership of buf
void write_se_result(char* buf); void write_se_result(char* buf);
//doesn't take ownership of buf
void write_trace_result(redqueen_trace_t* trace_state);
//doesn' take ownership of buf //doesn' take ownership of buf
void write_debug_result(char* buf); void write_debug_result(char* buf);
void delete_redqueen_files(void); void delete_redqueen_files(void);
void delete_trace_files(void); void fsync_redqueen_files(void);
void fsync_all_traces(void);

View File

@ -24,6 +24,7 @@ void handle_hypercall_kafl_get_host_config(struct kvm_run *run, CPUState *cpu, u
config.bitmap_size = GET_GLOBAL_STATE()->shared_bitmap_size; config.bitmap_size = GET_GLOBAL_STATE()->shared_bitmap_size;
config.ijon_bitmap_size = GET_GLOBAL_STATE()->shared_ijon_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.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); write_virtual_memory(vaddr, (uint8_t*)&config, sizeof(host_config_t), cpu);
GET_GLOBAL_STATE()->get_host_config_done = true; GET_GLOBAL_STATE()->get_host_config_done = true;
@ -101,4 +102,4 @@ void handle_hypercall_kafl_set_agent_config(struct kvm_run *run, CPUState *cpu,
exit(1); exit(1);
} }
GET_GLOBAL_STATE()->set_agent_config_done = true; GET_GLOBAL_STATE()->set_agent_config_done = true;
} }

View File

@ -19,6 +19,7 @@ typedef struct host_config_s{
uint32_t bitmap_size; uint32_t bitmap_size;
uint32_t ijon_bitmap_size; uint32_t ijon_bitmap_size;
uint32_t payload_buffer_size; uint32_t payload_buffer_size;
uint32_t worker_id;
/* more to come */ /* more to come */
} __attribute__((packed)) host_config_t; } __attribute__((packed)) host_config_t;

View File

@ -349,6 +349,13 @@ void handle_hypercall_kafl_release(struct kvm_run *run, CPUState *cpu, uint64_t
if (init_state){ if (init_state){
init_state = false; init_state = false;
} else { } else {
//printf(CORE_PREFIX, "Got STARVED notification (num=%llu)\n", run->hypercall.args[0]);
if (run->hypercall.args[0] > 0) {
GET_GLOBAL_STATE()->starved = 1;
} else {
GET_GLOBAL_STATE()->starved = 0;
}
synchronization_disable_pt(cpu); synchronization_disable_pt(cpu);
release_print_once(cpu); release_print_once(cpu);
} }
@ -435,13 +442,28 @@ static void handle_hypercall_kafl_submit_panic(struct kvm_run *run, CPUState *cp
if(hypercall_enabled){ if(hypercall_enabled){
QEMU_PT_PRINTF(CORE_PREFIX, "Panic address:\t%lx", hypercall_arg); QEMU_PT_PRINTF(CORE_PREFIX, "Panic address:\t%lx", hypercall_arg);
write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD, PAYLOAD_BUFFER_SIZE, cpu); if (run->hypercall.longmode) {
write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_64, PAYLOAD_BUFFER_SIZE, cpu);
} else {
write_virtual_memory(hypercall_arg, (uint8_t*)PANIC_PAYLOAD_32, PAYLOAD_BUFFER_SIZE, cpu);
}
}
}
static void handle_hypercall_kafl_submit_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
if(hypercall_enabled){
QEMU_PT_PRINTF(CORE_PREFIX, "kASAN address:\t%lx", hypercall_arg);
if (run->hypercall.longmode){
write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_64, PAYLOAD_BUFFER_SIZE, cpu);
} else {
write_virtual_memory(hypercall_arg, (uint8_t*)KASAN_PAYLOAD_32, PAYLOAD_BUFFER_SIZE, cpu);
}
} }
} }
//#define PANIC_DEBUG //#define PANIC_DEBUG
static void handle_hypercall_kafl_panic(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){
static char reason[1024]; static char reason[1024];
if(hypercall_enabled){ if(hypercall_enabled){
#ifdef PANIC_DEBUG #ifdef PANIC_DEBUG
@ -550,6 +572,27 @@ static void handle_hypercall_kafl_panic_extended(struct kvm_run *run, CPUState *
} }
} }
static void handle_hypercall_kafl_kasan(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
if(hypercall_enabled){
#ifdef PANIC_DEBUG
if(hypercall_arg){
QEMU_PT_PRINTF(CORE_PREFIX, "ASan notification in user mode!");
} else{
QEMU_PT_PRINTF(CORE_PREFIX, "ASan notification in kernel mode!");
}
#endif
if(fast_reload_snapshot_exists(get_fast_reload_snapshot())){
synchronization_lock_asan_found();
//synchronization_stop_vm_kasan(cpu);
} else{
QEMU_PT_PRINTF(CORE_PREFIX, "KASAN detected during initialization of stage 1 or stage 2 loader");
//hypercall_snd_char(KAFL_PROTO_KASAN);
QEMU_PT_PRINTF_DEBUG("Protocol - SEND: KAFL_PROTO_KASAN");
}
}
}
static void handle_hypercall_kafl_lock(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){ 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")){ if(is_called_in_fuzzing_mode("KVM_EXIT_KAFL_LOCK")){
@ -572,7 +615,7 @@ static void handle_hypercall_kafl_printf(struct kvm_run *run, CPUState *cpu, uin
#ifdef DEBUG_HPRINTF #ifdef DEBUG_HPRINTF
fprintf(stderr, "%s %s\n", __func__, hprintf_buffer); fprintf(stderr, "%s %s\n", __func__, hprintf_buffer);
#endif #endif
set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strnlen(hprintf_buffer, HPRINTF_SIZE)+1); set_hprintf_auxiliary_buffer(GET_GLOBAL_STATE()->auxilary_buffer, hprintf_buffer, strnlen(hprintf_buffer, HPRINTF_SIZE));
synchronization_lock(); synchronization_lock();
} }
@ -671,81 +714,97 @@ void pt_set_disable_patches_pending(CPUState *cpu){
GET_GLOBAL_STATE()->patches_disable_pending = true; GET_GLOBAL_STATE()->patches_disable_pending = true;
} }
void pt_enable_rqi_trace(CPUState *cpu){ static void handle_hypercall_kafl_dump_file(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg)
if (GET_GLOBAL_STATE()->redqueen_state){ {
redqueen_set_trace_mode(GET_GLOBAL_STATE()->redqueen_state); kafl_dump_file_t file_obj;
}
}
void pt_disable_rqi_trace(CPUState *cpu){
if (GET_GLOBAL_STATE()->redqueen_state){
redqueen_unset_trace_mode(GET_GLOBAL_STATE()->redqueen_state);
return;
}
}
static void handle_hypercall_kafl_dump_file(struct kvm_run *run, CPUState *cpu, uint64_t hypercall_arg){
/* TODO: check via aux buffer if we should allow this hypercall during fuzzing */
/*
if(GET_GLOBAL_STATE()->in_fuzzing_mode){
return;
}
*/
char filename[256] = {0}; char filename[256] = {0};
char* host_path = NULL;
FILE* f = NULL;
uint64_t vaddr = hypercall_arg; uint64_t vaddr = hypercall_arg;
kafl_dump_file_t file_obj;
memset((void*)&file_obj, 0, sizeof(kafl_dump_file_t)); 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)){
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;
void* page = malloc(0x1000);
read_virtual_memory(file_obj.file_name_str_ptr, (uint8_t*)&filename, sizeof(char)*256, cpu);
filename[255] = 0;
char* base_name = basename(filename);
char* host_path = NULL;
assert(asprintf(&host_path, "%s/dump/%s", GET_GLOBAL_STATE()->workdir_path , base_name) != -1);
//fprintf(stderr, "dumping file %s -> %s (bytes %ld) in append_mode=%d\n", base_name, host_path, file_obj.bytes, file_obj.append);
FILE* f = NULL;
if(file_obj.append){
f = fopen(host_path, "a+");
}
else{
f = fopen(host_path, "w+");
}
int32_t bytes = file_obj.bytes;
uint32_t pos = 0;
while(bytes > 0){
if(bytes >= 0x1000){
read_virtual_memory(file_obj.data_ptr+pos, (uint8_t*)page, 0x1000, cpu);
fwrite(page, 1, 0x1000, f);
}
else{
read_virtual_memory(file_obj.data_ptr+pos, (uint8_t*)page, bytes, cpu);
fwrite(page, 1, bytes, f);
}
bytes -= 0x1000;
pos += 0x1000;
}
fclose(f);
free(host_path);
free(page);
} }
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;
QEMU_PT_PRINTF(CORE_PREFIX, "%s: dump %d bytes to %s (append=%u)\n",
__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);
err_out1:
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){
@ -804,7 +863,9 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall
ret = 0; ret = 0;
break; break;
case KVM_EXIT_KAFL_SUBMIT_KASAN: case KVM_EXIT_KAFL_SUBMIT_KASAN:
nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_SUBMIT_KASAN)..."); //timeout_reload_pending = false;
//fprintf(stderr, "KVM_EXIT_KAFL_SUBMIT_KASAN\n");
handle_hypercall_kafl_submit_kasan(run, cpu, arg);
ret = 0; ret = 0;
break; break;
case KVM_EXIT_KAFL_PANIC: case KVM_EXIT_KAFL_PANIC:
@ -814,7 +875,9 @@ int handle_kafl_hypercall(struct kvm_run *run, CPUState *cpu, uint64_t hypercall
ret = 0; ret = 0;
break; break;
case KVM_EXIT_KAFL_KASAN: case KVM_EXIT_KAFL_KASAN:
nyx_abort((char*)"Deprecated hypercall called (HYPERCALL_KAFL_KASAN)..."); //timeout_reload_pending = false;
//fprintf(stderr, "KVM_EXIT_KAFL_KASAN\n");
handle_hypercall_kafl_kasan(run, cpu, arg);
ret = 0; ret = 0;
break; break;
case KVM_EXIT_KAFL_LOCK: case KVM_EXIT_KAFL_LOCK:

View File

@ -46,18 +46,40 @@ bool check_bitmap_byte(uint32_t value);
* 0f 01 c1 vmcall * 0f 01 c1 vmcall
* f4 hlt * f4 hlt
*/ */
#define PANIC_PAYLOAD "\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)
* fa cli
* b8 1f 00 00 00 mov $0x1f,%eax
* bb 08 00 00 00 mov $0x8,%ebx
* b9 00 00 00 00 mov $0x0,%ecx
* 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"
/* /*
* KASAN Notifier Payload (x86-64) * KASAN Notifier Payload (x86-64)
* fa cli * fa cli
* 48 c7 c0 1f 00 00 00 mov rax,0x1f * 48 c7 c0 1f 00 00 00 mov rax,0x1f
* 48 c7 c3 08 00 00 00 mov rbx,0x9 * 48 c7 c3 09 00 00 00 mov rbx,0x9
* 48 c7 c1 00 00 00 00 mov rcx,0x0 * 48 c7 c1 00 00 00 00 mov rcx,0x0
* 0f 01 c1 vmcall * 0f 01 c1 vmcall
* f4 hlt * f4 hlt
*/ */
#define KASAN_PAYLOAD "\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)
* fa cli
* b8 1f 00 00 00 mov $0x1f,%eax
* bb 09 00 00 00 mov $0x9,%ebx
* b9 00 00 00 00 mov $0x0,%ecx
* 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"
/* /*
* printk Notifier Payload (x86-64) * printk Notifier Payload (x86-64)
@ -92,8 +114,7 @@ void hypercall_reload(void);
void handle_hypercall_kafl_acquire(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_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);
@ -109,8 +130,6 @@ void pt_enable_rqo(CPUState *cpu);
void pt_disable_rqo(CPUState *cpu); void pt_disable_rqo(CPUState *cpu);
void pt_enable_rqi(CPUState *cpu); void pt_enable_rqi(CPUState *cpu);
void pt_disable_rqi(CPUState *cpu); void pt_disable_rqi(CPUState *cpu);
void pt_enable_rqi_trace(CPUState *cpu);
void pt_disable_rqi_trace(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_redqueen_update_blacklist(CPUState *cpu, bool newval);
void pt_set_enable_patches_pending(CPUState *cpu); void pt_set_enable_patches_pending(CPUState *cpu);

View File

@ -51,6 +51,7 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include "nyx/state/state.h" #include "nyx/state/state.h"
#include "nyx/sharedir.h" #include "nyx/sharedir.h"
#include "nyx/helpers.h" #include "nyx/helpers.h"
#include "nyx/trace_dump.h"
#include <time.h> #include <time.h>
@ -89,6 +90,7 @@ typedef struct nyx_interface_state {
uint32_t input_buffer_size; uint32_t input_buffer_size;
bool dump_pt_trace; bool dump_pt_trace;
bool edge_cb_trace;
bool redqueen; bool redqueen;
@ -260,30 +262,6 @@ static bool verify_workdir_state(nyx_interface_state *s, Error **errp){
} }
free(tmp); free(tmp);
assert(asprintf(&tmp, "%s/page_cache.lock", workdir) != -1);
if (!file_exits(tmp)){
fprintf(stderr, "%s does not exist...", tmp);
free(tmp);
return false;
}
free(tmp);
assert(asprintf(&tmp, "%s/page_cache.addr", workdir) != -1);
if (!file_exits(tmp)){
fprintf(stderr, "%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)){
fprintf(stderr, "%s does not exist...\n", tmp);
free(tmp);
return false;
}
free(tmp);
assert(asprintf(&tmp, "%s/page_cache", workdir) != -1); assert(asprintf(&tmp, "%s/page_cache", workdir) != -1);
init_page_cache(tmp); init_page_cache(tmp);
@ -301,9 +279,13 @@ static bool verify_workdir_state(nyx_interface_state *s, Error **errp){
init_redqueen_state(); init_redqueen_state();
if(s->dump_pt_trace){ if(s->dump_pt_trace){
assert(asprintf(&tmp, "%s/pt_trace_dump_%d", workdir, id) != -1); assert(asprintf(&tmp, "%s/pt_trace_dump_%d", workdir, id) != -1);
pt_open_pt_trace_file(tmp); pt_trace_dump_init(tmp);
free(tmp); free(tmp);
}
if(s->edge_cb_trace){
redqueen_trace_init();
} }
@ -398,6 +380,7 @@ static void nyx_realize(DeviceState *dev, Error **errp){
if(s->cow_primary_size){ if(s->cow_primary_size){
set_global_cow_cache_primary_size(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)){ if (!s->workdir || !verify_workdir_state(s, errp)){
fprintf(stderr, "[QEMU-Nyx] Error: work dir...\n"); fprintf(stderr, "[QEMU-Nyx] Error: work dir...\n");
@ -449,6 +432,7 @@ static Property nyx_interface_properties[] = {
DEFINE_PROP_UINT32("bitmap_size", nyx_interface_state, bitmap_size, DEFAULT_NYX_BITMAP_SIZE), 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_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("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(),

View File

@ -215,8 +215,14 @@ bool remap_slot(uint64_t addr, uint32_t slot, CPUState *cpu, int fd, uint64_t sh
QLIST_FOREACH_RCU(block, &ram_list.blocks, next) { QLIST_FOREACH_RCU(block, &ram_list.blocks, next) {
if(!memcmp(block->idstr, "pc.ram", 6)){ if(!memcmp(block->idstr, "pc.ram", 6)){
/* TODO: put assert calls here */ /* TODO: put assert calls here */
munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE); if (munmap((void*)(((uint64_t)block->host) + phys_addr_ram_offset), x86_64_PAGE_SIZE) == -1) {
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)); fprintf(stderr, "%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) {
fprintf(stderr, "%s: mmap failed!\n", __func__);
assert(false);
}
//printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE)); //printf("MMUNMAP: %d\n", munmap((void*)(((uint64_t)block->host) + phys_addr), x86_64_PAGE_SIZE));
//printf("MMAP: %p\n", mmap((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, (i*x86_64_PAGE_SIZE))); //printf("MMAP: %p\n", mmap((void*)(((uint64_t)block->host) + phys_addr), 0x1000, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, (i*x86_64_PAGE_SIZE)));
@ -285,6 +291,7 @@ void resize_shared_memory(uint32_t new_size, uint32_t* shm_size, void** shm_ptr,
bool remap_payload_buffer(uint64_t virt_guest_addr, CPUState *cpu){ 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_fd && GET_GLOBAL_STATE()->shared_payload_buffer_size);
assert(GET_GLOBAL_STATE()->shared_payload_buffer_size % x86_64_PAGE_SIZE == 0);
RAMBlock *block; RAMBlock *block;
refresh_kvm_non_dirty(cpu); refresh_kvm_non_dirty(cpu);

View File

@ -25,6 +25,9 @@
#define UNMAPPED_PAGE 0xFFFFFFFFFFFFFFFFULL #define UNMAPPED_PAGE 0xFFFFFFFFFFFFFFFFULL
static void page_cache_unlock(page_cache_t* self);
static void page_cache_lock(page_cache_t* self);
#ifndef STANDALONE_DECODER #ifndef STANDALONE_DECODER
static bool reload_addresses(page_cache_t* self){ static bool reload_addresses(page_cache_t* self){
#else #else
@ -40,6 +43,8 @@ bool reload_addresses(page_cache_t* self){
if(self_offset != self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE){ if(self_offset != self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE){
//fprintf(stderr, "Reloading files ...\n"); //fprintf(stderr, "Reloading files ...\n");
page_cache_lock(self); // don't read while someone else is writing?
lseek(self->fd_address_file, self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE, SEEK_SET); lseek(self->fd_address_file, self->num_pages*PAGE_CACHE_ADDR_LINE_SIZE, SEEK_SET);
offset = self->num_pages; offset = self->num_pages;
while(read(self->fd_address_file, &value, PAGE_CACHE_ADDR_LINE_SIZE)){ while(read(self->fd_address_file, &value, PAGE_CACHE_ADDR_LINE_SIZE)){
@ -79,6 +84,8 @@ bool reload_addresses(page_cache_t* self){
munmap(self->page_data, self->num_pages*PAGE_SIZE); munmap(self->page_data, self->num_pages*PAGE_SIZE);
self->num_pages = self_offset/PAGE_CACHE_ADDR_LINE_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); self->page_data = mmap(NULL, (self->num_pages)*PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, self->fd_page_file, 0);
page_cache_unlock(self);
return true; return true;
} }
@ -359,12 +366,12 @@ page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_w
self->lookup = kh_init(PC_CACHE); self->lookup = kh_init(PC_CACHE);
self->fd_page_file = open(tmp1, O_CLOEXEC | O_RDWR, S_IRWXU); self->fd_page_file = open(tmp1, O_CLOEXEC | O_CREAT | O_RDWR, 0644);
self->fd_address_file = open(tmp2, O_CLOEXEC | O_RDWR, S_IRWXU); self->fd_address_file = open(tmp2, O_CLOEXEC | O_CREAT | O_RDWR, 0644);
#ifndef STANDALONE_DECODER #ifndef STANDALONE_DECODER
self->cpu = cpu; self->cpu = cpu;
self->fd_lock = open(tmp3, O_CLOEXEC); self->fd_lock = open(tmp3, O_CLOEXEC | O_CREAT, 0644);
assert(self->fd_lock > 0); assert(self->fd_lock > 0);
#else #else
if(self->fd_page_file == -1 || self->fd_address_file == -1){ if(self->fd_page_file == -1 || self->fd_address_file == -1){
@ -381,7 +388,11 @@ page_cache_t* page_cache_new(const char* cache_file, uint8_t disassembler_word_w
self->last_page = 0xFFFFFFFFFFFFFFFF; self->last_page = 0xFFFFFFFFFFFFFFFF;
self->last_addr = 0xFFFFFFFFFFFFFFFF; self->last_addr = 0xFFFFFFFFFFFFFFFF;
#ifndef STANDALONE_DECODER
QEMU_PT_PRINTF(PAGE_CACHE_PREFIX, "%s (%s - %s)", __func__, tmp1, tmp2); QEMU_PT_PRINTF(PAGE_CACHE_PREFIX, "%s (%s - %s)", __func__, tmp1, tmp2);
#else
QEMU_PT_PRINTF(PAGE_CACHE_PREFIX, "%s (%s - %s) WORD_WIDTH: %d", __func__, tmp1, tmp2, disassembler_word_width);
#endif
free(tmp3); free(tmp3);
free(tmp2); free(tmp2);

View File

@ -34,36 +34,21 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
#include "nyx/memory_access.h" #include "nyx/memory_access.h"
#include "nyx/interface.h" #include "nyx/interface.h"
#include "nyx/debug.h" #include "nyx/debug.h"
#include "nyx/file_helper.h"
#ifdef CONFIG_REDQUEEN
#include "nyx/redqueen.h" #include "nyx/redqueen.h"
#include "nyx/redqueen_patch.h" #include "nyx/redqueen_patch.h"
#include "nyx/patcher.h" #include "nyx/patcher.h"
#endif
#include "nyx/page_cache.h" #include "nyx/page_cache.h"
#include "nyx/state/state.h" #include "nyx/state/state.h"
#include <libxdc.h> #include <libxdc.h>
#include "nyx/helpers.h" #include "nyx/helpers.h"
#include "nyx/trace_dump.h"
#include "nyx/redqueen_trace.h"
#define PT_BUFFER_MMAP_ADDR 0x3ffff0000000 #define PT_BUFFER_MMAP_ADDR 0x3ffff0000000
uint32_t state_byte = 0;
uint32_t last = 0;
int pt_trace_dump_fd = 0;
bool should_dump_pt_trace= false;
void pt_open_pt_trace_file(char* filename){
printf("using pt trace at %s",filename);
pt_trace_dump_fd = open(filename, O_WRONLY);
should_dump_pt_trace = true;
assert(pt_trace_dump_fd >= 0);
}
void pt_trucate_pt_trace_file(void){
if(should_dump_pt_trace){
assert(lseek(pt_trace_dump_fd, 0, SEEK_SET) == 0);
assert(ftruncate(pt_trace_dump_fd, 0)==0);
}
}
static void pt_set(CPUState *cpu, run_on_cpu_data arg){ static void pt_set(CPUState *cpu, run_on_cpu_data arg){
asm volatile("" ::: "memory"); asm volatile("" ::: "memory");
} }
@ -98,12 +83,6 @@ static inline int pt_ioctl(int fd, unsigned long request, unsigned long arg){
return ioctl(fd, request, arg); return ioctl(fd, request, arg);
} }
static inline uint64_t mix_bits(uint64_t v) {
v ^= (v >> 31);
v *= 0x7fb5d329728ea185;
return v;
}
#ifdef DUMP_AND_DEBUG_PT #ifdef DUMP_AND_DEBUG_PT
void dump_pt_trace(void* buffer, int bytes){ void dump_pt_trace(void* buffer, int bytes){
static FILE* f = NULL; static FILE* f = NULL;
@ -131,12 +110,13 @@ void dump_pt_trace(void* buffer, int bytes){
#endif #endif
void pt_dump(CPUState *cpu, int bytes){ void pt_dump(CPUState *cpu, int bytes){
if(should_dump_pt_trace){ //pt_write_pt_dump_file(cpu->pt_mmap, bytes);
assert(bytes == write(pt_trace_dump_fd, cpu->pt_mmap, bytes));
}
if(!(GET_GLOBAL_STATE()->redqueen_state && GET_GLOBAL_STATE()->redqueen_state->intercept_mode)){ 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){ 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; GET_GLOBAL_STATE()->pt_trace_size += bytes;
//dump_pt_trace(cpu->pt_mmap, bytes);
pt_write_pt_dump_file(cpu->pt_mmap, bytes);
decoder_result_t result = libxdc_decode(GET_GLOBAL_STATE()->decoder, cpu->pt_mmap, bytes); decoder_result_t result = libxdc_decode(GET_GLOBAL_STATE()->decoder, cpu->pt_mmap, bytes);
switch(result){ switch(result){
case decoder_success: case decoder_success:
@ -150,7 +130,7 @@ void pt_dump(CPUState *cpu, int bytes){
GET_GLOBAL_STATE()->decoder_page_fault_addr = libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder); GET_GLOBAL_STATE()->decoder_page_fault_addr = libxdc_get_page_fault_addr(GET_GLOBAL_STATE()->decoder);
break; break;
case decoder_unkown_packet: case decoder_unkown_packet:
fprintf(stderr, "WARNING: libxdc_decode returned decoder_error\n"); fprintf(stderr, "WARNING: libxdc_decode returned unknown_packet\n");
break; break;
case decoder_error: case decoder_error:
fprintf(stderr, "WARNING: libxdc_decode returned decoder_error\n"); fprintf(stderr, "WARNING: libxdc_decode returned decoder_error\n");
@ -165,8 +145,11 @@ int pt_enable(CPUState *cpu, bool hmp_mode){
if(!fast_reload_set_bitmap(get_fast_reload_snapshot())){ if(!fast_reload_set_bitmap(get_fast_reload_snapshot())){
coverage_bitmap_reset(); coverage_bitmap_reset();
} }
//pt_reset_bitmap(); if (GET_GLOBAL_STATE()->trace_mode) {
pt_trucate_pt_trace_file(); redqueen_trace_reset();
alt_bitmap_reset();
}
pt_truncate_pt_dump_file();
return pt_cmd(cpu, KVM_VMX_PT_ENABLE, hmp_mode); return pt_cmd(cpu, KVM_VMX_PT_ENABLE, hmp_mode);
} }
@ -248,6 +231,10 @@ void pt_init_decoder(CPUState *cpu){
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); 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); 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);
} }
int pt_disable_ip_filtering(CPUState *cpu, uint8_t addrn, bool hmp_mode){ int pt_disable_ip_filtering(CPUState *cpu, uint8_t addrn, bool hmp_mode){

View File

@ -24,9 +24,6 @@ along with QEMU-PT. If not, see <http://www.gnu.org/licenses/>.
void pt_init_decoder(CPUState *cpu); void pt_init_decoder(CPUState *cpu);
void pt_reset_bitmap(void);
void pt_setup_bitmap(void* ptr);
int pt_enable(CPUState *cpu, bool hmp_mode); int pt_enable(CPUState *cpu, bool hmp_mode);
int pt_disable(CPUState *cpu, bool hmp_mode); int pt_disable(CPUState *cpu, bool hmp_mode);
int pt_enable_ip_filtering(CPUState *cpu, uint8_t addrn, bool redqueen, bool hmp_mode); int pt_enable_ip_filtering(CPUState *cpu, uint8_t addrn, bool redqueen, bool hmp_mode);
@ -39,9 +36,6 @@ void pt_post_kvm_run(CPUState *cpu);
void pt_handle_overflow(CPUState *cpu); void pt_handle_overflow(CPUState *cpu);
void pt_dump(CPUState *cpu, int bytes); void pt_dump(CPUState *cpu, int bytes);
void pt_bitmap(uint64_t from, uint64_t to);
void pt_open_pt_trace_file(char* filename);
void pt_trucate_pt_trace_file(void);
#endif #endif

View File

@ -49,7 +49,6 @@ redqueen_t* new_rq_state(CPUState *cpu, page_cache_t* page_cache){
res->cpu = cpu; res->cpu = cpu;
res->intercept_mode = false; res->intercept_mode = false;
res->trace_mode = false;
res->singlestep_enabled = false; res->singlestep_enabled = false;
res->hooks_applied = 0; res->hooks_applied = 0;
res->page_cache = page_cache; res->page_cache = page_cache;
@ -225,44 +224,6 @@ void redqueen_callback(void* opaque, disassembler_mode_t mode, uint64_t start_ad
} }
} }
static void redqueen_trace_enabled(redqueen_t* self){
int unused __attribute__((unused));
if(self->trace_mode){
//libxdc_enable_tracing(GET_GLOBAL_STATE()->decoder);
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, self->trace_state);
//redqueen_trace_register_transition(self->trace_state, INIT_TRACE_IP, ip);
//last_ip = ip;
}
}
static void redqueen_trace_disabled(redqueen_t* self){
int unused __attribute__((unused));
if(self->trace_mode){
libxdc_disable_tracing(GET_GLOBAL_STATE()->decoder);
//redqueen_trace_register_transition(self->trace_state, last_ip, ip);
//edqueen_trace_register_transition(self->trace_state, ip, INIT_TRACE_IP);
}
}
void redqueen_set_trace_mode(redqueen_t* self){
delete_trace_files();
self->trace_mode = true;
redqueen_trace_enabled(self);
}
void redqueen_unset_trace_mode(redqueen_t* self){
//write_trace_result(self->trace_state);
//redqueen_trace_reset(self->trace_state);
redqueen_trace_disabled(self);
self->trace_mode = false;
}
void destroy_rq_state(redqueen_t* self){ void destroy_rq_state(redqueen_t* self){
redqueen_trace_free(self->trace_state); redqueen_trace_free(self->trace_state);
kh_destroy(RQ, self->lookup); kh_destroy(RQ, self->lookup);

View File

@ -70,7 +70,6 @@ KHASH_MAP_INIT_INT64(RQ, uint32_t)
typedef struct redqueen_s{ typedef struct redqueen_s{
khash_t(RQ) *lookup; khash_t(RQ) *lookup;
bool intercept_mode; bool intercept_mode;
bool trace_mode;
bool singlestep_enabled; bool singlestep_enabled;
int hooks_applied; int hooks_applied;
CPUState *cpu; CPUState *cpu;
@ -109,10 +108,6 @@ void enable_rq_intercept_mode(redqueen_t* self);
void disable_rq_intercept_mode(redqueen_t* self); void disable_rq_intercept_mode(redqueen_t* self);
void redqueen_register_transition(redqueen_t* self, uint64_t ip, uint64_t transition_val);
void redqueen_set_trace_mode(redqueen_t* self);
void redqueen_unset_trace_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_registers(redqueen_t* self);

View File

@ -2,7 +2,73 @@
#include <unistd.h> #include <unistd.h>
#include <stdio.h> #include <stdio.h>
#include <assert.h> #include <assert.h>
#include "redqueen_trace.h" #include "redqueen_trace.h"
#include "redqueen.h"
#include "state/state.h"
/* write full trace of edge transitions rather than sorted list? */
//#define KAFL_FULL_TRACES
int trace_fd = 0;
int redqueen_trace_enabled = false;
uint32_t alt_bitmap_size = 0;
uint8_t* alt_bitmap = NULL;
void alt_bitmap_init(void* ptr, uint32_t 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);
}
}
static inline uint64_t mix_bits(uint64_t v) {
v ^= (v >> 31);
v *= 0x7fb5d329728ea185;
return v;
}
/*
* quick+dirty bitmap based on libxdc trace callback
* similar but not itentical to libxdc bitmap.
*/
static void alt_bitmap_add(uint64_t from, uint64_t to)
{
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)]++;
}
}
}
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;
}
redqueen_trace_t* redqueen_trace_new(void){ redqueen_trace_t* redqueen_trace_new(void){
redqueen_trace_t* self = malloc(sizeof(redqueen_trace_t)); redqueen_trace_t* self = malloc(sizeof(redqueen_trace_t));
@ -13,12 +79,6 @@ redqueen_trace_t* redqueen_trace_new(void){
return self; return self;
} }
void redqueen_trace_reset(redqueen_trace_t* self){
kh_destroy(RQ_TRACE, self->lookup);
self->lookup = kh_init(RQ_TRACE);
self->num_ordered_transitions = 0;
}
void redqueen_trace_free(redqueen_trace_t* self){ void redqueen_trace_free(redqueen_trace_t* self){
kh_destroy(RQ_TRACE, self->lookup); kh_destroy(RQ_TRACE, self->lookup);
free(self->ordered_transitions); free(self->ordered_transitions);
@ -28,6 +88,15 @@ 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_register_transition(redqueen_trace_t* self, disassembler_mode_t mode, uint64_t from, uint64_t to){
khiter_t k; khiter_t k;
int ret; int ret;
uint64_t exit_ip = 0xffffffffffffffff;
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;
#endif
uint128_t key = (((uint128_t)from)<<64) | ((uint128_t)to); uint128_t key = (((uint128_t)from)<<64) | ((uint128_t)to);
k = kh_get(RQ_TRACE, self->lookup, key); k = kh_get(RQ_TRACE, self->lookup, key);
if(k != kh_end(self->lookup)){ if(k != kh_end(self->lookup)){
@ -41,30 +110,74 @@ void redqueen_trace_register_transition(redqueen_trace_t* self, disassembler_mod
} }
} }
void redqueen_trace_write_file(redqueen_trace_t* self, int fd){ static void redqueen_trace_write(void){
#ifdef KAFL_FULL_TRACES
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++){ for(size_t i = 0; i < self->num_ordered_transitions; i++){
khiter_t k; khiter_t k;
uint128_t key = self->ordered_transitions[i]; uint128_t key = self->ordered_transitions[i];
k = kh_get(RQ_TRACE, self->lookup, key); k = kh_get(RQ_TRACE, self->lookup, key);
assert(k != kh_end(self->lookup)); assert(k != kh_end(self->lookup));
dprintf(fd, "%lx,%lx,%lx\n", (uint64_t)(key>>64), (uint64_t)key, kh_value(self->lookup, k) ); 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;
}
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_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);
}
}
#ifdef DEBUG_MAIN #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();
for (uint64_t j = 0; j < 0x5; j++){ for (uint64_t j = 0; j < 0x5; j++){
redqueen_trace_register_transition(rq_obj, 0xBADF, 0xC0FFEE); redqueen_trace_register_transition(rq_obj, 0xBADF, 0xC0FFEE);
redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE); redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE);
for (uint64_t i = 0; i < 0x10000; i++){ for (uint64_t i = 0; i < 0x10000; i++){
redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE); redqueen_trace_register_transition(rq_obj, 0xBADBEEF, 0xC0FFEE);
} }
redqueen_trace_write_file(rq_obj, STDOUT_FILENO); redqueen_trace_write(rq_obj, STDOUT_FILENO);
redqueen_trace_reset(rq_obj); redqueen_trace_reset();
} }
redqueen_trace_free(rq_obj); redqueen_trace_free(rq_obj);

View File

@ -1,3 +1,10 @@
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include "qemu/osdep.h"
#pragma once #pragma once
#include "khash.h" #include "khash.h"
#include <libxdc.h> #include <libxdc.h>
@ -36,8 +43,17 @@ typedef struct redqueen_trace_s{
uint128_t* ordered_transitions; uint128_t* ordered_transitions;
} redqueen_trace_t; } redqueen_trace_t;
/* libxdc outputs no bitmap in trace mode */
void alt_bitmap_reset(void);
void alt_bitmap_init(void* ptr, uint32_t size);
redqueen_trace_t* redqueen_trace_new(void); redqueen_trace_t* redqueen_trace_new(void);
void redqueen_trace_reset(redqueen_trace_t* self);
void redqueen_trace_free(redqueen_trace_t* self); 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_register_transition(redqueen_trace_t* self, disassembler_mode_t mode, uint64_t from, uint64_t to);
void redqueen_trace_write_file(redqueen_trace_t* self, int fd);
void redqueen_trace_init(void);
void redqueen_set_trace_mode(void);
void redqueen_unset_trace_mode(void);
void redqueen_trace_flush(void);
void redqueen_trace_reset(void);

View File

@ -42,19 +42,19 @@ static size_t get_file_size(const char* file){
static char* sharedir_scan(sharedir_t* self, const char* file){ static char* sharedir_scan(sharedir_t* self, const char* file){
char* path = NULL; /*
assert(asprintf(&path, "%s/%s", self->dir, file) != -1); * 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);
char* real_path = realpath(path, NULL); if (file[0] != '/' && !strstr(file, "/../") &&
real_path && file_exits(real_path)) {
free(path);
if(real_path && !strncmp(self->dir, real_path, strlen(self->dir)) && file_exits(real_path)){
return real_path; return real_path;
} }
if(real_path){ free(real_path);
free(real_path);
}
return NULL; return NULL;
} }
@ -115,15 +115,15 @@ static FILE* get_file_ptr(sharedir_t* self, sharedir_file_t* obj){
if(obj == self->last_file_obj_ptr && self->last_file_f){ if(obj == self->last_file_obj_ptr && self->last_file_f){
return self->last_file_f; return self->last_file_f;
} }
else{
if(self->last_file_f){ if(self->last_file_f){
fclose(self->last_file_f); fclose(self->last_file_f);
}
FILE* f = fopen(obj->path, "r");
self->last_file_f = f;
self->last_file_obj_ptr = obj;
return f;
} }
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){ uint64_t sharedir_request_file(sharedir_t* self, const char* file, uint8_t* page_buffer){
@ -167,6 +167,7 @@ uint64_t sharedir_request_file(sharedir_t* self, const char* file, uint8_t* page
} }
} }
else{ else{
fprintf(stderr, "WARNING: No such file in sharedir: %s\n", file);
return 0xFFFFFFFFFFFFFFFFUL; return 0xFFFFFFFFFFFFFFFFUL;
} }
} }

View File

@ -376,6 +376,12 @@ nyx_device_state_t* nyx_device_state_init_from_snapshot(const char* snapshot_fol
return self; return self;
} }
/*
* This is where QemuFile is created for later fast_snapshot creation
* we use fast_qemu_savevm_state() to create a regular snapshot to QEMUFile
* 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* nyx_device_state_init(void){
nyx_device_state_t* self = malloc(sizeof(nyx_device_state_t)); nyx_device_state_t* self = malloc(sizeof(nyx_device_state_t));

View File

@ -283,13 +283,45 @@ static void add_post_fptr(state_reallocation_t* self, void* fptr, uint32_t versi
extern void fast_get_pci_config_device(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_get_pci_irq_state(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){
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);
return size;
}
static const QEMUFileOps fast_loadvm_ops = {
.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)
{
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);
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){ static void add_get(state_reallocation_t* self, void* fptr, void* opaque, size_t size, void* field, QEMUFile* f, const char* name){
if(!self){ if(!self){
return; return;
} }
void (*handler)(void* , size_t, void*) = NULL; void (*handler)(void* , size_t, void*) = NULL;
void* data = NULL; uint8_t* data = NULL;
if(!strcmp(name, "timer")){ if(!strcmp(name, "timer")){
debug_fprintf(stderr, "SKPPING: %ld\n", size*-1); debug_fprintf(stderr, "SKPPING: %ld\n", size*-1);
@ -315,13 +347,21 @@ static void add_get(state_reallocation_t* self, void* fptr, void* opaque, size_t
data = malloc(sizeof(uint8_t)*size); data = malloc(sizeof(uint8_t)*size);
qemu_get_buffer(f, (uint8_t*)data, size); qemu_get_buffer(f, (uint8_t*)data, size);
} }
else if(!strcmp(name, "virtio")){
fprintf(stderr, "WARNING: ATTEMPTING FAST GET for %s\n", name);
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{ else{
fprintf(stderr, "WARNING: NOT IMPLEMENTED FAST GET ROUTINE for %s\n", name); fprintf(stderr, "WARNING: NOT IMPLEMENTED FAST GET ROUTINE for %s\n", name);
abort(); abort();
return; 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; self->get_fptr[self->fast_state_get_fptr_pos] = handler;
self->get_opaque[self->fast_state_get_fptr_pos] = opaque; self->get_opaque[self->fast_state_get_fptr_pos] = opaque;
self->get_size[self->fast_state_get_fptr_pos] = size; self->get_size[self->fast_state_get_fptr_pos] = size;
@ -481,19 +521,21 @@ static inline int get_handler(state_reallocation_t* self, QEMUFile* f, void* cur
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name); add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
} }
else if(!strcmp(field->info->name, "pci config")){ else if(!strcmp(field->info->name, "pci config")){
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size); fprintf(stderr, "type: %s (size: %lx)\n", field->info->name, size);
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name); 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")){ else if(!strcmp(field->info->name, "pci irq state")){
//fprintf(stderr, "type: %s (size: %x)\n", field->info->name, size); fprintf(stderr, "type: %s (size: %lx)\n", field->info->name, size);
add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name); add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
} }
else if(!strcmp(field->info->name, "virtio")){ else if(!strcmp(field->info->name, "virtio")){
fprintf(stderr, "type: %s (size: %lx)\n", field->info->name, size); add_get(self, (void*) field->info->get, curr_elem, size, (void*) field, f, field->info->name);
abort(); /* not yet implemented */ //fprintf(stderr, "[QEMU-PT] %s: WARNING no handler for %s, type %s, size %lx!\n",
// __func__, vmsd_name, field->info->name, size);
} }
else{ else{
fprintf(stderr, "FAIL field->info->name: %s\n", field->info->name); fprintf(stderr, "[QEMU-PT] %s: WARNING no handler for %s, type %s, size %lx!\n",
__func__, vmsd_name, field->info->name, size);
assert(0); assert(0);
} }
@ -918,6 +960,7 @@ state_reallocation_t* state_reallocation_new(QEMUFile *f){
self->tmp_snapshot.enabled = false; self->tmp_snapshot.enabled = false;
self->tmp_snapshot.fast_state_size = 0; self->tmp_snapshot.fast_state_size = 0;
// actually enumerate the devices here
fdl_enumerate_global_states(self, f); 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);

View File

@ -50,6 +50,7 @@ struct QEMUFile_tmp {
struct fast_savevm_opaque_t{ struct fast_savevm_opaque_t{
FILE* f; FILE* f;
uint8_t* buf; uint8_t* buf;
size_t buflen;
uint64_t pos; uint64_t pos;
void* output_buffer; void* output_buffer;
uint32_t* output_buffer_size; uint32_t* output_buffer_size;

View File

@ -45,6 +45,7 @@ void state_init_global(void){
global_state.nyx_fdl = false; global_state.nyx_fdl = false;
global_state.workdir_path = NULL; global_state.workdir_path = NULL;
global_state.worker_id = 0xffff;
global_state.fast_reload_enabled = false; global_state.fast_reload_enabled = false;
global_state.fast_reload_mode = false; global_state.fast_reload_mode = false;
@ -89,6 +90,8 @@ void state_init_global(void){
global_state.in_fuzzing_mode = false; global_state.in_fuzzing_mode = false;
global_state.in_reload_mode = true; global_state.in_reload_mode = true;
global_state.starved = false;
global_state.trace_mode = false;
global_state.shutdown_requested = false; global_state.shutdown_requested = false;
global_state.cow_cache_full = false; global_state.cow_cache_full = false;
@ -233,4 +236,4 @@ void set_payload_pages(uint64_t* payload_pages, uint32_t pages){
void set_workdir_path(char* workdir){ void set_workdir_path(char* workdir){
assert(workdir && !global_state.workdir_path); assert(workdir && !global_state.workdir_path);
assert(asprintf(&global_state.workdir_path, "%s", workdir) != -1); assert(asprintf(&global_state.workdir_path, "%s", workdir) != -1);
} }

View File

@ -49,6 +49,7 @@ typedef struct qemu_nyx_state_s{
bool nyx_fdl; bool nyx_fdl;
char* workdir_path; char* workdir_path;
uint32_t worker_id;
/* FAST VM RELOAD */ /* FAST VM RELOAD */
bool fast_reload_enabled; bool fast_reload_enabled;
@ -131,6 +132,8 @@ typedef struct qemu_nyx_state_s{
bool in_fuzzing_mode; bool in_fuzzing_mode;
bool in_reload_mode; bool in_reload_mode;
bool starved;
bool trace_mode;
bool shutdown_requested; bool shutdown_requested;
bool cow_cache_full; bool cow_cache_full;

View File

@ -277,12 +277,12 @@ void synchronization_lock(void){
//last_timeout = false; //last_timeout = false;
if(unlikely(GET_GLOBAL_STATE()->in_redqueen_reload_mode || GET_GLOBAL_STATE()->redqueen_state->trace_mode)){ if(unlikely(GET_GLOBAL_STATE()->in_redqueen_reload_mode)) {
if(GET_GLOBAL_STATE()->redqueen_state->trace_mode){ fsync_redqueen_files();
write_trace_result(GET_GLOBAL_STATE()->redqueen_state->trace_state); }
redqueen_trace_reset(GET_GLOBAL_STATE()->redqueen_state->trace_state);
} if (unlikely(GET_GLOBAL_STATE()->trace_mode)) {
fsync_all_traces(); redqueen_trace_flush();
} }
interface_send_char(NYX_INTERFACE_PING); interface_send_char(NYX_INTERFACE_PING);
@ -291,7 +291,12 @@ void synchronization_lock(void){
pthread_mutex_unlock(&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);
set_success_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer, 1);
//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;
/* /*
@ -335,6 +340,25 @@ void synchronization_lock_crash_found(void){
in_fuzzing_loop = false; 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);
}
pt_disable(qemu_get_cpu(0), false);
handle_tmp_snapshot_state();
set_asan_auxiliary_result_buffer(GET_GLOBAL_STATE()->auxilary_buffer);
perform_reload();
//synchronization_lock();
in_fuzzing_loop = false;
}
void synchronization_lock_timeout_found(void){ void synchronization_lock_timeout_found(void){
//fprintf(stderr, "<%d>\t%s\n", getpid(), __func__); //fprintf(stderr, "<%d>\t%s\n", getpid(), __func__);

View File

@ -37,6 +37,7 @@ void synchronization_lock_hprintf(void);
void synchronization_lock(void); void synchronization_lock(void);
void synchronization_lock_crash_found(void); void synchronization_lock_crash_found(void);
void synchronization_lock_asan_found(void);
void synchronization_lock_timeout_found(void); void synchronization_lock_timeout_found(void);
void synchronization_lock_shutdown_detected(void); void synchronization_lock_shutdown_detected(void);
void synchronization_cow_full_detected(void); void synchronization_cow_full_detected(void);
@ -45,4 +46,4 @@ void synchronization_enter_fuzzing_loop(CPUState *cpu);
void synchronization_payload_buffer_write_detected(void); void synchronization_payload_buffer_write_detected(void);
void enable_timeout_detector(timeout_detector_t* timeout_detector); void enable_timeout_detector(timeout_detector_t* timeout_detector);
void reset_timeout_detector_timeout(timeout_detector_t* timeout_detector); void reset_timeout_detector_timeout(timeout_detector_t* timeout_detector);

66
nyx/trace_dump.c Normal file
View File

@ -0,0 +1,66 @@
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <assert.h>
#include "state/state.h"
#include "trace_dump.h"
/* dump PT trace as returned from HW */
char *pt_trace_dump_filename;
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)
{
int test_fd;
//fprintf(stderr, "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);
}
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;
if (!pt_dump_enabled)
return;
fd = open(pt_trace_dump_filename, O_APPEND|O_WRONLY, 0644);
//fd = open(pt_trace_dump_filename, O_CREAT|O_TRUNC|O_WRONLY, 0644);
if (fd < 0) {
fprintf(stderr, "Error writing pt_trace_dump to %s: %s\n", pt_trace_dump_filename, strerror(errno));
assert(0);
}
assert(bytes == write(fd, data, bytes));
close(fd);
}

6
nyx/trace_dump.h Normal file
View File

@ -0,0 +1,6 @@
#pragma once
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);