From: Kyle Hale Date: Fri, 29 Apr 2011 22:06:17 +0000 (-0500) Subject: additions for syscall hijacking X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=603e4c1a451138080ded3d4e3cd3b8716741db89;p=palacios.releases.git additions for syscall hijacking --- diff --git a/Kconfig b/Kconfig index 7a48606..d312c0b 100644 --- a/Kconfig +++ b/Kconfig @@ -178,6 +178,24 @@ config INSPECTOR help Enable inspection framework for vm internal state +config SYSCALL_HIJACK + bool "Enable System Call Interposition" + depends on EXPERIMENTAL + default n + help + Enable the VMM to hijack system calls executed by the guest. + If enabled, the VMM will intercept software interrupt (INT) instructions, + Fast-System Call instructions (SYSENTER, SYSCALL), and the LIDT instruction + +config HIJACK_SYSCALL_MSR + bool "Intercept Syscall-related MSR reads & writes" + depends on SYSCALL_HIJACK + default n + help + Allow the VMM to intercept reads and writes to MSRs + related to SYSCALL and SYSENTER instructions. Specifically, + it will intercept R/W to STAR, CSTAR, and LSTAR. + endmenu @@ -408,6 +426,14 @@ config DEBUG_VNET help Enable the Vnet debug in Palacios +config DEBUG_SYSCALL_HIJACK + bool "Enable Syscall hijack Debug in Palacios" + default n + depends on EXPERIMENTAL && SYSCALL_HIJACK && DEBUG_ON + help + Enable Debugging printouts for syscall hijacking + code in Palacios + endmenu diff --git a/palacios/include/palacios/vmm_ctrl_regs.h b/palacios/include/palacios/vmm_ctrl_regs.h index e072a04..3cc1932 100644 --- a/palacios/include/palacios/vmm_ctrl_regs.h +++ b/palacios/include/palacios/vmm_ctrl_regs.h @@ -27,6 +27,15 @@ #define EFER_MSR 0xc0000080 +// KCH: for system-call interposition +#define STAR_MSR 0xc0000081 +#define LSTAR_MSR 0xc0000082 +#define CSTAR_MSR 0xc0000083 +#define SF_MASK_MSR 0xc0000084 +#define FS_BASE_MSR 0xc0000100 +#define GS_BASE_MSR 0xc0000101 +#define KERN_GS_BASE_MSR 0xc0000102 + struct cr0_real { uint_t pe : 1; uint_t mp : 1; @@ -215,6 +224,13 @@ int v3_handle_cr4_read(struct guest_info * info); int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data); int v3_handle_efer_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data); +int v3_handle_star_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data); +int v3_handle_star_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data); +int v3_handle_lstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data); +int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data); +int v3_handle_cstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data); +int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data); + int v3_handle_vm_cr_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data); int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data); diff --git a/palacios/include/palacios/vmm_decoder.h b/palacios/include/palacios/vmm_decoder.h index aba2d40..82253be 100644 --- a/palacios/include/palacios/vmm_decoder.h +++ b/palacios/include/palacios/vmm_decoder.h @@ -34,7 +34,7 @@ typedef enum { V3_INVALID_OP, V3_OP_SETB, V3_OP_SETBE, V3_OP_SETL, V3_OP_SETLE, V3_OP_SETNB, V3_OP_SETNBE, V3_OP_SETNL, V3_OP_SETNLE, V3_OP_SETNO, V3_OP_SETNP, V3_OP_SETNS, V3_OP_SETNZ, V3_OP_SETO, V3_OP_SETP, V3_OP_SETS, - V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX } v3_op_type_t; + V3_OP_SETZ, V3_OP_MOVS, V3_OP_STOS, V3_OP_MOVZX, V3_OP_MOVSX, V3_OP_INT } v3_op_type_t; typedef enum {INVALID_OPERAND, REG_OPERAND, MEM_OPERAND, IMM_OPERAND} v3_operand_type_t; diff --git a/palacios/include/palacios/vmm_instr_decoder.h b/palacios/include/palacios/vmm_instr_decoder.h index 4341910..7c48244 100644 --- a/palacios/include/palacios/vmm_instr_decoder.h +++ b/palacios/include/palacios/vmm_instr_decoder.h @@ -29,6 +29,7 @@ typedef enum { SMSW, CLTS, INVLPG, + INT, // KCH: adding software interrupts MOV_CR2, MOV_2CR, @@ -309,6 +310,7 @@ static int get_operand_width(struct guest_info * info, struct x86_instr * instr, return -1; } + case INT: // KCH case MOV_DR2: case MOV_2DR: case MOV_CR2: @@ -1334,7 +1336,10 @@ static op_form_t op_code_to_form(uint8_t * instr, int * length) { case 0xf4: return HLT; - + + // KCH + case 0xcd: + return INT; case 0xf6: { struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]); @@ -1497,6 +1502,7 @@ static char * op_form_to_str(op_form_t form) { case SETO: return "SETO"; case STOS_8: return "STOS_8"; case STOS: return "STOS"; + case INT: return "INT"; // KCH case INVALID_INSTR: default: diff --git a/palacios/include/palacios/vmm_intr.h b/palacios/include/palacios/vmm_intr.h index 626b98b..8a63383 100644 --- a/palacios/include/palacios/vmm_intr.h +++ b/palacios/include/palacios/vmm_intr.h @@ -58,6 +58,10 @@ struct v3_intr_core_state { uint_t irq_started; uint_t irq_vector; + // KCH + uint_t sw_intr_pending; + uint_t sw_intr_vector; + uint8_t virq_map[MAX_IRQ / 8]; v3_lock_t irq_lock; @@ -79,6 +83,7 @@ int v3_lower_virq(struct guest_info * info, int irq); int v3_raise_irq(struct v3_vm_info * vm, int irq); int v3_lower_irq(struct v3_vm_info * vm, int irq); +int v3_signal_sw_intr(struct guest_info * core, int vec); struct intr_ctrl_ops { diff --git a/palacios/src/palacios/Makefile b/palacios/src/palacios/Makefile index 5747261..c505b60 100644 --- a/palacios/src/palacios/Makefile +++ b/palacios/src/palacios/Makefile @@ -76,5 +76,6 @@ obj-$(CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o obj-$(CONFIG_SYMCALL) += vmm_symcall.o obj-$(CONFIG_SYMMOD) += vmm_symmod.o +obj-$(CONFIG_SYSCALL_HIJACK) += vmm_syscall_hijack.o obj-y += mmu/ diff --git a/palacios/src/palacios/svm.c b/palacios/src/palacios/svm.c index bb65a6f..59af9a7 100644 --- a/palacios/src/palacios/svm.c +++ b/palacios/src/palacios/svm.c @@ -135,6 +135,12 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { ctrl_area->instrs.PAUSE = 1; ctrl_area->instrs.shutdown_evts = 1; + /* KCH: intercept writes to IDTR and SW Interrupts (INT) */ +#ifdef CONFIG_SYSCALL_HIJACK + ctrl_area->instrs.WR_IDTR = 0; + ctrl_area->instrs.INTn = 1; +#endif + /* DEBUG FOR RETURN CODE */ ctrl_area->exit_code = 1; @@ -223,6 +229,22 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) { &v3_handle_efer_write, core); +#ifdef CONFIG_HIJACK_MSR + /* KCH: for syscall interposition */ + v3_hook_msr(core->vm_info, STAR_MSR, + &v3_handle_star_read, + &v3_handle_star_write, + core); + v3_hook_msr(core->vm_info, LSTAR_MSR, + &v3_handle_lstar_read, + &v3_handle_lstar_write, + core); + v3_hook_msr(core->vm_info, CSTAR_MSR, + &v3_handle_cstar_read, + &v3_handle_cstar_write, + core); +#endif + if (core->shdw_pg_mode == SHADOW_PAGING) { PrintDebug("Creating initial shadow page table\n"); @@ -422,9 +444,18 @@ static int update_irq_entry_state(struct guest_info * info) { case V3_NMI: guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI; break; - case V3_SOFTWARE_INTR: - guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR; - break; + case V3_SOFTWARE_INTR: { + PrintDebug("KCH: Caught an injected software interrupt\n"); + PrintDebug("\ttype: %d, vector: %d\n", SVM_INJECTION_SOFT_INTR, info->intr_core_state.sw_intr_vector); + guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR; + guest_ctrl->EVENTINJ.vector = info->intr_core_state.sw_intr_vector; + guest_ctrl->EVENTINJ.valid = 1; + + // clear out stuff? + info->intr_core_state.sw_intr_pending = 0; + info->intr_core_state.sw_intr_vector = 0; + break; + } case V3_VIRTUAL_IRQ: guest_ctrl->EVENTINJ.type = SVM_INJECTION_IRQ; break; diff --git a/palacios/src/palacios/svm_handler.c b/palacios/src/palacios/svm_handler.c index 7016197..62fe695 100644 --- a/palacios/src/palacios/svm_handler.c +++ b/palacios/src/palacios/svm_handler.c @@ -33,6 +33,7 @@ #include #include #include +#include #ifndef CONFIG_DEBUG_SVM #undef PrintDebug @@ -193,6 +194,26 @@ int v3_handle_svm_exit(struct guest_info * info, addr_t exit_code, addr_t exit_i } break; } +#ifdef CONFIG_SYSCALL_HIJACK + case VMEXIT_IDTR_WRITE: // KCH: syscall interposition +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("IDTR Write\n"); +#endif + if (v3_handle_idtr_write(info) == -1) { + PrintError("Error handling IDTR write\n"); + return -1; + } + break; + case VMEXIT_SWINT: +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("Intercepting SW Interrupt\n"); +#endif + if (v3_handle_swint(info) == -1) { + PrintError("Error handling software interrupt\n"); + return -1; + } + break; +#endif case VMEXIT_INVLPG: if (info->shdw_pg_mode == SHADOW_PAGING) { #ifdef CONFIG_DEBUG_SHADOW_PAGING diff --git a/palacios/src/palacios/vmm_ctrl_regs.c b/palacios/src/palacios/vmm_ctrl_regs.c index b27df4b..cc1fac6 100644 --- a/palacios/src/palacios/vmm_ctrl_regs.c +++ b/palacios/src/palacios/vmm_ctrl_regs.c @@ -582,6 +582,63 @@ int v3_handle_efer_write(struct guest_info * core, uint_t msr, struct v3_msr src return 0; } + +/* KCH: all of the star handlers are for syscall interposition */ +int v3_handle_star_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { + +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("STAR Read\n"); +#endif + + return 0; +} + + +int v3_handle_star_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("STAR Write\n"); +#endif + return 0; +} + + +int v3_handle_lstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { + +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("LSTAR Read\n"); +#endif + return 0; +} + + +int v3_handle_lstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("LSTAR Write\n"); +#endif + return 0; +} + + +int v3_handle_cstar_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { + +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("CSTAR Read\n"); +#endif + return 0; +} + + +int v3_handle_cstar_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + +#ifdef CONFIG_DEBUG_SYSCALL_HIJACK + PrintDebug("CSTAR Write\n"); +#endif + return 0; +} + + int v3_handle_vm_cr_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { /* tell the guest that the BIOS disabled SVM, that way it doesn't get * confused by the fact that CPUID reports SVM as available but it still diff --git a/palacios/src/palacios/vmm_decoder.c b/palacios/src/palacios/vmm_decoder.c index ca52e8a..67e96ae 100644 --- a/palacios/src/palacios/vmm_decoder.c +++ b/palacios/src/palacios/vmm_decoder.c @@ -146,6 +146,7 @@ static char * op_type_to_str(v3_op_type_t type) { case V3_OP_STOS: return "V3_OP_STOS"; case V3_OP_MOVZX: return "V3_OP_MOVZX"; case V3_OP_MOVSX: return "V3_OP_MOVSX"; + case V3_OP_INT: return "V3_OP_INT"; // KCH case V3_INVALID_OP: default: return "V3_INVALID_OP"; diff --git a/palacios/src/palacios/vmm_intr.c b/palacios/src/palacios/vmm_intr.c index c9c1800..0c0a677 100644 --- a/palacios/src/palacios/vmm_intr.c +++ b/palacios/src/palacios/vmm_intr.c @@ -33,7 +33,6 @@ - struct intr_controller { struct intr_ctrl_ops * ctrl_ops; @@ -50,6 +49,8 @@ struct intr_router { }; + + void v3_init_intr_controllers(struct guest_info * info) { struct v3_intr_core_state * intr_state = &(info->intr_core_state); @@ -95,6 +96,7 @@ void v3_deinit_intr_routers(struct v3_vm_info * vm) { } } + void * v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * priv_data) { struct intr_controller * ctrlr = (struct intr_controller *)V3_Malloc(sizeof(struct intr_controller)); @@ -106,6 +108,7 @@ void * v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_op return (void *)ctrlr; } + void v3_remove_intr_controller(struct guest_info * core, void * handle) { struct v3_intr_core_state * intr_state = &(core->intr_core_state); struct intr_controller * ctrlr = handle; @@ -128,6 +131,7 @@ void v3_remove_intr_controller(struct guest_info * core, void * handle) { V3_Free(ctrlr); } + void * v3_register_intr_router(struct v3_vm_info * vm, struct intr_router_ops * ops, void * priv_data) { struct intr_router * router = (struct intr_router *)V3_Malloc(sizeof(struct intr_router)); @@ -139,6 +143,7 @@ void * v3_register_intr_router(struct v3_vm_info * vm, struct intr_router_ops * return (void *)router; } + void v3_remove_intr_router(struct v3_vm_info * vm, void * handle) { struct intr_router * router = handle; struct intr_router * tmp = NULL; @@ -161,7 +166,6 @@ void v3_remove_intr_router(struct v3_vm_info * vm, void * handle) { } - static inline struct v3_irq_hook * get_irq_hook(struct v3_vm_info * vm, uint_t irq) { V3_ASSERT(irq <= 256); return vm->intr_routers.hooks[irq]; @@ -199,7 +203,6 @@ int v3_hook_irq(struct v3_vm_info * vm, } - static int passthrough_irq_handler(struct v3_vm_info * vm, struct v3_interrupt * intr, void * priv_data) { PrintDebug("[passthrough_irq_handler] raise_irq=%d (guest=0x%p)\n", intr->irq, (void *)vm); @@ -207,6 +210,7 @@ static int passthrough_irq_handler(struct v3_vm_info * vm, struct v3_interrupt * return v3_raise_irq(vm, intr->irq); } + int v3_hook_passthrough_irq(struct v3_vm_info * vm, uint_t irq) { int rc = v3_hook_irq(vm, irq, passthrough_irq_handler, NULL); @@ -220,9 +224,6 @@ int v3_hook_passthrough_irq(struct v3_vm_info * vm, uint_t irq) { } - - - int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr) { PrintDebug("v3_deliver_irq: irq=%d state=0x%p, \n", intr->irq, (void *)intr); @@ -237,9 +238,6 @@ int v3_deliver_irq(struct v3_vm_info * vm, struct v3_interrupt * intr) { } - - - int v3_raise_virq(struct guest_info * info, int irq) { struct v3_intr_core_state * intr_state = &(info->intr_core_state); int major = irq / 8; @@ -250,6 +248,7 @@ int v3_raise_virq(struct guest_info * info, int irq) { return 0; } + int v3_lower_virq(struct guest_info * info, int irq) { struct v3_intr_core_state * intr_state = &(info->intr_core_state); int major = irq / 8; @@ -277,6 +276,7 @@ int v3_lower_irq(struct v3_vm_info * vm, int irq) { return 0; } + int v3_raise_irq(struct v3_vm_info * vm, int irq) { struct intr_router * router = NULL; struct v3_intr_routers * routers = &(vm->intr_routers); @@ -294,11 +294,22 @@ int v3_raise_irq(struct v3_vm_info * vm, int irq) { } +int v3_signal_sw_intr(struct guest_info * core, int vec) { + struct v3_intr_core_state * intr_state = &(core->intr_core_state); + + PrintDebug("KCH: Signalling a software interrupt in vmm_intr.c\n"); + PrintDebug("\tINT vector: %d\n", vec); + + intr_state->sw_intr_pending = 1; + intr_state->sw_intr_vector = vec; + return 0; +} + + void v3_clear_pending_intr(struct guest_info * core) { struct v3_intr_core_state * intr_state = &(core->intr_core_state); intr_state->irq_pending = 0; - } @@ -328,6 +339,12 @@ v3_intr_type_t v3_intr_pending(struct guest_info * info) { } } + // KCH: not sure about this + if (intr_state->sw_intr_pending == 1) { + ret = V3_SOFTWARE_INTR; + } + + v3_unlock_irqrestore(intr_state->irq_lock, irq_state); return ret; @@ -402,9 +419,6 @@ intr_type_t v3_get_intr_type(struct guest_info * info) { */ - - - int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t type) { struct v3_intr_core_state * intr_state = &(info->intr_core_state); diff --git a/palacios/src/palacios/vmm_v3dec.c b/palacios/src/palacios/vmm_v3dec.c index 4fa6e04..50bba30 100644 --- a/palacios/src/palacios/vmm_v3dec.c +++ b/palacios/src/palacios/vmm_v3dec.c @@ -487,6 +487,10 @@ static v3_op_type_t op_form_to_type(op_form_t form) { case MOV_2CR: return V3_OP_MOV2CR; + // KCH: for syscall interposition + case INT: + return V3_OP_INT; + case MOV_MEM2_8: case MOV_MEM2: diff --git a/palacios/src/palacios/vmm_xed.c b/palacios/src/palacios/vmm_xed.c index bb1e856..9f3d7ac 100644 --- a/palacios/src/palacios/vmm_xed.c +++ b/palacios/src/palacios/vmm_xed.c @@ -443,6 +443,19 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins case XED_OPERAND_IMM0: + { + v3_op->size = xed_decoded_inst_get_immediate_width(&xed_instr); + + if (v3_op->size > 4) { + PrintError("Unhandled 64 bit immediates\n"); + return -1; + } + v3_op->operand = xed_decoded_inst_get_unsigned_immediate(&xed_instr); + + v3_op->type = IMM_OPERAND; + + } + break; case XED_OPERAND_AGEN: case XED_OPERAND_PTR: case XED_OPERAND_RELBR: @@ -581,7 +594,7 @@ int v3_decode(struct guest_info * info, addr_t instr_ptr, struct x86_instr * ins instr->third_operand.type = REG_OPERAND; - PrintDebug("Operand 3 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op))); + PrintDebug("Operand 2 mode: %s\n", xed_operand_action_enum_t2str(xed_operand_rw(op))); if (xed_operand_read(op)) { @@ -1270,6 +1283,10 @@ static v3_op_type_t get_opcode(xed_iform_enum_t iform) { case XED_IFORM_INVLPG_MEMb: return V3_OP_INVLPG; + // KCH + case XED_IFORM_INT_IMM: + return V3_OP_INT; + /* Data Instructions */