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.


Context-based output infrastructure (V3_Print, etc) and modifications to use it
[palacios.git] / palacios / src / gears / ext_code_inject.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
21 #include <palacios/vmm.h>
22 #include <palacios/vm_guest.h>
23 #include <palacios/vm_guest_mem.h>
24 #include <palacios/vmm_intr.h>
25 #include <palacios/vmm_extensions.h>
26 #include <palacios/vmm_decoder.h>
27 #include <palacios/vmm_types.h>
28 #include <palacios/vmm_hypercall.h>
29 #include <palacios/vmcb.h>
30
31 #include <gears/code_inject.h> 
32 #include <gears/execve_hook.h>
33 #include <gears/sw_intr.h>
34
35 #include "elf.h"
36
37 struct v3_code_injects code_injects;
38
39 static char mmap_code[] =   "\xb8\xc0\x00\x00\x00\x31\xdb\xb9"
40                             "\x00\x00\x10\x00\xba\x01\x00\x00"
41                             "\x00\xbd\x02\x00\x00\x00\x09\xea"
42                             "\xbd\x04\x00\x00\x00\x09\xea\xbe"
43                             "\x02\x00\x00\x00\xbd\x20\x00\x00"
44                             "\x00\x09\xee\xbf\xff\xff\xff\xff"
45                             "\x31\xed\xcd\x80\x89\xc3\xb9\x00"
46                             "\x00\x10\x00\xc7\x00\xef\xbe\xad"
47                             "\xde\x05\x00\x10\x00\x00\x81\xe9"
48                             "\x00\x10\x00\x00\x75\xed\xb8\x00"
49                             "\xf0\x00\x00\x0f\x01\xd9";
50
51 static char munmap_code[] = "\xb8\x5b\x00\x00\x00\xb9\x00\x00"
52                             "\x10\x00\xcd\x80\x89\xc3\xb8\x03"
53                             "\xf0\x00\x00\x0f\x01\xd9";
54
55 static char vmmcall_code[] = "\x48\xc7\xc0\x02\xf0\x00\x00\x0f"
56                              "\x01\xd9";
57
58 static const char elf_magic[] = {0x7f, 'E', 'L', 'F'};
59
60
61 /*
62  * the presence of this is kind of a hack, and exists because
63  * when one of the below hypercall handlers is invoked, we don't
64  * have an elegant way of deciding which inject queue (normal or exec-hooked)
65  * to pull the first element from, so we have this place marker
66  *
67  * This could be ugly with more than one core...
68  */
69 static struct v3_code_inject_info * current_inject;
70
71
72 static int free_code_inject (struct v3_vm_info * vm, struct v3_code_inject_info * inject) {
73     list_del(&(inject->inject_node));
74     V3_Free(inject);
75     return 0;
76 }
77
78
79 /* 
80  * helper function to save a chunk of code in an inject object's state and
81  * overwrite it with something else (mostly for injecting hypercalls)
82  */
83 static int v3_plant_code (struct guest_info * core, struct v3_code_inject_info * inject,
84                           char * hva, char * code, uint_t size) {
85     int i;
86
87     // first back up old code
88     inject->old_code = (char*)V3_Malloc(size);
89
90     if (!inject->old_code) {
91         PrintError(core->vm_info, core, "Cannot allocate in planting code\n");
92         return -1;
93     }
94
95     for (i = 0; i < size; i++)
96         inject->old_code[i] = *(hva + i);
97
98     // overwrite
99     for (i = 0; i < size; i++)
100         *(hva + i) = *(code + i);
101
102     return 0;
103 }
104
105
106 static int v3_restore_pre_mmap_state (struct guest_info * core, struct v3_code_inject_info * inject) {
107     int ret;
108     addr_t rip_hva, mmap_gva;
109
110     if ((mmap_gva = (addr_t)core->vm_regs.rbx) < 0) {
111         PrintError(core->vm_info, core, "Error running mmap in guest: v3_restore_pre_mmap_state\n");
112         return -1;
113     }
114
115     inject->code_region_gva = mmap_gva;
116
117         ret = v3_gva_to_hva(core, 
118                                                 get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
119                                                 &rip_hva);
120     if (ret == -1) {
121                 PrintError(core->vm_info, core, "Error translating RIP address: v3_restore_pre_mmap_state\n");
122                 return -1;
123     }
124
125     // restore the code overwritten by mmap code
126     memcpy((void*)rip_hva, (void*)inject->old_code, MMAP_SIZE);
127     V3_Free(inject->old_code);
128
129     v3_do_static_inject(core, inject, MMAP_COMPLETE, mmap_gva);
130     return 0;
131 }
132
133
134 static int v3_restore_pre_inject_state (struct guest_info * core, struct v3_code_inject_info * inject) {
135     int ret;
136     addr_t rip_hva;
137
138     // restore original register state at int 80
139     memcpy(&core->vm_regs, &inject->regs, sizeof(struct v3_gprs));
140     memcpy(&core->ctrl_regs, &inject->ctrl_regs, sizeof(struct v3_ctrl_regs));
141
142         ret = v3_gva_to_hva(core, 
143                                                 get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
144                                                 &rip_hva);
145     if (ret == -1) {
146                 PrintError(core->vm_info, core, "Error translating RIP address: v3_pre_inject_state\n");
147                 return -1;
148     }
149
150     // increment original rip by 2 to skip the int 80
151     core->rip = inject->rip + 2;
152     return 0;
153 }
154
155
156 /* 
157  * This function completes stage 1 of the inject. It is invoked when code to
158  * mmap space for the real code has been injected and has completed. This mmap
159  * code will hypercall back into Placios, getting us here.
160  */
161 static int mmap_init_handler (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
162     struct v3_code_inject_info * inject = current_inject;
163     v3_restore_pre_mmap_state(core, inject);
164     return 0;
165 }
166
167
168 /* 
169  * This function is stage 3 of the injection process. It is invoked when the injected code 
170  * has run to completeion and run a hypercall at its tail to get back into the
171  * VMM. After this, it only remains to unmap the space we injected it into (the
172  * 4th and final stage)
173  */
174 static int inject_code_finish (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
175     struct v3_code_inject_info * inject = current_inject;
176     addr_t hva;
177
178     // is the original int 80 page still paged in?
179     if (v3_gva_to_hva(core, 
180                         get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
181                         &hva) == -1) {
182         PrintError(core->vm_info, core, "No mapping in shadow page table: inject_code_finish\n");
183         return -1;
184     }
185
186     inject->old_code = V3_Malloc(MUNMAP_SIZE);
187
188     if (!inject->old_code) {
189         PrintError(core->vm_info, core, "Problem mallocing old code segment\n");
190         return -1;
191     }
192
193     // save old code and overwrite with munmap
194     v3_plant_code(core, inject, (char*)hva, munmap_code, MUNMAP_SIZE);
195
196     // set rbx with gva of code region
197     core->vm_regs.rbx = inject->code_region_gva;
198
199     // set rip back
200     core->rip = inject->rip;
201     return 0;
202 }
203
204
205 //
206 // this is 4th and final stage of the code injection process. It is invoked after code
207 // has been injected to run the munmap system call on our previosuly allocated
208 // memory chunk. It results in the clean
209 // up and removal of the current inject's structures and state, and its
210 // removal from any injection queues
211 // 
212 static int munmap_finish (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
213     struct v3_code_inject_info * inject = current_inject;
214     int i = 0;
215     addr_t hva;
216
217     if (core->vm_regs.rbx < 0) {
218         PrintError(core->vm_info, core, "Problem munmapping injected code\n");
219         return -1;
220     }
221
222     if (v3_gva_to_hva(core, 
223                         get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
224                         &hva) == -1) {
225         PrintError(core->vm_info, core, "No mapping in shadow page table: inject_code_finish\n");
226         return -1;
227     }
228
229     for (i = 0; i < MUNMAP_SIZE; i++) 
230         *(char*)(hva + i) = *(char*)(inject->old_code + i);
231
232     V3_Free(inject->old_code);
233
234     v3_restore_pre_inject_state(core, inject);
235
236     // clean up
237     v3_remove_code_inject(core->vm_info, inject);
238     current_inject = NULL;
239     
240     // raise the original int 80 again, causing an exec
241     return v3_raise_swintr(core, SW_INTR_SYSCALL_VEC);
242 }
243
244
245 /* 
246  * This function is comprises stage 2 of the injection process. Here, the
247  * injected code is copied one page at a time. Each time a new page must be
248  * copied, Palacios injects a page fault for it to bring it into the guest and
249  * host page tables. The fault address will be somewhere in our previously
250  * mmap'd region, but we will jump back to the same RIP every time, which
251  * contains the hypercall that invokes this function.
252  */
253 static int mmap_pf_handler (struct guest_info * core, unsigned int hcall_id, void * priv_data) {
254     struct v3_code_inject_info * inject = current_inject;
255     pf_error_t err;
256     int i, offset = core->vm_regs.rbx;
257     addr_t hva, gva = core->vm_regs.rcx;
258     memset((void*)&err, 0, sizeof(pf_error_t));
259
260     // was page fault handled by guest kernel?
261         if (v3_gva_to_hva(core, 
262                                                 get_addr_linear(core, gva, &(core->segments.ds)),
263                                                 &hva) == -1) {
264         PrintError(core->vm_info, core, "No mapping in shadow page table: mmap_pf_handler\n");
265         return -1;
266     }
267     
268     if (offset >= inject->code_size) {
269         core->rip = gva - offset + inject->func_offset;
270
271         // restore registers (here, really just for sane ebp/esp)
272         memcpy(&core->vm_regs, &inject->regs, sizeof(struct v3_gprs));
273         memcpy(&core->ctrl_regs, &inject->ctrl_regs, sizeof(struct v3_ctrl_regs));
274
275         if (v3_gva_to_hva(core, 
276                             get_addr_linear(core, inject->rip, &(core->segments.cs)),
277                             &hva) == -1) {
278             PrintError(core->vm_info, core, "No mapping for old RIP in shadow page table: mmap_pf_handler: %p\n", (void*)inject->rip);
279             return -1;
280         }
281
282         // restore the hypercall with original int 80 code
283         for (i = 0; i < VMMCALL_SIZE; i++) 
284             *(char*)(hva + i) = *(char*)(inject->old_code + i);
285
286         V3_Free(inject->old_code);
287
288         if (v3_gva_to_hva(core, 
289                             get_addr_linear(core, core->rip, &(core->segments.cs)),
290                             &hva) == -1) {
291             PrintError(core->vm_info, core, "No mapping for new RIP in shadow page table: mmap_pf_handler: %p\n", (void*)core->rip);
292             return -1;
293         }
294
295         return 0;
296     }
297
298     // copy the next page of code
299     for (i = 0; i < PAGE_SIZE; i++) 
300         *(char*)(hva + i) = *(char*)(inject->code + offset + i);
301
302
303     core->vm_regs.rbx += PAGE_SIZE;
304     core->vm_regs.rcx += PAGE_SIZE;
305
306     // to account for rip being incremented by hcall handler
307     core->rip -= VMMCALL_SIZE;
308
309     // inject the page fault for next page
310     err.user = 1;
311     err.write = 1;
312     v3_inject_guest_pf(core, gva + PAGE_SIZE, err);
313
314     return 0;
315 }
316
317
318 static int init_code_inject (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) {
319     struct v3_code_injects * injects = &code_injects;
320     INIT_LIST_HEAD(&(injects->code_inject_list));
321     INIT_LIST_HEAD(&(injects->hooked_code_injects));
322
323     injects->active = 1;
324
325     current_inject = NULL;
326
327     v3_register_hypercall(vm, 0xf000, mmap_init_handler, NULL);
328     v3_register_hypercall(vm, 0xf001, inject_code_finish, NULL);
329     v3_register_hypercall(vm, 0xf002, mmap_pf_handler, NULL);
330     v3_register_hypercall(vm, 0xf003, munmap_finish, NULL);
331     return 0;
332 }
333
334
335 static int deinit_code_inject (struct v3_vm_info * vm, void * priv_data) {
336     struct v3_code_injects * injects = &code_injects;
337     struct v3_code_inject_info * inject = NULL;
338     struct v3_code_inject_info * tmp = NULL;
339
340     list_for_each_entry_safe(inject, tmp, &(injects->code_inject_list), inject_node) {
341         free_code_inject(vm, inject); 
342     }
343
344     list_for_each_entry_safe(inject, tmp, &(injects->hooked_code_injects), inject_node) {
345         free_code_inject(vm, inject); 
346     }
347
348     v3_remove_hypercall(vm, 0xf000);
349     v3_remove_hypercall(vm, 0xf001);
350     v3_remove_hypercall(vm, 0xf002);
351     v3_remove_hypercall(vm, 0xf003);
352     return 0;
353 }
354
355
356
357
358 /* KCH currently unused */
359 /* this dynamic linking stuff will eventually be moved out of this file... */
360 static addr_t v3_get_dyn_entry (struct guest_info * core, addr_t elf_gva, addr_t elf_hva, 
361                                     int section_code) {
362     ElfW(Ehdr) *ehdr;
363     ElfW(Phdr) *phdr, *phdr_cursor;
364     ElfW(Dyn) *dyn = NULL;
365     int i, j, num_dyn;
366     addr_t hva;
367
368     ehdr = (ElfW(Ehdr)*)elf_hva;
369     phdr = (ElfW(Phdr)*)(elf_hva + ehdr->e_phoff);
370     phdr_cursor = phdr;
371
372     //PrintDebug(core->vm_info, core, "num phdrs: %d\n", ehdr->e_phnum);
373     for (i = 0; i < ehdr->e_phnum; i++, phdr_cursor++) {
374         if (phdr_cursor->p_type == PT_DYNAMIC) {
375             num_dyn = phdr_cursor->p_filesz / sizeof(ElfW(Dyn));
376             dyn = (ElfW(Dyn)*)(elf_hva + phdr_cursor->p_offset);
377
378             // make sure this addr is paged in 
379             if (v3_gva_to_gpa(core, elf_gva + phdr_cursor->p_offset, &hva) == -1) {
380                 PrintError(core->vm_info, core, "Dynamic segment isn't paged in\n");
381                 return 0;
382             }
383
384             for (j = 0; j < num_dyn; j++, dyn++) {
385                 if (dyn->d_tag == section_code) {
386                     switch (section_code) {
387                         case DT_STRSZ:
388                         case DT_SYMENT:
389                         case DT_PLTREL:
390                             return (addr_t)dyn->d_un.d_val;
391                         default:
392                             return (addr_t)dyn->d_un.d_ptr;
393                     }
394                 }
395             }
396             break;
397         }
398     }
399     return 0;
400 }
401
402
403 static int v3_do_resolve (struct guest_info * core, addr_t elf_gva, addr_t elf_hva) {
404
405     addr_t got_gva, symtab_gva, strtab_gva;
406
407     if ((got_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_PLTGOT)) == 0) {
408         PrintError(core->vm_info, core, "Problem getting at PLTGOT in v3_do_resolve\n");
409         return -1;
410     }
411
412
413     if ((strtab_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_STRTAB)) == 0) {
414         PrintError(core->vm_info, core, "Problem getting at PLTGOT in v3_do_resolve\n");
415         return -1;
416     }
417
418     if ((symtab_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_SYMTAB)) == 0) {
419         PrintError(core->vm_info, core, "Problem getting at PLTGOT in v3_do_resolve\n");
420         return -1;
421     }
422
423
424     PrintDebug(core->vm_info, core, "Got gva: %p\n", (void*)got_gva);
425     PrintDebug(core->vm_info, core, "Symtab gva: %p\n", (void*)symtab_gva);
426     PrintDebug(core->vm_info, core, "Strtab gva: %p\n", (void*)strtab_gva);
427     return 0;
428 }
429
430 static int v3_do_cont (struct guest_info * core, struct v3_code_inject_info * inject,  addr_t check) {
431
432     addr_t hva;
433     pf_error_t err_code;
434     int ret;
435
436     ret = v3_gva_to_gpa(core, check, &hva);
437
438     // page fault wasn't handled by kernel??
439     if (ret == -1) {
440         PrintError(core->vm_info, core, "ERROR: no mapping in guest page table!\n");
441         return -1;
442     }
443
444         ret = v3_gva_to_hva(core, 
445                                                 get_addr_linear(core, check, &(core->segments.cs)),
446                                                 &hva);
447
448     // this should never happen...
449         if (ret == -1) {
450         PrintError(core->vm_info, core, "ERROR: no mapping in shadow page table\n");
451         return -1;
452         }
453     
454     if (strncmp(elf_magic, (char*)hva, ELF_MAG_SIZE) != 0) {
455
456         check -= PAGE_SIZE;
457         inject->cont->check_addr = check;
458         inject->cont->cont_func = v3_do_cont;
459
460         memset((void*)&err_code, 0, sizeof(pf_error_t));
461         err_code.user = 1;
462
463         if (v3_inject_guest_pf(core, check, err_code) < 0) {
464             PrintError(core->vm_info, core, "Problem injecting pf\n");
465             return -1;
466         }
467
468         return E_NEED_PF;
469     }
470
471     PrintDebug(core->vm_info, core, "Found ELF!\n");
472     V3_Free(inject->cont);
473     inject->cont = NULL;
474     return v3_do_resolve(core, check, hva);
475 }
476  
477
478 /*
479  * mmap_state: 0 = no inject space in procces yet
480  *             1 = code segment space mmap'd, still need data
481  *             2 = code & data segments mmap'd, ready to inject real code
482  *
483  */
484 //
485 // return  E_NEED_PF up the call stack to signal page fault injection
486 // (so rip doesn't get incremented and sw_intr doesn't get injected
487 //
488 int v3_do_inject (struct guest_info * core, struct v3_code_inject_info * inject, int mmap_state) {
489         addr_t rip_hva, elf_hva, elf_gva;
490         int ret = 0, i = 0;
491     pf_error_t err_code;
492
493     memset((void*)&err_code, 0, sizeof(pf_error_t));
494         
495         ret = v3_gva_to_hva(core, 
496                                                 get_addr_linear(core, (addr_t)core->rip, &(core->segments.cs)),
497                                                 &rip_hva);
498         if (ret == -1) {
499                 PrintError(core->vm_info, core, "Error translating RIP address in v3_do_inject\n");
500                 return -1;
501         }
502
503     elf_gva = (addr_t)(core->rip & 0xfffffffffffff000);
504
505     for (i = 0; i < PAGES_BACK; i++, elf_gva -= PAGE_SIZE) {
506     
507         ret = v3_gva_to_hva(core, 
508                             get_addr_linear(core, elf_gva, &(core->segments.cs)),
509                             &elf_hva);
510
511         // need to page in
512         if (ret == -1) {
513
514             PrintDebug(core->vm_info, core, "Found a page we need to fault in\n");
515             inject->cont = (struct v3_cont *)V3_Malloc(sizeof(struct v3_cont));
516
517             if (!inject->cont) {
518                 PrintError(core->vm_info, core, "Cannot allocate in doing inject\n");
519                 return -1;
520             }
521
522             ret = v3_gva_to_gpa(core, elf_gva, &elf_hva);
523
524             if (ret == -1) {
525                 PrintDebug(core->vm_info, core, "no mapping in guest page table\n");
526             }
527
528             inject->cont->check_addr = elf_gva;
529             inject->cont->cont_func = v3_do_cont;
530             err_code.user = 1;
531
532             PrintDebug(core->vm_info, core, "Injecting pf for addr: %p\n", (void*) elf_gva);
533
534             if (v3_inject_guest_pf(core, elf_gva, err_code) < 0) {
535                 PrintError(core->vm_info, core, "Problem injecting pf\n");
536                 return -1;
537             }
538
539             return E_NEED_PF;
540         }
541
542         if (strncmp(elf_magic, (char*)elf_hva, ELF_MAG_SIZE) == 0) {
543             PrintDebug(core->vm_info, core, "Found elf_magic!\n");
544             break;
545         }
546
547     }
548
549
550     V3_Free(inject->cont);
551     inject->cont = NULL;
552     return v3_do_resolve(core, elf_gva, elf_hva);
553
554     PrintDebug(core->vm_info, core, "Planting code\n");
555     v3_plant_code(core, inject, (char*)rip_hva, mmap_code, MMAP_SIZE);
556
557     PrintDebug(core->vm_info, core, "Saving register context\n");
558     PrintDebug(core->vm_info, core, "First 8 bytes 0x%lx\n", *(long*)rip_hva);
559     /* may need to save v3_ctrl registers too... */
560     memcpy(&inject->regs, &core->vm_regs, sizeof(struct v3_gprs));
561     inject->rip = core->rip;
562
563     /* jump to injected code */
564     PrintDebug(core->vm_info, core, "Jumping to injected code\n");
565         return 0;
566 }
567
568
569 /*
570  * mmap_state: NO_MMAP = no inject space mmap'd in procces yet
571  *             MMAP_COMPLETE = mmap complete, time to do real inject
572  *
573  */
574 int v3_do_static_inject (struct guest_info * core, struct v3_code_inject_info * inject,
575                          int mmap_state, addr_t region_gva) {
576         addr_t rip_hva;
577         int ret;
578
579         
580         ret = v3_gva_to_hva(core, 
581                                                 get_addr_linear(core, (addr_t)core->rip, &(core->segments.cs)),
582                                                 &rip_hva);
583         if (ret == -1) {
584                 PrintError(core->vm_info, core, "Error translating RIP address: v3_do_static_inject\n");
585                 return -1;
586         }
587
588     switch (mmap_state) { 
589         case NO_MMAP: 
590         {
591             // inject mmap code
592             v3_plant_code(core, inject, (char*)rip_hva, mmap_code, MMAP_SIZE);
593
594             // save registers (gprs and ctrl regs, and rip)
595             memcpy(&inject->regs, &core->vm_regs, sizeof(struct v3_gprs));
596             memcpy(&inject->ctrl_regs, &core->ctrl_regs, sizeof(struct v3_ctrl_regs));
597             inject->rip = core->rip;
598
599             // jump to mmap code, and squash original swintr
600             return E_NEED_PF;
601         }
602         case MMAP_COMPLETE:
603         {
604             pf_error_t err_code;
605             memset((void*)&err_code, 0, sizeof(pf_error_t));
606
607             ret = v3_gva_to_hva(core, 
608                                 get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)),
609                                 &rip_hva);
610             if (ret == -1) {
611                 PrintError(core->vm_info, core, "Error translating RIP address: v3_do_static_inject\n");
612                 return -1;
613             }
614
615             // inject hypercall code
616             v3_plant_code(core, inject, (char*)rip_hva, vmmcall_code, VMMCALL_SIZE);
617
618             /* store current copy offset in rbx, fault gva in rcx */
619             core->vm_regs.rbx = 0;
620             core->vm_regs.rcx = region_gva;
621
622             err_code.user = 1;
623             err_code.write = 1;
624
625             // inject the first page fault for the code block
626             if (v3_inject_guest_pf(core, region_gva, err_code) < 0) {
627                 PrintError(core->vm_info, core, "Problem injecting page fault in v3_do_static_inject\n");
628                 return -1;
629             }
630
631             // returning here will run hypercall 0xf002
632             // This will get us back in v3_mmap_pf_handler
633             core->rip = inject->rip;
634             return 0;
635         }
636         default:
637             PrintError(core->vm_info, core, "Invalid mmap state\n");
638             return -1;
639     }
640         return 0;
641 }
642
643
644 /*
645  * This function is invoked in one of two ways:
646  * 1. A syscall has been intercepted and we've popped off the next pending
647  * inject
648  * 2. An exec has been intercepted and we've popped off the next hooked inject
649  *
650  */
651 int v3_handle_guest_inject (struct guest_info * core, void * priv_data) {
652     struct v3_code_inject_info * inject = (struct v3_code_inject_info *)priv_data;
653
654     /* eventually this should turn into a mutex lock */
655     if (current_inject) {
656         PrintError(core->vm_info, core, "An inject is already in progress\n");
657         return -1;
658     } else {
659         current_inject = inject;
660         inject->in_progress = 1;
661     }
662
663     if (!inject->is_dyn) {
664         return v3_do_static_inject(core, inject, 0, (addr_t)NULL);
665     } else {
666         if (inject->cont) 
667            return inject->cont->cont_func(core, inject, inject->cont->check_addr);
668         else 
669            return v3_do_inject(core, inject, 0);
670     }
671
672     return 0;
673 }
674
675
676 int v3_insert_code_inject (void * ginfo, void * code, int size, 
677                            char * bin_file, int is_dyn, int is_exec_hooked, int func_offset) {
678     struct v3_code_injects * injects = &code_injects;
679     struct v3_vm_info * vm = (struct v3_vm_info *)ginfo;
680     struct v3_code_inject_info * inject;
681
682     if (!injects->active) {
683         PrintError(vm, VCORE_NONE, "Code injection has not been initialized\n");
684         return -1;
685     }
686
687     inject = V3_Malloc(sizeof(struct v3_code_inject_info));
688     if (!inject) {
689         PrintError(vm, VCORE_NONE, "Error allocating inject info in v3_insert_code_inject\n");
690         return -1;
691     }
692
693     memset(inject, 0, sizeof(struct v3_code_inject_info));
694
695     inject->code = code;
696     inject->code_size = size;
697     inject->is_dyn = is_dyn;
698     inject->func_offset = func_offset;
699     inject->bin_file = bin_file;
700     inject->is_exec_hooked = is_exec_hooked;
701
702     if (is_exec_hooked) {
703         v3_hook_executable(vm, bin_file, v3_handle_guest_inject, (void*)inject);
704         list_add_tail(&(inject->inject_node), &(injects->hooked_code_injects));
705     } else {
706         list_add_tail(&(inject->inject_node), &(injects->code_inject_list));
707     }
708
709     return 0;
710 }
711
712
713 int v3_remove_code_inject (struct v3_vm_info * vm, struct v3_code_inject_info * inject) {
714
715     PrintDebug(vm, VCORE_NONE, "Removing and freeing code inject\n");
716     if (inject->is_exec_hooked) {
717         if (v3_unhook_executable(vm, inject->bin_file) < 0) {
718             PrintError(vm, VCORE_NONE, "Problem unhooking executable in v3_remove_code_inject\n");
719             return -1;
720         }
721     }
722
723     free_code_inject(vm, inject);
724     return 0;
725 }
726
727
728 static struct v3_extension_impl code_inject_impl = {
729         .name = "code_inject",
730         .init = init_code_inject,
731         .deinit = deinit_code_inject,
732         .core_init = NULL,
733         .core_deinit = NULL,
734         .on_entry = NULL,
735         .on_exit = NULL
736 };
737 register_extension(&code_inject_impl);
738