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.


moved software interrupt injection to core interrupt code
[palacios.git] / palacios / src / extensions / ext_syscall_hijack.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/vm_guest_mem.h>
22 #include <palacios/vm_guest.h>
23 #include <palacios/vmm_intr.h>
24 #include <palacios/vmm_decoder.h>
25 #include <palacios/vmm_string.h>
26 #include <palacios/vmm_shadow_paging.h>
27 #include <palacios/vmm_extensions.h>
28 #include <palacios/vmm_intr.h>
29
30 #include <interfaces/syscall_hijack.h>
31 #include <interfaces/sw_intr.h>
32
33 #include "syscall_ref.h"
34
35 #ifndef V3_CONFIG_DEBUG_EXT_SYSCALL_HIJACK
36 #undef PrintDebug
37 #define PrintDebug(fmt, args...)
38 #endif
39
40 #define MAX_CHARS 256
41 #ifndef max
42     #define max(a, b) ( ((a) > (b)) ? (a) : (b) )
43 #endif
44
45 #define SYSCALL_INT_VECTOR 0x80
46
47
48 struct v3_syscall_hook {
49     int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data);
50     void * priv_data;
51 };
52
53 static struct v3_syscall_hook * syscall_hooks[512];
54
55
56 static int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data) {
57  
58     uint_t syscall_nr = (uint_t) core->vm_regs.rax;
59     int err = 0;
60
61     struct v3_syscall_hook * hook = syscall_hooks[syscall_nr];
62     if (hook == NULL) {
63 #ifdef V3_CONFIG_EXT_SYSCALL_PASSTHROUGH
64         if (v3_hook_passthrough_syscall(core, syscall_nr) == -1) {
65             PrintDebug("Error hooking passthrough syscall\n");
66             return -1;
67         }
68         hook = syscall_hooks[syscall_nr];
69 #else
70         return v3_raise_swintr(core, vector);
71 #endif
72     }
73     
74     err = hook->handler(core, syscall_nr, hook->priv_data);
75     if (err == -1) {
76         PrintDebug("V3 Syscall Handler: Error in syscall hook\n");
77         return -1;
78     }
79
80     return 0;
81 }
82
83
84 static int init_syscall_hijack (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
85
86     return 0;
87 }
88
89
90 static int init_syscall_hijack_core (struct guest_info * core, void * priv_data) {
91
92     v3_hook_swintr(core, SYSCALL_INT_VECTOR, v3_syscall_handler, NULL);
93     return 0;
94 }
95
96
97 static void print_arg (struct  guest_info * core, v3_reg_t reg, uint8_t argnum) {
98
99     addr_t hva;
100     int ret = 0;
101     
102     PrintDebug("\t ARG%d: INT - %ld\n", argnum, (long) reg);
103
104     if (core->mem_mode == PHYSICAL_MEM) {
105         ret = v3_gpa_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva);
106     }
107     else { 
108         ret = v3_gva_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva);
109     }
110
111     PrintDebug("\t       STR - ");
112     if (ret == -1) {
113         PrintDebug("\n");
114         return;
115     }
116         
117     uint32_t c = max(MAX_CHARS, 4096 - (hva % 4096));
118     int i = 0;
119     for (; i < c && *((char*)(hva + i)) != 0; i++) {
120         PrintDebug("%c", *((char*)(hva + i)));
121     }
122     PrintDebug("\n");
123 }
124
125
126 static void print_syscall (uint8_t is64, struct guest_info * core) {
127
128     if (is64) {
129         PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name64(core->vm_regs.rax));
130     } else {
131         PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name32(core->vm_regs.rax));
132     }
133
134     print_arg(core, core->vm_regs.rbx, 1);
135     print_arg(core, core->vm_regs.rcx, 2);
136     print_arg(core, core->vm_regs.rdx, 3);
137 }
138
139
140
141
142 static struct v3_extension_impl syscall_impl = {
143     .name = "syscall_intercept",
144     .init = init_syscall_hijack,
145     .deinit = NULL,
146     .core_init = init_syscall_hijack_core,
147     .core_deinit = NULL,
148     .on_entry = NULL,
149     .on_exit = NULL
150 };
151
152 register_extension(&syscall_impl);
153
154
155
156
157 static inline struct v3_syscall_hook * get_syscall_hook (struct guest_info * core, uint_t syscall_nr) {
158     return syscall_hooks[syscall_nr];
159
160
161
162 int v3_hook_syscall (struct guest_info * core,
163     uint_t syscall_nr,
164     int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data),
165     void * priv_data) 
166 {
167     struct v3_syscall_hook * hook = (struct v3_syscall_hook *)V3_Malloc(sizeof(struct v3_syscall_hook));
168
169     
170     if (hook == NULL) {
171         return -1;
172     }
173
174     if (get_syscall_hook(core, syscall_nr) != NULL) {
175         PrintError("System Call #%d already hooked\n", syscall_nr);
176         return -1;
177     }
178
179     hook->handler = handler;
180     hook->priv_data = priv_data;
181
182     syscall_hooks[syscall_nr] = hook;
183
184     return 0;
185 }
186
187
188 static int passthrough_syscall_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
189     print_syscall(0, core);
190     return 0;
191 }
192
193
194 int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr) {
195     
196     int rc = v3_hook_syscall(core, syscall_nr, passthrough_syscall_handler, NULL);
197
198     if (rc) {
199         PrintError("failed to hook syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core);
200         return -1;
201     } else {
202         PrintDebug("hooked syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core);
203         return 0;
204     }
205
206     /* shouldn't get here */
207     return 0;
208 }
209
210 /*
211 int v3_sysexecve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) {
212     addr_t hva, key;
213     struct exec_hook * hook;
214     int ret;
215     
216     ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva);
217     if (ret == -1) {
218         PrintDebug("Error translating file path in sysexecve handler\n");
219         return -1;
220     }
221
222     key = v3_hash_buffer((uchar_t*)hva, strlen((uchar_t*)hva));
223     if ((hook = (struct exec_hook*)v3_htable_search(core->exec_hooks.bin_table, key)) != NULL) {
224        if (hook->handler(core, NULL) == -1) {
225             PrintDebug("Error handling execve hook\n");
226             return -1;
227         }
228     } 
229         
230     return 0;
231 }
232
233 */