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.


aa5bce266557b04f62ec58de2cffdf4836fe5894
[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) {
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) {
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     memset(hook, 0, sizeof(struct exec_hook));
104     
105     hook->handler = handler;
106     hook->priv_data = priv_data;
107     
108     // we hash the name of the file to produce a key
109     key = v3_hash_buffer((uchar_t*)binfile, strlen(binfile));
110
111     v3_htable_insert(hooks->bin_table, key, (addr_t)hook);
112     list_add(&(hook->hook_node), &(hooks->hook_list));
113
114     return 0;
115 }
116
117
118 int v3_unhook_executable (struct v3_vm_info * vm, const uchar_t * binfile) {
119     struct exec_hook * hook;
120     struct v3_exec_hooks * hooks = &exec_hooks;
121     addr_t key;
122
123     key = v3_hash_buffer((uchar_t*)binfile, strlen((uchar_t*)binfile));
124     if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) {
125         free_hook(vm, hook);
126     } else {
127         PrintError("Could not unhook executable '%s'\n", binfile);
128         return -1;
129     }
130
131     if (v3_htable_remove(hooks->bin_table, key, 0) == (addr_t)NULL) {
132         PrintError("Error trying to remove key from htable: v3_unhook_executable\n");
133         return -1;
134     }
135
136     return 0;
137 }
138
139 static struct v3_extension_impl execve_impl = {
140         .name = "execve_intercept",
141         .init = init_exec_hooks,
142         .deinit = NULL,
143         .core_init = init_exec_hooks_core,
144         .core_deinit = deinit_exec_hooks_core,
145         .on_entry = NULL,
146         .on_exit = NULL
147 };
148
149 register_extension(&execve_impl);
150
151
152 int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
153     addr_t hva, key;
154         struct v3_exec_hooks * hooks = &exec_hooks;
155     struct exec_hook * hook;
156     int ret;
157
158     
159     // TODO: make sure this returns immediately if we're not booted up already
160     if (core->mem_mode == PHYSICAL_MEM) {
161         ret = v3_gpa_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
162     } else {
163         ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);      
164     }
165
166     if (ret == -1) {
167         PrintError("Error translating file path in sysexecve handler\n");
168         return 0;
169     }
170
171     key = v3_hash_buffer((uchar_t*)hva, strlen((uchar_t*)hva));
172     if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) {
173         
174         ret = hook->handler(core, hook->priv_data);
175        if (ret == -1) {
176             PrintDebug("Error handling execve hook\n");
177             return -1;
178        }
179
180 #ifdef V3_CONFIG_EXT_CODE_INJECT
181         if (ret == E_NEED_PF) {
182             return E_NEED_PF;
183         }
184 #endif
185     } 
186
187     return 0;
188 }
189