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.


Linux implementation of Gears interfaces
Kyle Hale [Fri, 13 Apr 2012 21:47:49 +0000 (16:47 -0500)]
linux_module/Makefile
linux_module/iface-code-inject.c [new file with mode: 0644]
linux_module/iface-code-inject.h [new file with mode: 0644]
linux_module/iface-env-inject.c [new file with mode: 0644]
linux_module/iface-env-inject.h [new file with mode: 0644]
linux_module/ioctls.txt

index 0c20052..b2e73df 100644 (file)
@@ -37,6 +37,9 @@ v3vee-$(V3_CONFIG_VNET) +=    palacios-vnet.o \
                                palacios-vnet-ctrl.o   \
                                palacios-vnet-brg.o
 
+v3vee-$(V3_CONFIG_HOST_HYPERCALL) += iface-host-hypercall.o
+v3vee-$(V3_CONFIG_EXT_CODE_INJECT) += iface-code-inject.o
+v3vee-$(V3_CONFIG_EXT_ENV_INJECT) += iface-env-inject.o
 
 v3vee-objs := $(v3vee-y) ../libv3vee.a
 obj-m := v3vee.o
diff --git a/linux_module/iface-code-inject.c b/linux_module/iface-code-inject.c
new file mode 100644 (file)
index 0000000..ff63326
--- /dev/null
@@ -0,0 +1,141 @@
+/* 
+ * Linux interface for guest-context code injection
+ *
+ * (c) Kyle C. Hale 2011
+ *
+ */
+
+#include <linux/elf.h>
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
+#include <linux/module.h>
+
+#include <gears/code_inject.h>
+
+#include "palacios.h"
+#include "vm.h"
+#include "linux-exts.h"
+#include "iface-code-inject.h"
+
+
+/* eventually this should probably be a hash table,
+ * hashed on unique inject data 
+ */
+static struct top_half_data *top_map[MAX_INJ] = {[0 ... MAX_INJ - 1] = 0};
+
+static int register_top(struct top_half_data *top) {
+    int i;
+
+    for (i = 0; i < MAX_INJ; i++) {
+        if (!top_map[i]) {
+            top_map[i] = top;
+            return i;
+        }
+    }
+
+    return -1;
+}
+
+
+static void free_inject_data (void) {
+    int i;
+
+    for(i = 0; i < MAX_INJ; i++) {
+        if (top_map[i]) {
+            kfree(top_map[i]->elf_data);
+            kfree(top_map[i]);
+        }
+    }
+}
+
+
+
+static int vm_tophalf_inject (struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) {
+    struct top_half_data top_arg;
+    struct top_half_data * top;
+
+    top = kmalloc(sizeof(struct top_half_data), GFP_KERNEL);
+    if (IS_ERR(top)) {
+        printk("Palacios Error: could not allocate space for top half data\n");
+        return -EFAULT;
+    }
+    memset(top, 0, sizeof(struct top_half_data));
+    
+    printk("Palacios: Loading ELF data...\n");
+    if (copy_from_user(&top_arg, (void __user *)arg, sizeof(struct top_half_data))) {
+        printk("palacios: error copying ELF from userspace\n");
+        return -EFAULT;
+    }
+
+    top->elf_size = top_arg.elf_size;
+    top->func_offset = top_arg.func_offset;
+    top->is_dyn = top_arg.is_dyn;
+
+    /* we have a binary name */
+    if (top_arg.is_exec_hooked) {
+        strcpy(top->bin_file, top_arg.bin_file);
+        top->is_exec_hooked = 1;
+        printk("top->bin_file is %s\n", top->bin_file);
+    } 
+
+    printk("Palacios: Allocating %lu B of kernel memory for ELF binary data...\n", top->elf_size);
+    top->elf_data = kmalloc(top->elf_size, GFP_KERNEL);
+    if (IS_ERR(top->elf_data)) {
+        printk("Palacios Error: could not allocate space for binary image\n");
+        return -EFAULT;
+    }
+    memset(top->elf_data, 0, top->elf_size);
+
+    printk("Palacios: Copying ELF image into kernel module...\n");
+    if (copy_from_user(top->elf_data, (void __user *)top_arg.elf_data, top->elf_size)) {
+        printk("Palacios: Error loading elf data\n");
+        return -EFAULT;
+    }
+
+    if (register_top(top) < 0) 
+        return -1;
+    
+    printk("Palacios: setting up inject code...\n");
+    if (v3_insert_code_inject(guest->v3_ctx, top->elf_data, top->elf_size, 
+                         top->bin_file, top->is_dyn, top->is_exec_hooked, top->func_offset) < 0) {
+        printk("Palacios Error: error setting up inject code\n");
+        return -1;
+    }
+
+    printk("Palacios: injection registration complete\n");
+    return 0;
+}
+
+
+static int init_code_inject (void) {
+    return 0;
+}
+
+
+static int deinit_code_inject (void) {
+    return 0;
+}
+
+
+static int guest_init_code_inject (struct v3_guest * guest, void ** vm_data) {
+    add_guest_ctrl(guest, V3_VM_TOPHALF_INJECT, vm_tophalf_inject, NULL);
+    return 0;
+}
+
+
+static int guest_deinit_code_inject (struct v3_guest * guest, void * vm_data) {
+    free_inject_data();
+    return 0;
+}
+
+
+static struct linux_ext code_inject_ext = {
+    .name = "CODE_INJECT",
+    .init = init_code_inject,
+    .deinit = deinit_code_inject,
+    .guest_init = guest_init_code_inject,
+    .guest_deinit = guest_deinit_code_inject 
+};
+
+register_extension(&code_inject_ext);
diff --git a/linux_module/iface-code-inject.h b/linux_module/iface-code-inject.h
new file mode 100644 (file)
index 0000000..f7bb7b8
--- /dev/null
@@ -0,0 +1,31 @@
+#ifndef __IFACE_CODE_INJECT_H__
+#define __IFACE_CODE_INJECT_H__
+
+#define V3_VM_TOPHALF_INJECT 12123
+#define V3_VM_HYPERCALL_ADD 12124
+#define V3_VM_HYPERCALL_REMOVE 12125
+
+#define MAX_INJ 128
+
+struct top_half_data {
+    unsigned long elf_size;
+    void *elf_data;
+    int got_offset;
+    int plt_offset;
+    int func_offset;
+    char bin_file[256];
+    int hcall_nr;
+    int inject_id;
+    int is_dyn;
+    int is_exec_hooked;
+};
+
+#define HCALL_NAME_MAX 256
+
+struct hcall_data {
+  int   fd;
+  int   hcall_nr;
+  char  fn[HCALL_NAME_MAX];
+};
+
+#endif
diff --git a/linux_module/iface-env-inject.c b/linux_module/iface-env-inject.c
new file mode 100644 (file)
index 0000000..1719abb
--- /dev/null
@@ -0,0 +1,148 @@
+/* 
+ * Linux interface for guest-context environment variable injection
+ *
+ * (c) Kyle C. Hale 2012
+ *
+ */
+
+#include <linux/uaccess.h>
+#include <linux/vmalloc.h>
+
+#include <gears/env_inject.h>
+
+#include "palacios.h"
+#include "vm.h"
+#include "linux-exts.h"
+#include "iface-env-inject.h"
+
+
+static struct env_data * env_map[MAX_ENV_INJECT] = {[0 ... MAX_ENV_INJECT - 1] = 0};
+
+
+static int register_env(struct env_data * env) {
+    int i;
+
+    for (i = 0; i < MAX_ENV_INJECT; i++) {
+        if (!env_map[i]) {
+            env_map[i] = env;
+            return i;
+        }
+    }
+    return -1;
+}
+
+
+static void free_inject_data (void) {
+    int i, j;
+
+    for(i = 0; i < MAX_ENV_INJECT; i++) {
+        if (env_map[i]) {
+            for (j = 0; j < env_map[i]->num_strings; j++) 
+                kfree(env_map[i]->strings[j]);
+
+            kfree(env_map[i]->strings);
+            kfree(env_map[i]);
+        }
+    }
+}
+
+
+
+static int vm_env_inject (struct v3_guest * guest, unsigned int cmd, unsigned long arg, void * priv_data) {
+    struct env_data env_arg;
+    struct env_data * env;
+    int i;
+
+    printk("Palacios: Loading environment data...\n");
+    if (copy_from_user(&env_arg, (void __user *)arg, sizeof(struct env_data))) {
+        printk("palacios: error copying environment data from userspace\n");
+        return -EFAULT;
+    }
+
+    env = kmalloc(sizeof(struct env_data), GFP_KERNEL);
+    if (IS_ERR(env)) {
+        printk("Palacios Error: could not allocate space for environment data\n");
+        return -EFAULT;
+    }
+
+    memset(env, 0, sizeof(struct env_data));
+
+    env->num_strings = env_arg.num_strings;
+    
+    strcpy(env->bin_name, env_arg.bin_name);
+    printk("Binary hooked on: %s\n", env->bin_name);
+
+    //printk("Palacios: Allocating space for %u env var string ptrs...\n", env->num_strings);
+    env->strings = kmalloc(env->num_strings*sizeof(char*), GFP_KERNEL);
+    if (IS_ERR(env->strings)) {
+        printk("Palacios Error: could not allocate space for env var strings\n");
+        return -EFAULT;
+    }
+    memset(env->strings, 0, env->num_strings*sizeof(char*));
+
+    //printk("Palacios: copying env var string pointers\n");
+    if (copy_from_user(env->strings, (void __user *)env_arg.strings, env->num_strings*sizeof(char*))) {
+        printk("Palacios: Error copying string pointers\n");
+        return -EFAULT;
+    }
+
+    for (i = 0; i < env->num_strings; i++) {
+        char * tmp  = kmalloc(MAX_STRING_LEN, GFP_KERNEL);
+        if (IS_ERR(tmp)) {
+            printk("Palacios Error: could not allocate space for env var string #%d\n", i);
+            return -EFAULT;
+        }
+
+        if (copy_from_user(tmp, (void __user *)env->strings[i], MAX_STRING_LEN)) {
+            printk("Palacios: Error copying string #%d\n", i);
+            return -EFAULT;
+        }
+        env->strings[i] = tmp;
+    }
+
+    printk("Palacios: registering environment data...\n");
+    if (register_env(env) < 0) 
+        return -1;
+    
+    printk("Palacios: passing data off to palacios...\n");
+    if (v3_insert_env_inject(guest->v3_ctx, env->strings, env->num_strings, env->bin_name) < 0) {
+        printk("Palacios: Error passing off environment data\n");
+        return -1;
+    }
+
+    printk("Palacios: environment injection registration complete\n");
+    return 0;
+}
+
+
+static int init_env_inject (void) {
+    return 0;
+}
+
+
+static int deinit_env_inject (void) {
+    return 0;
+}
+
+
+static int guest_init_env_inject (struct v3_guest * guest, void ** vm_data) {
+    add_guest_ctrl(guest, V3_VM_ENV_INJECT, vm_env_inject, NULL);
+    return 0;
+}
+
+
+static int guest_deinit_env_inject (struct v3_guest * guest, void * vm_data) {
+    free_inject_data();
+    return 0;
+}
+
+
+static struct linux_ext env_inject_ext = {
+    .name = "ENV_INJECT",
+    .init = init_env_inject,
+    .deinit = deinit_env_inject,
+    .guest_init = guest_init_env_inject,
+    .guest_deinit = guest_deinit_env_inject 
+};
+
+register_extension(&env_inject_ext);
diff --git a/linux_module/iface-env-inject.h b/linux_module/iface-env-inject.h
new file mode 100644 (file)
index 0000000..d565e4a
--- /dev/null
@@ -0,0 +1,18 @@
+#ifndef __IFACE_ENV_INJECT_H__
+#define __IFACE_ENV_INJECT_H__
+
+
+#define MAX_NUM_STRINGS 10
+#define MAX_STRING_LEN 128
+#define MAX_ENV_INJECT 10
+
+#define V3_VM_ENV_INJECT 13125
+
+struct env_data {
+    int num_strings;
+    char ** strings;
+    char bin_name[MAX_STRING_LEN];
+};
+
+
+#endif
index 30112e8..322dd5a 100644 (file)
@@ -22,3 +22,11 @@ VM Commands (/dev/v3-vm*)
 258 -- (IFACE) VGA Console Framebuf Query
 
 10245 -- (IFACE) Connect Host Device
+
+12123 -- (EXT) Inject Top Half Code into Guest
+
+12124 -- (EXT) Register host hypercall (remember to insmod first)
+12124 -- (EXT) Unregister host hypercall 
+
+13125 -- (EXT) Inject Environment Variables into Guest Process
+