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.


additions for syscall hijacking
Kyle Hale [Fri, 29 Apr 2011 22:06:17 +0000 (17:06 -0500)]
13 files changed:
Kconfig
palacios/include/palacios/vmm_ctrl_regs.h
palacios/include/palacios/vmm_decoder.h
palacios/include/palacios/vmm_instr_decoder.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/vmm_ctrl_regs.c
palacios/src/palacios/vmm_decoder.c
palacios/src/palacios/vmm_intr.c
palacios/src/palacios/vmm_v3dec.c
palacios/src/palacios/vmm_xed.c

diff --git a/Kconfig b/Kconfig
index 7a48606..d312c0b 100644 (file)
--- 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
 
 
index e072a04..3cc1932 100644 (file)
 
 #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);
 
index aba2d40..82253be 100644 (file)
@@ -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;
index 4341910..7c48244 100644 (file)
@@ -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:
index 626b98b..8a63383 100644 (file)
@@ -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 {
index 5747261..c505b60 100644 (file)
@@ -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/
index bb65a6f..59af9a7 100644 (file)
@@ -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;
index 7016197..62fe695 100644 (file)
@@ -33,6 +33,7 @@
 #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
@@ -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
index b27df4b..cc1fac6 100644 (file)
@@ -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
index ca52e8a..67e96ae 100644 (file)
@@ -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";
index c9c1800..0c0a677 100644 (file)
@@ -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);
 
index 4fa6e04..50bba30 100644 (file)
@@ -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:
index bb1e856..9f3d7ac 100644 (file)
@@ -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 */