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
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
#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;
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);
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;
SMSW,
CLTS,
INVLPG,
+ INT, // KCH: adding software interrupts
MOV_CR2,
MOV_2CR,
return -1;
}
+ case INT: // KCH
case MOV_DR2:
case MOV_2DR:
case MOV_CR2:
case 0xf4:
return HLT;
-
+
+ // KCH
+ case 0xcd:
+ return INT;
case 0xf6: {
struct modrm_byte * modrm = (struct modrm_byte *)&(instr[1]);
case SETO: return "SETO";
case STOS_8: return "STOS_8";
case STOS: return "STOS";
+ case INT: return "INT"; // KCH
case INVALID_INSTR:
default:
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;
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 {
obj-$(CONFIG_SYMCALL) += vmm_symcall.o
obj-$(CONFIG_SYMMOD) += vmm_symmod.o
+obj-$(CONFIG_SYSCALL_HIJACK) += vmm_syscall_hijack.o
obj-y += mmu/
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;
&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");
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;
#include <palacios/vmm_hypercall.h>
#include <palacios/vmm_cpuid.h>
#include <palacios/vmm_direct_paging.h>
+#include <palacios/vmm_syscall_hijack.h>
#ifndef CONFIG_DEBUG_SVM
#undef PrintDebug
}
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
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
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";
-
struct intr_controller {
struct intr_ctrl_ops * ctrl_ops;
};
+
+
void v3_init_intr_controllers(struct guest_info * info) {
struct v3_intr_core_state * intr_state = &(info->intr_core_state);
}
}
+
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));
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;
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));
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;
}
-
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];
}
-
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);
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);
}
-
-
-
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);
}
-
-
-
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;
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;
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);
}
+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;
-
}
}
}
+ // 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;
*/
-
-
-
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);
case MOV_2CR:
return V3_OP_MOV2CR;
+ // KCH: for syscall interposition
+ case INT:
+ return V3_OP_INT;
+
case MOV_MEM2_8:
case MOV_MEM2:
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:
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)) {
case XED_IFORM_INVLPG_MEMb:
return V3_OP_INVLPG;
+ // KCH
+ case XED_IFORM_INT_IMM:
+ return V3_OP_INT;
+
/* Data Instructions */