The purpose of this option is to allow features under development to be committed to the mainline
to more easily track changes and provide access to multiple developers
- config VNET
- depends on EXPERIMENTAL
- bool "Enable Vnet in Palacios"
- default n
- help
- Enable the Vnet in Palacios
-
+
+config INSPECTOR
+ bool "Enable VM inspection"
+ depends on EXPERIMENTAL
+ default n
+ help
+ Enable inspection framework for vm internal state
+
- config SW_INTERRUPTS
- bool "Enable interception and hooking of software interrupts"
- depends on EXPERIMENTAL
- default n
- help
- This feature will cause the VMM to intercept the execution
- of software interrupts (i.e. the INTn instruction) and enable
- any INT vector to be hooked
-
- config SWINTR_PASSTHROUGH
- bool "Hook all unhandled sofware interrupts for passthrough"
- depends on SW_INTERRUPTS
- default n
- help
- If enabled, this will cause all software interrupts
- (INT instruction vectors) to be hooked for passthrough.
- May reduce performance but useful for debugging.
-
- config SYSCALL_HIJACK
- bool "Enable System Call Hijacking"
- depends on SW_INTERRUPTS
- default n
- help
- Enable the VMM to hijack system calls executed by the guest.
- If enabled, the VMM will hook execution of INT 80
- (support for Fast-System Calls coming soon)
-
- config SYSCALL_PASSTHROUGH
- bool "Hook all unhandled system calls for passthrough"
- depends on SYSCALL_HIJACK
- default n
- help
- If enabled, this option will cause all system calls
- that are not explicitly hooked to be hooked for
- passthrough. This is useful for debugging.
-
- 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
This turns on debugging for the device manager
- config DEBUG_VNET
- depends on EXPERIMENTAL && VNET
- bool "Enable Vnet Debug in Palacios"
- default n
- help
- Enable the Vnet debug in Palacios
+
+config DEBUG_SYSCALL_HIJACK
+ bool "Enable Syscall Hijack Debug in Palacios"
+ default n
+ depends on DEBUG_ON && SYSCALL_HIJACK
+ help
+ Enable Debugging printouts for syscall hijacking
+ code in Palacios
+
+
endmenu
struct v3_sym_core_state;
#endif
- #ifdef CONFIG_SYSCALL_HIJACK
++#ifdef V3_CONFIG_SYSCALL_HIJACK
+#include <palacios/vmm_syscall_hijack.h>
+#include <palacios/vmm_execve_hook.h>
+#endif
+
#include <palacios/vmm_config.h>
/* This structure is how we get exceptions for the guest */
struct v3_excp_state excp_state;
- #ifdef CONFIG_SYSCALL_HIJACK
++#ifdef V3_CONFIG_SYSCALL_HIJACK
+ struct v3_syscall_hook_map sc_hook_map;
+ struct v3_execve_varchunk var_dump;
+ struct v3_exec_hooks exec_hooks;
+#endif
+
v3_cpu_mode_t cpu_mode;
v3_mem_mode_t mem_mode;
#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
++#define STAR_MSR 0xc0000081 /* Legacy mode SYSCALL target */
++#define LSTAR_MSR 0xc0000082 /* Long mode SYSCALL target */
++#define CSTAR_MSR 0xc0000083 /* compat mode SYSCALL target */
++#define SF_MASK_MSR 0xc0000084 /* EFLAGS mask for syscall */
++#define FS_BASE_MSR 0xc0000100 /* 64-bit FS base */
++#define GS_BASE_MSR 0xc0000101 /* 64-bit GS base */
++#define KERN_GS_BASE_MSR 0xc0000102 /* swapGS GS shadow */
++
++/* Intel specific */
++#define IA32_SYSENTER_CS_MSR 0x00000174
++#define IA32_SYSENTER_ESP_MSR 0x00000175
++#define IA32_SYSENTER_EIP_MSR 0x00000176
+
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_seeip_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data);
++int v3_handle_seeip_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);
help
Provides the inspection extension
++config SW_INTERRUPTS
++ bool "Enable interception and hooking of software interrupts"
++ default n
++ help
++ This feature will cause the VMM to intercept the execution
++ of software interrupts (i.e. the INTn instruction) and enable
++ any INT vector to be hooked
++
++config SWINTR_PASSTHROUGH
++ bool "Hook all unhandled sofware interrupts for passthrough"
++ depends on SW_INTERRUPTS
++ default n
++ help
++ If enabled, this will cause all software interrupts
++ (INT instruction vectors) to be hooked for passthrough.
++ May reduce performance but useful for debugging.
++
++config SYSCALL_HIJACK
++ bool "Enable System Call Hijacking"
++ depends on SW_INTERRUPTS
++ default n
++ help
++ Enable the VMM to hijack system calls executed by the guest.
++ If enabled, the VMM will hook execution of INT 80
++ (support for Fast-System Calls coming soon)
++
++config SYSCALL_PASSTHROUGH
++ bool "Hook all unhandled system calls for passthrough"
++ depends on SYSCALL_HIJACK
++ default n
++ help
++ If enabled, this option will cause all system calls
++ that are not explicitly hooked to be hooked for
++ passthrough. This is useful for debugging.
++
++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
obj-y += null.o
- obj-$(CONFIG_EXT_MTRRS) += ext_mtrr.o
- obj-$(CONFIG_EXT_VTSC) += ext_vtsc.o
- obj-$(CONFIG_EXT_VTIME) += ext_vtime.o
- obj-$(CONFIG_EXT_INSPECTOR) += ext_inspector.o
+ obj-$(V3_CONFIG_EXT_MTRRS) += ext_mtrr.o
+ obj-$(V3_CONFIG_EXT_VTSC) += ext_vtsc.o
+ obj-$(V3_CONFIG_EXT_VTIME) += ext_vtime.o
+ obj-$(V3_CONFIG_EXT_INSPECTOR) += ext_inspector.o
++
++obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_syscall_hijack.o
++obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_linux_syscall_map.o
++obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_mpi_accel.o
++obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_process_environment.o
++obj-$(V3_CONFIG_SYSCALL_HIJACK) += vmm_execve_hook.o
- obj-$(CONFIG_INSTRUMENT_VMM) += vmm_instrument.o
- obj-$(CONFIG_TELEMETRY) += vmm_telemetry.o
+ obj-$(V3_CONFIG_TELEMETRY) += vmm_telemetry.o
- obj-$(CONFIG_VNET) += vmm_vnet_core.o
-
-
- 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-$(CONFIG_SYSCALL_HIJACK) += vmm_linux_syscall_map.o
- obj-$(CONFIG_SYSCALL_HIJACK) += vmm_mpi_accel.o
- obj-$(CONFIG_SYSCALL_HIJACK) += vmm_process_environment.o
- obj-$(CONFIG_SYSCALL_HIJACK) += vmm_execve_hook.o
+ obj-$(V3_CONFIG_SYMBIOTIC) += vmm_symbiotic.o vmm_symspy.o
+ obj-$(V3_CONFIG_SYMCALL) += vmm_symcall.o
+ obj-$(V3_CONFIG_SYMMOD) += vmm_symmod.o
-
obj-y += mmu/
ctrl_area->instrs.PAUSE = 1;
ctrl_area->instrs.shutdown_evts = 1;
+ /* KCH: intercept SW Interrupts (INT instr) */
- #ifdef CONFIG_SW_INTERRUPTS
++#ifdef V3_CONFIG_SW_INTERRUPTS
+ 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 and SYSENTER interception */
++#ifdef V3_CONFIG_HIJACK_SYSCALL_MSR
++ /* KCH: we're not hooking these to TRAP them,
++ instead, we're going to catch the target EIP.
++ Hopefully this EIP is the entry point in the ELF located in the
++ vsyscall page. We can inject checks into the code segment such that
++ we don't have to exit on uninteresting system calls. This should
++ give us much better performance than INT 80, and should even obviate
++ the need to deal with software interrupts at all */
+ 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);
++
++ /* KCH: this probably isn't necessary, as
++ SYSENTER is only used in legacy mode. In fact,
++ in long mode it results in an illegal instruction
++ exception */
++ v3_hook_msr(core->vm_info, IA32_SYSENTER_EIP_MSR,
++ &v3_handle_seeip_read,
++ &v3_handle_seeip_write,
++ core);
+#endif
+
if (core->shdw_pg_mode == SHADOW_PAGING) {
PrintDebug("Creating initial shadow page table\n");
#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
+ #ifndef V3_CONFIG_DEBUG_SVM
#undef PrintDebug
#define PrintDebug(fmt, args...)
#endif
}
break;
}
+ case VMEXIT_SWINT:
+#ifdef CONFIG_DEBUG_INTERRUPTS
+ PrintDebug("Intercepted SW Interrupt\n");
+#endif
+ if (v3_handle_swintr(info) == -1) {
+ PrintError("Error handling software interrupt\n");
+ return -1;
+ }
+ break;
case VMEXIT_INVLPG:
if (info->shdw_pg_mode == SHADOW_PAGING) {
- #ifdef CONFIG_DEBUG_SHADOW_PAGING
+ #ifdef V3_CONFIG_DEBUG_SHADOW_PAGING
PrintDebug("Invlpg\n");
#endif
if (v3_handle_shadow_invlpg(info) == -1) {
#include <palacios/vmm_xed.h>
#include <palacios/vmm_direct_paging.h>
- #ifdef CONFIG_SYSCALL_HIJACK
++#ifdef V3_CONFIG_SYSCALL_HIJACK
+#include <palacios/vmm_syscall_hijack.h>
+#include <palacios/vmm_mpi_accel.h>
+#endif
+
v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
v3_init_symbiotic_core(core);
#endif
+// KCH
- #ifdef CONFIG_SYSCALL_HIJACK
++#ifdef V3_CONFIG_SYSCALL_HIJACK
+ v3_init_exec_hooks(core);
+ v3_init_mpi_accel(core);
- //v3_hook_swintr(core, 0x80, v3_syscall_handler, NULL);
- /* hook a poll syscall */
- //v3_hook_syscall(core, 5, v3_sysopen_handler, NULL);
- //v3_hook_syscall(core, 21, v3_sysmount_handler, NULL);
- //char * args[2];
- //args[0] = "./envtest";
- //args[1] = "LD_PRELOAD=./libcwrap.so";
- //v3_hook_syscall(core, 11, v3_sysexecve_handler, (void*)args);
+#endif
+
// init SVM/VMX
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
++#ifdef V3_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
++#ifdef V3_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
++#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
++ ulong_t entry = ((ulong_t)src.hi << 32) | (ulong_t)src.lo;
+ PrintDebug("LSTAR Write\n");
++ PrintDebug("\tKernel syscall entry point: 0x%lx\n", entry);
+#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
++#ifdef V3_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
++#ifdef V3_CONFIG_DEBUG_SYSCALL_HIJACK
+ PrintDebug("CSTAR Write\n");
+#endif
++ return 0;
++}
++
++int v3_handle_seeip_read(struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) {
++ /* we don't care about reads */
++ return 0;
++}
++
++int v3_handle_seeip_write(struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) {
++#ifdef V3_CONFIG_DEBUG_SYSALL_HIJACK
++ PrintDebug("SYSENTER_EIP 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
#include <palacios/vmm_ctrl_regs.h>
#include <palacios/vmm_lock.h>
+#include <palacios/vm_guest_mem.h>
+#include <palacios/vmm_decoder.h>
- #ifndef CONFIG_DEBUG_INTERRUPTS
+ #ifndef V3_CONFIG_DEBUG_INTERRUPTS
#undef PrintDebug
#define PrintDebug(fmt, args...)
#endif
}
+int v3_signal_swintr(struct guest_info * core, int vector) {
+ struct v3_intr_core_state * intr_state = &(core->intr_core_state);
+
+ PrintDebug("Signaling software interrupt in vmm_intr.c\n");
+ PrintDebug("\tINT vector: %d\n", vector);
+
+ intr_state->swintr_posted = 1;
+ intr_state->swintr_vector = vector;
+ return 0;
+}
+
+
+int v3_handle_swintr(struct guest_info * core) {
+
+ int ret = 0;
+ void * instr_ptr = NULL;
+ struct x86_instr instr;
+
+ if (core->mem_mode == PHYSICAL_MEM) {
+ ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
+ } else {
+ ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr);
+ }
+
+ if (ret == -1) {
+ PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip);
+ return -1;
+ }
+
+ if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
+ PrintError("V3 SWintr Handler: Decoding Error\n");
+ return -1;
+ }
+
+ uint8_t vector = instr.dst_operand.operand;
+
+ struct v3_swintr_hook * hook = core->intr_core_state.swintr_hooks[vector];
+ if (hook == NULL) {
- #ifdef CONFIG_SWINTR_PASSTHROUGH
++#ifdef V3_CONFIG_SWINTR_PASSTHROUGH
+ if (v3_hook_passthrough_swintr(core, vector) == -1) {
+ PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n");
+ return -1;
+ }
+ hook = core->intr_core_state.swintr_hooks[vector];
+#else
+ core->rip += instr.instr_length;
+ return v3_signal_swintr(core, vector);
+#endif
+ }
+
+ ret = hook->handler(core, vector, NULL);
+ if (ret == -1) {
+ PrintDebug("V3 SWintr Handler: Error in swintr hook\n");
+ return -1;
+ }
+
- /* at some point we may need to prioritize swints
++ /* KCH: at some point we may need to prioritize swints
+ so that they finish in time for the next
- instruction */
++ instruction... */
+ core->rip += instr.instr_length;
+ return v3_signal_swintr(core, vector);
+}
+
+
+static inline struct v3_swintr_hook * get_swintr_hook(struct guest_info * core, uint8_t vector) {
+ return core->intr_core_state.swintr_hooks[vector];
+}
+
+
+int v3_hook_swintr(struct guest_info * core,
+ uint8_t vector,
+ int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data),
+ void * priv_data)
+{
+
+ struct v3_swintr_hook * hook = (struct v3_swintr_hook *)V3_Malloc(sizeof(struct v3_swintr_hook));
+
+ if (hook == NULL) {
+ return -1;
+ }
+
+ if (get_swintr_hook(core, vector) != NULL) {
+ PrintError("SWINT %d already hooked\n", vector);
+ return -1;
+ }
+
+ hook->handler = handler;
+ hook->priv_data = priv_data;
+
+ core->intr_core_state.swintr_hooks[vector] = hook;
+
+ return 0;
+}
+
+
+static int passthrough_swintr_handler(struct guest_info * core, uint8_t vector, void * priv_data) {
+
+ PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n",
+ vector, (void *)core);
+
+ return 0;
+}
+
+
+int v3_hook_passthrough_swintr(struct guest_info * core, uint8_t vector) {
+
+ int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL);
+
+ if (rc) {
+ PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void *)core);
+ return -1;
+ } else {
+ PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void *)core);
+ return 0;
+ }
+
+ /* shouldn't get here */
+ return 0;
+}
+
+
void v3_clear_pending_intr(struct guest_info * core) {
struct v3_intr_core_state * intr_state = &(core->intr_core_state);