2 * This file is part of the Palacios Virtual Machine Monitor developed
3 * by the V3VEE Project with funding from the United States National
4 * Science Foundation and the Department of Energy.
6 * The V3VEE Project is a joint project between Northwestern University
7 * and the University of New Mexico. You can find out more at
10 * Copyright (c) 2011, Kyle C. Hale <kh@u.norhtwestern.edu>
11 * Copyright (c) 2011, The V3VEE Project <http://www.v3vee.org>
12 * All rights reserved.
14 * Author: Kyle C. Hale <kh@u.northwestern.edu>
16 * This is free software. You are permitted to use,
17 * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
20 #include <palacios/vmm.h>
21 #include <palacios/vmm_string.h>
22 #include <palacios/vmm_hashtable.h>
23 #include <palacios/vmm_extensions.h>
24 #include <palacios/vmm_decoder.h>
25 #include <palacios/vm_guest.h>
26 #include <palacios/vm_guest_mem.h>
28 #include <gears/syscall_hijack.h>
29 #include <gears/execve_hook.h>
30 #include <gears/syscall_ref.h>
32 #ifdef V3_CONFIG_EXT_CODE_INJECT
33 #include <gears/code_inject.h>
36 static struct v3_exec_hooks exec_hooks;
38 static int free_hook (struct v3_vm_info * vm, struct exec_hook * hook) {
39 list_del(&(hook->hook_node));
44 static uint_t exec_hash_fn (addr_t key) {
45 return v3_hash_long(key, sizeof(void *) * 8);
49 static int exec_eq_fn (addr_t key1, addr_t key2) {
50 return (key1 == key2);
54 static int init_exec_hooks (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
59 static int init_exec_hooks_core (struct guest_info * core, void * priv_data, void ** core_data) {
60 struct v3_exec_hooks * hooks = &exec_hooks;
61 INIT_LIST_HEAD(&(hooks->hook_list));
62 hooks->bin_table = v3_create_htable(0, exec_hash_fn, exec_eq_fn);
64 if (hooks->bin_table == NULL) {
65 PrintError("Problem creating execve hash table\n");
69 if (core->cpu_mode == LONG || core->cpu_mode == LONG_32_COMPAT) {
70 PrintDebug("Hooking execve 64\n");
71 v3_hook_syscall(core, SYS64_EXECVE, v3_execve_handler, NULL);
73 PrintDebug("Hooking execve, cpu mode: %x\n", core->cpu_mode);
74 v3_hook_syscall(core, SYS32_EXECVE, v3_execve_handler, NULL);
79 static int deinit_exec_hooks_core (struct guest_info * core, void * priv_data, void * core_data) {
80 struct v3_exec_hooks * hooks = &exec_hooks;
81 struct exec_hook * hook = NULL;
82 struct exec_hook * tmp = NULL;
84 list_for_each_entry_safe(hook, tmp, &(hooks->hook_list), hook_node) {
85 free_hook(core->vm_info, hook);
88 v3_free_htable(hooks->bin_table, 0, 0);
94 int v3_hook_executable (struct v3_vm_info * vm,
95 const uchar_t * binfile,
96 int (*handler)(struct guest_info * core, void * priv_data),
99 struct exec_hook * hook = V3_Malloc(sizeof(struct exec_hook));
100 struct v3_exec_hooks * hooks = &exec_hooks;
104 PrintError("Cannot allocate in hooking exec\n");
108 memset(hook, 0, sizeof(struct exec_hook));
110 hook->handler = handler;
111 hook->priv_data = priv_data;
113 // we hash the name of the file to produce a key
114 key = v3_hash_buffer((uchar_t*)binfile, strlen(binfile));
116 v3_htable_insert(hooks->bin_table, key, (addr_t)hook);
117 list_add(&(hook->hook_node), &(hooks->hook_list));
123 int v3_unhook_executable (struct v3_vm_info * vm, const uchar_t * binfile) {
124 struct exec_hook * hook;
125 struct v3_exec_hooks * hooks = &exec_hooks;
128 key = v3_hash_buffer((uchar_t*)binfile, strlen((uchar_t*)binfile));
129 if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) {
132 PrintError("Could not unhook executable '%s'\n", binfile);
136 if (v3_htable_remove(hooks->bin_table, key, 0) == (addr_t)NULL) {
137 PrintError("Error trying to remove key from htable: v3_unhook_executable\n");
144 static struct v3_extension_impl execve_impl = {
145 .name = "execve_intercept",
146 .init = init_exec_hooks,
148 .core_init = init_exec_hooks_core,
149 .core_deinit = deinit_exec_hooks_core,
154 register_extension(&execve_impl);
157 int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
159 struct v3_exec_hooks * hooks = &exec_hooks;
160 struct exec_hook * hook;
164 // TODO: make sure this returns immediately if we're not booted up already
165 if (core->mem_mode == PHYSICAL_MEM) {
166 ret = v3_gpa_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
168 ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
172 PrintError("Error translating file path in sysexecve handler\n");
176 key = v3_hash_buffer((uchar_t*)hva, strlen((uchar_t*)hva));
177 if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) {
179 ret = hook->handler(core, hook->priv_data);
181 PrintDebug("Error handling execve hook\n");
185 #ifdef V3_CONFIG_EXT_CODE_INJECT
186 if (ret == E_NEED_PF) {