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.


add cleanup for Palacios extensions, add per-core data to extensions
[palacios.git] / palacios / src / gears / ext_execve_hook.c
1 /* 
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.  
5  *
6  * The V3VEE Project is a joint project between Northwestern University
7  * and the University of New Mexico.  You can find out more at 
8  * http://www.v3vee.org
9  *
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.
13  *
14  * Author: Kyle C. Hale <kh@u.northwestern.edu>
15  *
16  * This is free software.  You are permitted to use,
17  * redistribute, and modify it as specified in the file "V3VEE_LICENSE".
18  */
19
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>
27
28 #include <gears/syscall_hijack.h>
29 #include <gears/execve_hook.h>
30 #include <gears/syscall_ref.h>
31
32 #ifdef V3_CONFIG_EXT_CODE_INJECT
33 #include <gears/code_inject.h>
34 #endif
35
36 static struct v3_exec_hooks exec_hooks;
37
38 static int free_hook (struct v3_vm_info * vm, struct exec_hook * hook) {
39     list_del(&(hook->hook_node));
40     V3_Free(hook);
41     return 0;
42 }
43     
44 static uint_t exec_hash_fn (addr_t key) {
45     return v3_hash_long(key, sizeof(void *) * 8);
46 }
47
48
49 static int exec_eq_fn (addr_t key1, addr_t key2) {
50     return (key1 == key2);
51 }
52
53
54 static int init_exec_hooks (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
55
56     return 0;
57 }
58
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);
63
64     if (hooks->bin_table == NULL) {
65         PrintError("Problem creating execve hash table\n");
66         return -1;
67     }
68
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);
72     } else {
73         PrintDebug("Hooking execve, cpu mode: %x\n", core->cpu_mode);
74         v3_hook_syscall(core, SYS32_EXECVE, v3_execve_handler, NULL);
75     }
76     return 0;
77 }
78
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;
83     
84     list_for_each_entry_safe(hook, tmp, &(hooks->hook_list), hook_node) {
85         free_hook(core->vm_info, hook);
86     }
87
88     v3_free_htable(hooks->bin_table, 0, 0);
89
90     return 0;
91 }
92
93
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),
97     void * priv_data) 
98 {
99     struct exec_hook * hook = V3_Malloc(sizeof(struct exec_hook));
100     struct v3_exec_hooks * hooks = &exec_hooks;
101     addr_t key;
102
103     if (!hook) {
104         PrintError("Cannot allocate in hooking exec\n");
105         return -1;
106     }
107     
108     memset(hook, 0, sizeof(struct exec_hook));
109     
110     hook->handler = handler;
111     hook->priv_data = priv_data;
112     
113     // we hash the name of the file to produce a key
114     key = v3_hash_buffer((uchar_t*)binfile, strlen(binfile));
115
116     v3_htable_insert(hooks->bin_table, key, (addr_t)hook);
117     list_add(&(hook->hook_node), &(hooks->hook_list));
118
119     return 0;
120 }
121
122
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;
126     addr_t key;
127
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) {
130         free_hook(vm, hook);
131     } else {
132         PrintError("Could not unhook executable '%s'\n", binfile);
133         return -1;
134     }
135
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");
138         return -1;
139     }
140
141     return 0;
142 }
143
144 static struct v3_extension_impl execve_impl = {
145         .name = "execve_intercept",
146         .init = init_exec_hooks,
147         .deinit = NULL,
148         .core_init = init_exec_hooks_core,
149         .core_deinit = deinit_exec_hooks_core,
150         .on_entry = NULL,
151         .on_exit = NULL
152 };
153
154 register_extension(&execve_impl);
155
156
157 int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
158     addr_t hva, key;
159         struct v3_exec_hooks * hooks = &exec_hooks;
160     struct exec_hook * hook;
161     int ret;
162
163     
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);
167     } else {
168         ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);      
169     }
170
171     if (ret == -1) {
172         PrintError("Error translating file path in sysexecve handler\n");
173         return 0;
174     }
175
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) {
178         
179         ret = hook->handler(core, hook->priv_data);
180        if (ret == -1) {
181             PrintDebug("Error handling execve hook\n");
182             return -1;
183        }
184
185 #ifdef V3_CONFIG_EXT_CODE_INJECT
186         if (ret == E_NEED_PF) {
187             return E_NEED_PF;
188         }
189 #endif
190     } 
191
192     return 0;
193 }
194