X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=blobdiff_plain;f=palacios%2Fsrc%2Fgears%2Fext_syscall_hijack.c;h=c31bb5991ebc06286907fecfb499d7ea0833637d;hb=c8b23e99efde3aa5a2c26d1b8e9bc7dc914e6113;hp=f68818255cc699e273b41f201316bde320f5f75a;hpb=7229981629c6baa0afb61cc99cfcf6dd029c9c93;p=palacios.git diff --git a/palacios/src/gears/ext_syscall_hijack.c b/palacios/src/gears/ext_syscall_hijack.c index f688182..c31bb59 100644 --- a/palacios/src/gears/ext_syscall_hijack.c +++ b/palacios/src/gears/ext_syscall_hijack.c @@ -62,7 +62,7 @@ static void print_arg (struct guest_info * core, v3_reg_t reg, uint8_t argnum) addr_t hva; int ret = 0; - PrintDebug("\t ARG%d: INT - %ld\n", argnum, (long) reg); + PrintDebug(core->vm_info, core, "\t ARG%d: INT - %ld\n", argnum, (long) reg); if (core->mem_mode == PHYSICAL_MEM) { ret = v3_gpa_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva); @@ -71,27 +71,27 @@ static void print_arg (struct guest_info * core, v3_reg_t reg, uint8_t argnum) ret = v3_gva_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva); } - PrintDebug("\t STR - "); + PrintDebug(core->vm_info, core, "\t STR - "); if (ret == -1) { - PrintDebug("\n"); + PrintDebug(core->vm_info, core, "\n"); return; } uint32_t c = max(MAX_CHARS, 4096 - (hva % 4096)); int i = 0; for (; i < c && *((char*)(hva + i)) != 0; i++) { - PrintDebug("%c", *((char*)(hva + i))); + PrintDebug(core->vm_info, core, "%c", *((char*)(hva + i))); } - PrintDebug("\n"); + PrintDebug(core->vm_info, core, "\n"); } static void print_syscall (uint8_t is64, struct guest_info * core) { if (is64) { - PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name64(core->vm_regs.rax)); + PrintDebug(core->vm_info, core, "Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name64(core->vm_regs.rax)); } else { - PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name32(core->vm_regs.rax)); + PrintDebug(core->vm_info, core, "Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name32(core->vm_regs.rax)); } print_arg(core, core->vm_regs.rbx, 1); @@ -103,7 +103,7 @@ static void print_syscall (uint8_t is64, struct guest_info * core) { int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data) { uint_t syscall_nr = (uint_t) core->vm_regs.rax; - int err = 0, ret = 0; + int err = 0; struct v3_syscall_hook * hook = syscall_hooks[syscall_nr]; @@ -113,15 +113,10 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da core->rip = syscall_info.target_addr; #endif -#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT - PrintDebug("In v3_syscall_handler: syscall_nr - %d\n", syscall_nr); -#endif - - if (hook == NULL) { #ifdef V3_CONFIG_EXT_SYSCALL_PASSTHROUGH if (v3_hook_passthrough_syscall(core, syscall_nr) == -1) { - PrintDebug("Error hooking passthrough syscall\n"); + PrintDebug(core->vm_info, core, "Error hooking passthrough syscall\n"); return -1; } hook = syscall_hooks[syscall_nr]; @@ -138,6 +133,7 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da if (list_empty(&(injects->code_inject_list))) { return 0; } else { + int ret; inject = (struct v3_code_inject_info*) list_first_entry( &(injects->code_inject_list), @@ -145,7 +141,7 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da inject_node); if (inject == NULL) { - PrintError("Problem getting inject from inject list\n"); + PrintError(core->vm_info, core, "Problem getting inject from inject list\n"); return -1; } @@ -155,7 +151,7 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da // do the inject and don't fall over if there's an inject already in // progress if ((ret = v3_handle_guest_inject(core, (void*)inject)) == -1) { - PrintError("Could not run code injection: v3_syscall_handler\n"); + PrintError(core->vm_info, core, "Could not run code injection: v3_syscall_handler\n"); return 0; } else { return ret; @@ -168,7 +164,7 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da err = hook->handler(core, syscall_nr, hook->priv_data); if (err == -1) { - PrintDebug("V3 Syscall Handler: Error in syscall hook\n"); + PrintDebug(core->vm_info, core, "V3 Syscall Handler: Error in syscall hook\n"); return -1; } @@ -184,87 +180,117 @@ int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_da static int v3_handle_lstar_write (struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { syscall_info.target_addr = (uint64_t) ((((uint64_t)src.hi) << 32) | src.lo); - PrintDebug("LSTAR Write: %p\n", (void*)syscall_info.target_addr); - core->ctrl_regs.lstar = syscall_info.target_addr; + PrintDebug(core->vm_info, core, "LSTAR Write: %p\n", (void*)syscall_info.target_addr); + core->msrs.lstar = syscall_info.target_addr; return 0; } // virtualize the lstar static int v3_handle_lstar_read (struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { - PrintDebug("LSTAR Read\n"); + PrintDebug(core->vm_info, core, "LSTAR Read\n"); dst->value = syscall_info.target_addr; return 0; } static int syscall_setup (struct guest_info * core, unsigned int hcall_id, void * priv_data) { - addr_t syscall_stub, syscall_map, ssa; + addr_t syscall_stub, syscall_map_gva, syscall_map_hva, ssa_gva, ssa_hva; syscall_stub = (addr_t)core->vm_regs.rbx; - syscall_map = (addr_t)core->vm_regs.rcx; - ssa = (addr_t)core->vm_regs.rdx; + syscall_map_gva = (addr_t)core->vm_regs.rcx; + ssa_gva = (addr_t)core->vm_regs.rdx; - PrintDebug("made it to syscall setup hypercall\n"); - PrintDebug("\t&syscall_stub (rbx): %p\n\t&syscall_map (rcx): %p\n", (void*)syscall_stub, (void*)syscall_map); - PrintDebug("\t&ssa (rdx): %p\n", (void*)ssa); + PrintDebug(core->vm_info, core, "syscall setup hypercall:\n"); + PrintDebug(core->vm_info, core, "\t&syscall_stub (rbx): %p\n\t&syscall_map (rcx): %p\n", (void*)syscall_stub, (void*)syscall_map_gva); + PrintDebug(core->vm_info, core, "\t&ssa (rdx): %p\n", (void*)ssa_gva); + // the guest vitual address of the asm syscall handling routine syscall_info.syscall_stub = syscall_stub; - syscall_info.syscall_map = (uint8_t*)syscall_map; - syscall_info.ssa = ssa; + + + // now get the hva of the system call map so we can manipulate it in the VMM + if (v3_gva_to_hva(core, get_addr_linear(core, syscall_map_gva, &(core->segments.ds)), &syscall_map_hva) == 1) { + PrintError(core->vm_info, core, "Problem translating gva to hva for syscall map\n"); + return -1; + } + + if (v3_gva_to_hva(core, get_addr_linear(core, ssa_gva, &(core->segments.ds)), &ssa_hva) == 1) { + PrintError(core->vm_info, core, "Problem translating gva to hva for syscall map\n"); + return -1; + } + + PrintDebug(core->vm_info, core, "\t&syscall_map (hva): %p\n", (void*) syscall_map_hva); + PrintDebug(core->vm_info, core, "\t&ssa (hva): %p\n", (void*) ssa_hva); + + syscall_info.syscall_map = (uint8_t*)syscall_map_hva; + syscall_info.ssa = ssa_hva; /* return the original syscall entry point */ core->vm_regs.rax = syscall_info.target_addr; /* redirect syscalls henceforth */ - core->ctrl_regs.lstar = syscall_stub; + core->msrs.lstar = syscall_stub; return 0; } static int syscall_cleanup (struct guest_info * core, unsigned int hcall_id, void * priv_data) { - core->ctrl_regs.lstar = syscall_info.target_addr; - PrintDebug("original syscall entry point restored\n"); + core->msrs.lstar = syscall_info.target_addr; + PrintDebug(core->vm_info, core, "original syscall entry point restored\n"); return 0; } static int sel_syscall_handle (struct guest_info * core, unsigned int hcall_id, void * priv_data) { - int ret; - addr_t hva; struct v3_gprs regs; - PrintDebug("caught a selectively exited syscall!\n"); - ret = v3_gva_to_hva(core, get_addr_linear(core, syscall_info.ssa, &(core->segments.ds)), &hva); - if (ret == -1) { - PrintError("Problem translating state save area address in sel_syscall_handle\n"); - return -1; - } + PrintDebug(core->vm_info, core, "caught a selectively exited syscall\n"); /* setup registers for handler routines. They should be in the same state * as when the system call was originally invoked */ memcpy((void*)®s, (void*)&core->vm_regs, sizeof(struct v3_gprs)); - memcpy((void*)&core->vm_regs, (void*)hva, sizeof(struct v3_gprs)); + memcpy((void*)&core->vm_regs, (void*)syscall_info.ssa, sizeof(struct v3_gprs)); - v3_print_guest_state(core); - - // TODO: call syscall-independent handler + //v3_print_guest_state(core); + v3_syscall_handler(core, 0, NULL); - memcpy((void*)hva, (void*)&core->vm_regs, sizeof(struct v3_gprs)); + memcpy((void*)syscall_info.ssa, (void*)&core->vm_regs, sizeof(struct v3_gprs)); memcpy((void*)&core->vm_regs, (void*)®s,sizeof(struct v3_gprs)); return 0; } +// TODO: make these three functions guest-dependent +int v3_syscall_on (void * ginfo, uint8_t syscall_nr) { + PrintDebug(VM_NONE, VCORE_NONE, "Enabling exiting for syscall #%d\n", syscall_nr); + syscall_info.syscall_map[syscall_nr] = 1; + return 0; +} + + +int v3_syscall_off (void * ginfo, uint8_t syscall_nr) { + PrintDebug(VM_NONE, VCORE_NONE, "Disabling exiting for syscall #%d\n", syscall_nr); + syscall_info.syscall_map[syscall_nr] = 0; + return 0; +} + + +int v3_syscall_stat (void * ginfo, uint8_t syscall_nr) { + return syscall_info.syscall_map[syscall_nr]; +} + #endif static int init_syscall_hijack (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { + #ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT - v3_register_hypercall(vm, 0x5CA11, sel_syscall_handle, NULL); - v3_register_hypercall(vm, 0x5CA12, syscall_setup, NULL); - v3_register_hypercall(vm, 0x5CA13, syscall_cleanup, NULL); + v3_register_hypercall(vm, SYSCALL_HANDLE_HCALL, sel_syscall_handle, NULL); + v3_register_hypercall(vm, SYSCALL_SETUP_HCALL, syscall_setup, NULL); + v3_register_hypercall(vm, SYSCALL_CLEANUP_HCALL, syscall_cleanup, NULL); #endif + return 0; } @@ -272,25 +298,25 @@ static int init_syscall_hijack (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, voi #ifdef V3_CONFIG_EXT_SYSCALL_INSTR static int v3_handle_lstar_write (struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { - PrintDebug("KCH: LSTAR Write\n"); - //PrintDebug("\tvalue: 0x%x%x\n", src.hi, src.lo); + PrintDebug(core->vm_info, core, "KCH: LSTAR Write\n"); + //PrintDebug(core->vm_info, core, "\tvalue: 0x%x%x\n", src.hi, src.lo); syscall_info.target_addr = (uint64_t) ((((uint64_t)src.hi) << 32) | src.lo); // Set LSTAR value seen by hardware while the guest is running - PrintDebug("replacing with %lx\n", SYSCALL_MAGIC_ADDR); - core->ctrl_regs.lstar = SYSCALL_MAGIC_ADDR; + PrintDebug(core->vm_info, core, "replacing with %lx\n", SYSCALL_MAGIC_ADDR); + core->msrs.lstar = SYSCALL_MAGIC_ADDR; return 0; } static int v3_handle_lstar_read (struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { - PrintDebug("KCH: LSTAR Read\n"); + PrintDebug(core->vm_info, core, "KCH: LSTAR Read\n"); dst->value = syscall_info.target_addr; return 0; } #endif -static int init_syscall_hijack_core (struct guest_info * core, void * priv_data) { +static int init_syscall_hijack_core (struct guest_info * core, void * priv_data, void ** core_data) { #ifdef V3_CONFIG_EXT_SW_INTERRUPTS v3_hook_swintr(core, SYSCALL_INT_VECTOR, v3_syscall_handler, NULL); @@ -313,8 +339,8 @@ static int deinit_syscall_hijack (struct v3_vm_info * vm, void * priv_data) { static struct v3_extension_impl syscall_impl = { .name = "syscall_intercept", - .init = init_syscall_hijack, - .deinit = deinit_syscall_hijack, + .vm_init = init_syscall_hijack, + .vm_deinit = deinit_syscall_hijack, .core_init = init_syscall_hijack_core, .core_deinit = NULL, .on_entry = NULL, @@ -338,11 +364,12 @@ int v3_hook_syscall (struct guest_info * core, if (hook == NULL) { + PrintError(core->vm_info, core, "Cannot allocate for syscall hook\n"); return -1; } if (get_syscall_hook(core, syscall_nr) != NULL) { - PrintError("System Call #%d already hooked\n", syscall_nr); + PrintError(core->vm_info, core, "System Call #%d already hooked\n", syscall_nr); return -1; } @@ -351,7 +378,7 @@ int v3_hook_syscall (struct guest_info * core, syscall_hooks[syscall_nr] = hook; - PrintDebug("Hooked Syscall #%d\n", syscall_nr); + PrintDebug(core->vm_info, core, "Hooked Syscall #%d\n", syscall_nr); return 0; } @@ -368,10 +395,10 @@ int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr) { int rc = v3_hook_syscall(core, syscall_nr, passthrough_syscall_handler, NULL); if (rc) { - PrintError("failed to hook syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core); + PrintError(core->vm_info, core, "failed to hook syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core); return -1; } else { - PrintDebug("hooked syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core); + PrintDebug(core->vm_info, core, "hooked syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core); return 0; }