2 * V3 Top Half Injection Utility
3 * This code allows a user to inject a "top half" of code into a running guest.
4 * The "bottom half" (a hypercall handler) is inserted using another utility.
6 * (c) Kyle C. Hale, 2011
16 #include <sys/types.h>
17 #include <sys/ioctl.h>
19 #include "iface-code-inject.h"
22 #define __ELF_INJECT_CLASS 32
24 #define ElfW(type) _ElfW (Elf, __ELF_INJECT_CLASS, type)
25 #define _ElfW(e,w,t) _ElfW_1 (e, w, _##t)
26 #define _ElfW_1(e,w,t) e##w##t
29 /* look for PT_DYNAMIC to see if it's dynamically linked */
30 static int is_dynamic (ElfW(Ehdr) * ehdr) {
32 ElfW(Phdr) * phdr = (ElfW(Phdr)*)((char*)ehdr + ehdr->e_phoff);
33 ElfW(Phdr) * phdr_cursor;
37 for (i = 0; i < ehdr->e_phnum; i++, phdr_cursor++) {
38 if (phdr_cursor->p_type == PT_DYNAMIC)
46 int main (int argc, char **argv) {
48 char *top_half = NULL;
49 char *bin_file = NULL;
50 int t_fd, err, bytes_read, entry;
52 struct top_half_data elf;
55 if (argc < 4 || argc > 5) {
56 // TODO: add a better explanation here
57 v3_usage("/dev/v3-vm<N> <inject-code> <code-entry-offset> [inject-point-exe]\n\n"
58 "\tinject-code : the binary file to be injected\n\n"
59 "\tcode-entry-offset : offset in the binary to .text\n\n"
60 "\tinject-point-exe : if exec-hooked injection is used, use this exec name\n");
66 entry = strtol(argv[3], NULL, 0);
71 t_fd = open(top_half, O_RDONLY);
73 fprintf(stderr, "Error opening top half .o file: %s\n", top_half);
77 if (fstat(t_fd, &t_stat) < 0) {
78 fprintf(stderr, "Error: could not stat ELF binary file %s\n", top_half);
82 memset(&elf, 0, sizeof(struct top_half_data));
84 elf.elf_size = t_stat.st_size;
87 strcpy(elf.bin_file, bin_file);
88 elf.is_exec_hooked = 1;
90 elf.is_exec_hooked = 0;
95 elf.elf_data = malloc(elf.elf_size);
97 fprintf(stderr, "Error allocating memory for ELF data\n");
101 printf("Loading ELF binary...\n");
102 if ((bytes_read = read(t_fd, elf.elf_data, elf.elf_size)) < 0) {
103 fprintf(stderr, "Error loading ELF binary %s\n", top_half);
107 printf("Loaded. %d Bytes of data read\n", bytes_read);
108 elf_hdr = (ElfW(Ehdr)*)elf.elf_data;
110 /* set the entry point */
111 elf.func_offset = entry;
113 /* check the ELF magic nr to make sure this is a valid ELF */
114 if (elf_hdr->e_ident[EI_MAG0] != 0x7f ||
115 elf_hdr->e_ident[EI_MAG1] != 'E' ||
116 elf_hdr->e_ident[EI_MAG2] != 'L' ||
117 elf_hdr->e_ident[EI_MAG3] != 'F') {
119 fprintf(stderr, "Error: Invalid ELF binary %s\n", top_half);
123 /* make sure the ELF is an actual executable file */
124 if (elf_hdr->e_type != ET_EXEC) {
125 fprintf(stderr, "Error: ELF must be an executable file %s\n", top_half);
129 /* is it a dynamically linked executable? */
130 elf.is_dyn = is_dynamic(elf_hdr);
133 printf("Transferring control to Palacios\n");
134 err = v3_vm_ioctl(vm_dev, V3_VM_TOPHALF_INJECT, &elf);
136 fprintf(stderr, "Error providing top half to palacios: %s\n", top_half);