From: Kyle Hale Date: Fri, 13 Apr 2012 21:47:49 +0000 (-0500) Subject: Linux implementation of Gears interfaces X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=5aa80b40b7bd2ab3e2de1f9cb6851cdec6963f79;p=palacios.releases.git Linux implementation of Gears interfaces --- diff --git a/linux_module/Makefile b/linux_module/Makefile index 0c20052..b2e73df 100644 --- a/linux_module/Makefile +++ b/linux_module/Makefile @@ -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 index 0000000..ff63326 --- /dev/null +++ b/linux_module/iface-code-inject.c @@ -0,0 +1,141 @@ +/* + * Linux interface for guest-context code injection + * + * (c) Kyle C. Hale 2011 + * + */ + +#include +#include +#include + +#include + +#include + +#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 index 0000000..f7bb7b8 --- /dev/null +++ b/linux_module/iface-code-inject.h @@ -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 index 0000000..1719abb --- /dev/null +++ b/linux_module/iface-env-inject.c @@ -0,0 +1,148 @@ +/* + * Linux interface for guest-context environment variable injection + * + * (c) Kyle C. Hale 2012 + * + */ + +#include +#include + +#include + +#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 index 0000000..d565e4a --- /dev/null +++ b/linux_module/iface-env-inject.h @@ -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 diff --git a/linux_module/ioctls.txt b/linux_module/ioctls.txt index 30112e8..322dd5a 100644 --- a/linux_module/ioctls.txt +++ b/linux_module/ioctls.txt @@ -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 +