Palacios Public Git Repository

To checkout Palacios execute

  git clone http://v3vee.org/palacios/palacios.web/palacios.git
This will give you the master branch. You probably want the devel branch or one of the release branches. To switch to the devel branch, simply execute
  cd palacios
  git checkout --track -b devel origin/devel
The other branches are similar.


added ability to inject an env variable into guest user process
Kyle Hale [Wed, 18 May 2011 23:14:43 +0000 (18:14 -0500)]
Kconfig
palacios/include/palacios/vm_guest.h
palacios/include/palacios/vm_guest_mem.h
palacios/include/palacios/vmm_intr.h
palacios/src/palacios/Makefile
palacios/src/palacios/svm.c
palacios/src/palacios/svm_handler.c
palacios/src/palacios/vm_guest.c
palacios/src/palacios/vm_guest_mem.c
palacios/src/palacios/vmm_intr.c

diff --git a/Kconfig b/Kconfig
index 4241627..3c98783 100644 (file)
--- a/Kconfig
+++ b/Kconfig
@@ -178,14 +178,41 @@ config INSPECTOR
        help 
          Enable inspection framework for vm internal state
 
-config SYSCALL_HIJACK
-    bool "Enable System Call Interposition"
+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 intercept software interrupt (INT) instructions,
-      Fast-System Call instructions (SYSENTER, SYSCALL), and the LIDT instruction
+      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"
@@ -427,13 +454,14 @@ config DEBUG_VNET
           Enable the Vnet debug in Palacios
 
 config DEBUG_SYSCALL_HIJACK
-        bool "Enable Syscall hijack Debug in Palacios"
+        bool "Enable Syscall Hijack Debug in Palacios"
         default n
-        depends on EXPERIMENTAL && SYSCALL_HIJACK && DEBUG_ON
+        depends on DEBUG_ON && SYSCALL_HIJACK
         help
           Enable Debugging printouts for syscall hijacking
           code in Palacios
 
+
 endmenu
 
 
index 5d4527f..b427f5a 100644 (file)
 struct v3_sym_core_state;
 #endif
 
+#ifdef CONFIG_SYSCALL_HIJACK
+#include <palacios/vmm_syscall_hijack.h>
+#endif
+
 
 
 #include <palacios/vmm_config.h>
@@ -90,6 +94,11 @@ struct guest_info {
     /* This structure is how we get exceptions for the guest */
     struct v3_excp_state excp_state;
 
+#ifdef CONFIG_SYSCALL_HIJACK
+    struct v3_syscall_hook_map sc_hook_map;
+    struct v3_execve_varchunk var_dump;
+#endif
+
 
     v3_cpu_mode_t cpu_mode;
     v3_mem_mode_t mem_mode;
index db6a6a0..6d983ae 100644 (file)
@@ -99,6 +99,9 @@ int v3_hva_to_gva(struct guest_info * guest_info, addr_t host_va, addr_t  * gues
 
 
 
+// KCH
+// Check if pte for this gva has certain permissions
+int v3_gva_can_access(struct guest_info * core, addr_t gva);
 
 
 
index 8a63383..62c8667 100644 (file)
@@ -41,6 +41,13 @@ struct v3_irq_hook {
     void * priv_data;
 };
 
+// KCH
+struct v3_swintr_hook {
+    int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data);
+    void * priv_data;
+};
+
+
 #define MAX_IRQ 256
 
 
@@ -58,9 +65,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;
+    // KCH: for injecting SW Interrupts
+    uint_t swintr_posted;
+    uint_t swintr_vector;
+    struct v3_swintr_hook * swintr_hooks[256];
 
     uint8_t virq_map[MAX_IRQ / 8];
 
@@ -83,7 +91,6 @@ 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 {
@@ -99,7 +106,6 @@ struct intr_router_ops {
 
 void v3_clear_pending_intr(struct guest_info * core);
 
-
 void * v3_register_intr_controller(struct guest_info * info, struct intr_ctrl_ops * ops, void * priv_data);
 void * v3_register_intr_router(struct v3_vm_info * vm, struct intr_router_ops * ops, void * priv_data);
 
@@ -118,7 +124,6 @@ int v3_injecting_intr(struct guest_info * info, uint_t intr_num, v3_intr_type_t
 */
 
 
-
 int v3_hook_irq(struct v3_vm_info * vm, 
                uint_t irq,
                int (*handler)(struct v3_vm_info * vm, struct v3_interrupt * intr, void * priv_data),
@@ -127,6 +132,16 @@ int v3_hook_irq(struct v3_vm_info * vm,
 int v3_hook_passthrough_irq(struct v3_vm_info * vm, uint_t irq);
 
 
+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);
+
+int v3_hook_passthrough_swintr(struct guest_info * core, uint8_t vector);
+
+
+int v3_signal_swintr(struct guest_info * core, int vec);
+int v3_handle_swintr(struct guest_info * core);
 
 #endif // !__V3VEE__
 
index 6a24b89..3bb87a6 100644 (file)
@@ -75,6 +75,8 @@ 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_syscall_hijack.o 
+obj-$(CONFIG_SYSCALL_HIJACK) += linux_32_syscalls.o
+obj-$(CONFIG_SYSCALL_HIJACK) += linux_64_syscalls.o
 
 obj-y += mmu/
index 59af9a7..6f160c7 100644 (file)
@@ -135,9 +135,8 @@ 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;
+    /* KCH: intercept SW Interrupts (INT instr) */
+#ifdef CONFIG_SW_INTERRUPTS
     ctrl_area->instrs.INTn = 1;
 #endif
 
@@ -230,7 +229,7 @@ static void Init_VMCB_BIOS(vmcb_t * vmcb, struct guest_info * core) {
                core);
 
 #ifdef CONFIG_HIJACK_MSR
-    /* KCH: for syscall interposition */
+    /* KCH: for syscall hijacking */
     v3_hook_msr(core->vm_info, STAR_MSR,
         &v3_handle_star_read,
         &v3_handle_star_write,
@@ -445,15 +444,20 @@ static int update_irq_entry_state(struct guest_info * info) {
                guest_ctrl->EVENTINJ.type = SVM_INJECTION_NMI;
                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);
+#ifdef CONFIG_DEBUG_INTERRUPTS
+            PrintDebug("Caught an injected software interrupt\n");
+            PrintDebug("\ttype: %d, vector: %d\n", SVM_INJECTION_SOFT_INTR, info->intr_core_state.swintr_vector);
+#endif
             guest_ctrl->EVENTINJ.type = SVM_INJECTION_SOFT_INTR;
-            guest_ctrl->EVENTINJ.vector = info->intr_core_state.sw_intr_vector;
+            guest_ctrl->EVENTINJ.vector = info->intr_core_state.swintr_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;
+            /* reset the software interrupt state. 
+                we can do this because we know only one
+                sw int can be posted at a time on a given 
+                core, unlike irqs */
+            info->intr_core_state.swintr_posted = 0;
+            info->intr_core_state.swintr_vector = 0;
             break;
         }
            case V3_VIRTUAL_IRQ:
index 62fe695..8822116 100644 (file)
@@ -194,26 +194,15 @@ 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");
+#ifdef CONFIG_DEBUG_INTERRUPTS
+        PrintDebug("Intercepted SW Interrupt\n");
 #endif
-        if (v3_handle_swint(info) == -1) {
+        if (v3_handle_swintr(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
index 4ab0134..5281dd4 100644 (file)
 #include <palacios/vmm_xed.h>
 #include <palacios/vmm_direct_paging.h>
 
+#ifdef CONFIG_SYSCALL_HIJACK
+#include <palacios/vmm_syscall_hijack.h>
+#endif
+
 
 
 v3_cpu_mode_t v3_get_vm_cpu_mode(struct guest_info * info) {
@@ -678,6 +682,16 @@ int v3_init_core(struct guest_info * core) {
     v3_init_symbiotic_core(core);
 #endif
 
+/* KCH: Hook INT 80
+      not sure about this location though...*/
+#ifdef CONFIG_SYSCALL_HIJACK
+    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);
+    v3_hook_syscall(core, 11, v3_sysexecve_handler, NULL);
+#endif  
+
     // init SVM/VMX
 
 
index ca6c601..0fd6075 100644 (file)
@@ -168,15 +168,15 @@ int v3_gva_to_gpa(struct guest_info * guest_info, addr_t gva, addr_t * gpa) {
     switch (guest_info->cpu_mode) {
        case PROTECTED:
            if (v3_translate_guest_pt_32(guest_info, guest_cr3, gva, gpa) == -1) {
-               PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n", 
-                          (void *)gva, (void *)(addr_t)guest_cr3);
+               /*PrintDebug("Could not translate addr (%p) through 32 bit guest PT at %p\n", 
+                          (void *)gva, (void *)(addr_t)guest_cr3);*/
                return -1;
            }
            break;
        case PROTECTED_PAE:
            if (v3_translate_guest_pt_32pae(guest_info, guest_cr3, gva, gpa) == -1) {
-               PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n", 
-                          (void *)gva, (void *)(addr_t)guest_cr3);
+               /*PrintDebug("Could not translate addr (%p) through 32 bitpae guest PT at %p\n", 
+                          (void *)gva, (void *)(addr_t)guest_cr3);*/
                return -1;
            }
            break;
@@ -184,8 +184,8 @@ int v3_gva_to_gpa(struct guest_info * guest_info, addr_t gva, addr_t * gpa) {
        case LONG_32_COMPAT:
        case LONG_16_COMPAT:
            if (v3_translate_guest_pt_64(guest_info, guest_cr3, gva, gpa) == -1) {
-               PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n", 
-                          (void *)gva, (void *)(addr_t)guest_cr3);
+               /*PrintDebug("Could not translate addr (%p) through 64 bit guest PT at %p\n", 
+                          (void *)gva, (void *)(addr_t)guest_cr3);*/
                return -1;
            }
            break;
@@ -266,8 +266,8 @@ int v3_gva_to_hva(struct guest_info * guest_info, addr_t gva, addr_t * hva) {
     *hva = 0;
 
     if (v3_gva_to_gpa(guest_info, gva, &gpa) != 0) {
-       PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
-                  (void *)gva);
+       /*PrintError("In GVA->HVA: Invalid GVA(%p)->GPA lookup\n", 
+                  (void *)gva);*/
        return -1;
     }
 
@@ -317,6 +317,56 @@ int v3_hva_to_gva(struct guest_info * guest_info, addr_t hva, addr_t * gva) {
 
 
 
+/* KCH: currently only checks if we can perform a user-mode write
+   return 1 on success */
+int v3_gva_can_access(struct guest_info * core, addr_t gva) {
+
+    v3_reg_t guest_cr3 = 0;
+    pf_error_t access_type;
+    pt_access_status_t access_status;
+
+    access_type.write = 1;
+    access_type.user = 1;
+    
+    if (core->mem_mode == PHYSICAL_MEM) {
+        return -1;
+    }
+    
+    if (core->shdw_pg_mode == SHADOW_PAGING) {
+        guest_cr3 = core->shdw_pg_state.guest_cr3;
+    } else {
+        guest_cr3 = core->ctrl_regs.cr3;
+    }
+    
+    // guest is in paged mode
+    switch (core->cpu_mode) {
+    case PROTECTED:
+        if (v3_check_guest_pt_32(core, guest_cr3, gva, access_type, &access_status) == -1) {
+            return -1;
+        }
+        break;
+    case PROTECTED_PAE:
+        if (v3_check_guest_pt_32pae(core, guest_cr3, gva, access_type, &access_status) == -1) {
+            return -1;
+        }
+        break;
+    case LONG:
+    case LONG_32_COMPAT:
+    case LONG_16_COMPAT:
+        if (v3_check_guest_pt_64(core, guest_cr3, gva, access_type, &access_status) == -1) {
+            return -1;
+        }
+        break;
+    default:
+        return -1;
+    }
+
+    if (access_status != PT_ACCESS_OK) {
+        return 0;
+    } else {
+        return 1;
+    }
+}
 
 
 
index 0c0a677..101663b 100644 (file)
@@ -25,6 +25,8 @@
 #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
 #undef PrintDebug
@@ -167,7 +169,7 @@ 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);
+    V3_ASSERT(irq <= 255);
     return vm->intr_routers.hooks[irq];
 }
 
@@ -294,14 +296,138 @@ int v3_raise_irq(struct v3_vm_info * vm, int irq) {
 }
 
 
-int v3_signal_sw_intr(struct guest_info * core, int vec) {
+int v3_signal_swintr(struct guest_info * core, int vector) {
     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);
+    PrintDebug("Signaling software interrupt in vmm_intr.c\n");
+    PrintDebug("\tINT vector: %d\n", vector);
     
-    intr_state->sw_intr_pending = 1;
-    intr_state->sw_intr_vector = vec;
+    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 Syscall Hijack: Could not translate Instruction Address (%p)\n", (void *)core->rip);
+        return -1;
+    }
+
+    if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) {
+        PrintError("V3 Syscall Hijack: Decoding Error\n");
+        return -1;
+    }
+
+    uint8_t vector = instr.dst_operand.operand;
+
+    //PrintDebug("KCH: SWINT\n");
+    //PrintDebug("KCH: Data - %x\n",*((uint32_t*)instr_ptr));
+    //PrintDebug("\t RIP: %llx CS: %x\n", core->rip, core->segments.cs.selector);
+    //PrintDebug("KCH: Disassembling\n\t");
+    //addr_t rip = (addr_t) core->rip;
+    //v3_disasm(core, instr_ptr, &rip, 1); 
+    
+    //v3_print_instr(&instr);
+    // only consider system calls
+
+    /*
+    if (vector == 0x80) {
+        print_syscall(0, core);
+    }
+    */
+
+    struct v3_swintr_hook * hook = core->intr_core_state.swintr_hooks[vector];
+    if (hook == NULL) {
+#ifdef CONFIG_SWINTR_PASSTHROUGH
+        if (v3_hook_passthrough_swintr(core, vector) == -1) {
+            PrintDebug("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 SWINT Handler: Error in swint hook\n");
+        return -1;
+    }
+
+    /* make software interrupts prioritized so they finish in time for the next
+        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;
 }
 
@@ -339,12 +465,11 @@ v3_intr_type_t v3_intr_pending(struct guest_info * info) {
        }
     }
 
-    // KCH: not sure about this
-    if (intr_state->sw_intr_pending == 1) {
+    // KCH
+    if (intr_state->swintr_posted == 1) {
         ret = V3_SOFTWARE_INTR;
     }
         
-
     v3_unlock_irqrestore(intr_state->irq_lock, irq_state);
 
     return ret;