From: Kyle Hale Date: Fri, 13 Apr 2012 21:23:36 +0000 (-0500) Subject: New Gears Tools And Structure X-Git-Url: http://v3vee.org/palacios/gitweb/gitweb.cgi?a=commitdiff_plain;h=7229981629c6baa0afb61cc99cfcf6dd029c9c93;p=palacios.git New Gears Tools And Structure --- diff --git a/palacios/include/gears/code_inject.h b/palacios/include/gears/code_inject.h new file mode 100644 index 0000000..b2fb7fc --- /dev/null +++ b/palacios/include/gears/code_inject.h @@ -0,0 +1,97 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __CODE_INJECT_H__ +#define __CODE_INJECT_H__ + +int v3_insert_code_inject (void *ginfo, void *code, int size, char *bin_file, + int is_dyn, int is_exec_hooked, int func_offset); + +#ifdef __V3VEE__ + +#define E_NEED_PF -2 + +#define MMAP_SIZE 86 +#define MUNMAP_SIZE 22 +#define VMMCALL_SIZE 10 + +#define PAGES_BACK 50 +#define ELF_MAG_SIZE 4 +#define NO_MMAP 0 +#define MMAP_COMPLETE 1 + +struct v3_code_injects { + struct list_head code_inject_list; + struct list_head hooked_code_injects; + int active; +}; + + +// TODO: adjust size of boolean members +struct v3_code_inject_info { + + // pointer to ELF and its size + void *code; + int code_size; + + + // indicates this is a hooked inject + int is_exec_hooked; + char * bin_file; + + // important offsets to ELF sections + // for the injected code + int func_offset; + int got_offset; + int plt_offset; + + + int is_dyn; + addr_t code_region_gva; + // continuation-style function for + // page fault handling + struct v3_cont *cont; + + + // the following are for saving context + char *old_code; + struct v3_gprs regs; + struct v3_ctrl_regs ctrl_regs; + uint64_t rip; + + struct list_head inject_node; + + int in_progress; +}; + +struct v3_cont { + addr_t check_addr; + int (*cont_func)(struct guest_info * core, struct v3_code_inject_info * inject, + addr_t check); +}; + +int v3_remove_code_inject(struct v3_vm_info * vm, struct v3_code_inject_info * inject); +int v3_do_inject(struct guest_info * core, struct v3_code_inject_info * inject, int mmap_state); +int v3_do_static_inject(struct guest_info * core, struct v3_code_inject_info * inject, + int mmap_state, addr_t region_gva); +int v3_handle_guest_inject(struct guest_info * core, void * priv_data); + +#endif /* ! __V3VEE__ */ + +#endif diff --git a/palacios/include/gears/env_inject.h b/palacios/include/gears/env_inject.h new file mode 100644 index 0000000..f1a48c9 --- /dev/null +++ b/palacios/include/gears/env_inject.h @@ -0,0 +1,43 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2012, Kyle C. Hale + * Copyright (c) 2012, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __ENV_INJECT_H__ +#define __ENV_INJECT_H__ + +int v3_insert_env_inject (void *ginfo, char ** strings, int num_strings, char * bin_name); + +#ifdef __V3VEE__ + +struct v3_env_injects { + struct list_head env_inject_list; +}; + + +struct v3_env_inject_info { + char ** env_vars; + int num_env_vars; + struct list_head inject_node; + char * bin_name; +}; + +int v3_remove_env_inject (struct v3_vm_info * vm, struct v3_env_inject_info * inject); + +#endif /* ! __V3VEE__ */ + +#endif diff --git a/palacios/include/gears/execve_hook.h b/palacios/include/gears/execve_hook.h new file mode 100644 index 0000000..c32ae4b --- /dev/null +++ b/palacios/include/gears/execve_hook.h @@ -0,0 +1,49 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +#ifndef __EXECVE_HOOK_H__ +#define __EXECVE_HOOK_H__ + +#ifdef __V3VEE__ + +struct v3_exec_hooks { + struct list_head hook_list; + struct hashtable * bin_table; +}; + + +struct exec_hook { + int (*handler)(struct guest_info * core, void * priv_data); + struct list_head hook_node; + void * priv_data; +}; + + +int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data); + +#endif + +int v3_hook_executable (struct v3_vm_info * vm, + const uchar_t * binfile, + int (*handler)(struct guest_info * core, void * priv_data), + void * priv_data); + +int v3_unhook_executable (struct v3_vm_info * core, const uchar_t * binfile); +#endif diff --git a/palacios/include/gears/process_environment.h b/palacios/include/gears/process_environment.h new file mode 100644 index 0000000..efe4735 --- /dev/null +++ b/palacios/include/gears/process_environment.h @@ -0,0 +1,51 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __PROCESS_ENVIRONMENT_H__ +#define __PROCESS_ENVIRONMENT_H__ + +#ifdef __V3VEE__ + + +#include +#include +#include + + +struct v3_execve_varchunk { + char ** argv; + char ** envp; + uint_t argc; + uint_t envc; + uint_t bytes; + int active; +}; + +int v3_replace_arg (struct guest_info * core, uint_t argnum, const char * newval); +int v3_replace_env (struct guest_info * core, const char * envname, const char * newval); + +int v3_inject_strings (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt); + +addr_t v3_prepare_guest_stack (struct guest_info * core, uint_t bytes_needed); + + +#endif + +#endif + diff --git a/palacios/include/gears/sw_intr.h b/palacios/include/gears/sw_intr.h new file mode 100644 index 0000000..45c2bdc --- /dev/null +++ b/palacios/include/gears/sw_intr.h @@ -0,0 +1,37 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +#ifndef __SW_INTR_H__ +#define __SW_INTR_H__ + +#include + +#define SW_INTR_SYSCALL_VEC 0x80 + +int v3_handle_swintr (struct guest_info * core); + +int v3_hook_swintr (struct guest_info * core, + uint8_t vector, + int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data), + void * priv_data); +int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector); + + +#endif diff --git a/palacios/include/gears/syscall_hijack.h b/palacios/include/gears/syscall_hijack.h new file mode 100644 index 0000000..4db6088 --- /dev/null +++ b/palacios/include/gears/syscall_hijack.h @@ -0,0 +1,68 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __SYSCALL_HIJACK_H__ +#define __SYSCALL_HIJACK_H__ + +#define STAR_MSR 0xc0000081 /* Legacy mode SYSCALL target */ +#define LSTAR_MSR 0xc0000082 /* Long mode SYSCALL target */ +#define CSTAR_MSR 0xc0000083 /* compat mode SYSCALL target */ +#define SF_MASK_MSR 0xc0000084 /* EFLAGS mask for syscall */ +#define SYSENTER_CS_MSR 0x00000174 /* SYSENTER/EXIT are for legacy mode only on AMD */ +#define SYSENTER_ESP_MSR 0x00000175 +#define SYSENTER_EIP_MSR 0x00000176 + +/* Intel specific */ +#define IA32_SYSENTER_CS_MSR 0x00000174 +#define IA32_SYSENTER_ESP_MSR 0x00000175 +#define IA32_SYSENTER_EIP_MSR 0x00000176 + +#define MAX_CHARS 256 +#ifndef max + #define max(a, b) ( ((a) > (b)) ? (a) : (b) ) +#endif + +#define SYSCALL_INT_VECTOR 0x80 +#define SYSCALL_CPUID_NUM 0x80000001 +#define SYSENTER_CPUID_NUM 0x00000001 + +#define SYSCALL_MAGIC_ADDR 0xffffffffffffffff + +#define KERNEL_PHYS_LOAD_ADDR 0x1000000 + + +struct v3_syscall_info { + uint64_t target_addr; + uint8_t syscall_map_injected; + char * syscall_page_backup; + uint8_t * syscall_map; + addr_t syscall_stub; + // state save area + addr_t ssa; +}; + +int v3_hook_syscall (struct guest_info * core, + uint_t syscall_nr, + int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data), + void * priv_data); + +int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr); +int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data); + +#endif diff --git a/palacios/include/gears/syscall_ref.h b/palacios/include/gears/syscall_ref.h new file mode 100644 index 0000000..260ff33 --- /dev/null +++ b/palacios/include/gears/syscall_ref.h @@ -0,0 +1,665 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#ifndef __SYSCALL_REF_H__ +#define __SYSCALL_REF_H__ + +char * get_linux_syscall_name32 (uint_t syscall_nr); +char * get_linux_syscall_name64 (uint_t syscall_nr); + + +/* 32bit syscalls */ +#define SYS32_RESTART_SYSCALL 0 +#define SYS32_EXIT 1 +#define SYS32_FORK 2 +#define SYS32_READ 3 +#define SYS32_WRITE 4 +#define SYS32_OPEN 5 +#define SYS32_CLOSE 6 +#define SYS32_WAITPID 7 +#define SYS32_CREAT 8 +#define SYS32_LINK 9 +#define SYS32_UNLINK 10 +#define SYS32_EXECVE 11 +#define SYS32_CHDIR 12 +#define SYS32_TIME 13 +#define SYS32_MKNOD 14 +#define SYS32_CHMOD 15 +#define SYS32_LCHOWN 16 +#define SYS32_BREAK 17 +#define SYS32_OLDSTAT 18 +#define SYS32_LSEEK 19 +#define SYS32_GETPID 20 +#define SYS32_MOUNT 21 +#define SYS32_UMOUNT 22 +#define SYS32_SETUID 23 +#define SYS32_GETUID 24 +#define SYS32_STIME 25 +#define SYS32_PTRACE 26 +#define SYS32_ALARM 27 +#define SYS32_OLDFSTAT 28 +#define SYS32_PAUSE 29 +#define SYS32_UTIME 30 +#define SYS32_STTY 31 +#define SYS32_GTTY 32 +#define SYS32_ACCESS 33 +#define SYS32_NICE 34 +#define SYS32_FTIME 35 +#define SYS32_SYNC 36 +#define SYS32_KILL 37 +#define SYS32_RENAME 38 +#define SYS32_MKDIR 39 +#define SYS32_RMDIR 40 +#define SYS32_DUP 41 +#define SYS32_PIPE 42 +#define SYS32_TIMES 43 +#define SYS32_PROF 44 +#define SYS32_BRK 45 +#define SYS32_SETGID 46 +#define SYS32_GETGID 47 +#define SYS32_SIGNAL 48 +#define SYS32_GETEUID 49 +#define SYS32_GETEGID 50 +#define SYS32_ACCT 51 +#define SYS32_UMOUNT2 52 +#define SYS32_LOCK 53 +#define SYS32_IOCTL 54 +#define SYS32_FCNTL 55 +#define SYS32_MPX 56 +#define SYS32_SETPGID 57 +#define SYS32_ULIMIT 58 +#define SYS32_OLDOLDUNAME 59 +#define SYS32_UMASK 60 +#define SYS32_CHROOT 61 +#define SYS32_USTAT 62 +#define SYS32_DUP2 63 +#define SYS32_GETPPID 64 +#define SYS32_GETPGRP 65 +#define SYS32_SETSID 66 +#define SYS32_SIGACTION 67 +#define SYS32_SGETMASK 68 +#define SYS32_SSETMASK 69 +#define SYS32_SETREUID 70 +#define SYS32_SETREGID 71 +#define SYS32_SIGSUSPEND 72 +#define SYS32_SIGPENDING 73 +#define SYS32_SETHOSTNAME 74 +#define SYS32_SETRLIMIT 75 +#define SYS32_GETRLIMIT 76 +#define SYS32_GETRUSAGE 77 +#define SYS32_GETTIMEOFDAY 78 +#define SYS32_SETTIMEOFDAY 79 +#define SYS32_GETGROUPS 80 +#define SYS32_SETGROUPS 81 +#define SYS32_SELECT 82 +#define SYS32_SYMLINK 83 +#define SYS32_OLDLSTAT 84 +#define SYS32_READLINK 85 +#define SYS32_USELIB 86 +#define SYS32_SWAPON 87 +#define SYS32_REBOOT 88 +#define SYS32_READDIR 89 +#define SYS32_MMAP 90 +#define SYS32_MUNMAP 91 +#define SYS32_TRUNCATE 92 +#define SYS32_FTRUNCATE 93 +#define SYS32_FCHMOD 94 +#define SYS32_FCHOWN 95 +#define SYS32_GETPRIORITY 96 +#define SYS32_SETPRIORITY 97 +#define SYS32_PROFIL 98 +#define SYS32_STATFS 99 +#define SYS32_FSTATFS 100 +#define SYS32_IOPERM 101 +#define SYS32_SOCKETCALL 102 +#define SYS32_SYSLOG 103 +#define SYS32_SETITIMER 104 +#define SYS32_GETITIMER 105 +#define SYS32_STAT 106 +#define SYS32_LSTAT 107 +#define SYS32_FSTAT 108 +#define SYS32_OLDUNAME 109 +#define SYS32_IOPL 110 +#define SYS32_VHANGUP 111 +#define SYS32_IDLE 112 +#define SYS32_VM86OLD 113 +#define SYS32_WAIT4 114 +#define SYS32_SWAPOFF 115 +#define SYS32_SYSINFO 116 +#define SYS32_IPC 117 +#define SYS32_FSYNC 118 +#define SYS32_SIGRETURN 119 +#define SYS32_CLONE 120 +#define SYS32_SETDOMAINNAME 121 +#define SYS32_UNAME 122 +#define SYS32_MODIFY_LDT 123 +#define SYS32_ADJTIMEX 124 +#define SYS32_MPROTECT 125 +#define SYS32_SIGPROCMASK 126 +#define SYS32_CREATE_MODULE 127 +#define SYS32_INIT_MODULE 128 +#define SYS32_DELETE_MODULE 129 +#define SYS32_GET_KERNEL_SYMS 130 +#define SYS32_QUOTACTL 131 +#define SYS32_GETPGID 132 +#define SYS32_FCHDIR 133 +#define SYS32_BDFLUSH 134 +#define SYS32_SYSFS 135 +#define SYS32_PERSONALITY 136 +#define SYS32_AFS_SYSCALL 137 +#define SYS32_SETFSUID 138 +#define SYS32_SETFSGID 139 +#define SYS32__LLSEEK 140 +#define SYS32_GETDENTS 141 +#define SYS32__NEWSELECT 142 +#define SYS32_FLOCK 143 +#define SYS32_MSYNC 144 +#define SYS32_READV 145 +#define SYS32_WRITEV 146 +#define SYS32_GETSID 147 +#define SYS32_FDATASYNC 148 +#define SYS32__SYSCTL 149 +#define SYS32_MLOCK 150 +#define SYS32_MUNLOCK 151 +#define SYS32_MLOCKALL 152 +#define SYS32_MUNLOCKALL 153 +#define SYS32_SCHED_SETPARAM 154 +#define SYS32_SCHED_GETPARAM 155 +#define SYS32_SCHED_SETSCHEDULER 156 +#define SYS32_SCHED_GETSCHEDULER 157 +#define SYS32_SCHED_YIELD 158 +#define SYS32_SCHED_GET_PRIORITY_MAX 159 +#define SYS32_SCHED_GET_PRIORITY_MIN 160 +#define SYS32_SCHED_RR_GET_INTERVAL 161 +#define SYS32_NANOSLEEP 162 +#define SYS32_MREMAP 163 +#define SYS32_SETRESUID 164 +#define SYS32_GETRESUID 165 +#define SYS32_VM86 166 +#define SYS32_QUERY_MODULE 167 +#define SYS32_POLL 168 +#define SYS32_NFSSERVCTL 169 +#define SYS32_SETRESGID 170 +#define SYS32_GETRESGID 171 +#define SYS32_PRCTL 172 +#define SYS32_RT_SIGRETURN 173 +#define SYS32_RT_SIGACTION 174 +#define SYS32_RT_SIGPROCMASK 175 +#define SYS32_RT_SIGPENDING 176 +#define SYS32_RT_SIGTIMEDWAIT 177 +#define SYS32_RT_SIGQUEUEINFO 178 +#define SYS32_RT_SIGSUSPEND 179 +#define SYS32_PREAD64 180 +#define SYS32_PWRITE64 181 +#define SYS32_CHOWN 182 +#define SYS32_GETCWD 183 +#define SYS32_CAPGET 184 +#define SYS32_CAPSET 185 +#define SYS32_SIGALTSTACK 186 +#define SYS32_SENDFILE 187 +#define SYS32_GETPMSG 188 +#define SYS32_PUTPMSG 189 +#define SYS32_VFORK 190 +#define SYS32_UGETRLIMIT 191 +#define SYS32_MMAP2 192 +#define SYS32_TRUNCATE64 193 +#define SYS32_FTRUNCATE64 194 +#define SYS32_STAT64 195 +#define SYS32_LSTAT64 196 +#define SYS32_FSTAT64 197 +#define SYS32_LCHOWN32 198 +#define SYS32_GETUID32 199 +#define SYS32_GETGID32 200 +#define SYS32_GETEUID32 201 +#define SYS32_GETEGID32 202 +#define SYS32_SETREUID32 203 +#define SYS32_SETREGID32 204 +#define SYS32_GETGROUPS32 205 +#define SYS32_SETGROUPS32 206 +#define SYS32_FCHOWN32 207 +#define SYS32_SETRESUID32 208 +#define SYS32_GETRESUID32 209 +#define SYS32_SETRESGID32 210 +#define SYS32_GETRESGID32 211 +#define SYS32_CHOWN32 212 +#define SYS32_SETUID32 213 +#define SYS32_SETGID32 214 +#define SYS32_SETFSUID32 215 +#define SYS32_SETFSGID32 216 +#define SYS32_PIVOT_ROOT 217 +#define SYS32_MINCORE 218 +#define SYS32_MADVISE1 219 +#define SYS32_GETDENTS64 220 +#define SYS32_FCNTL64 221 +#define SYS32_GETTID 224 +#define SYS32_READAHEAD 225 +#define SYS32_SETXATTR 226 +#define SYS32_LSETXATTR 227 +#define SYS32_FSETXATTR 228 +#define SYS32_GETXATTR 229 +#define SYS32_LGETXATTR 230 +#define SYS32_FGETXATTR 231 +#define SYS32_LISTXATTR 232 +#define SYS32_LLISTXATTR 233 +#define SYS32_FLISTXATTR 234 +#define SYS32_REMOVEXATTR 235 +#define SYS32_LREMOVEXATTR 236 +#define SYS32_FREMOVEXATTR 237 +#define SYS32_TKILL 238 +#define SYS32_SENDFILE64 239 +#define SYS32_FUTEX 240 +#define SYS32_SCHED_SETAFFINITY 241 +#define SYS32_SCHED_GETAFFINITY 242 +#define SYS32_SET_THREAD_AREA 243 +#define SYS32_GET_THREAD_AREA 244 +#define SYS32_IO_SETUP 245 +#define SYS32_IO_DESTROY 246 +#define SYS32_IO_GETEVENTS 247 +#define SYS32_IO_SUBMIT 248 +#define SYS32_IO_CANCEL 249 +#define SYS32_FADVISE64 250 +#define SYS32_EXIT_GROUP 252 +#define SYS32_LOOKUP_DCOOKIE 253 +#define SYS32_EPOLL_CREATE 254 +#define SYS32_EPOLL_CTL 255 +#define SYS32_EPOLL_WAIT 256 +#define SYS32_REMAP_FILE_PAGES 257 +#define SYS32_SET_TID_ADDRESS 258 +#define SYS32_TIMER_CREATE 259 +#define SYS32_TIMER_SETTIME 260 +#define SYS32_TIMER_GETTIME 261 +#define SYS32_TIMER_GETOVERRUN 262 +#define SYS32_TIMER_DELETE 263 +#define SYS32_CLOCK_SETTIME 264 +#define SYS32_CLOCK_GETTIME 265 +#define SYS32_CLOCK_GETRES 266 +#define SYS32_CLOCK_NANOSLEEP 267 +#define SYS32_STATFS64 268 +#define SYS32_FSTATFS64 269 +#define SYS32_TGKILL 270 +#define SYS32_UTIMES 271 +#define SYS32_FADVISE64_64 272 +#define SYS32_VSERVER 273 +#define SYS32_MBIND 274 +#define SYS32_GET_MEMPOLICY 275 +#define SYS32_SET_MEMPOLICY 276 +#define SYS32_MQ_OPEN 277 +#define SYS32_MQ_UNLINK 278 +#define SYS32_MQ_TIMEDSEND 279 +#define SYS32_MQ_TIMEDRECEIVE 280 +#define SYS32_MQ_NOTIFY 281 +#define SYS32_MQ_GETSETATTR 282 +#define SYS32_KEXEC_LOAD 283 +#define SYS32_WAITID 284 +#define SYS32_SYS32_SETALTROOT 285 +#define SYS32_ADD_KEY 286 +#define SYS32_REQUEST_KEY 287 +#define SYS32_KEYCTL 288 +#define SYS32_IOPRIO_SET 289 +#define SYS32_IOPRIO_GET 290 +#define SYS32_INOTIFY_INIT 291 +#define SYS32_INOTIFY_ADD_WATCH 292 +#define SYS32_INOTIFY_RM_WATCH 293 +#define SYS32_MIGRATE_PAGES 294 +#define SYS32_OPENAT 295 +#define SYS32_MKDIRAT 296 +#define SYS32_MKNODAT 297 +#define SYS32_FCHOWNAT 298 +#define SYS32_FUTIMESAT 299 +#define SYS32_FSTATAT64 300 +#define SYS32_UNLINKAT 301 +#define SYS32_RENAMEAT 302 +#define SYS32_LINKAT 303 +#define SYS32_SYMLINKAT 304 +#define SYS32_READLINKAT 305 +#define SYS32_FCHMODAT 306 +#define SYS32_FACCESSAT 307 +#define SYS32_PSELECT6 308 +#define SYS32_PPOLL 309 +#define SYS32_UNSHARE 310 +#define SYS32_SET_ROBUST_LIST 311 +#define SYS32_GET_ROBUST_LIST 312 +#define SYS32_SPLICE 313 +#define SYS32_SYNC_FILE_RANGE 314 +#define SYS32_TEE 315 +#define SYS32_VMSPLICE 316 +#define SYS32_MOVE_PAGES 317 +#define SYS32_GETCPU 318 +#define SYS32_EPOLL_PWAIT 319 +#define SYS32_UTIMENSAT 320 +#define SYS32_SIGNALFD 321 +#define SYS32_TIMERFD_CREATE 322 +#define SYS32_EVENTFD 323 +#define SYS32_FALLOCATE 324 +#define SYS32_TIMERFD_SETTIME 325 +#define SYS32_TIMERFD_GETTIME 326 +#define SYS32_SIGNALFD4 327 +#define SYS32_EVENTFD2 328 +#define SYS32_EPOLL_CREATE1 329 +#define SYS32_DUP3 330 +#define SYS32_PIPE2 331 +#define SYS32_INOTIFY_INIT1 332 +#define SYS32_PREADV 333 +#define SYS32_PWRITEV 334 +#define SYS32_RT_TGSIGQUEUEINFO 335 +#define SYS32_PERF_EVENT_OPEN 336 + +/* 64bit syscalls */ +#define SYS64_READ 0 +#define SYS64_WRITE 1 +#define SYS64_OPEN 2 +#define SYS64_CLOSE 3 +#define SYS64_STAT 4 +#define SYS64_FSTAT 5 +#define SYS64_LSTAT 6 +#define SYS64_POLL 7 +#define SYS64_LSEEK 8 +#define SYS64_MMAP 9 +#define SYS64_MPROTECT 10 +#define SYS64_MUNMAP 11 +#define SYS64_BRK 12 +#define SYS64_RT_SIGACTION 13 +#define SYS64_RT_SIGPROCMASK 14 +#define SYS64_RT_SIGRETURN 15 +#define SYS64_IOCTL 16 +#define SYS64_PREAD64 17 +#define SYS64_PWRITE64 18 +#define SYS64_READV 19 +#define SYS64_WRITEV 20 +#define SYS64_ACCESS 21 +#define SYS64_PIPE 22 +#define SYS64_SELECT 23 +#define SYS64_SCHED_YIELD 24 +#define SYS64_MREMAP 25 +#define SYS64_MSYNC 26 +#define SYS64_MINCORE 27 +#define SYS64_MADVISE 28 +#define SYS64_SHMGET 29 +#define SYS64_SHMAT 30 +#define SYS64_SHMCTL 31 +#define SYS64_DUP 32 +#define SYS64_DUP2 33 +#define SYS64_PAUSE 34 +#define SYS64_NANOSLEEP 35 +#define SYS64_GETITIMER 36 +#define SYS64_ALARM 37 +#define SYS64_SETITIMER 38 +#define SYS64_GETPID 39 +#define SYS64_SENDFILE 40 +#define SYS64_SOCKET 41 +#define SYS64_CONNECT 42 +#define SYS64_ACCEPT 43 +#define SYS64_SENDTO 44 +#define SYS64_RECVFROM 45 +#define SYS64_SENDMSG 46 +#define SYS64_RECVMSG 47 +#define SYS64_SHUTDOWN 48 +#define SYS64_BIND 49 +#define SYS64_LISTEN 50 +#define SYS64_GETSOCKNAME 51 +#define SYS64_GETPEERNAME 52 +#define SYS64_SOCKETPAIR 53 +#define SYS64_SETSOCKOPT 54 +#define SYS64_GETSOCKOPT 55 +#define SYS64_CLONE 56 +#define SYS64_FORK 57 +#define SYS64_VFORK 58 +#define SYS64_EXECVE 59 +#define SYS64_EXIT 60 +#define SYS64_WAIT4 61 +#define SYS64_KILL 62 +#define SYS64_UNAME 63 +#define SYS64_SEMGET 64 +#define SYS64_SEMOP 65 +#define SYS64_SEMCTL 66 +#define SYS64_SHMDT 67 +#define SYS64_MSGGET 68 +#define SYS64_MSGSND 69 +#define SYS64_MSGRCV 70 +#define SYS64_MSGCTL 71 +#define SYS64_FCNTL 72 +#define SYS64_FLOCK 73 +#define SYS64_FSYNC 74 +#define SYS64_FDATASYNC 75 +#define SYS64_TRUNCATE 76 +#define SYS64_FTRUNCATE 77 +#define SYS64_GETDENTS 78 +#define SYS64_GETCWD 79 +#define SYS64_CHDIR 80 +#define SYS64_FCHDIR 81 +#define SYS64_RENAME 82 +#define SYS64_MKDIR 83 +#define SYS64_RMDIR 84 +#define SYS64_CREAT 85 +#define SYS64_LINK 86 +#define SYS64_UNLINK 87 +#define SYS64_SYMLINK 88 +#define SYS64_READLINK 89 +#define SYS64_CHMOD 90 +#define SYS64_FCHMOD 91 +#define SYS64_CHOWN 92 +#define SYS64_FCHOWN 93 +#define SYS64_LCHOWN 94 +#define SYS64_UMASK 95 +#define SYS64_GETTIMEOFDAY 96 +#define SYS64_GETRLIMIT 97 +#define SYS64_GETRUSAGE 98 +#define SYS64_SYSINFO 99 +#define SYS64_TIMES 100 +#define SYS64_PTRACE 101 +#define SYS64_GETUID 102 +#define SYS64_SYSLOG 103 +#define SYS64_GETGID 104 +#define SYS64_SETUID 105 +#define SYS64_SETGID 106 +#define SYS64_GETEUID 107 +#define SYS64_GETEGID 108 +#define SYS64_SETPGID 109 +#define SYS64_GETPPID 110 +#define SYS64_GETPGRP 111 +#define SYS64_SETSID 112 +#define SYS64_SETREUID 113 +#define SYS64_SETREGID 114 +#define SYS64_GETGROUPS 115 +#define SYS64_SETGROUPS 116 +#define SYS64_SETRESUID 117 +#define SYS64_GETRESUID 118 +#define SYS64_SETRESGID 119 +#define SYS64_GETRESGID 120 +#define SYS64_GETPGID 121 +#define SYS64_SETFSUID 122 +#define SYS64_SETFSGID 123 +#define SYS64_GETSID 124 +#define SYS64_CAPGET 125 +#define SYS64_CAPSET 126 +#define SYS64_RT_SIGPENDING 127 +#define SYS64_RT_SIGTIMEDWAIT 128 +#define SYS64_RT_SIGQUEUEINFO 129 +#define SYS64_RT_SIGSUSPEND 130 +#define SYS64_SIGALTSTACK 131 +#define SYS64_UTIME 132 +#define SYS64_MKNOD 133 +#define SYS64_USELIB 134 +#define SYS64_PERSONALITY 135 +#define SYS64_USTAT 136 +#define SYS64_STATFS 137 +#define SYS64_FSTATFS 138 +#define SYS64_SYSFS 139 +#define SYS64_GETPRIORITY 140 +#define SYS64_SETPRIORITY 141 +#define SYS64_SCHED_SETPARAM 142 +#define SYS64_SCHED_GETPARAM 143 +#define SYS64_SCHED_SETSCHEDULER 144 +#define SYS64_SCHED_GETSCHEDULER 145 +#define SYS64_SCHED_GET_PRIORITY_MAX 146 +#define SYS64_SCHED_GET_PRIORITY_MIN 147 +#define SYS64_SCHED_RR_GET_INTERVAL 148 +#define SYS64_MLOCK 149 +#define SYS64_MUNLOCK 150 +#define SYS64_MLOCKALL 151 +#define SYS64_MUNLOCKALL 152 +#define SYS64_VHANGUP 153 +#define SYS64_MODIFY_LDT 154 +#define SYS64_PIVOT_ROOT 155 +#define SYS64__SYSCTL 156 +#define SYS64_PRCTL 157 +#define SYS64_ARCH_PRCTL 158 +#define SYS64_ADJTIMEX 159 +#define SYS64_SETRLIMIT 160 +#define SYS64_CHROOT 161 +#define SYS64_SYNC 162 +#define SYS64_ACCT 163 +#define SYS64_SETTIMEOFDAY 164 +#define SYS64_MOUNT 165 +#define SYS64_UMOUNT2 166 +#define SYS64_SWAPON 167 +#define SYS64_SWAPOFF 168 +#define SYS64_REBOOT 169 +#define SYS64_SETHOSTNAME 170 +#define SYS64_SETDOMAINNAME 171 +#define SYS64_IOPL 172 +#define SYS64_IOPERM 173 +#define SYS64_CREATE_MODULE 174 +#define SYS64_INIT_MODULE 175 +#define SYS64_DELETE_MODULE 176 +#define SYS64_GET_KERNEL_SYMS 177 +#define SYS64_QUERY_MODULE 178 +#define SYS64_QUOTACTL 179 +#define SYS64_NFSSERVCTL 180 +#define SYS64_GETPMSG 181 +#define SYS64_PUTPMSG 182 +#define SYS64_AFS_SYSCALL 183 +#define SYS64_TUXCALL 184 +#define SYS64_SECURITY 185 +#define SYS64_GETTID 186 +#define SYS64_READAHEAD 187 +#define SYS64_SETXATTR 188 +#define SYS64_LSETXATTR 189 +#define SYS64_FSETXATTR 190 +#define SYS64_GETXATTR 191 +#define SYS64_LGETXATTR 192 +#define SYS64_FGETXATTR 193 +#define SYS64_LISTXATTR 194 +#define SYS64_LLISTXATTR 195 +#define SYS64_FLISTXATTR 196 +#define SYS64_REMOVEXATTR 197 +#define SYS64_LREMOVEXATTR 198 +#define SYS64_FREMOVEXATTR 199 +#define SYS64_TKILL 200 +#define SYS64_TIME 201 +#define SYS64_FUTEX 202 +#define SYS64_SCHED_SETAFFINITY 203 +#define SYS64_SCHED_GETAFFINITY 204 +#define SYS64_SET_THREAD_AREA 205 +#define SYS64_IO_SETUP 206 +#define SYS64_IO_DESTROY 207 +#define SYS64_IO_GETEVENTS 208 +#define SYS64_IO_SUBMIT 209 +#define SYS64_IO_CANCEL 210 +#define SYS64_GET_THREAD_AREA 211 +#define SYS64_LOOKUP_DCOOKIE 212 +#define SYS64_EPOLL_CREATE 213 +#define SYS64_EPOLL_CTL_OLD 214 +#define SYS64_EPOLL_WAIT_OLD 215 +#define SYS64_REMAP_FILE_PAGES 216 +#define SYS64_GETDENTS64 217 +#define SYS64_SET_TID_ADDRESS 218 +#define SYS64_RESTART_SYSCALL 219 +#define SYS64_SEMTIMEDOP 220 +#define SYS64_FADVISE64 221 +#define SYS64_TIMER_CREATE 222 +#define SYS64_TIMER_SETTIME 223 +#define SYS64_TIMER_GETTIME 224 +#define SYS64_TIMER_GETOVERRUN 225 +#define SYS64_TIMER_DELETE 226 +#define SYS64_CLOCK_SETTIME 227 +#define SYS64_CLOCK_GETTIME 228 +#define SYS64_CLOCK_GETRES 229 +#define SYS64_CLOCK_NANOSLEEP 230 +#define SYS64_EXIT_GROUP 231 +#define SYS64_EPOLL_WAIT 232 +#define SYS64_EPOLL_CTL 233 +#define SYS64_TGKILL 234 +#define SYS64_UTIMES 235 +#define SYS64_VSERVER 236 +#define SYS64_MBIND 237 +#define SYS64_SET_MEMPOLICY 238 +#define SYS64_GET_MEMPOLICY 239 +#define SYS64_MQ_OPEN 240 +#define SYS64_MQ_UNLINK 241 +#define SYS64_MQ_TIMEDSEND 242 +#define SYS64_MQ_TIMEDRECEIVE 243 +#define SYS64_MQ_NOTIFY 244 +#define SYS64_MQ_GETSETATTR 245 +#define SYS64_KEXEC_LOAD 246 +#define SYS64_WAITID 247 +#define SYS64_ADD_KEY 248 +#define SYS64_REQUEST_KEY 249 +#define SYS64_KEYCTL 250 +#define SYS64_IOPRIO_SET 251 +#define SYS64_IOPRIO_GET 252 +#define SYS64_INOTIFY_INIT 253 +#define SYS64_INOTIFY_ADD_WATCH 254 +#define SYS64_INOTIFY_RM_WATCH 255 +#define SYS64_MIGRATE_PAGES 256 +#define SYS64_OPENAT 257 +#define SYS64_MKDIRAT 258 +#define SYS64_MKNODAT 259 +#define SYS64_FCHOWNAT 260 +#define SYS64_FUTIMESAT 261 +#define SYS64_NEWFSTATAT 262 +#define SYS64_UNLINKAT 263 +#define SYS64_RENAMEAT 264 +#define SYS64_LINKAT 265 +#define SYS64_SYMLINKAT 266 +#define SYS64_READLINKAT 267 +#define SYS64_FCHMODAT 268 +#define SYS64_FACCESSAT 269 +#define SYS64_PSELECT6 270 +#define SYS64_PPOLL 271 +#define SYS64_UNSHARE 272 +#define SYS64_SET_ROBUST_LIST 273 +#define SYS64_GET_ROBUST_LIST 274 +#define SYS64_SPLICE 275 +#define SYS64_TEE 276 +#define SYS64_SYNC_FILE_RANGE 277 +#define SYS64_VMSPLICE 278 +#define SYS64_MOVE_PAGES 279 +#define SYS64_UTIMENSAT 280 +#define SYS64_EPOLL_PWAIT 281 +#define SYS64_SIGNALFD 282 +#define SYS64_TIMERFD_CREATE 283 +#define SYS64_EVENTFD 284 +#define SYS64_FALLOCATE 285 +#define SYS64_TIMERFD_SETTIME 286 +#define SYS64_TIMERFD_GETTIME 287 +#define SYS64_ACCEPT4 288 +#define SYS64_SIGNALFD4 289 +#define SYS64_EVENTFD2 290 +#define SYS64_EPOLL_CREATE1 291 +#define SYS64_DUP3 292 +#define SYS64_PIPE2 293 +#define SYS64_INOTIFY_INIT1 294 +#define SYS64_PREADV 295 +#define SYS64_PWRITEV 296 +#define SYS64_RT_TGSIGQUEUEINFO 297 +#define SYS64_PERF_EVENT_OPEN 298 + + +#endif diff --git a/palacios/src/gears/Kconfig b/palacios/src/gears/Kconfig new file mode 100644 index 0000000..46db427 --- /dev/null +++ b/palacios/src/gears/Kconfig @@ -0,0 +1,104 @@ +menu GEARS + +config GEARS + bool "Enable GEARS in Palacios" + default n + help + This is the Guest Examination and Revision Services, an extension used + to modify guest code and implement guest-context VMM services in Palacios + +config EXT_SW_INTERRUPTS + bool "Enable interception and hooking of software interrupts" + depends on GEARS + default n + help + This feature will cause the VMM to intercept the execution + of software interrupts (i.e. the INTn instruction) and enable + any INT vector to be hooked. Extension name is "swintr_intercept" + +config DEBUG_EXT_SW_INTERRUPTS + bool "Enable debugging of software interrupt interception code" + depends on GEARS + depends on EXT_SW_INTERRUPTS + default n + help + This will enable useful debugging printouts for software + intercept code + +config EXT_SWINTR_PASSTHROUGH + bool "Hook all unhandled sofware interrupts for passthrough" + depends on GEARS + depends on EXT_SW_INTERRUPTS + default n + help + If enabled, this will cause all software interrupts + (INT instruction vectors) to be hooked for passthrough. + May reduce performance but useful for debugging. + +config EXT_SYSCALL_HIJACK + bool "Enable System Call Hijacking" + default n + depends on GEARS + depends on EXT_SW_INTERRUPTS + help + Enable the VMM to hijack system calls executed by the guest. + If enabled, the VMM will hook execution of INT 80 + + +config EXT_SELECTIVE_SYSCALL_EXIT + bool "Enable dynamic selective exiting of system calls" + default n + depends on GEARS + depends on EXT_SYSCALL_HIJACK + help + If enabled, this option will allow the VMM to selectively + enable and disable exiting on specific system calls. + +config DEBUG_EXT_SYSCALL_HIJACK + bool "Enable Syscall Hijack Debug in Palacios" + depends on GEARS + depends on EXT_SYSCALL_HIJACK + default n + help + Enable Debugging printouts for syscall hijacking code + in Palacios + + +config EXT_SYSCALL_PASSTHROUGH + bool "Hook all unhandled system calls for passthrough" + depends on GEARS + depends on EXT_SYSCALL_HIJACK + default n + help + If enabled, this option will cause all system calls + that are not explicitly hooked to be hooked for + passthrough. This is useful for debugging. + +config EXT_EXECVE_HOOK + bool "Hook calls to execve" + depends on GEARS + depends on EXT_SYSCALL_HIJACK + default n + help + This option will cause the interception of all calls + to the execve system call + +config EXT_ENV_INJECT + bool "Enable environment variable injection" + depends on GEARS + depends on EXT_EXECVE_HOOK + default n + help + Enables development extension for overriding env vars + for certain executables + +config EXT_CODE_INJECT + bool "Allow code injection" + depends on GEARS + depends on EXT_SYSCALL_HIJACK + default n + help + This option will allow code to be injected and run in the + guest context + +endmenu diff --git a/palacios/src/gears/Makefile b/palacios/src/gears/Makefile new file mode 100644 index 0000000..dfbc5fd --- /dev/null +++ b/palacios/src/gears/Makefile @@ -0,0 +1,7 @@ +obj-$(V3_CONFIG_EXT_SW_INTERRUPTS) += ext_sw_intr.o +obj-$(V3_CONFIG_EXT_SYSCALL_HIJACK) += ext_syscall_hijack.o +obj-$(V3_CONFIG_EXT_EXECVE_HOOK) += ext_execve_hook.o +obj-$(V3_CONFIG_EXT_EXECVE_HOOK) += ext_process_environment.o +obj-$(V3_CONFIG_EXT_CODE_INJECT) += ext_code_inject.o +obj-$(V3_CONFIG_EXT_ENV_INJECT) += ext_env_inject.o + diff --git a/palacios/src/gears/elf.h b/palacios/src/gears/elf.h new file mode 100644 index 0000000..4179614 --- /dev/null +++ b/palacios/src/gears/elf.h @@ -0,0 +1,1173 @@ +/* This file defines standard ELF types, structures, and macros. + Copyright (C) 1995-2003,2004,2005,2006 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +#ifndef _ELF_H_ +#define _ELF_H_ + + +#include + +#define __ELF_SIZE 32 + +#define ElfW(type) _ElfW (Elf, __ELF_SIZE, type) +#define _ElfW(e,w,t) _ElfW_1 (e, w, _##t) +#define _ElfW_1(e,w,t) e##w##t + +/* Standard ELF types. */ + +/* Type for a 16-bit quantity. */ +typedef uint16_t Elf32_Half; +typedef uint16_t Elf64_Half; + +/* Types for signed and unsigned 32-bit quantities. */ +typedef uint32_t Elf32_Word; +typedef sint32_t Elf32_Sword; +typedef uint32_t Elf64_Word; +typedef sint32_t Elf64_Sword; + +/* Types for signed and unsigned 64-bit quantities. */ +typedef uint64_t Elf32_Xword; +typedef sint64_t Elf32_Sxword; +typedef uint64_t Elf64_Xword; +typedef sint64_t Elf64_Sxword; + +/* Type of addresses. */ +typedef uint32_t Elf32_Addr; +typedef uint64_t Elf64_Addr; + +/* Type of file offsets. */ +typedef uint32_t Elf32_Off; +typedef uint64_t Elf64_Off; + +/* Type for section indices, which are 16-bit quantities. */ +typedef uint16_t Elf32_Section; +typedef uint16_t Elf64_Section; + +/* Type for version symbol information. */ +typedef Elf32_Half Elf32_Versym; +typedef Elf64_Half Elf64_Versym; + + + +/* The ELF file header. This appears at the start of every ELF file. */ + +#define EI_NIDENT (16) + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf32_Half e_type; /* Object file type */ + Elf32_Half e_machine; /* Architecture */ + Elf32_Word e_version; /* Object file version */ + Elf32_Addr e_entry; /* Entry point virtual address */ + Elf32_Off e_phoff; /* Program header table file offset */ + Elf32_Off e_shoff; /* Section header table file offset */ + Elf32_Word e_flags; /* Processor-specific flags */ + Elf32_Half e_ehsize; /* ELF header size in bytes */ + Elf32_Half e_phentsize; /* Program header table entry size */ + Elf32_Half e_phnum; /* Program header table entry count */ + Elf32_Half e_shentsize; /* Section header table entry size */ + Elf32_Half e_shnum; /* Section header table entry count */ + Elf32_Half e_shstrndx; /* Section header string table index */ +} Elf32_Ehdr; + +typedef struct +{ + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ + Elf64_Half e_type; /* Object file type */ + Elf64_Half e_machine; /* Architecture */ + Elf64_Word e_version; /* Object file version */ + Elf64_Addr e_entry; /* Entry point virtual address */ + Elf64_Off e_phoff; /* Program header table file offset */ + Elf64_Off e_shoff; /* Section header table file offset */ + Elf64_Word e_flags; /* Processor-specific flags */ + Elf64_Half e_ehsize; /* ELF header size in bytes */ + Elf64_Half e_phentsize; /* Program header table entry size */ + Elf64_Half e_phnum; /* Program header table entry count */ + Elf64_Half e_shentsize; /* Section header table entry size */ + Elf64_Half e_shnum; /* Section header table entry count */ + Elf64_Half e_shstrndx; /* Section header string table index */ +} Elf64_Ehdr; + +/* Fields in the e_ident array. The EI_* macros are indices into the + array. The macros under each EI_* macro are the values the byte + may have. */ + +#define EI_MAG0 0 /* File identification byte 0 index */ +#define ELFMAG0 0x7f /* Magic number byte 0 */ + +#define EI_MAG1 1 /* File identification byte 1 index */ +#define ELFMAG1 'E' /* Magic number byte 1 */ + +#define EI_MAG2 2 /* File identification byte 2 index */ +#define ELFMAG2 'L' /* Magic number byte 2 */ + +#define EI_MAG3 3 /* File identification byte 3 index */ +#define ELFMAG3 'F' /* Magic number byte 3 */ + +/* Conglomeration of the identification bytes, for easy testing as a word. */ +#define ELFMAG "\177ELF" +#define SELFMAG 4 + +#define EI_CLASS 4 /* File class byte index */ +#define ELFCLASSNONE 0 /* Invalid class */ +#define ELFCLASS32 1 /* 32-bit objects */ +#define ELFCLASS64 2 /* 64-bit objects */ +#define ELFCLASSNUM 3 + +#define EI_DATA 5 /* Data encoding byte index */ +#define ELFDATANONE 0 /* Invalid data encoding */ +#define ELFDATA2LSB 1 /* 2's complement, little endian */ +#define ELFDATA2MSB 2 /* 2's complement, big endian */ +#define ELFDATANUM 3 + +#define EI_VERSION 6 /* File version byte index */ + /* Value must be EV_CURRENT */ + +#define EI_OSABI 7 /* OS ABI identification */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_SYSV 0 /* Alias. */ +#define ELFOSABI_HPUX 1 /* HP-UX */ +#define ELFOSABI_NETBSD 2 /* NetBSD. */ +#define ELFOSABI_LINUX 3 /* Linux. */ +#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ +#define ELFOSABI_AIX 7 /* IBM AIX. */ +#define ELFOSABI_IRIX 8 /* SGI Irix. */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ +#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define EI_ABIVERSION 8 /* ABI version */ + +#define EI_PAD 9 /* Byte index of padding bytes */ + +/* Legal values for e_type (object file type). */ + +#define ET_NONE 0 /* No file type */ +#define ET_REL 1 /* Relocatable file */ +#define ET_EXEC 2 /* Executable file */ +#define ET_DYN 3 /* Shared object file */ +#define ET_CORE 4 /* Core file */ +#define ET_NUM 5 /* Number of defined types */ +#define ET_LOOS 0xfe00 /* OS-specific range start */ +#define ET_HIOS 0xfeff /* OS-specific range end */ +#define ET_LOPROC 0xff00 /* Processor-specific range start */ +#define ET_HIPROC 0xffff /* Processor-specific range end */ + +/* Legal values for e_machine (architecture). */ + +#define EM_NONE 0 /* No machine */ +#define EM_M32 1 /* AT&T WE 32100 */ +#define EM_SPARC 2 /* SUN SPARC */ +#define EM_386 3 /* Intel 80386 */ +#define EM_68K 4 /* Motorola m68k family */ +#define EM_88K 5 /* Motorola m88k family */ +#define EM_860 7 /* Intel 80860 */ +#define EM_MIPS 8 /* MIPS R3000 big-endian */ +#define EM_S370 9 /* IBM System/370 */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ + +#define EM_PARISC 15 /* HPPA */ +#define EM_VPP500 17 /* Fujitsu VPP500 */ +#define EM_SPARC32PLUS 18 /* Sun's "v8plus" */ +#define EM_960 19 /* Intel 80960 */ +#define EM_PPC 20 /* PowerPC */ +#define EM_PPC64 21 /* PowerPC 64-bit */ +#define EM_S390 22 /* IBM S390 */ + +#define EM_V800 36 /* NEC V800 series */ +#define EM_FR20 37 /* Fujitsu FR20 */ +#define EM_RH32 38 /* TRW RH-32 */ +#define EM_RCE 39 /* Motorola RCE */ +#define EM_ARM 40 /* ARM */ +#define EM_FAKE_ALPHA 41 /* Digital Alpha */ +#define EM_SH 42 /* Hitachi SH */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit */ +#define EM_TRICORE 44 /* Siemens Tricore */ +#define EM_ARC 45 /* Argonaut RISC Core */ +#define EM_H8_300 46 /* Hitachi H8/300 */ +#define EM_H8_300H 47 /* Hitachi H8/300H */ +#define EM_H8S 48 /* Hitachi H8S */ +#define EM_H8_500 49 /* Hitachi H8/500 */ +#define EM_IA_64 50 /* Intel Merced */ +#define EM_MIPS_X 51 /* Stanford MIPS-X */ +#define EM_COLDFIRE 52 /* Motorola Coldfire */ +#define EM_68HC12 53 /* Motorola M68HC12 */ +#define EM_MMA 54 /* Fujitsu MMA Multimedia Accelerator*/ +#define EM_PCP 55 /* Siemens PCP */ +#define EM_NCPU 56 /* Sony nCPU embeeded RISC */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor */ +#define EM_STARCORE 58 /* Motorola Start*Core processor */ +#define EM_ME16 59 /* Toyota ME16 processor */ +#define EM_ST100 60 /* STMicroelectronic ST100 processor */ +#define EM_TINYJ 61 /* Advanced Logic Corp. Tinyj emb.fam*/ +#define EM_X86_64 62 /* AMD x86-64 architecture */ +#define EM_PDSP 63 /* Sony DSP Processor */ + +#define EM_FX66 66 /* Siemens FX66 microcontroller */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 mc */ +#define EM_ST7 68 /* STmicroelectronics ST7 8 bit mc */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller */ +#define EM_SVX 73 /* Silicon Graphics SVx */ +#define EM_ST19 74 /* STMicroelectronics ST19 8 bit mc */ +#define EM_VAX 75 /* Digital VAX */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded processor */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded processor */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit processor */ +#define EM_HUANY 81 /* Harvard University machine-independent object files */ +#define EM_PRISM 82 /* SiTera Prism */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller */ +#define EM_FR30 84 /* Fujitsu FR30 */ +#define EM_D10V 85 /* Mitsubishi D10V */ +#define EM_D30V 86 /* Mitsubishi D30V */ +#define EM_V850 87 /* NEC v850 */ +#define EM_M32R 88 /* Mitsubishi M32R */ +#define EM_MN10300 89 /* Matsushita MN10300 */ +#define EM_MN10200 90 /* Matsushita MN10200 */ +#define EM_PJ 91 /* picoJava */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5 */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture */ +#define EM_NUM 95 + +/* If it is necessary to assign new unofficial EM_* values, please + pick large random numbers (0x8523, 0xa7f2, etc.) to minimize the + chances of collision with official or non-GNU unofficial values. */ + +#define EM_ALPHA 0x9026 + +/* Legal values for e_version (version). */ + +#define EV_NONE 0 /* Invalid ELF version */ +#define EV_CURRENT 1 /* Current version */ +#define EV_NUM 2 + +/* Section header. */ + +typedef struct +{ + Elf32_Word sh_name; /* Section name (string tbl index) */ + Elf32_Word sh_type; /* Section type */ + Elf32_Word sh_flags; /* Section flags */ + Elf32_Addr sh_addr; /* Section virtual addr at execution */ + Elf32_Off sh_offset; /* Section file offset */ + Elf32_Word sh_size; /* Section size in bytes */ + Elf32_Word sh_link; /* Link to another section */ + Elf32_Word sh_info; /* Additional section information */ + Elf32_Word sh_addralign; /* Section alignment */ + Elf32_Word sh_entsize; /* Entry size if section holds table */ +} Elf32_Shdr; + +typedef struct +{ + Elf64_Word sh_name; /* Section name (string tbl index) */ + Elf64_Word sh_type; /* Section type */ + Elf64_Xword sh_flags; /* Section flags */ + Elf64_Addr sh_addr; /* Section virtual addr at execution */ + Elf64_Off sh_offset; /* Section file offset */ + Elf64_Xword sh_size; /* Section size in bytes */ + Elf64_Word sh_link; /* Link to another section */ + Elf64_Word sh_info; /* Additional section information */ + Elf64_Xword sh_addralign; /* Section alignment */ + Elf64_Xword sh_entsize; /* Entry size if section holds table */ +} Elf64_Shdr; + +/* Special section indices. */ + +#define SHN_UNDEF 0 /* Undefined section */ +#define SHN_LORESERVE 0xff00 /* Start of reserved indices */ +#define SHN_LOPROC 0xff00 /* Start of processor-specific */ +#define SHN_BEFORE 0xff00 /* Order section before all others + (Solaris). */ +#define SHN_AFTER 0xff01 /* Order section after all others + (Solaris). */ +#define SHN_HIPROC 0xff1f /* End of processor-specific */ +#define SHN_LOOS 0xff20 /* Start of OS-specific */ +#define SHN_HIOS 0xff3f /* End of OS-specific */ +#define SHN_ABS 0xfff1 /* Associated symbol is absolute */ +#define SHN_COMMON 0xfff2 /* Associated symbol is common */ +#define SHN_XINDEX 0xffff /* Index is in extra table. */ +#define SHN_HIRESERVE 0xffff /* End of reserved indices */ + +/* Legal values for sh_type (section type). */ + +#define SHT_NULL 0 /* Section header table entry unused */ +#define SHT_PROGBITS 1 /* Program data */ +#define SHT_SYMTAB 2 /* Symbol table */ +#define SHT_STRTAB 3 /* String table */ +#define SHT_RELA 4 /* Relocation entries with addends */ +#define SHT_HASH 5 /* Symbol hash table */ +#define SHT_DYNAMIC 6 /* Dynamic linking information */ +#define SHT_NOTE 7 /* Notes */ +#define SHT_NOBITS 8 /* Program space with no data (bss) */ +#define SHT_REL 9 /* Relocation entries, no addends */ +#define SHT_SHLIB 10 /* Reserved */ +#define SHT_DYNSYM 11 /* Dynamic linker symbol table */ +#define SHT_INIT_ARRAY 14 /* Array of constructors */ +#define SHT_FINI_ARRAY 15 /* Array of destructors */ +#define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ +#define SHT_GROUP 17 /* Section group */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ +#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_LOOS 0x60000000 /* Start OS-specific. */ +#define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ +#define SHT_GNU_LIBLIST 0x6ffffff7 /* Prelink library list */ +#define SHT_CHECKSUM 0x6ffffff8 /* Checksum for DSO content. */ +#define SHT_LOSUNW 0x6ffffffa /* Sun-specific low bound. */ +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_GNU_verdef 0x6ffffffd /* Version definition section. */ +#define SHT_GNU_verneed 0x6ffffffe /* Version needs section. */ +#define SHT_GNU_versym 0x6fffffff /* Version symbol table. */ +#define SHT_HISUNW 0x6fffffff /* Sun-specific high bound. */ +#define SHT_HIOS 0x6fffffff /* End OS-specific type */ +#define SHT_LOPROC 0x70000000 /* Start of processor-specific */ +#define SHT_HIPROC 0x7fffffff /* End of processor-specific */ +#define SHT_LOUSER 0x80000000 /* Start of application-specific */ +#define SHT_HIUSER 0x8fffffff /* End of application-specific */ + +/* Legal values for sh_flags (section flags). */ + +#define SHF_WRITE (1 << 0) /* Writable */ +#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */ +#define SHF_EXECINSTR (1 << 2) /* Executable */ +#define SHF_MERGE (1 << 4) /* Might be merged */ +#define SHF_STRINGS (1 << 5) /* Contains nul-terminated strings */ +#define SHF_INFO_LINK (1 << 6) /* `sh_info' contains SHT index */ +#define SHF_LINK_ORDER (1 << 7) /* Preserve order after combining */ +#define SHF_OS_NONCONFORMING (1 << 8) /* Non-standard OS specific handling + required */ +#define SHF_GROUP (1 << 9) /* Section is member of a group. */ +#define SHF_TLS (1 << 10) /* Section hold thread-local data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific */ +#define SHF_ORDERED (1 << 30) /* Special ordering requirement + (Solaris). */ +#define SHF_EXCLUDE (1 << 31) /* Section is excluded unless + referenced or allocated (Solaris).*/ + +/* Section group handling. */ +#define GRP_COMDAT 0x1 /* Mark group as COMDAT. */ + +/* Symbol table entry. */ + +typedef struct +{ + Elf32_Word st_name; /* Symbol name (string tbl index) */ + Elf32_Addr st_value; /* Symbol value */ + Elf32_Word st_size; /* Symbol size */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf32_Section st_shndx; /* Section index */ +} Elf32_Sym; + +typedef struct +{ + Elf64_Word st_name; /* Symbol name (string tbl index) */ + unsigned char st_info; /* Symbol type and binding */ + unsigned char st_other; /* Symbol visibility */ + Elf64_Section st_shndx; /* Section index */ + Elf64_Addr st_value; /* Symbol value */ + Elf64_Xword st_size; /* Symbol size */ +} Elf64_Sym; + +/* The syminfo section if available contains additional information about + every dynamic symbol. */ + +typedef struct +{ + Elf32_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf32_Half si_flags; /* Per symbol flags */ +} Elf32_Syminfo; + +typedef struct +{ + Elf64_Half si_boundto; /* Direct bindings, symbol bound to */ + Elf64_Half si_flags; /* Per symbol flags */ +} Elf64_Syminfo; + +/* Possible values for si_boundto. */ +#define SYMINFO_BT_SELF 0xffff /* Symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* Symbol bound to parent */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* Beginning of reserved entries */ + +/* Possible bitmasks for si_flags. */ +#define SYMINFO_FLG_DIRECT 0x0001 /* Direct bound symbol */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* Pass-thru symbol for translator */ +#define SYMINFO_FLG_COPY 0x0004 /* Symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* Symbol bound to object to be lazy + loaded */ +/* Syminfo version values. */ +#define SYMINFO_NONE 0 +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + + +/* How to extract and insert information held in the st_info field. */ + +#define ELF32_ST_BIND(val) (((unsigned char) (val)) >> 4) +#define ELF32_ST_TYPE(val) ((val) & 0xf) +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Both Elf32_Sym and Elf64_Sym use the same one-byte st_info field. */ +#define ELF64_ST_BIND(val) ELF32_ST_BIND (val) +#define ELF64_ST_TYPE(val) ELF32_ST_TYPE (val) +#define ELF64_ST_INFO(bind, type) ELF32_ST_INFO ((bind), (type)) + +/* Legal values for ST_BIND subfield of st_info (symbol binding). */ + +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* Weak symbol */ +#define STB_NUM 3 /* Number of defined types. */ +#define STB_LOOS 10 /* Start of OS-specific */ +#define STB_HIOS 12 /* End of OS-specific */ +#define STB_LOPROC 13 /* Start of processor-specific */ +#define STB_HIPROC 15 /* End of processor-specific */ + +/* Legal values for ST_TYPE subfield of st_info (symbol type). */ + +#define STT_NOTYPE 0 /* Symbol type is unspecified */ +#define STT_OBJECT 1 /* Symbol is a data object */ +#define STT_FUNC 2 /* Symbol is a code object */ +#define STT_SECTION 3 /* Symbol associated with a section */ +#define STT_FILE 4 /* Symbol's name is file name */ +#define STT_COMMON 5 /* Symbol is a common data object */ +#define STT_TLS 6 /* Symbol is thread-local data object*/ +#define STT_NUM 7 /* Number of defined types. */ +#define STT_LOOS 10 /* Start of OS-specific */ +#define STT_HIOS 12 /* End of OS-specific */ +#define STT_LOPROC 13 /* Start of processor-specific */ +#define STT_HIPROC 15 /* End of processor-specific */ + + +/* Symbol table indices are found in the hash buckets and chain table + of a symbol hash table section. This special index value indicates + the end of a chain, meaning no further symbols are found in that bucket. */ + +#define STN_UNDEF 0 /* End of a chain. */ + + +/* How to extract and insert information held in the st_other field. */ + +#define ELF32_ST_VISIBILITY(o) ((o) & 0x03) + +/* For ELF64 the definitions are the same. */ +#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o) + +/* Symbol visibility specification encoded in the st_other field. */ +#define STV_DEFAULT 0 /* Default symbol visibility rules */ +#define STV_INTERNAL 1 /* Processor specific hidden class */ +#define STV_HIDDEN 2 /* Sym unavailable in other modules */ +#define STV_PROTECTED 3 /* Not preemptible, not exported */ + + +/* Relocation table entry without addend (in section of type SHT_REL). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ +} Elf32_Rel; + +/* I have seen two different definitions of the Elf64_Rel and + Elf64_Rela structures, so we'll leave them out until Novell (or + whoever) gets their act together. */ +/* The following, at least, is used on Sparc v9, MIPS, and Alpha. */ + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ +} Elf64_Rel; + +/* Relocation table entry with addend (in section of type SHT_RELA). */ + +typedef struct +{ + Elf32_Addr r_offset; /* Address */ + Elf32_Word r_info; /* Relocation type and symbol index */ + Elf32_Sword r_addend; /* Addend */ +} Elf32_Rela; + +typedef struct +{ + Elf64_Addr r_offset; /* Address */ + Elf64_Xword r_info; /* Relocation type and symbol index */ + Elf64_Sxword r_addend; /* Addend */ +} Elf64_Rela; + +/* How to extract and insert information held in the r_info field. */ + +#define ELF32_R_SYM(val) ((val) >> 8) +#define ELF32_R_TYPE(val) ((val) & 0xff) +#define ELF32_R_INFO(sym, type) (((sym) << 8) + ((type) & 0xff)) + +#define ELF64_R_SYM(i) ((i) >> 32) +#define ELF64_R_TYPE(i) ((i) & 0xffffffff) +#define ELF64_R_INFO(sym,type) ((((Elf64_Xword) (sym)) << 32) + (type)) + +/* Program segment header. */ + +typedef struct +{ + Elf32_Word p_type; /* Segment type */ + Elf32_Off p_offset; /* Segment file offset */ + Elf32_Addr p_vaddr; /* Segment virtual address */ + Elf32_Addr p_paddr; /* Segment physical address */ + Elf32_Word p_filesz; /* Segment size in file */ + Elf32_Word p_memsz; /* Segment size in memory */ + Elf32_Word p_flags; /* Segment flags */ + Elf32_Word p_align; /* Segment alignment */ +} Elf32_Phdr; + +typedef struct +{ + Elf64_Word p_type; /* Segment type */ + Elf64_Word p_flags; /* Segment flags */ + Elf64_Off p_offset; /* Segment file offset */ + Elf64_Addr p_vaddr; /* Segment virtual address */ + Elf64_Addr p_paddr; /* Segment physical address */ + Elf64_Xword p_filesz; /* Segment size in file */ + Elf64_Xword p_memsz; /* Segment size in memory */ + Elf64_Xword p_align; /* Segment alignment */ +} Elf64_Phdr; + +/* Legal values for p_type (segment type). */ + +#define PT_NULL 0 /* Program header table entry unused */ +#define PT_LOAD 1 /* Loadable program segment */ +#define PT_DYNAMIC 2 /* Dynamic linking information */ +#define PT_INTERP 3 /* Program interpreter */ +#define PT_NOTE 4 /* Auxiliary information */ +#define PT_SHLIB 5 /* Reserved */ +#define PT_PHDR 6 /* Entry for header table itself */ +#define PT_TLS 7 /* Thread-local storage segment */ +#define PT_NUM 8 /* Number of defined types */ +#define PT_LOOS 0x60000000 /* Start of OS-specific */ +#define PT_GNU_EH_FRAME 0x6474e550 /* GCC .eh_frame_hdr segment */ +#define PT_GNU_STACK 0x6474e551 /* Indicates stack executability */ +#define PT_GNU_RELRO 0x6474e552 /* Read-only after relocation */ +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* Stack segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* End of OS-specific */ +#define PT_LOPROC 0x70000000 /* Start of processor-specific */ +#define PT_HIPROC 0x7fffffff /* End of processor-specific */ + +/* Legal values for p_flags (segment flags). */ + +#define PF_X (1 << 0) /* Segment is executable */ +#define PF_W (1 << 1) /* Segment is writable */ +#define PF_R (1 << 2) /* Segment is readable */ +#define PF_MASKOS 0x0ff00000 /* OS-specific */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific */ + +/* Legal values for note segment descriptor types for core files. */ + +#define NT_PRSTATUS 1 /* Contains copy of prstatus struct */ +#define NT_FPREGSET 2 /* Contains copy of fpregset struct */ +#define NT_PRPSINFO 3 /* Contains copy of prpsinfo struct */ +#define NT_PRXREG 4 /* Contains copy of prxregset struct */ +#define NT_TASKSTRUCT 4 /* Contains copy of task structure */ +#define NT_PLATFORM 5 /* String from sysinfo(SI_PLATFORM) */ +#define NT_AUXV 6 /* Contains copy of auxv array */ +#define NT_GWINDOWS 7 /* Contains copy of gwindows struct */ +#define NT_ASRS 8 /* Contains copy of asrset struct */ +#define NT_PSTATUS 10 /* Contains copy of pstatus struct */ +#define NT_PSINFO 13 /* Contains copy of psinfo struct */ +#define NT_PRCRED 14 /* Contains copy of prcred struct */ +#define NT_UTSNAME 15 /* Contains copy of utsname struct */ +#define NT_LWPSTATUS 16 /* Contains copy of lwpstatus struct */ +#define NT_LWPSINFO 17 /* Contains copy of lwpinfo struct */ +#define NT_PRFPXREG 20 /* Contains copy of fprxregset struct*/ + +/* Legal values for the note segment descriptor types for object files. */ + +#define NT_VERSION 1 /* Contains a version string. */ + + +/* Dynamic section entry. */ + +typedef struct +{ + Elf32_Sword d_tag; /* Dynamic entry type */ + union + { + Elf32_Word d_val; /* Integer value */ + Elf32_Addr d_ptr; /* Address value */ + } d_un; +} Elf32_Dyn; + +typedef struct +{ + Elf64_Sxword d_tag; /* Dynamic entry type */ + union + { + Elf64_Xword d_val; /* Integer value */ + Elf64_Addr d_ptr; /* Address value */ + } d_un; +} Elf64_Dyn; + +/* Legal values for d_tag (dynamic entry type). */ + +#define DT_NULL 0 /* Marks end of dynamic section */ +#define DT_NEEDED 1 /* Name of needed library */ +#define DT_PLTRELSZ 2 /* Size in bytes of PLT relocs */ +#define DT_PLTGOT 3 /* Processor defined value */ +#define DT_HASH 4 /* Address of symbol hash table */ +#define DT_STRTAB 5 /* Address of string table */ +#define DT_SYMTAB 6 /* Address of symbol table */ +#define DT_RELA 7 /* Address of Rela relocs */ +#define DT_RELASZ 8 /* Total size of Rela relocs */ +#define DT_RELAENT 9 /* Size of one Rela reloc */ +#define DT_STRSZ 10 /* Size of string table */ +#define DT_SYMENT 11 /* Size of one symbol table entry */ +#define DT_INIT 12 /* Address of init function */ +#define DT_FINI 13 /* Address of termination function */ +#define DT_SONAME 14 /* Name of shared object */ +#define DT_RPATH 15 /* Library search path (deprecated) */ +#define DT_SYMBOLIC 16 /* Start symbol search here */ +#define DT_REL 17 /* Address of Rel relocs */ +#define DT_RELSZ 18 /* Total size of Rel relocs */ +#define DT_RELENT 19 /* Size of one Rel reloc */ +#define DT_PLTREL 20 /* Type of reloc in PLT */ +#define DT_DEBUG 21 /* For debugging; unspecified */ +#define DT_TEXTREL 22 /* Reloc might modify .text */ +#define DT_JMPREL 23 /* Address of PLT relocs */ +#define DT_BIND_NOW 24 /* Process relocations of object */ +#define DT_INIT_ARRAY 25 /* Array with addresses of init fct */ +#define DT_FINI_ARRAY 26 /* Array with addresses of fini fct */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of DT_INIT_ARRAY */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of DT_FINI_ARRAY */ +#define DT_RUNPATH 29 /* Library search path */ +#define DT_FLAGS 30 /* Flags for the object being loaded */ +#define DT_ENCODING 32 /* Start of encoded range */ +#define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ +#define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_NUM 34 /* Number used */ +#define DT_LOOS 0x6000000d /* Start of OS-specific */ +#define DT_HIOS 0x6ffff000 /* End of OS-specific */ +#define DT_LOPROC 0x70000000 /* Start of processor-specific */ +#define DT_HIPROC 0x7fffffff /* End of processor-specific */ +#define DT_PROCNUM DT_MIPS_NUM /* Most used by any processor */ + +/* DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + Dyn.d_un.d_val field of the Elf*_Dyn structure. This follows Sun's + approach. */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_GNU_PRELINKED 0x6ffffdf5 /* Prelinking timestamp */ +#define DT_GNU_CONFLICTSZ 0x6ffffdf6 /* Size of conflict section */ +#define DT_GNU_LIBLISTSZ 0x6ffffdf7 /* Size of library list */ +#define DT_CHECKSUM 0x6ffffdf8 +#define DT_PLTPADSZ 0x6ffffdf9 +#define DT_MOVEENT 0x6ffffdfa +#define DT_MOVESZ 0x6ffffdfb +#define DT_FEATURE_1 0x6ffffdfc /* Feature selection (DTF_*). */ +#define DT_POSFLAG_1 0x6ffffdfd /* Flags for DT_* entries, effecting + the following DT_* entry. */ +#define DT_SYMINSZ 0x6ffffdfe /* Size of syminfo table (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* Entry size of syminfo */ +#define DT_VALRNGHI 0x6ffffdff +#define DT_VALTAGIDX(tag) (DT_VALRNGHI - (tag)) /* Reverse order! */ +#define DT_VALNUM 12 + +/* DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + + If any adjustment is made to the ELF object after it has been + built these entries will need to be adjusted. */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table. */ +#define DT_TLSDESC_PLT 0x6ffffef6 +#define DT_TLSDESC_GOT 0x6ffffef7 +#define DT_GNU_CONFLICT 0x6ffffef8 /* Start of conflict section */ +#define DT_GNU_LIBLIST 0x6ffffef9 /* Library list */ +#define DT_CONFIG 0x6ffffefa /* Configuration information. */ +#define DT_DEPAUDIT 0x6ffffefb /* Dependency auditing. */ +#define DT_AUDIT 0x6ffffefc /* Object auditing. */ +#define DT_PLTPAD 0x6ffffefd /* PLT padding. */ +#define DT_MOVETAB 0x6ffffefe /* Move table. */ +#define DT_SYMINFO 0x6ffffeff /* Syminfo table. */ +#define DT_ADDRRNGHI 0x6ffffeff +#define DT_ADDRTAGIDX(tag) (DT_ADDRRNGHI - (tag)) /* Reverse order! */ +#define DT_ADDRNUM 11 + +/* The versioning entry types. The next are defined as part of the + GNU extension. */ +#define DT_VERSYM 0x6ffffff0 + +#define DT_RELACOUNT 0x6ffffff9 +#define DT_RELCOUNT 0x6ffffffa + +/* These were chosen by Sun. */ +#define DT_FLAGS_1 0x6ffffffb /* State flags, see DF_1_* below. */ +#define DT_VERDEF 0x6ffffffc /* Address of version definition + table */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of version definitions */ +#define DT_VERNEED 0x6ffffffe /* Address of table with needed + versions */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of needed versions */ +#define DT_VERSIONTAGIDX(tag) (DT_VERNEEDNUM - (tag)) /* Reverse order! */ +#define DT_VERSIONTAGNUM 16 + +/* Sun added these machine-independent extensions in the "processor-specific" + range. Be compatible. */ +#define DT_AUXILIARY 0x7ffffffd /* Shared object to load before self */ +#define DT_FILTER 0x7fffffff /* Shared object to get values from */ +#define DT_EXTRATAGIDX(tag) ((Elf32_Word)-((Elf32_Sword) (tag) <<1>>1)-1) +#define DT_EXTRANUM 3 + +/* Values of `d_un.d_val' in the DT_FLAGS entry. */ +#define DF_ORIGIN 0x00000001 /* Object may use DF_ORIGIN */ +#define DF_SYMBOLIC 0x00000002 /* Symbol resolutions starts here */ +#define DF_TEXTREL 0x00000004 /* Object contains text relocations */ +#define DF_BIND_NOW 0x00000008 /* No lazy binding for this object */ +#define DF_STATIC_TLS 0x00000010 /* Module uses the static TLS model */ + +/* State flags selectable in the `d_un.d_val' element of the DT_FLAGS_1 + entry in the dynamic section. */ +#define DF_1_NOW 0x00000001 /* Set RTLD_NOW for this object. */ +#define DF_1_GLOBAL 0x00000002 /* Set RTLD_GLOBAL for this object. */ +#define DF_1_GROUP 0x00000004 /* Set RTLD_GROUP for this object. */ +#define DF_1_NODELETE 0x00000008 /* Set RTLD_NODELETE for this object.*/ +#define DF_1_LOADFLTR 0x00000010 /* Trigger filtee loading at runtime.*/ +#define DF_1_INITFIRST 0x00000020 /* Set RTLD_INITFIRST for this object*/ +#define DF_1_NOOPEN 0x00000040 /* Set RTLD_NOOPEN for this object. */ +#define DF_1_ORIGIN 0x00000080 /* $ORIGIN must be handled. */ +#define DF_1_DIRECT 0x00000100 /* Direct binding enabled. */ +#define DF_1_TRANS 0x00000200 +#define DF_1_INTERPOSE 0x00000400 /* Object is used to interpose. */ +#define DF_1_NODEFLIB 0x00000800 /* Ignore default lib search path. */ +#define DF_1_NODUMP 0x00001000 /* Object can't be dldump'ed. */ +#define DF_1_CONFALT 0x00002000 /* Configuration alternative created.*/ +#define DF_1_ENDFILTEE 0x00004000 /* Filtee terminates filters search. */ +#define DF_1_DISPRELDNE 0x00008000 /* Disp reloc applied at build time. */ +#define DF_1_DISPRELPND 0x00010000 /* Disp reloc applied at run-time. */ + +/* Flags for the feature selection in DT_FEATURE_1. */ +#define DTF_1_PARINIT 0x00000001 +#define DTF_1_CONFEXP 0x00000002 + +/* Flags in the DT_POSFLAG_1 entry effecting only the next DT_* entry. */ +#define DF_P1_LAZYLOAD 0x00000001 /* Lazyload following object. */ +#define DF_P1_GROUPPERM 0x00000002 /* Symbols from next object are not + generally available. */ + +/* Version definition sections. */ + +typedef struct +{ + Elf32_Half vd_version; /* Version revision */ + Elf32_Half vd_flags; /* Version information */ + Elf32_Half vd_ndx; /* Version Index */ + Elf32_Half vd_cnt; /* Number of associated aux entries */ + Elf32_Word vd_hash; /* Version name hash value */ + Elf32_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf32_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf32_Verdef; + +typedef struct +{ + Elf64_Half vd_version; /* Version revision */ + Elf64_Half vd_flags; /* Version information */ + Elf64_Half vd_ndx; /* Version Index */ + Elf64_Half vd_cnt; /* Number of associated aux entries */ + Elf64_Word vd_hash; /* Version name hash value */ + Elf64_Word vd_aux; /* Offset in bytes to verdaux array */ + Elf64_Word vd_next; /* Offset in bytes to next verdef + entry */ +} Elf64_Verdef; + + +/* Legal values for vd_version (version revision). */ +#define VER_DEF_NONE 0 /* No version */ +#define VER_DEF_CURRENT 1 /* Current version */ +#define VER_DEF_NUM 2 /* Given version number */ + +/* Legal values for vd_flags (version information flags). */ +#define VER_FLG_BASE 0x1 /* Version definition of file itself */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + +/* Versym symbol index values. */ +#define VER_NDX_LOCAL 0 /* Symbol is local. */ +#define VER_NDX_GLOBAL 1 /* Symbol is global. */ +#define VER_NDX_LORESERVE 0xff00 /* Beginning of reserved entries. */ +#define VER_NDX_ELIMINATE 0xff01 /* Symbol is to be eliminated. */ + +/* Auxialiary version information. */ + +typedef struct +{ + Elf32_Word vda_name; /* Version or dependency names */ + Elf32_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf32_Verdaux; + +typedef struct +{ + Elf64_Word vda_name; /* Version or dependency names */ + Elf64_Word vda_next; /* Offset in bytes to next verdaux + entry */ +} Elf64_Verdaux; + + +/* Version dependency section. */ + +typedef struct +{ + Elf32_Half vn_version; /* Version of structure */ + Elf32_Half vn_cnt; /* Number of associated aux entries */ + Elf32_Word vn_file; /* Offset of filename for this + dependency */ + Elf32_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf32_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf32_Verneed; + +typedef struct +{ + Elf64_Half vn_version; /* Version of structure */ + Elf64_Half vn_cnt; /* Number of associated aux entries */ + Elf64_Word vn_file; /* Offset of filename for this + dependency */ + Elf64_Word vn_aux; /* Offset in bytes to vernaux array */ + Elf64_Word vn_next; /* Offset in bytes to next verneed + entry */ +} Elf64_Verneed; + + +/* Legal values for vn_version (version revision). */ +#define VER_NEED_NONE 0 /* No version */ +#define VER_NEED_CURRENT 1 /* Current version */ +#define VER_NEED_NUM 2 /* Given version number */ + +/* Auxiliary needed version information. */ + +typedef struct +{ + Elf32_Word vna_hash; /* Hash value of dependency name */ + Elf32_Half vna_flags; /* Dependency specific information */ + Elf32_Half vna_other; /* Unused */ + Elf32_Word vna_name; /* Dependency name string offset */ + Elf32_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf32_Vernaux; + +typedef struct +{ + Elf64_Word vna_hash; /* Hash value of dependency name */ + Elf64_Half vna_flags; /* Dependency specific information */ + Elf64_Half vna_other; /* Unused */ + Elf64_Word vna_name; /* Dependency name string offset */ + Elf64_Word vna_next; /* Offset in bytes to next vernaux + entry */ +} Elf64_Vernaux; + + +/* Legal values for vna_flags. */ +#define VER_FLG_WEAK 0x2 /* Weak version identifier */ + + +/* Auxiliary vector. */ + +/* This vector is normally only used by the program interpreter. The + usual definition in an ABI supplement uses the name auxv_t. The + vector is not usually defined in a standard file, but it + can't hurt. We rename it to avoid conflicts. The sizes of these + types are an arrangement between the exec server and the program + interpreter, so we don't fully specify them here. */ + +typedef struct +{ + uint32_t a_type; /* Entry type */ + union + { + uint32_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf32_auxv_t; + +typedef struct +{ + uint64_t a_type; /* Entry type */ + union + { + uint64_t a_val; /* Integer value */ + /* We use to have pointer elements added here. We cannot do that, + though, since it does not work when using 32-bit definitions + on 64-bit platforms and vice versa. */ + } a_un; +} Elf64_auxv_t; + +/* Legal values for a_type (entry type). */ + +#define AT_NULL 0 /* End of vector */ +#define AT_IGNORE 1 /* Entry should be ignored */ +#define AT_EXECFD 2 /* File descriptor of program */ +#define AT_PHDR 3 /* Program headers for program */ +#define AT_PHENT 4 /* Size of program header entry */ +#define AT_PHNUM 5 /* Number of program headers */ +#define AT_PAGESZ 6 /* System page size */ +#define AT_BASE 7 /* Base address of interpreter */ +#define AT_FLAGS 8 /* Flags */ +#define AT_ENTRY 9 /* Entry point of program */ +#define AT_NOTELF 10 /* Program is not ELF */ +#define AT_UID 11 /* Real uid */ +#define AT_EUID 12 /* Effective uid */ +#define AT_GID 13 /* Real gid */ +#define AT_EGID 14 /* Effective gid */ +#define AT_CLKTCK 17 /* Frequency of times() */ + +/* Some more special a_type values describing the hardware. */ +#define AT_PLATFORM 15 /* String identifying platform. */ +#define AT_HWCAP 16 /* Machine dependent hints about + processor capabilities. */ + +/* This entry gives some information about the FPU initialization + performed by the kernel. */ +#define AT_FPUCW 18 /* Used FPU control word. */ + +/* Cache block sizes. */ +#define AT_DCACHEBSIZE 19 /* Data cache block size. */ +#define AT_ICACHEBSIZE 20 /* Instruction cache block size. */ +#define AT_UCACHEBSIZE 21 /* Unified cache block size. */ + +/* A special ignored value for PPC, used by the kernel to control the + interpretation of the AUXV. Must be > 16. */ +#define AT_IGNOREPPC 22 /* Entry should be ignored. */ + +#define AT_SECURE 23 /* Boolean, was exec setuid-like? */ + +/* Pointer to the global system page used for system calls and other + nice things. */ +#define AT_SYSINFO 32 +#define AT_SYSINFO_EHDR 33 + +/* Shapes of the caches. Bits 0-3 contains associativity; bits 4-7 contains + log2 of line size; mask those to get cache size. */ +#define AT_L1I_CACHESHAPE 34 +#define AT_L1D_CACHESHAPE 35 +#define AT_L2_CACHESHAPE 36 +#define AT_L3_CACHESHAPE 37 + +/* Note section contents. Each entry in the note section begins with + a header of a fixed form. */ + +typedef struct +{ + Elf32_Word n_namesz; /* Length of the note's name. */ + Elf32_Word n_descsz; /* Length of the note's descriptor. */ + Elf32_Word n_type; /* Type of the note. */ +} Elf32_Nhdr; + +typedef struct +{ + Elf64_Word n_namesz; /* Length of the note's name. */ + Elf64_Word n_descsz; /* Length of the note's descriptor. */ + Elf64_Word n_type; /* Type of the note. */ +} Elf64_Nhdr; + +/* Known names of notes. */ + +/* Solaris entries in the note section have this name. */ +#define ELF_NOTE_SOLARIS "SUNW Solaris" + +/* Note entries for GNU systems have this name. */ +#define ELF_NOTE_GNU "GNU" + + +/* Defined types of notes for Solaris. */ + +/* Value of descriptor (one word) is desired pagesize for the binary. */ +#define ELF_NOTE_PAGESIZE_HINT 1 + + +/* Defined note types for GNU systems. */ + +/* ABI information. The descriptor consists of words: + word 0: OS descriptor + word 1: major version of the ABI + word 2: minor version of the ABI + word 3: subminor version of the ABI +*/ +#define ELF_NOTE_ABI 1 + +/* Known OSes. These value can appear in word 0 of an ELF_NOTE_ABI + note section entry. */ +#define ELF_NOTE_OS_LINUX 0 +#define ELF_NOTE_OS_GNU 1 +#define ELF_NOTE_OS_SOLARIS2 2 +#define ELF_NOTE_OS_FREEBSD 3 + + +/* Move records. */ +typedef struct +{ + Elf32_Xword m_value; /* Symbol value. */ + Elf32_Word m_info; /* Size and index. */ + Elf32_Word m_poffset; /* Symbol offset. */ + Elf32_Half m_repeat; /* Repeat count. */ + Elf32_Half m_stride; /* Stride info. */ +} Elf32_Move; + +typedef struct +{ + Elf64_Xword m_value; /* Symbol value. */ + Elf64_Xword m_info; /* Size and index. */ + Elf64_Xword m_poffset; /* Symbol offset. */ + Elf64_Half m_repeat; /* Repeat count. */ + Elf64_Half m_stride; /* Stride info. */ +} Elf64_Move; + +/* Macro to construct move records. */ +#define ELF32_M_SYM(info) ((info) >> 8) +#define ELF32_M_SIZE(info) ((unsigned char) (info)) +#define ELF32_M_INFO(sym, size) (((sym) << 8) + (unsigned char) (size)) + +#define ELF64_M_SYM(info) ELF32_M_SYM (info) +#define ELF64_M_SIZE(info) ELF32_M_SIZE (info) +#define ELF64_M_INFO(sym, size) ELF32_M_INFO (sym, size) + + +/* Intel 80386 specific definitions. */ + +/* i386 relocs. */ + +#define R_386_NONE 0 /* No reloc */ +#define R_386_32 1 /* Direct 32 bit */ +#define R_386_PC32 2 /* PC relative 32 bit */ +#define R_386_GOT32 3 /* 32 bit GOT entry */ +#define R_386_PLT32 4 /* 32 bit PLT address */ +#define R_386_COPY 5 /* Copy symbol at runtime */ +#define R_386_GLOB_DAT 6 /* Create GOT entry */ +#define R_386_JMP_SLOT 7 /* Create PLT entry */ +#define R_386_RELATIVE 8 /* Adjust by program base */ +#define R_386_GOTOFF 9 /* 32 bit offset to GOT */ +#define R_386_GOTPC 10 /* 32 bit PC relative offset to GOT */ +#define R_386_32PLT 11 +#define R_386_TLS_TPOFF 14 /* Offset in static TLS block */ +#define R_386_TLS_IE 15 /* Address of GOT entry for static TLS + block offset */ +#define R_386_TLS_GOTIE 16 /* GOT entry for static TLS block + offset */ +#define R_386_TLS_LE 17 /* Offset relative to static TLS + block */ +#define R_386_TLS_GD 18 /* Direct 32 bit for GNU version of + general dynamic thread local data */ +#define R_386_TLS_LDM 19 /* Direct 32 bit for GNU version of + local dynamic thread local data + in LE code */ +#define R_386_16 20 +#define R_386_PC16 21 +#define R_386_8 22 +#define R_386_PC8 23 +#define R_386_TLS_GD_32 24 /* Direct 32 bit for general dynamic + thread local data */ +#define R_386_TLS_GD_PUSH 25 /* Tag for pushl in GD TLS code */ +#define R_386_TLS_GD_CALL 26 /* Relocation for call to + __tls_get_addr() */ +#define R_386_TLS_GD_POP 27 /* Tag for popl in GD TLS code */ +#define R_386_TLS_LDM_32 28 /* Direct 32 bit for local dynamic + thread local data in LE code */ +#define R_386_TLS_LDM_PUSH 29 /* Tag for pushl in LDM TLS code */ +#define R_386_TLS_LDM_CALL 30 /* Relocation for call to + __tls_get_addr() in LDM code */ +#define R_386_TLS_LDM_POP 31 /* Tag for popl in LDM TLS code */ +#define R_386_TLS_LDO_32 32 /* Offset relative to TLS block */ +#define R_386_TLS_IE_32 33 /* GOT entry for negated static TLS + block offset */ +#define R_386_TLS_LE_32 34 /* Negated offset relative to static + TLS block */ +#define R_386_TLS_DTPMOD32 35 /* ID of module containing symbol */ +#define R_386_TLS_DTPOFF32 36 /* Offset in TLS block */ +#define R_386_TLS_TPOFF32 37 /* Negated offset in static TLS block */ +/* Keep this the last entry. */ +#define R_386_NUM 38 + + +/* Legal values for l_flags. */ + +#define LL_NONE 0 +#define LL_EXACT_MATCH (1 << 0) /* Require exact match */ +#define LL_IGNORE_INT_VER (1 << 1) /* Ignore interface version */ +#define LL_REQUIRE_MINOR (1 << 2) +#define LL_EXPORTS (1 << 3) +#define LL_DELAY_LOAD (1 << 4) +#define LL_DELTA (1 << 5) + +/* Entries found in sections of type SHT_MIPS_CONFLICT. */ + +typedef Elf32_Addr Elf32_Conflict; + + +/* AMD x86-64 relocations. */ +#define R_X86_64_NONE 0 /* No reloc */ +#define R_X86_64_64 1 /* Direct 64 bit */ +#define R_X86_64_PC32 2 /* PC relative 32 bit signed */ +#define R_X86_64_GOT32 3 /* 32 bit GOT entry */ +#define R_X86_64_PLT32 4 /* 32 bit PLT address */ +#define R_X86_64_COPY 5 /* Copy symbol at runtime */ +#define R_X86_64_GLOB_DAT 6 /* Create GOT entry */ +#define R_X86_64_JUMP_SLOT 7 /* Create PLT entry */ +#define R_X86_64_RELATIVE 8 /* Adjust by program base */ +#define R_X86_64_GOTPCREL 9 /* 32 bit signed PC relative + offset to GOT */ +#define R_X86_64_32 10 /* Direct 32 bit zero extended */ +#define R_X86_64_32S 11 /* Direct 32 bit sign extended */ +#define R_X86_64_16 12 /* Direct 16 bit zero extended */ +#define R_X86_64_PC16 13 /* 16 bit sign extended pc relative */ +#define R_X86_64_8 14 /* Direct 8 bit sign extended */ +#define R_X86_64_PC8 15 /* 8 bit sign extended pc relative */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in module's TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in initial TLS block */ +#define R_X86_64_TLSGD 19 /* 32 bit signed PC relative offset + to two GOT entries for GD symbol */ +#define R_X86_64_TLSLD 20 /* 32 bit signed PC relative offset + to two GOT entries for LD symbol */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* 32 bit signed PC relative offset + to GOT entry for IE symbol */ +#define R_X86_64_TPOFF32 23 /* Offset in initial TLS block */ + +#define R_X86_64_NUM 24 + +struct link_map { + + Elf64_Addr l_addr; + char *l_name; + Elf64_Dyn *l_ld; + struct link_map *l_next, *l_prev; +}; + +#endif /* elf.h */ diff --git a/palacios/src/gears/ext_code_inject.c b/palacios/src/gears/ext_code_inject.c new file mode 100644 index 0000000..d5bdfb8 --- /dev/null +++ b/palacios/src/gears/ext_code_inject.c @@ -0,0 +1,725 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include "elf.h" + +struct v3_code_injects code_injects; + +static char mmap_code[] = "\xb8\xc0\x00\x00\x00\x31\xdb\xb9" + "\x00\x00\x10\x00\xba\x01\x00\x00" + "\x00\xbd\x02\x00\x00\x00\x09\xea" + "\xbd\x04\x00\x00\x00\x09\xea\xbe" + "\x02\x00\x00\x00\xbd\x20\x00\x00" + "\x00\x09\xee\xbf\xff\xff\xff\xff" + "\x31\xed\xcd\x80\x89\xc3\xb9\x00" + "\x00\x10\x00\xc7\x00\xef\xbe\xad" + "\xde\x05\x00\x10\x00\x00\x81\xe9" + "\x00\x10\x00\x00\x75\xed\xb8\x00" + "\xf0\x00\x00\x0f\x01\xd9"; + +static char munmap_code[] = "\xb8\x5b\x00\x00\x00\xb9\x00\x00" + "\x10\x00\xcd\x80\x89\xc3\xb8\x03" + "\xf0\x00\x00\x0f\x01\xd9"; + +static char vmmcall_code[] = "\x48\xc7\xc0\x02\xf0\x00\x00\x0f" + "\x01\xd9"; + +static const char elf_magic[] = {0x7f, 'E', 'L', 'F'}; + + +/* + * the presence of this is kind of a hack, and exists because + * when one of the below hypercall handlers is invoked, we don't + * have an elegant way of deciding which inject queue (normal or exec-hooked) + * to pull the first element from, so we have this place marker + * + * This could be ugly with more than one core... + */ +static struct v3_code_inject_info * current_inject; + + +static int free_code_inject (struct v3_vm_info * vm, struct v3_code_inject_info * inject) { + list_del(&(inject->inject_node)); + V3_Free(inject); + return 0; +} + + +/* + * helper function to save a chunk of code in an inject object's state and + * overwrite it with something else (mostly for injecting hypercalls) + */ +static int v3_plant_code (struct guest_info * core, struct v3_code_inject_info * inject, + char * hva, char * code, uint_t size) { + int i; + + // first back up old code + inject->old_code = (char*)V3_Malloc(size); + for (i = 0; i < size; i++) + inject->old_code[i] = *(hva + i); + + // overwrite + for (i = 0; i < size; i++) + *(hva + i) = *(code + i); + + return 0; +} + + +static int v3_restore_pre_mmap_state (struct guest_info * core, struct v3_code_inject_info * inject) { + int ret; + addr_t rip_hva, mmap_gva; + + if ((mmap_gva = (addr_t)core->vm_regs.rbx) < 0) { + PrintError("Error running mmap in guest: v3_restore_pre_mmap_state\n"); + return -1; + } + + inject->code_region_gva = mmap_gva; + + ret = v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)), + &rip_hva); + if (ret == -1) { + PrintError("Error translating RIP address: v3_restore_pre_mmap_state\n"); + return -1; + } + + // restore the code overwritten by mmap code + memcpy((void*)rip_hva, (void*)inject->old_code, MMAP_SIZE); + V3_Free(inject->old_code); + + v3_do_static_inject(core, inject, MMAP_COMPLETE, mmap_gva); + return 0; +} + + +static int v3_restore_pre_inject_state (struct guest_info * core, struct v3_code_inject_info * inject) { + int ret; + addr_t rip_hva; + + // restore original register state at int 80 + memcpy(&core->vm_regs, &inject->regs, sizeof(struct v3_gprs)); + memcpy(&core->ctrl_regs, &inject->ctrl_regs, sizeof(struct v3_ctrl_regs)); + + ret = v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)), + &rip_hva); + if (ret == -1) { + PrintError("Error translating RIP address: v3_pre_inject_state\n"); + return -1; + } + + // increment original rip by 2 to skip the int 80 + core->rip = inject->rip + 2; + return 0; +} + + +/* + * This function completes stage 1 of the inject. It is invoked when code to + * mmap space for the real code has been injected and has completed. This mmap + * code will hypercall back into Placios, getting us here. + */ +static int mmap_init_handler (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + struct v3_code_inject_info * inject = current_inject; + v3_restore_pre_mmap_state(core, inject); + return 0; +} + + +/* + * This function is stage 3 of the injection process. It is invoked when the injected code + * has run to completeion and run a hypercall at its tail to get back into the + * VMM. After this, it only remains to unmap the space we injected it into (the + * 4th and final stage) + */ +static int inject_code_finish (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + struct v3_code_inject_info * inject = current_inject; + addr_t hva; + + // is the original int 80 page still paged in? + if (v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)), + &hva) == -1) { + PrintError("No mapping in shadow page table: inject_code_finish\n"); + return -1; + } + + inject->old_code = V3_Malloc(MUNMAP_SIZE); + if (!inject->old_code) { + PrintError("Problem mallocing old code segment\n"); + return -1; + } + + // save old code and overwrite with munmap + v3_plant_code(core, inject, (char*)hva, munmap_code, MUNMAP_SIZE); + + // set rbx with gva of code region + core->vm_regs.rbx = inject->code_region_gva; + + // set rip back + core->rip = inject->rip; + return 0; +} + + +// +// this is 4th and final stage of the code injection process. It is invoked after code +// has been injected to run the munmap system call on our previosuly allocated +// memory chunk. It results in the clean +// up and removal of the current inject's structures and state, and its +// removal from any injection queues +// +static int munmap_finish (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + struct v3_code_inject_info * inject = current_inject; + int i = 0; + addr_t hva; + + if (core->vm_regs.rbx < 0) { + PrintError("Problem munmapping injected code\n"); + return -1; + } + + if (v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)), + &hva) == -1) { + PrintError("No mapping in shadow page table: inject_code_finish\n"); + return -1; + } + + for (i = 0; i < MUNMAP_SIZE; i++) + *(char*)(hva + i) = *(char*)(inject->old_code + i); + + V3_Free(inject->old_code); + + v3_restore_pre_inject_state(core, inject); + + // clean up + v3_remove_code_inject(core->vm_info, inject); + current_inject = NULL; + + // raise the original int 80 again, causing an exec + return v3_raise_swintr(core, SW_INTR_SYSCALL_VEC); +} + + +/* + * This function is comprises stage 2 of the injection process. Here, the + * injected code is copied one page at a time. Each time a new page must be + * copied, Palacios injects a page fault for it to bring it into the guest and + * host page tables. The fault address will be somewhere in our previously + * mmap'd region, but we will jump back to the same RIP every time, which + * contains the hypercall that invokes this function. + */ +static int mmap_pf_handler (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + struct v3_code_inject_info * inject = current_inject; + pf_error_t err; + int i, offset = core->vm_regs.rbx; + addr_t hva, gva = core->vm_regs.rcx; + memset((void*)&err, 0, sizeof(pf_error_t)); + + // was page fault handled by guest kernel? + if (v3_gva_to_hva(core, + get_addr_linear(core, gva, &(core->segments.ds)), + &hva) == -1) { + PrintError("No mapping in shadow page table: mmap_pf_handler\n"); + return -1; + } + + if (offset >= inject->code_size) { + core->rip = gva - offset + inject->func_offset; + + // restore registers (here, really just for sane ebp/esp) + memcpy(&core->vm_regs, &inject->regs, sizeof(struct v3_gprs)); + memcpy(&core->ctrl_regs, &inject->ctrl_regs, sizeof(struct v3_ctrl_regs)); + + if (v3_gva_to_hva(core, + get_addr_linear(core, inject->rip, &(core->segments.cs)), + &hva) == -1) { + PrintError("No mapping for old RIP in shadow page table: mmap_pf_handler: %p\n", (void*)inject->rip); + return -1; + } + + // restore the hypercall with original int 80 code + for (i = 0; i < VMMCALL_SIZE; i++) + *(char*)(hva + i) = *(char*)(inject->old_code + i); + + V3_Free(inject->old_code); + + if (v3_gva_to_hva(core, + get_addr_linear(core, core->rip, &(core->segments.cs)), + &hva) == -1) { + PrintError("No mapping for new RIP in shadow page table: mmap_pf_handler: %p\n", (void*)core->rip); + return -1; + } + + return 0; + } + + // copy the next page of code + for (i = 0; i < PAGE_SIZE; i++) + *(char*)(hva + i) = *(char*)(inject->code + offset + i); + + + core->vm_regs.rbx += PAGE_SIZE; + core->vm_regs.rcx += PAGE_SIZE; + + // to account for rip being incremented by hcall handler + core->rip -= VMMCALL_SIZE; + + // inject the page fault for next page + err.user = 1; + err.write = 1; + v3_inject_guest_pf(core, gva + PAGE_SIZE, err); + + return 0; +} + + +static int init_code_inject (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { + struct v3_code_injects * injects = &code_injects; + INIT_LIST_HEAD(&(injects->code_inject_list)); + INIT_LIST_HEAD(&(injects->hooked_code_injects)); + + injects->active = 1; + + current_inject = NULL; + + v3_register_hypercall(vm, 0xf000, mmap_init_handler, NULL); + v3_register_hypercall(vm, 0xf001, inject_code_finish, NULL); + v3_register_hypercall(vm, 0xf002, mmap_pf_handler, NULL); + v3_register_hypercall(vm, 0xf003, munmap_finish, NULL); + return 0; +} + + +static int deinit_code_inject (struct v3_vm_info * vm, void * priv_data) { + struct v3_code_injects * injects = &code_injects; + struct v3_code_inject_info * inject = NULL; + struct v3_code_inject_info * tmp = NULL; + + list_for_each_entry_safe(inject, tmp, &(injects->code_inject_list), inject_node) { + free_code_inject(vm, inject); + } + + list_for_each_entry_safe(inject, tmp, &(injects->hooked_code_injects), inject_node) { + free_code_inject(vm, inject); + } + + v3_remove_hypercall(vm, 0xf000); + v3_remove_hypercall(vm, 0xf001); + v3_remove_hypercall(vm, 0xf002); + v3_remove_hypercall(vm, 0xf003); + return 0; +} + + + + +/* KCH currently unused */ +/* this dynamic linking stuff will eventually be moved out of this file... */ +static addr_t v3_get_dyn_entry (struct guest_info * core, addr_t elf_gva, addr_t elf_hva, + int section_code) { + ElfW(Ehdr) *ehdr; + ElfW(Phdr) *phdr, *phdr_cursor; + ElfW(Dyn) *dyn = NULL; + int i, j, num_dyn; + addr_t hva; + + ehdr = (ElfW(Ehdr)*)elf_hva; + phdr = (ElfW(Phdr)*)(elf_hva + ehdr->e_phoff); + phdr_cursor = phdr; + + //PrintDebug("num phdrs: %d\n", ehdr->e_phnum); + for (i = 0; i < ehdr->e_phnum; i++, phdr_cursor++) { + if (phdr_cursor->p_type == PT_DYNAMIC) { + num_dyn = phdr_cursor->p_filesz / sizeof(ElfW(Dyn)); + dyn = (ElfW(Dyn)*)(elf_hva + phdr_cursor->p_offset); + + // make sure this addr is paged in + if (v3_gva_to_gpa(core, elf_gva + phdr_cursor->p_offset, &hva) == -1) { + PrintError("Dynamic segment isn't paged in\n"); + return 0; + } + + for (j = 0; j < num_dyn; j++, dyn++) { + if (dyn->d_tag == section_code) { + switch (section_code) { + case DT_STRSZ: + case DT_SYMENT: + case DT_PLTREL: + return (addr_t)dyn->d_un.d_val; + default: + return (addr_t)dyn->d_un.d_ptr; + } + } + } + break; + } + } + return 0; +} + + +static int v3_do_resolve (struct guest_info * core, addr_t elf_gva, addr_t elf_hva) { + + addr_t got_gva, symtab_gva, strtab_gva; + + if ((got_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_PLTGOT)) == 0) { + PrintError("Problem getting at PLTGOT in v3_do_resolve\n"); + return -1; + } + + + if ((strtab_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_STRTAB)) == 0) { + PrintError("Problem getting at PLTGOT in v3_do_resolve\n"); + return -1; + } + + if ((symtab_gva = v3_get_dyn_entry(core, elf_gva, elf_hva, DT_SYMTAB)) == 0) { + PrintError("Problem getting at PLTGOT in v3_do_resolve\n"); + return -1; + } + + + PrintDebug("Got gva: %p\n", (void*)got_gva); + PrintDebug("Symtab gva: %p\n", (void*)symtab_gva); + PrintDebug("Strtab gva: %p\n", (void*)strtab_gva); + return 0; +} + +static int v3_do_cont (struct guest_info * core, struct v3_code_inject_info * inject, addr_t check) { + + addr_t hva; + pf_error_t err_code; + int ret; + + ret = v3_gva_to_gpa(core, check, &hva); + + // page fault wasn't handled by kernel?? + if (ret == -1) { + PrintError("ERROR: no mapping in guest page table!\n"); + return -1; + } + + ret = v3_gva_to_hva(core, + get_addr_linear(core, check, &(core->segments.cs)), + &hva); + + // this should never happen... + if (ret == -1) { + PrintError("ERROR: no mapping in shadow page table\n"); + return -1; + } + + if (strncmp(elf_magic, (char*)hva, ELF_MAG_SIZE) != 0) { + + check -= PAGE_SIZE; + inject->cont->check_addr = check; + inject->cont->cont_func = v3_do_cont; + + memset((void*)&err_code, 0, sizeof(pf_error_t)); + err_code.user = 1; + + if (v3_inject_guest_pf(core, check, err_code) < 0) { + PrintError("Problem injecting pf\n"); + return -1; + } + + return E_NEED_PF; + } + + PrintDebug("Found ELF!\n"); + V3_Free(inject->cont); + inject->cont = NULL; + return v3_do_resolve(core, check, hva); +} + + +/* + * mmap_state: 0 = no inject space in procces yet + * 1 = code segment space mmap'd, still need data + * 2 = code & data segments mmap'd, ready to inject real code + * + */ +// +// return E_NEED_PF up the call stack to signal page fault injection +// (so rip doesn't get incremented and sw_intr doesn't get injected +// +int v3_do_inject (struct guest_info * core, struct v3_code_inject_info * inject, int mmap_state) { + addr_t rip_hva, elf_hva, elf_gva; + int ret = 0, i = 0; + pf_error_t err_code; + + memset((void*)&err_code, 0, sizeof(pf_error_t)); + + ret = v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)core->rip, &(core->segments.cs)), + &rip_hva); + if (ret == -1) { + PrintError("Error translating RIP address in v3_do_inject\n"); + return -1; + } + + elf_gva = (addr_t)(core->rip & 0xfffffffffffff000); + + for (i = 0; i < PAGES_BACK; i++, elf_gva -= PAGE_SIZE) { + + ret = v3_gva_to_hva(core, + get_addr_linear(core, elf_gva, &(core->segments.cs)), + &elf_hva); + + // need to page in + if (ret == -1) { + + PrintDebug("Found a page we need to fault in\n"); + inject->cont = (struct v3_cont *)V3_Malloc(sizeof(struct v3_cont)); + ret = v3_gva_to_gpa(core, elf_gva, &elf_hva); + + if (ret == -1) { + PrintDebug("no mapping in guest page table\n"); + } + + inject->cont->check_addr = elf_gva; + inject->cont->cont_func = v3_do_cont; + err_code.user = 1; + + PrintDebug("Injecting pf for addr: %p\n", (void*) elf_gva); + + if (v3_inject_guest_pf(core, elf_gva, err_code) < 0) { + PrintError("Problem injecting pf\n"); + return -1; + } + + return E_NEED_PF; + } + + if (strncmp(elf_magic, (char*)elf_hva, ELF_MAG_SIZE) == 0) { + PrintDebug("Found elf_magic!\n"); + break; + } + + } + + + V3_Free(inject->cont); + inject->cont = NULL; + return v3_do_resolve(core, elf_gva, elf_hva); + + PrintDebug("Planting code\n"); + v3_plant_code(core, inject, (char*)rip_hva, mmap_code, MMAP_SIZE); + + PrintDebug("Saving register context\n"); + PrintDebug("First 8 bytes 0x%lx\n", *(long*)rip_hva); + /* may need to save v3_ctrl registers too... */ + memcpy(&inject->regs, &core->vm_regs, sizeof(struct v3_gprs)); + inject->rip = core->rip; + + /* jump to injected code */ + PrintDebug("Jumping to injected code\n"); + return 0; +} + + +/* + * mmap_state: NO_MMAP = no inject space mmap'd in procces yet + * MMAP_COMPLETE = mmap complete, time to do real inject + * + */ +int v3_do_static_inject (struct guest_info * core, struct v3_code_inject_info * inject, + int mmap_state, addr_t region_gva) { + addr_t rip_hva; + int ret; + + + ret = v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)core->rip, &(core->segments.cs)), + &rip_hva); + if (ret == -1) { + PrintError("Error translating RIP address: v3_do_static_inject\n"); + return -1; + } + + switch (mmap_state) { + case NO_MMAP: + { + // inject mmap code + v3_plant_code(core, inject, (char*)rip_hva, mmap_code, MMAP_SIZE); + + // save registers (gprs and ctrl regs, and rip) + memcpy(&inject->regs, &core->vm_regs, sizeof(struct v3_gprs)); + memcpy(&inject->ctrl_regs, &core->ctrl_regs, sizeof(struct v3_ctrl_regs)); + inject->rip = core->rip; + + // jump to mmap code, and squash original swintr + return E_NEED_PF; + } + case MMAP_COMPLETE: + { + pf_error_t err_code; + memset((void*)&err_code, 0, sizeof(pf_error_t)); + + ret = v3_gva_to_hva(core, + get_addr_linear(core, (addr_t)inject->rip, &(core->segments.cs)), + &rip_hva); + if (ret == -1) { + PrintError("Error translating RIP address: v3_do_static_inject\n"); + return -1; + } + + // inject hypercall code + v3_plant_code(core, inject, (char*)rip_hva, vmmcall_code, VMMCALL_SIZE); + + /* store current copy offset in rbx, fault gva in rcx */ + core->vm_regs.rbx = 0; + core->vm_regs.rcx = region_gva; + + err_code.user = 1; + err_code.write = 1; + + // inject the first page fault for the code block + if (v3_inject_guest_pf(core, region_gva, err_code) < 0) { + PrintError("Problem injecting page fault in v3_do_static_inject\n"); + return -1; + } + + // returning here will run hypercall 0xf002 + // This will get us back in v3_mmap_pf_handler + core->rip = inject->rip; + return 0; + } + default: + PrintError("Invalid mmap state\n"); + return -1; + } + return 0; +} + + +/* + * This function is invoked in one of two ways: + * 1. A syscall has been intercepted and we've popped off the next pending + * inject + * 2. An exec has been intercepted and we've popped off the next hooked inject + * + */ +int v3_handle_guest_inject (struct guest_info * core, void * priv_data) { + struct v3_code_inject_info * inject = (struct v3_code_inject_info *)priv_data; + + /* eventually this should turn into a mutex lock */ + if (current_inject) { + PrintError("An inject is already in progress\n"); + return -1; + } else { + current_inject = inject; + inject->in_progress = 1; + } + + if (!inject->is_dyn) { + return v3_do_static_inject(core, inject, 0, (addr_t)NULL); + } else { + if (inject->cont) + return inject->cont->cont_func(core, inject, inject->cont->check_addr); + else + return v3_do_inject(core, inject, 0); + } + + return 0; +} + + +int v3_insert_code_inject (void * ginfo, void * code, int size, + char * bin_file, int is_dyn, int is_exec_hooked, int func_offset) { + struct v3_code_injects * injects = &code_injects; + struct v3_vm_info * vm = (struct v3_vm_info *)ginfo; + struct v3_code_inject_info * inject; + + if (!injects->active) { + PrintError("Code injection has not been initialized\n"); + return -1; + } + + inject = V3_Malloc(sizeof(struct v3_code_inject_info)); + if (!inject) { + PrintError("Error allocating inject info in v3_insert_code_inject\n"); + return -1; + } + + memset(inject, 0, sizeof(struct v3_code_inject_info)); + + inject->code = code; + inject->code_size = size; + inject->is_dyn = is_dyn; + inject->func_offset = func_offset; + inject->bin_file = bin_file; + inject->is_exec_hooked = is_exec_hooked; + + if (is_exec_hooked) { + v3_hook_executable(vm, bin_file, v3_handle_guest_inject, (void*)inject); + list_add_tail(&(inject->inject_node), &(injects->hooked_code_injects)); + } else { + list_add_tail(&(inject->inject_node), &(injects->code_inject_list)); + } + + return 0; +} + + +int v3_remove_code_inject (struct v3_vm_info * vm, struct v3_code_inject_info * inject) { + + PrintDebug("Removing and freeing code inject\n"); + if (inject->is_exec_hooked) { + if (v3_unhook_executable(vm, inject->bin_file) < 0) { + PrintError("Problem unhooking executable in v3_remove_code_inject\n"); + return -1; + } + } + + free_code_inject(vm, inject); + return 0; +} + + +static struct v3_extension_impl code_inject_impl = { + .name = "code_inject", + .init = init_code_inject, + .deinit = deinit_code_inject, + .core_init = NULL, + .core_deinit = NULL, + .on_entry = NULL, + .on_exit = NULL +}; +register_extension(&code_inject_impl); + diff --git a/palacios/src/gears/ext_env_inject.c b/palacios/src/gears/ext_env_inject.c new file mode 100644 index 0000000..4988dcf --- /dev/null +++ b/palacios/src/gears/ext_env_inject.c @@ -0,0 +1,115 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ +#include +#include +#include +#include + +#include +#include +#include + +static struct v3_env_injects env_injects; + +static int free_env_inject (struct v3_vm_info * vm, struct v3_env_inject_info * inject) { + list_del(&(inject->inject_node)); + V3_Free(inject); + return 0; +} + +static int v3_env_inject_handler (struct guest_info * core, void * priv_data) { + int i = 0; + struct v3_env_inject_info * inject = (struct v3_env_inject_info*)priv_data; + + for (; i < inject->num_env_vars; i++) { + PrintDebug("Envvar[%d]: %s\n", i, inject->env_vars[i]); + } + + int ret = v3_inject_strings(core, (const char**)NULL, + (const char**)inject->env_vars, 0, inject->num_env_vars); + if (ret == -1) { + PrintDebug("Error injecting strings in v3_env_inject_handler\n"); + return -1; + } + + return 0; +} + +static int init_env_inject (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { + struct v3_env_injects * injects = &env_injects; + INIT_LIST_HEAD(&(injects->env_inject_list)); + return 0; +} + + +static int deinit_env_inject (struct v3_vm_info * vm, void * priv_data) { + struct v3_env_injects * injects = &env_injects; + struct v3_env_inject_info * inject = NULL; + struct v3_env_inject_info * tmp = NULL; + + list_for_each_entry_safe(inject, tmp, &(injects->env_inject_list), inject_node) { + free_env_inject(vm, inject); + } + + return 0; +} + + +int v3_insert_env_inject (void * ginfo, char ** strings, int num_strings, char * bin_name) { + struct v3_env_injects * injects = &env_injects; + struct v3_env_inject_info * inject = V3_Malloc(sizeof(struct v3_env_inject_info)); + + memset(inject, 0, sizeof(struct v3_env_inject_info)); + + inject->env_vars = strings; + inject->num_env_vars = num_strings; + inject->bin_name = bin_name; + + list_add(&(inject->inject_node), &(injects->env_inject_list)); + + v3_hook_executable((struct v3_vm_info *)ginfo, bin_name, v3_env_inject_handler, (void*)inject); + + return 0; +} + + +int v3_remove_env_inject (struct v3_vm_info * vm, struct v3_env_inject_info * inject) { + + if (v3_unhook_executable(vm, inject->bin_name) < 0) { + PrintError("Problem unhooking executable in v3_remove_env_inject\n"); + return -1; + } + + free_env_inject(vm, inject); + return 0; +} + + +static struct v3_extension_impl env_inject_impl = { + .name = "env_inject", + .init = init_env_inject, + .deinit = deinit_env_inject, + .core_init = NULL, + .core_deinit = NULL, + .on_entry = NULL, + .on_exit = NULL +}; + +register_extension(&env_inject_impl); + diff --git a/palacios/src/gears/ext_execve_hook.c b/palacios/src/gears/ext_execve_hook.c new file mode 100644 index 0000000..aa5bce2 --- /dev/null +++ b/palacios/src/gears/ext_execve_hook.c @@ -0,0 +1,189 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#ifdef V3_CONFIG_EXT_CODE_INJECT +#include +#endif + +static struct v3_exec_hooks exec_hooks; + +static int free_hook (struct v3_vm_info * vm, struct exec_hook * hook) { + list_del(&(hook->hook_node)); + V3_Free(hook); + return 0; +} + +static uint_t exec_hash_fn (addr_t key) { + return v3_hash_long(key, sizeof(void *) * 8); +} + + +static int exec_eq_fn (addr_t key1, addr_t key2) { + return (key1 == key2); +} + + +static int init_exec_hooks (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { + + return 0; +} + +static int init_exec_hooks_core (struct guest_info * core, void * priv_data) { + struct v3_exec_hooks * hooks = &exec_hooks; + INIT_LIST_HEAD(&(hooks->hook_list)); + hooks->bin_table = v3_create_htable(0, exec_hash_fn, exec_eq_fn); + + if (hooks->bin_table == NULL) { + PrintError("Problem creating execve hash table\n"); + return -1; + } + + if (core->cpu_mode == LONG || core->cpu_mode == LONG_32_COMPAT) { + PrintDebug("Hooking execve 64\n"); + v3_hook_syscall(core, SYS64_EXECVE, v3_execve_handler, NULL); + } else { + PrintDebug("Hooking execve, cpu mode: %x\n", core->cpu_mode); + v3_hook_syscall(core, SYS32_EXECVE, v3_execve_handler, NULL); + } + return 0; +} + +static int deinit_exec_hooks_core (struct guest_info * core, void * priv_data) { + struct v3_exec_hooks * hooks = &exec_hooks; + struct exec_hook * hook = NULL; + struct exec_hook * tmp = NULL; + + list_for_each_entry_safe(hook, tmp, &(hooks->hook_list), hook_node) { + free_hook(core->vm_info, hook); + } + + v3_free_htable(hooks->bin_table, 0, 0); + + return 0; +} + + +int v3_hook_executable (struct v3_vm_info * vm, + const uchar_t * binfile, + int (*handler)(struct guest_info * core, void * priv_data), + void * priv_data) +{ + struct exec_hook * hook = V3_Malloc(sizeof(struct exec_hook)); + struct v3_exec_hooks * hooks = &exec_hooks; + addr_t key; + + memset(hook, 0, sizeof(struct exec_hook)); + + hook->handler = handler; + hook->priv_data = priv_data; + + // we hash the name of the file to produce a key + key = v3_hash_buffer((uchar_t*)binfile, strlen(binfile)); + + v3_htable_insert(hooks->bin_table, key, (addr_t)hook); + list_add(&(hook->hook_node), &(hooks->hook_list)); + + return 0; +} + + +int v3_unhook_executable (struct v3_vm_info * vm, const uchar_t * binfile) { + struct exec_hook * hook; + struct v3_exec_hooks * hooks = &exec_hooks; + addr_t key; + + key = v3_hash_buffer((uchar_t*)binfile, strlen((uchar_t*)binfile)); + if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) { + free_hook(vm, hook); + } else { + PrintError("Could not unhook executable '%s'\n", binfile); + return -1; + } + + if (v3_htable_remove(hooks->bin_table, key, 0) == (addr_t)NULL) { + PrintError("Error trying to remove key from htable: v3_unhook_executable\n"); + return -1; + } + + return 0; +} + +static struct v3_extension_impl execve_impl = { + .name = "execve_intercept", + .init = init_exec_hooks, + .deinit = NULL, + .core_init = init_exec_hooks_core, + .core_deinit = deinit_exec_hooks_core, + .on_entry = NULL, + .on_exit = NULL +}; + +register_extension(&execve_impl); + + +int v3_execve_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) { + addr_t hva, key; + struct v3_exec_hooks * hooks = &exec_hooks; + struct exec_hook * hook; + int ret; + + + // TODO: make sure this returns immediately if we're not booted up already + if (core->mem_mode == PHYSICAL_MEM) { + ret = v3_gpa_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva); + } else { + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)core->vm_regs.rbx, &(core->segments.ds)), &hva); + } + + if (ret == -1) { + PrintError("Error translating file path in sysexecve handler\n"); + return 0; + } + + key = v3_hash_buffer((uchar_t*)hva, strlen((uchar_t*)hva)); + if ((hook = (struct exec_hook*)v3_htable_search(hooks->bin_table, key)) != NULL) { + + ret = hook->handler(core, hook->priv_data); + if (ret == -1) { + PrintDebug("Error handling execve hook\n"); + return -1; + } + +#ifdef V3_CONFIG_EXT_CODE_INJECT + if (ret == E_NEED_PF) { + return E_NEED_PF; + } +#endif + } + + return 0; +} + diff --git a/palacios/src/gears/ext_process_environment.c b/palacios/src/gears/ext_process_environment.c new file mode 100644 index 0000000..7267866 --- /dev/null +++ b/palacios/src/gears/ext_process_environment.c @@ -0,0 +1,644 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include + +#include + +static struct v3_execve_varchunk var_dump; + + +/* KCH: currently only checks if we can perform a user-mode write + return 1 on success */ +static int v3_gva_can_access(struct guest_info * core, addr_t gva) { + + v3_reg_t guest_cr3 = 0; + pf_error_t access_type; + pt_access_status_t access_status; + + access_type.write = 1; + access_type.user = 1; + + if (core->mem_mode == PHYSICAL_MEM) { + return -1; + } + + if (core->shdw_pg_mode == SHADOW_PAGING) { + guest_cr3 = core->shdw_pg_state.guest_cr3; + } else { + guest_cr3 = core->ctrl_regs.cr3; + } + + // guest is in paged mode + switch (core->cpu_mode) { + case PROTECTED: + if (v3_check_guest_pt_32(core, guest_cr3, gva, access_type, &access_status) == -1) { + return -1; + } + break; + case PROTECTED_PAE: + if (v3_check_guest_pt_32pae(core, guest_cr3, gva, access_type, &access_status) == -1) { + return -1; + } + break; + case LONG: + case LONG_32_COMPAT: + case LONG_16_COMPAT: + if (v3_check_guest_pt_64(core, guest_cr3, gva, access_type, &access_status) == -1) { + return -1; + } + break; + default: + return -1; + } + + if (access_status != PT_ACCESS_OK) { + return 0; + } else { + return 1; + } +} + +static int v3_copy_chunk_guest32(struct guest_info * core, addr_t gva, uint_t argcnt, uint_t envcnt) { + + int ret = 0, i = 0; + addr_t hva; + uint32_t tmp_args[var_dump.argc]; + uint32_t tmp_envs[var_dump.envc]; + + PrintDebug("Initiating copy into guest (32bit)\n"); + + ret = v3_gva_to_hva(core, get_addr_linear(core, gva, &(core->segments.ds)), &hva); + if (ret == -1) { + PrintDebug("Error translating gva in v3_copy_chunk_2guest\n"); + return -1; + } + + // copy the env strings (we're moving top-down through the stack) + char * host_cursor = (char*) hva; + uint32_t guest_cursor = (uint32_t) gva; + host_cursor -= strlen(var_dump.envp[i]) + 1; + guest_cursor -= strlen(var_dump.envp[i]) + 1; + while (i < var_dump.envc) { + //PrintDebug("Copying envvar#%d: %s\n", i, var_dump.envp[i]); + strcpy(host_cursor, var_dump.envp[i]); + tmp_envs[i] = guest_cursor; + i++; + if (i != var_dump.envc) { + host_cursor -= strlen(var_dump.envp[i]) + 1; + guest_cursor -= strlen(var_dump.envp[i]) + 1; + } + } + + // then the arg strings + i = 0; + host_cursor -= strlen(var_dump.argv[i]) + 1; + guest_cursor -= strlen(var_dump.argv[i]) + 1; + while (i < var_dump.argc) { + //PrintDebug("Copying arg #%d: %s\n", i, var_dump.argv[i]); + strcpy(host_cursor, var_dump.argv[i]); + tmp_args[i] = guest_cursor; + i++; + if (i != var_dump.argc) { + host_cursor -= strlen(var_dump.argv[i]) + 1; + guest_cursor -= strlen(var_dump.argv[i]) + 1; + } + } + + + // padding + host_cursor--; + guest_cursor--; + while ((long)host_cursor % 4) { + *host_cursor = 0; + host_cursor--; + guest_cursor--; + } + + // null ptr + host_cursor -= 4; + guest_cursor -= 4; + *((uint32_t*)host_cursor) = 0; + + host_cursor -= 4; + guest_cursor -= 4; + for (i = 0; i < var_dump.envc; i++) { + *((uint32_t*)host_cursor) = tmp_envs[i]; + host_cursor -= 4; + guest_cursor -= 4; + } + + core->vm_regs.rdx = guest_cursor + 4; + + *((uint32_t*)host_cursor) = 0; + host_cursor -= 4; + guest_cursor -= 4; + for (i = 0; i < var_dump.argc; i++) { + *((uint32_t*)host_cursor) = tmp_args[i]; + host_cursor -= 4; + guest_cursor -= 4; + } + + core->vm_regs.rcx = guest_cursor + 4; + + // free up our temporary storage in the VMM + for (i = 0; i < var_dump.argc; i++) { + V3_Free(var_dump.argv[i]); + } + for (i = 0; i < var_dump.envc; i++) { + V3_Free(var_dump.envp[i]); + } + + V3_Free(var_dump.envp); + V3_Free(var_dump.argv); + return 0; +} + + +static int v3_copy_chunk_vmm32(struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) { + + addr_t envp, argv; + uint_t argc = 0, envc = 0, bytes = 0; + char * cursor; + + PrintDebug("Initiating copy into vmm\n"); + + int ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rdx, &(core->segments.ds)), &envp); + if (ret == -1) { + PrintDebug("Error translating address in rdx\n"); + return 0; + } + + ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rcx, &(core->segments.ds)), &argv); + if (ret == -1) { + PrintDebug("Error translating address in rcx\n"); + return 0; + } + + cursor = (char*)argv; + while (*((uint32_t*)cursor) != 0) { + addr_t argvn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &argvn); + if (ret == -1) { + PrintDebug("Error translating address for argvn\n"); + } + argc++; + cursor += 4; + } + + /* account for new args */ + argc += argcnt; + var_dump.argv = (char**)V3_Malloc(sizeof(char*)*argc); + var_dump.argc = argc; + bytes += sizeof(uint32_t)*argc; + + cursor = (char*)argv; + int i = 0; + while (*((uint32_t*)cursor) != 0) { + addr_t argvn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &argvn); + if (ret == -1) { + PrintDebug("Error translating argvn address\n"); + } + + /* malloc room for the string */ + char * tmpstr = (char*)V3_Malloc(strlen((char*)argvn) + 1); + + /* copy the pointer */ + var_dump.argv[i] = tmpstr; + + /* copy the string */ + strncpy(tmpstr, (char*)argvn, strlen((char*)argvn) + 1); + i++; + cursor += 4; + bytes += strlen((char*)argvn) + 1; + } + + /* stick in new arg strings */ + int j = 0; + while (j < argcnt) { + char * tmpstr = (char*)V3_Malloc(strlen(argstrs[j]) + 1); + strncpy(tmpstr, argstrs[i], strlen(argstrs[j]) + 1); + var_dump.argv[i] = tmpstr; + bytes += strlen(argstrs[j]) + 1; + i++; j++; + } + + + cursor = (char*)envp; + while (*((uint32_t*)cursor) != 0) { + addr_t envpn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &envpn); + if (ret == -1) { + PrintDebug("Error translating address for envpn\n"); + } + envc++; + cursor += 4; + } + + envc += envcnt; + var_dump.envp = (char**)V3_Malloc(sizeof(char*)*envc); + var_dump.envc = envc; + bytes += sizeof(uint32_t)*envc; + + cursor = (char*)envp; + i = 0; + while (*((uint32_t*)cursor) != 0) { + addr_t envpn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint32_t*)cursor), &(core->segments.ds)), &envpn); + if (ret == -1) { + PrintDebug("Error translating address for envpn\n"); + } + + /* malloc room for the string */ + char * tmpstr = (char*)V3_Malloc(strlen((char*)envpn) + 1); + + /* copy the pointer */ + var_dump.envp[i] = tmpstr; + + /* deepcopy the string */ + strncpy(tmpstr, (char*)envpn, strlen((char*)envpn) + 1); + i++; + cursor += 4; + bytes += strlen((char*)envpn) + 1; + } + + /* put in our new env strings */ + j = 0; + while (j < envcnt) { + char * tmpstr = (char*)V3_Malloc(strlen(envstrs[j]) + 1); + strncpy(tmpstr, envstrs[j], strlen(envstrs[j]) + 1); + var_dump.envp[i] = tmpstr; + bytes += strlen(envstrs[j]) + 1; + i++; j++; + } + + + /* account for padding for strings + and 2 null pointers */ + bytes += (bytes % 4) + 8; + var_dump.bytes = bytes; + return bytes; +} + + +static int v3_inject_strings32 (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) { + + addr_t inject_gva; + uint_t bytes_needed = 0; + + /* copy out all of the arguments and the environment to the VMM */ + if ((bytes_needed = v3_copy_chunk_vmm32(core, argstrs, envstrs, argcnt, envcnt)) == -1) { + PrintDebug("Error copying out environment and arguments\n"); + return -1; + } + + PrintDebug("environment successfully copied into VMM\n"); + + inject_gva = v3_prepare_guest_stack(core, bytes_needed); + if (!inject_gva) { + PrintDebug("Not enough space on user stack\n"); + return -1; + } + + v3_copy_chunk_guest32(core, inject_gva, argcnt, envcnt); + + return 0; +} + + +static int v3_copy_chunk_guest64(struct guest_info * core, addr_t gva, uint_t argcnt, uint_t envcnt) { + + int ret = 0, i = 0; + addr_t hva; + uint64_t tmp_args[var_dump.argc]; + uint64_t tmp_envs[var_dump.envc]; + + PrintDebug("Initiating copy into guest (64bit)\n"); + + ret = v3_gva_to_hva(core, get_addr_linear(core, gva, &(core->segments.ds)), &hva); + if (ret == -1) { + PrintDebug("Error translating gva in v3_copy_chunk_2guest64\n"); + return -1; + } + + char * host_cursor = (char*) hva; + uint64_t guest_cursor = (uint64_t) gva; + host_cursor -= strlen(var_dump.envp[i]) + 1; + guest_cursor -= strlen(var_dump.envp[i]) + 1; + while (i < var_dump.envc) { + //PrintDebug("Copying envvar#%d: %s\n", i, var_dump.envp[i]); + strcpy(host_cursor, var_dump.envp[i]); + tmp_envs[i] = guest_cursor; + i++; + if (i != var_dump.envc) { + host_cursor -= strlen(var_dump.envp[i]) + 1; + guest_cursor -= strlen(var_dump.envp[i]) + 1; + } + } + + i = 0; + host_cursor -= strlen(var_dump.argv[i]) + 1; + guest_cursor -= strlen(var_dump.argv[i]) + 1; + while (i < var_dump.argc) { + //PrintDebug("Copying arg #%d: %s\n", i, var_dump.argv[i]); + strcpy(host_cursor, var_dump.argv[i]); + tmp_args[i] = guest_cursor; + i++; + if (i != var_dump.argc) { + host_cursor -= strlen(var_dump.argv[i]) + 1; + guest_cursor -= strlen(var_dump.argv[i]) + 1; + } + } + + // padding + host_cursor--; + guest_cursor--; + while ((long)host_cursor % 8) { + *host_cursor = 0; + host_cursor--; + guest_cursor--; + } + + // one null ptr + host_cursor -= 8; + guest_cursor -= 8; + *((uint64_t*)host_cursor) = 0; + + host_cursor -= 8; + guest_cursor -= 8; + for (i = 0; i < var_dump.envc; i++) { + *((uint64_t*)host_cursor) = tmp_envs[i]; + host_cursor -= 8; + guest_cursor -= 8; + } + + core->vm_regs.rdx = guest_cursor + 8; + + *((uint64_t*)host_cursor) = 0; + host_cursor -= 8; + guest_cursor -= 8; + for (i = 0; i < var_dump.argc; i++) { + *((uint64_t*)host_cursor) = tmp_args[i]; + host_cursor -= 8; + guest_cursor -= 8; + } + + core->vm_regs.rcx = guest_cursor + 8; + + for (i = 0; i < var_dump.argc; i++) { + V3_Free(var_dump.argv[i]); + } + for (i = 0; i < var_dump.envc; i++) { + V3_Free(var_dump.envp[i]); + } + + V3_Free(var_dump.envp); + V3_Free(var_dump.argv); + return 0; +} + + +static int v3_copy_chunk_vmm64(struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) { + + addr_t envp, argv; + uint_t argc = 0, envc = 0, bytes = 0; + char * cursor; + + PrintDebug("Initiating copy into vmm\n"); + + int ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rdx, &(core->segments.ds)), &envp); + if (ret == -1) { + PrintDebug("Error translating address in rdx\n"); + return 0; + } + + ret = v3_gva_to_hva(core, get_addr_linear(core, core->vm_regs.rcx, &(core->segments.ds)), &argv); + if (ret == -1) { + PrintDebug("Error translating address in rcx\n"); + return 0; + } + + cursor = (char*)argv; + while (*((uint64_t*)cursor) != 0) { + addr_t argvn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &argvn); + if (ret == -1) { + PrintDebug("Error translating address for argvn\n"); + } + argc++; + cursor += 8; + } + + /* account for new strings */ + argc += argcnt; + var_dump.argv = (char**)V3_Malloc(sizeof(char*)*argc); + var_dump.argc = argc; + bytes += sizeof(char*)*argc; + + cursor = (char*)argv; + int i = 0; + while (*((uint64_t*)cursor) != 0) { + addr_t argvn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &argvn); + if (ret == -1) { + PrintDebug("Error translating argvn address\n"); + } + + /* malloc room for the string */ + char * tmpstr = (char*)V3_Malloc(strlen((char*)argvn) + 1); + + /* copy the pointer */ + var_dump.argv[i] = tmpstr; + + /* copy the string */ + strncpy(tmpstr, (char*)argvn, strlen((char*)argvn) + 1); + i++; + cursor += 8; + bytes += strlen((char*)argvn) + 1; + } + + /* stick in new arg strings */ + int j = 0; + while (j < argcnt) { + char * tmpstr = (char*)V3_Malloc(strlen(argstrs[j]) + 1); + strncpy(tmpstr, argstrs[j], strlen(argstrs[j]) + 1); + var_dump.argv[i] = tmpstr; + bytes += strlen(argstrs[j]) + 1; + i++; j++; + } + + + cursor = (char*)envp; + while (*((uint64_t*)cursor) != 0) { + addr_t envpn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &envpn); + if (ret == -1) { + PrintDebug("Error translating address for envpn\n"); + } + envc++; + cursor += 8; + } + + envc += envcnt; + var_dump.envp = (char**)V3_Malloc(sizeof(char*)*envc); + var_dump.envc = envc; + bytes += sizeof(uint64_t)*(envc); + + + cursor = (char*)envp; + i = 0; + while (*((uint64_t*)cursor) != 0) { + addr_t envpn; + ret = v3_gva_to_hva(core, get_addr_linear(core, (addr_t)*((uint64_t*)cursor), &(core->segments.ds)), &envpn); + if (ret == -1) { + PrintDebug("Error translating address for envpn\n"); + } + + /* malloc room for the string */ + char * tmpstr = (char*)V3_Malloc(strlen((char*)envpn) + 1); + + /* copy the pointer */ + var_dump.envp[i] = tmpstr; + + /* deepcopy the string */ + strncpy(tmpstr, (char*)envpn, strlen((char*)envpn) + 1); + i++; + cursor += 8; + bytes += strlen((char*)envpn) + 1; + } + + /* stick in new env strings */ + j = 0; + while (j < envcnt) { + char * tmpstr = (char*)V3_Malloc(strlen(envstrs[j]) + 1); + strncpy(tmpstr, envstrs[i], strlen(envstrs[j]) + 1); + var_dump.envp[i] = tmpstr; + bytes += strlen(envstrs[j]) + 1; + i++; j++; + } + + + /* account for padding for strings + and 2 null pointers */ + bytes += (bytes % 8) + 16; + var_dump.bytes = bytes; + return bytes; +} + + +static int v3_inject_strings64 (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) { + + addr_t inject_gva; + uint_t bytes_needed = 0; + + /* copy out all of the arguments and the environment to the VMM */ + if ((bytes_needed = v3_copy_chunk_vmm64(core, argstrs, envstrs, argcnt, envcnt)) == -1) { + PrintDebug("Error copying out environment and arguments\n"); + return -1; + } + + PrintDebug("environment successfully copied into VMM\n"); + + inject_gva = v3_prepare_guest_stack(core, bytes_needed); + if (!inject_gva) { + PrintDebug("Not enough space on user stack\n"); + return -1; + } + + v3_copy_chunk_guest64(core, inject_gva, argcnt, envcnt); + return 0; +} + + +addr_t v3_prepare_guest_stack (struct guest_info * core, uint_t bytes_needed) { + + /* TODO: check if we've injected a page fault to get more stack space */ + + // do we have enough room between esp and the next page boundary? + uint_t rem_bytes = 4096 - (core->vm_regs.rsp % 4096); + + if (rem_bytes >= bytes_needed) { + return (addr_t)core->vm_regs.rsp; + } else { + // not enough room, find out how many pages we need (ceiling) + uint_t num_pages = (bytes_needed + 4095) / 4096; + + // check if num_pages are user & writable + int i = 0; + int pages_ok = 1; + addr_t gva = core->vm_regs.rsp + rem_bytes; + for (; i < num_pages; i++, gva -= 4096) { + if (!v3_gva_can_access(core, gva)) { + pages_ok = 0; + } + } + + if (pages_ok) { + return (addr_t)core->vm_regs.rsp; + } else { + + /* + // inject a page fault + pf_error_t fault_type = { + .write = 1, + .user = 1 + }; + + // hoping Linux will allocate all pages in between gva and esp + v3_inject_guest_pf(core, gva - (num_pages*4096), fault_type); + */ + return -1; + } + } +} + + +/* TODO: give these next to functions the ability to copy into guest stack */ +int v3_replace_arg (struct guest_info * core, uint_t argnum, const char * newval) { + + return 0; +} + + +int v3_replace_env (struct guest_info * core, const char * envname, const char * newval) { + + return 0; +} + + +int v3_inject_strings (struct guest_info * core, const char ** argstrs, const char ** envstrs, uint_t argcnt, uint_t envcnt) { + + if (core->cpu_mode == LONG) { + if (v3_inject_strings64(core, argstrs, envstrs, argcnt, envcnt) == -1) { + PrintDebug("Error injecting strings into environment (64)\n"); + return -1; + } + } else { + if (v3_inject_strings32(core, argstrs, envstrs, argcnt, envcnt) == -1) { + PrintDebug("Error injecting strings into environment (32)\n"); + return -1; + } + } + + return 0; +} diff --git a/palacios/src/gears/ext_sw_intr.c b/palacios/src/gears/ext_sw_intr.c new file mode 100644 index 0000000..f73b5eb --- /dev/null +++ b/palacios/src/gears/ext_sw_intr.c @@ -0,0 +1,227 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#ifdef V3_CONFIG_EXT_CODE_INJECT +#include +#endif + +#ifndef V3_CONFIG_DEBUG_EXT_SW_INTERRUPTS +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif + + +static int init_swintr_intercept (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { + return 0; +} + + +static int init_swintr_core_svm (struct guest_info * core, void * priv_data) { + vmcb_t * vmcb = (vmcb_t*)core->vmm_data; + vmcb_ctrl_t * ctrl_area = GET_VMCB_CTRL_AREA(vmcb); + + ctrl_area->instrs.INTn = 1; + return 0; +} + + +static int init_swintr_core_vmx (struct guest_info * core, void * priv_data) { + PrintError("Not implemented!\n"); + return -1; +} + + +static int init_swintr_intercept_core (struct guest_info * core, void * priv_data) { + v3_cpu_arch_t cpu_type = v3_get_cpu_type(V3_Get_CPU()); + + switch (cpu_type) { + case V3_SVM_CPU: + case V3_SVM_REV3_CPU: { + if (init_swintr_core_svm(core, priv_data) == -1) { + PrintError("Problem initializing svm software interrupt intercept\n"); + return -1; + } + break; + } + case V3_VMX_CPU: + case V3_VMX_EPT_CPU: + case V3_VMX_EPT_UG_CPU: { + if (init_swintr_core_vmx(core, priv_data) == -1) { + PrintError("Problem initializing vmx software interrupt intercept\n"); + return -1; + } + break; + } + default: + PrintError("software interrupt interception not supported on this architecture\n"); + return -1; + } + return 0; +} + + +struct v3_swintr_hook { + int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data); + void * priv_data; +}; + + +static struct v3_swintr_hook * swintr_hooks[256]; + +static inline struct v3_swintr_hook * get_swintr_hook (struct guest_info * core, uint8_t vector) { + return swintr_hooks[vector]; +} + + +static struct v3_extension_impl swintr_impl = { + .name = "swintr_intercept", + .init = init_swintr_intercept, + .deinit = NULL, + .core_init = init_swintr_intercept_core, + .core_deinit = NULL, + .on_entry = NULL, + .on_exit = NULL +}; + + +register_extension(&swintr_impl); + + +int v3_handle_swintr (struct guest_info * core) { + + int ret = 0; + void * instr_ptr = NULL; + struct x86_instr instr; + + if (core->mem_mode == PHYSICAL_MEM) { + ret = v3_gpa_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr); + } else { + ret = v3_gva_to_hva(core, get_addr_linear(core, core->rip, &(core->segments.cs)), (addr_t *)&instr_ptr); + } + + if (ret == -1) { + PrintError("V3 SWintr Handler: Could not translate Instruction Address (%p)\n", (void *)core->rip); + return -1; + } + + if (v3_decode(core, (addr_t)instr_ptr, &instr) == -1) { + PrintError("V3 SWintr Handler: Decoding Error\n"); + return -1; + } + + uint8_t vector = instr.dst_operand.operand; + + struct v3_swintr_hook * hook = swintr_hooks[vector]; + if (hook == NULL) { +#ifdef V3_CONFIG_EXT_SWINTR_PASSTHROUGH + if (v3_hook_passthrough_swintr(core, vector) == -1) { + PrintDebug("V3 SWintr Handler: Error hooking passthrough swintr\n"); + return -1; + } + hook = swintr_hooks[vector]; +#else + core->rip += instr.instr_length; + return v3_raise_swintr(core, vector); +#endif + } + + ret = hook->handler(core, vector, NULL); + if (ret == -1) { + PrintDebug("V3 SWintr Handler: Error in swintr hook\n"); + return -1; + } + +#ifdef V3_CONFIG_EXT_CODE_INJECT +// this is for injecting page faults +// we don't want to increment rip or inject +// the swint if we need to fault a page in + if (ret == E_NEED_PF) { + return 0; + } +#endif + /* at some point we _may_ need to prioritize swints + so that they finish in time for the next + instruction... */ + core->rip += instr.instr_length; + return v3_raise_swintr(core, vector); +} + + + +int v3_hook_swintr (struct guest_info * core, + uint8_t vector, + int (*handler)(struct guest_info * core, uint8_t vector, void * priv_data), + void * priv_data) +{ + struct v3_swintr_hook * hook = (struct v3_swintr_hook*)V3_Malloc(sizeof(struct v3_swintr_hook)); + + if (hook == NULL) { + return -1; + } + + if (get_swintr_hook(core, vector) != NULL) { + PrintError("swint %d already hooked\n", vector); + return -1; + } + + hook->handler = handler; + hook->priv_data = priv_data; + + swintr_hooks[vector] = hook; + + PrintDebug("Hooked Swintr #%d\n", vector); + + return 0; +} + + +static int passthrough_swintr_handler (struct guest_info * core, uint8_t vector, void * priv_data) { + PrintDebug("[passthrough_swint_handler] INT vector=%d (guest=0x%p)\n", + vector, (void*)core); + return 0; +} + + +int v3_hook_passthrough_swintr (struct guest_info * core, uint8_t vector) { + + int rc = v3_hook_swintr(core, vector, passthrough_swintr_handler, NULL); + + if (rc) { + PrintError("guest_swintr_injection: failed to hook swint 0x%x (guest=0x%p)\n", vector, (void*)core); + return -1; + } else { + PrintDebug("guest_swintr_injection: hooked swint 0x%x (guest=0x%p)\n", vector, (void*)core); + return 0; + } + + /* shouldn't get here */ + return 0; +} + + diff --git a/palacios/src/gears/ext_syscall_hijack.c b/palacios/src/gears/ext_syscall_hijack.c new file mode 100644 index 0000000..f688182 --- /dev/null +++ b/palacios/src/gears/ext_syscall_hijack.c @@ -0,0 +1,1031 @@ +/* + * This file is part of the Palacios Virtual Machine Monitor developed + * by the V3VEE Project with funding from the United States National + * Science Foundation and the Department of Energy. + * + * The V3VEE Project is a joint project between Northwestern University + * and the University of New Mexico. You can find out more at + * http://www.v3vee.org + * + * Copyright (c) 2011, Kyle C. Hale + * Copyright (c) 2011, The V3VEE Project + * All rights reserved. + * + * Author: Kyle C. Hale + * + * This is free software. You are permitted to use, + * redistribute, and modify it as specified in the file "V3VEE_LICENSE". + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#include +#include +#include + +#ifdef V3_CONFIG_EXT_CODE_INJECT +#include +#include +extern struct v3_code_injects code_injects; +#endif + +#ifndef V3_CONFIG_DEBUG_EXT_SYSCALL_HIJACK +#undef PrintDebug +#define PrintDebug(fmt, args...) +#endif + + +struct v3_syscall_hook { + int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data); + void * priv_data; +}; + +static struct v3_syscall_hook * syscall_hooks[512]; + +#if defined(V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT) || defined(V3_CONFIG_EXT_SYSCALL_INSTR) +static struct v3_syscall_info syscall_info; +#endif + +static void print_arg (struct guest_info * core, v3_reg_t reg, uint8_t argnum) { + + addr_t hva; + int ret = 0; + + PrintDebug("\t ARG%d: INT - %ld\n", argnum, (long) reg); + + if (core->mem_mode == PHYSICAL_MEM) { + ret = v3_gpa_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva); + } + else { + ret = v3_gva_to_hva(core, get_addr_linear(core, reg, &(core->segments.ds)), &hva); + } + + PrintDebug("\t STR - "); + if (ret == -1) { + PrintDebug("\n"); + return; + } + + uint32_t c = max(MAX_CHARS, 4096 - (hva % 4096)); + int i = 0; + for (; i < c && *((char*)(hva + i)) != 0; i++) { + PrintDebug("%c", *((char*)(hva + i))); + } + PrintDebug("\n"); +} + + +static void print_syscall (uint8_t is64, struct guest_info * core) { + + if (is64) { + PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name64(core->vm_regs.rax)); + } else { + PrintDebug("Syscall #%ld: \"%s\"\n", (long)core->vm_regs.rax, get_linux_syscall_name32(core->vm_regs.rax)); + } + + print_arg(core, core->vm_regs.rbx, 1); + print_arg(core, core->vm_regs.rcx, 2); + print_arg(core, core->vm_regs.rdx, 3); +} + + +int v3_syscall_handler (struct guest_info * core, uint8_t vector, void * priv_data) { + + uint_t syscall_nr = (uint_t) core->vm_regs.rax; + int err = 0, ret = 0; + + struct v3_syscall_hook * hook = syscall_hooks[syscall_nr]; + +#ifdef V3_CONFIG_EXT_SYSCALL_INSTR + // address originally written to LSTAR + if (!vector) + core->rip = syscall_info.target_addr; +#endif + +#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT + PrintDebug("In v3_syscall_handler: syscall_nr - %d\n", syscall_nr); +#endif + + + if (hook == NULL) { +#ifdef V3_CONFIG_EXT_SYSCALL_PASSTHROUGH + if (v3_hook_passthrough_syscall(core, syscall_nr) == -1) { + PrintDebug("Error hooking passthrough syscall\n"); + return -1; + } + hook = syscall_hooks[syscall_nr]; +#endif + +/* + * if this syscall isn't hooked, pop off a pending inject + * and run it + */ +#ifdef V3_CONFIG_EXT_CODE_INJECT + struct v3_code_injects * injects = &code_injects; + struct v3_code_inject_info * inject = NULL; + + if (list_empty(&(injects->code_inject_list))) { + return 0; + } else { + + inject = (struct v3_code_inject_info*) list_first_entry( + &(injects->code_inject_list), + struct v3_code_inject_info, + inject_node); + + if (inject == NULL) { + PrintError("Problem getting inject from inject list\n"); + return -1; + } + + if (inject->in_progress) + return 0; + + // do the inject and don't fall over if there's an inject already in + // progress + if ((ret = v3_handle_guest_inject(core, (void*)inject)) == -1) { + PrintError("Could not run code injection: v3_syscall_handler\n"); + return 0; + } else { + return ret; + } + } +#else + return 0; +#endif + } + + err = hook->handler(core, syscall_nr, hook->priv_data); + if (err == -1) { + PrintDebug("V3 Syscall Handler: Error in syscall hook\n"); + return -1; + } + +#ifdef V3_CONFIG_EXT_CODE_INJECT + if (err == E_NEED_PF) + return E_NEED_PF; +#endif + return 0; +} + + +#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT +static int v3_handle_lstar_write (struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + syscall_info.target_addr = (uint64_t) ((((uint64_t)src.hi) << 32) | src.lo); + + PrintDebug("LSTAR Write: %p\n", (void*)syscall_info.target_addr); + core->ctrl_regs.lstar = syscall_info.target_addr; + return 0; +} + + +// virtualize the lstar +static int v3_handle_lstar_read (struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { + PrintDebug("LSTAR Read\n"); + dst->value = syscall_info.target_addr; + return 0; +} + + +static int syscall_setup (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + addr_t syscall_stub, syscall_map, ssa; + + syscall_stub = (addr_t)core->vm_regs.rbx; + syscall_map = (addr_t)core->vm_regs.rcx; + ssa = (addr_t)core->vm_regs.rdx; + + PrintDebug("made it to syscall setup hypercall\n"); + PrintDebug("\t&syscall_stub (rbx): %p\n\t&syscall_map (rcx): %p\n", (void*)syscall_stub, (void*)syscall_map); + PrintDebug("\t&ssa (rdx): %p\n", (void*)ssa); + + syscall_info.syscall_stub = syscall_stub; + syscall_info.syscall_map = (uint8_t*)syscall_map; + syscall_info.ssa = ssa; + + /* return the original syscall entry point */ + core->vm_regs.rax = syscall_info.target_addr; + + /* redirect syscalls henceforth */ + core->ctrl_regs.lstar = syscall_stub; + return 0; +} + + +static int syscall_cleanup (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + + core->ctrl_regs.lstar = syscall_info.target_addr; + PrintDebug("original syscall entry point restored\n"); + return 0; +} + + +static int sel_syscall_handle (struct guest_info * core, unsigned int hcall_id, void * priv_data) { + int ret; + addr_t hva; + struct v3_gprs regs; + + PrintDebug("caught a selectively exited syscall!\n"); + ret = v3_gva_to_hva(core, get_addr_linear(core, syscall_info.ssa, &(core->segments.ds)), &hva); + if (ret == -1) { + PrintError("Problem translating state save area address in sel_syscall_handle\n"); + return -1; + } + + /* setup registers for handler routines. They should be in the same state + * as when the system call was originally invoked */ + memcpy((void*)®s, (void*)&core->vm_regs, sizeof(struct v3_gprs)); + memcpy((void*)&core->vm_regs, (void*)hva, sizeof(struct v3_gprs)); + + v3_print_guest_state(core); + + // TODO: call syscall-independent handler + + memcpy((void*)hva, (void*)&core->vm_regs, sizeof(struct v3_gprs)); + memcpy((void*)&core->vm_regs, (void*)®s,sizeof(struct v3_gprs)); + return 0; +} + + +#endif + +static int init_syscall_hijack (struct v3_vm_info * vm, v3_cfg_tree_t * cfg, void ** priv_data) { +#ifdef V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT + v3_register_hypercall(vm, 0x5CA11, sel_syscall_handle, NULL); + v3_register_hypercall(vm, 0x5CA12, syscall_setup, NULL); + v3_register_hypercall(vm, 0x5CA13, syscall_cleanup, NULL); +#endif + return 0; +} + + + +#ifdef V3_CONFIG_EXT_SYSCALL_INSTR +static int v3_handle_lstar_write (struct guest_info * core, uint_t msr, struct v3_msr src, void * priv_data) { + PrintDebug("KCH: LSTAR Write\n"); + //PrintDebug("\tvalue: 0x%x%x\n", src.hi, src.lo); + syscall_info.target_addr = (uint64_t) ((((uint64_t)src.hi) << 32) | src.lo); + + // Set LSTAR value seen by hardware while the guest is running + PrintDebug("replacing with %lx\n", SYSCALL_MAGIC_ADDR); + core->ctrl_regs.lstar = SYSCALL_MAGIC_ADDR; + return 0; +} + +static int v3_handle_lstar_read (struct guest_info * core, uint_t msr, struct v3_msr * dst, void * priv_data) { + PrintDebug("KCH: LSTAR Read\n"); + dst->value = syscall_info.target_addr; + return 0; +} +#endif + + +static int init_syscall_hijack_core (struct guest_info * core, void * priv_data) { + +#ifdef V3_CONFIG_EXT_SW_INTERRUPTS + v3_hook_swintr(core, SYSCALL_INT_VECTOR, v3_syscall_handler, NULL); +#endif + +#if defined(V3_CONFIG_EXT_SYSCALL_INSTR) || defined(V3_CONFIG_EXT_SELECTIVE_SYSCALL_EXIT) + v3_hook_msr(core->vm_info, LSTAR_MSR, + &v3_handle_lstar_read, + &v3_handle_lstar_write, + core); +#endif + + return 0; +} + +static int deinit_syscall_hijack (struct v3_vm_info * vm, void * priv_data) { + return 0; +} + + +static struct v3_extension_impl syscall_impl = { + .name = "syscall_intercept", + .init = init_syscall_hijack, + .deinit = deinit_syscall_hijack, + .core_init = init_syscall_hijack_core, + .core_deinit = NULL, + .on_entry = NULL, + .on_exit = NULL +}; + +register_extension(&syscall_impl); + + +static inline struct v3_syscall_hook * get_syscall_hook (struct guest_info * core, uint_t syscall_nr) { + return syscall_hooks[syscall_nr]; +} + + +int v3_hook_syscall (struct guest_info * core, + uint_t syscall_nr, + int (*handler)(struct guest_info * core, uint_t syscall_nr, void * priv_data), + void * priv_data) +{ + struct v3_syscall_hook * hook = (struct v3_syscall_hook *)V3_Malloc(sizeof(struct v3_syscall_hook)); + + + if (hook == NULL) { + return -1; + } + + if (get_syscall_hook(core, syscall_nr) != NULL) { + PrintError("System Call #%d already hooked\n", syscall_nr); + return -1; + } + + hook->handler = handler; + hook->priv_data = priv_data; + + syscall_hooks[syscall_nr] = hook; + + PrintDebug("Hooked Syscall #%d\n", syscall_nr); + + return 0; +} + + +static int passthrough_syscall_handler (struct guest_info * core, uint_t syscall_nr, void * priv_data) { + print_syscall(core->cpu_mode == LONG, core); + return 0; +} + + +int v3_hook_passthrough_syscall (struct guest_info * core, uint_t syscall_nr) { + + int rc = v3_hook_syscall(core, syscall_nr, passthrough_syscall_handler, NULL); + + if (rc) { + PrintError("failed to hook syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core); + return -1; + } else { + PrintDebug("hooked syscall 0x%x for passthrough (guest=0x%p)\n", syscall_nr, (void *)core); + return 0; + } + + /* shouldn't get here */ + return 0; +} + + + +char * get_linux_syscall_name32 (uint_t syscall_nr) { + + switch (syscall_nr) { + + case 0: return "restart_syscall"; break; + case 1: return "exit"; break; + case 2: return "fork"; break; + case 3: return "read"; break; + case 4: return "write"; break; + case 5: return "open"; break; + case 6: return "close"; break; + case 7: return "waitpid"; break; + case 8: return "creat"; break; + case 9: return "link"; break; + case 10: return "unlink"; break; + case 11: return "execve"; break; + case 12: return "chdir"; break; + case 13: return "time"; break; + case 14: return "mknod"; break; + case 15: return "chmod"; break; + case 16: return "lchown"; break; + case 17: return "break"; break; + case 18: return "oldstat"; break; + case 19: return "lseek"; break; + case 20: return "getpid"; break; + case 21: return "mount"; break; + case 22: return "umount"; break; + case 23: return "setuid"; break; + case 24: return "getuid"; break; + case 25: return "stime"; break; + case 26: return "ptrace"; break; + case 27: return "alarm"; break; + case 28: return "oldfstat"; break; + case 29: return "pause"; break; + case 30: return "utime"; break; + case 31: return "stty"; break; + case 32: return "gtty"; break; + case 33: return "access"; break; + case 34: return "nice"; break; + case 35: return "ftime"; break; + case 36: return "sync"; break; + case 37: return "kill"; break; + case 38: return "rename"; break; + case 39: return "mkdir"; break; + case 40: return "rmdir"; break; + case 41: return "dup"; break; + case 42: return "pipe"; break; + case 43: return "times"; break; + case 44: return "prof"; break; + case 45: return "brk"; break; + case 46: return "setgid"; break; + case 47: return "getgid"; break; + case 48: return "signal"; break; + case 49: return "geteuid"; break; + case 50: return "getegid"; break; + case 51: return "acct"; break; + case 52: return "umount2"; break; + case 53: return "lock"; break; + case 54: return "ioctl"; break; + case 55: return "fcntl"; break; + case 56: return "mpx"; break; + case 57: return "setpgid"; break; + case 58: return "ulimit"; break; + case 59: return "oldolduname"; break; + case 60: return "umask"; break; + case 61: return "chroot"; break; + case 62: return "ustat"; break; + case 63: return "dup2"; break; + case 64: return "getppid"; break; + case 65: return "getpgrp"; break; + case 66: return "setsid"; break; + case 67: return "sigaction"; break; + case 68: return "sgetmask"; break; + case 69: return "ssetmask"; break; + case 70: return "setreuid"; break; + case 71: return "setregid"; break; + case 72: return "sigsuspend"; break; + case 73: return "sigpending"; break; + case 74: return "sethostname"; break; + case 75: return "setrlimit"; break; + case 76: return "getrlimit"; break; + case 77: return "getrusage"; break; + case 78: return "gettimeofday"; break; + case 79: return "settimeofday"; break; + case 80: return "getgroups"; break; + case 81: return "setgroups"; break; + case 82: return "select"; break; + case 83: return "symlink"; break; + case 84: return "oldlstat"; break; + case 85: return "readlink"; break; + case 86: return "uselib"; break; + case 87: return "swapon"; break; + case 88: return "reboot"; break; + case 89: return "readdir"; break; + case 90: return "mmap"; break; + case 91: return "munmap"; break; + case 92: return "truncate"; break; + case 93: return "ftruncate"; break; + case 94: return "fchmod"; break; + case 95: return "fchown"; break; + case 96: return "getpriority"; break; + case 97: return "setpriority"; break; + case 98: return "profil"; break; + case 99: return "statfs"; break; + case 100: return "fstatfs"; break; + case 101: return "ioperm"; break; + case 102: return "socketcall"; break; + case 103: return "syslog"; break; + case 104: return "setitimer"; break; + case 105: return "getitimer"; break; + case 106: return "stat"; break; + case 107: return "lstat"; break; + case 108: return "fstat"; break; + case 109: return "olduname"; break; + case 110: return "iopl"; break; + case 111: return "vhangup"; break; + case 112: return "idle"; break; + case 113: return "vm86old"; break; + case 114: return "wait4"; break; + case 115: return "swapoff"; break; + case 116: return "sysinfo"; break; + case 117: return "ipc"; break; + case 118: return "fsync"; break; + case 119: return "sigreturn"; break; + case 120: return "clone"; break; + case 121: return "setdomainname"; break; + case 122: return "uname"; break; + case 123: return "modify_ldt"; break; + case 124: return "adjtimex"; break; + case 125: return "mprotect"; break; + case 126: return "sigprocmask"; break; + case 127: return "create_module"; break; + case 128: return "init_module"; break; + case 129: return "delete_module"; break; + case 130: return "get_kernel_syms"; break; + case 131: return "quotactl"; break; + case 132: return "getpgid"; break; + case 133: return "fchdir"; break; + case 134: return "bdflush"; break; + case 135: return "sysfs"; break; + case 136: return "personality"; break; + case 137: return "afs_syscall"; break; + case 138: return "setfsuid"; break; + case 139: return "setfsgid"; break; + case 140: return "_llseek"; break; + case 141: return "getdents"; break; + case 142: return "_newselect"; break; + case 143: return "flock"; break; + case 144: return "msync"; break; + case 145: return "readv"; break; + case 146: return "writev"; break; + case 147: return "getsid"; break; + case 148: return "fdatasync"; break; + case 149: return "_sysctl"; break; + case 150: return "mlock"; break; + case 151: return "munlock"; break; + case 152: return "mlockall"; break; + case 153: return "munlockall"; break; + case 154: return "sched_setparam"; break; + case 155: return "sched_getparam"; break; + case 156: return "sched_setscheduler"; break; + case 157: return "sched_getscheduler"; break; + case 158: return "sched_yield"; break; + case 159: return "sched_get_priority_max"; break; + case 160: return "sched_get_priority_min"; break; + case 161: return "sched_rr_get_interval"; break; + case 162: return "nanosleep"; break; + case 163: return "mremap"; break; + case 164: return "setresuid"; break; + case 165: return "getresuid"; break; + case 166: return "vm86"; break; + case 167: return "query_module"; break; + case 168: return "poll"; break; + case 169: return "nfsservctl"; break; + case 170: return "setresgid"; break; + case 171: return "getresgid"; break; + case 172: return "prctl"; break; + case 173: return "rt_sigreturn"; break; + case 174: return "rt_sigaction"; break; + case 175: return "rt_sigprocmask"; break; + case 176: return "rt_sigpending"; break; + case 177: return "rt_sigtimedwait"; break; + case 178: return "rt_sigqueueinfo"; break; + case 179: return "rt_sigsuspend"; break; + case 180: return "pread64"; break; + case 181: return "pwrite64"; break; + case 182: return "chown"; break; + case 183: return "getcwd"; break; + case 184: return "capget"; break; + case 185: return "capset"; break; + case 186: return "sigaltstack"; break; + case 187: return "sendfile"; break; + case 188: return "getpmsg"; break; + case 189: return "putpmsg"; break; + case 190: return "vfork"; break; + case 191: return "ugetrlimit"; break; + case 192: return "mmap2"; break; + case 193: return "truncate64"; break; + case 194: return "ftruncate64"; break; + case 195: return "stat64"; break; + case 196: return "lstat64"; break; + case 197: return "fstat64"; break; + case 198: return "lchown32"; break; + case 199: return "getuid32"; break; + case 200: return "getgid32"; break; + case 201: return "geteuid32"; break; + case 202: return "getegid32"; break; + case 203: return "setreuid32"; break; + case 204: return "setregid32"; break; + case 205: return "getgroups32"; break; + case 206: return "setgroups32"; break; + case 207: return "fchown32"; break; + case 208: return "setresuid32"; break; + case 209: return "getresuid32"; break; + case 210: return "setresgid32"; break; + case 211: return "getresgid32"; break; + case 212: return "chown32"; break; + case 213: return "setuid32"; break; + case 214: return "setgid32"; break; + case 215: return "setfsuid32"; break; + case 216: return "setfsgid32"; break; + case 217: return "pivot_root"; break; + case 218: return "mincore"; break; + case 219: return "madvise1"; break; + case 220: return "getdents64"; break; + case 221: return "fcntl64"; break; + case 224: return "gettid"; break; + case 225: return "readahead"; break; + case 226: return "setxattr"; break; + case 227: return "lsetxattr"; break; + case 228: return "fsetxattr"; break; + case 229: return "getxattr"; break; + case 230: return "lgetxattr"; break; + case 231: return "fgetxattr"; break; + case 232: return "listxattr"; break; + case 233: return "llistxattr"; break; + case 234: return "flistxattr"; break; + case 235: return "removexattr"; break; + case 236: return "lremovexattr"; break; + case 237: return "fremovexattr"; break; + case 238: return "tkill"; break; + case 239: return "sendfile64"; break; + case 240: return "futex"; break; + case 241: return "sched_setaffinity"; break; + case 242: return "sched_getaffinity"; break; + case 243: return "set_thread_area"; break; + case 244: return "get_thread_area"; break; + case 245: return "io_setup"; break; + case 246: return "io_destroy"; break; + case 247: return "io_getevents"; break; + case 248: return "io_submit"; break; + case 249: return "io_cancel"; break; + case 250: return "fadvise64"; break; + case 252: return "exit_group"; break; + case 253: return "lookup_dcookie"; break; + case 254: return "epoll_create"; break; + case 255: return "epoll_ctl"; break; + case 256: return "epoll_wait"; break; + case 257: return "remap_file_pages"; break; + case 258: return "set_tid_address"; break; + case 259: return "timer_create"; break; + case 260: return "timer_settime"; break; + case 261: return "timer_gettime"; break; + case 262: return "timer_getoverrun"; break; + case 263: return "timer_delete"; break; + case 264: return "clock_settime"; break; + case 265: return "clock_gettime"; break; + case 266: return "clock_getres"; break; + case 267: return "clock_nanosleep"; break; + case 268: return "statfs64"; break; + case 269: return "fstatfs64"; break; + case 270: return "tgkill"; break; + case 271: return "utimes"; break; + case 272: return "fadvise64_64"; break; + case 273: return "vserver"; break; + case 274: return "mbind"; break; + case 275: return "get_mempolicy"; break; + case 276: return "set_mempolicy"; break; + case 277: return "mq_open"; break; + case 278: return "mq_unlink"; break; + case 279: return "mq_timedsend"; break; + case 280: return "mq_timedreceive"; break; + case 281: return "mq_notify"; break; + case 282: return "mq_getsetattr"; break; + case 283: return "kexec_load"; break; + case 284: return "waitid"; break; + case 285: return "sys_setaltroot"; break; + case 286: return "add_key"; break; + case 287: return "request_key"; break; + case 288: return "keyctl"; break; + case 289: return "ioprio_set"; break; + case 290: return "ioprio_get"; break; + case 291: return "inotify_init"; break; + case 292: return "inotify_add_watch"; break; + case 293: return "inotify_rm_watch"; break; + case 294: return "migrate_pages"; break; + case 295: return "openat"; break; + case 296: return "mkdirat"; break; + case 297: return "mknodat"; break; + case 298: return "fchownat"; break; + case 299: return "futimesat"; break; + case 300: return "fstatat64"; break; + case 301: return "unlinkat"; break; + case 302: return "renameat"; break; + case 303: return "linkat"; break; + case 304: return "symlinkat"; break; + case 305: return "readlinkat"; break; + case 306: return "fchmodat"; break; + case 307: return "faccessat"; break; + case 308: return "pselect6"; break; + case 309: return "ppoll"; break; + case 310: return "unshare"; break; + case 311: return "set_robust_list"; break; + case 312: return "get_robust_list"; break; + case 313: return "splice"; break; + case 314: return "sync_file_range"; break; + case 315: return "tee"; break; + case 316: return "vmsplice"; break; + case 317: return "move_pages"; break; + case 318: return "getcpu"; break; + case 319: return "epoll_pwait"; break; + case 320: return "utimensat"; break; + case 321: return "signalfd"; break; + case 322: return "timerfd_create"; break; + case 323: return "eventfd"; break; + case 324: return "fallocate"; break; + case 325: return "timerfd_settime"; break; + case 326: return "timerfd_gettime"; break; + case 327: return "signalfd4"; break; + case 328: return "eventfd2"; break; + case 329: return "epoll_create1"; break; + case 330: return "dup3"; break; + case 331: return "pipe2"; break; + case 332: return "inotify_init1"; break; + case 333: return "preadv"; break; + case 334: return "pwritev"; break; + case 335: return "rt_tgsigqueueinfo"; break; + case 336: return "perf_event_open"; break; + default: return "UNKNOWN"; break; + } +} + + +char * get_linux_syscall_name64 (uint_t syscall_nr) { + + switch (syscall_nr) { + + case 0: return "read"; break; + case 1: return "write"; break; + case 2: return "open"; break; + case 3: return "close"; break; + case 4: return "stat"; break; + case 5: return "fstat"; break; + case 6: return "lstat"; break; + case 7: return "poll"; break; + case 8: return "lseek"; break; + case 9: return "mmap"; break; + case 10: return "mprotect"; break; + case 11: return "munmap"; break; + case 12: return "brk"; break; + case 13: return "rt_sigaction"; break; + case 14: return "rt_sigprocmask"; break; + case 15: return "rt_sigreturn"; break; + case 16: return "ioctl"; break; + case 17: return "pread64"; break; + case 18: return "pwrite64"; break; + case 19: return "readv"; break; + case 20: return "writev"; break; + case 21: return "access"; break; + case 22: return "pipe"; break; + case 23: return "select"; break; + case 24: return "sched_yield"; break; + case 25: return "mremap"; break; + case 26: return "msync"; break; + case 27: return "mincore"; break; + case 28: return "madvise"; break; + case 29: return "shmget"; break; + case 30: return "shmat"; break; + case 31: return "shmctl"; break; + case 32: return "dup"; break; + case 33: return "dup2"; break; + case 34: return "pause"; break; + case 35: return "nanosleep"; break; + case 36: return "getitimer"; break; + case 37: return "alarm"; break; + case 38: return "setitimer"; break; + case 39: return "getpid"; break; + case 40: return "sendfile"; break; + case 41: return "socket"; break; + case 42: return "connect"; break; + case 43: return "accept"; break; + case 44: return "sendto"; break; + case 45: return "recvfrom"; break; + case 46: return "sendmsg"; break; + case 47: return "recvmsg"; break; + case 48: return "shutdown"; break; + case 49: return "bind"; break; + case 50: return "listen"; break; + case 51: return "getsockname"; break; + case 52: return "getpeername"; break; + case 53: return "socketpair"; break; + case 54: return "setsockopt"; break; + case 55: return "getsockopt"; break; + case 56: return "clone"; break; + case 57: return "fork"; break; + case 58: return "vfork"; break; + case 59: return "execve"; break; + case 60: return "exit"; break; + case 61: return "wait4"; break; + case 62: return "kill"; break; + case 63: return "uname"; break; + case 64: return "semget"; break; + case 65: return "semop"; break; + case 66: return "semctl"; break; + case 67: return "shmdt"; break; + case 68: return "msgget"; break; + case 69: return "msgsnd"; break; + case 70: return "msgrcv"; break; + case 71: return "msgctl"; break; + case 72: return "fcntl"; break; + case 73: return "flock"; break; + case 74: return "fsync"; break; + case 75: return "fdatasync"; break; + case 76: return "truncate"; break; + case 77: return "ftruncate"; break; + case 78: return "getdents"; break; + case 79: return "getcwd"; break; + case 80: return "chdir"; break; + case 81: return "fchdir"; break; + case 82: return "rename"; break; + case 83: return "mkdir"; break; + case 84: return "rmdir"; break; + case 85: return "creat"; break; + case 86: return "link"; break; + case 87: return "unlink"; break; + case 88: return "symlink"; break; + case 89: return "readlink"; break; + case 90: return "chmod"; break; + case 91: return "fchmod"; break; + case 92: return "chown"; break; + case 93: return "fchown"; break; + case 94: return "lchown"; break; + case 95: return "umask"; break; + case 96: return "gettimeofday"; break; + case 97: return "getrlimit"; break; + case 98: return "getrusage"; break; + case 99: return "sysinfo"; break; + case 100: return "times"; break; + case 101: return "ptrace"; break; + case 102: return "getuid"; break; + case 103: return "syslog"; break; + case 104: return "getgid"; break; + case 105: return "setuid"; break; + case 106: return "setgid"; break; + case 107: return "geteuid"; break; + case 108: return "getegid"; break; + case 109: return "setpgid"; break; + case 110: return "getppid"; break; + case 111: return "getpgrp"; break; + case 112: return "setsid"; break; + case 113: return "setreuid"; break; + case 114: return "setregid"; break; + case 115: return "getgroups"; break; + case 116: return "setgroups"; break; + case 117: return "setresuid"; break; + case 118: return "getresuid"; break; + case 119: return "setresgid"; break; + case 120: return "getresgid"; break; + case 121: return "getpgid"; break; + case 122: return "setfsuid"; break; + case 123: return "setfsgid"; break; + case 124: return "getsid"; break; + case 125: return "capget"; break; + case 126: return "capset"; break; + case 127: return "rt_sigpending"; break; + case 128: return "rt_sigtimedwait"; break; + case 129: return "rt_sigqueueinfo"; break; + case 130: return "rt_sigsuspend"; break; + case 131: return "sigaltstack"; break; + case 132: return "utime"; break; + case 133: return "mknod"; break; + case 134: return "uselib"; break; + case 135: return "personality"; break; + case 136: return "ustat"; break; + case 137: return "statfs"; break; + case 138: return "fstatfs"; break; + case 139: return "sysfs"; break; + case 140: return "getpriority"; break; + case 141: return "setpriority"; break; + case 142: return "sched_setparam"; break; + case 143: return "sched_getparam"; break; + case 144: return "sched_setscheduler"; break; + case 145: return "sched_getscheduler"; break; + case 146: return "sched_get_priority_max"; break; + case 147: return "sched_get_priority_min"; break; + case 148: return "sched_rr_get_interval"; break; + case 149: return "mlock"; break; + case 150: return "munlock"; break; + case 151: return "mlockall"; break; + case 152: return "munlockall"; break; + case 153: return "vhangup"; break; + case 154: return "modify_ldt"; break; + case 155: return "pivot_root"; break; + case 156: return "_sysctl"; break; + case 157: return "prctl"; break; + case 158: return "arch_prctl"; break; + case 159: return "adjtimex"; break; + case 160: return "setrlimit"; break; + case 161: return "chroot"; break; + case 162: return "sync"; break; + case 163: return "acct"; break; + case 164: return "settimeofday"; break; + case 165: return "mount"; break; + case 166: return "umount2"; break; + case 167: return "swapon"; break; + case 168: return "swapoff"; break; + case 169: return "reboot"; break; + case 170: return "sethostname"; break; + case 171: return "setdomainname"; break; + case 172: return "iopl"; break; + case 173: return "ioperm"; break; + case 174: return "create_module"; break; + case 175: return "init_module"; break; + case 176: return "delete_module"; break; + case 177: return "get_kernel_syms"; break; + case 178: return "query_module"; break; + case 179: return "quotactl"; break; + case 180: return "nfsservctl"; break; + case 181: return "getpmsg"; break; + case 182: return "putpmsg"; break; + case 183: return "afs_syscall"; break; + case 184: return "tuxcall"; break; + case 185: return "security"; break; + case 186: return "gettid"; break; + case 187: return "readahead"; break; + case 188: return "setxattr"; break; + case 189: return "lsetxattr"; break; + case 190: return "fsetxattr"; break; + case 191: return "getxattr"; break; + case 192: return "lgetxattr"; break; + case 193: return "fgetxattr"; break; + case 194: return "listxattr"; break; + case 195: return "llistxattr"; break; + case 196: return "flistxattr"; break; + case 197: return "removexattr"; break; + case 198: return "lremovexattr"; break; + case 199: return "fremovexattr"; break; + case 200: return "tkill"; break; + case 201: return "time"; break; + case 202: return "futex"; break; + case 203: return "sched_setaffinity"; break; + case 204: return "sched_getaffinity"; break; + case 205: return "set_thread_area"; break; + case 206: return "io_setup"; break; + case 207: return "io_destroy"; break; + case 208: return "io_getevents"; break; + case 209: return "io_submit"; break; + case 210: return "io_cancel"; break; + case 211: return "get_thread_area"; break; + case 212: return "lookup_dcookie"; break; + case 213: return "epoll_create"; break; + case 214: return "epoll_ctl_old"; break; + case 215: return "epoll_wait_old"; break; + case 216: return "remap_file_pages"; break; + case 217: return "getdents64"; break; + case 218: return "set_tid_address"; break; + case 219: return "restart_syscall"; break; + case 220: return "semtimedop"; break; + case 221: return "fadvise64"; break; + case 222: return "timer_create"; break; + case 223: return "timer_settime"; break; + case 224: return "timer_gettime"; break; + case 225: return "timer_getoverrun"; break; + case 226: return "timer_delete"; break; + case 227: return "clock_settime"; break; + case 228: return "clock_gettime"; break; + case 229: return "clock_getres"; break; + case 230: return "clock_nanosleep"; break; + case 231: return "exit_group"; break; + case 232: return "epoll_wait"; break; + case 233: return "epoll_ctl"; break; + case 234: return "tgkill"; break; + case 235: return "utimes"; break; + case 236: return "vserver"; break; + case 237: return "mbind"; break; + case 238: return "set_mempolicy"; break; + case 239: return "get_mempolicy"; break; + case 240: return "mq_open"; break; + case 241: return "mq_unlink"; break; + case 242: return "mq_timedsend"; break; + case 243: return "mq_timedreceive"; break; + case 244: return "mq_notify"; break; + case 246: return "kexec_load"; break; + case 247: return "waitid"; break; + case 248: return "add_key"; break; + case 249: return "request_key"; break; + case 250: return "keyctl"; break; + case 251: return "ioprio_set"; break; + case 252: return "ioprio_get"; break; + case 253: return "inotify_init"; break; + case 254: return "inotify_add_watch"; break; + case 255: return "inotify_rm_watch"; break; + case 256: return "migrate_pages"; break; + case 257: return "openat"; break; + case 258: return "mkdirat"; break; + case 259: return "mknodat"; break; + case 260: return "fchownat"; break; + case 261: return "futimesat"; break; + case 262: return "newfstatat"; break; + case 263: return "unlinkat"; break; + case 264: return "renameat"; break; + case 265: return "linkat"; break; + case 266: return "symlinkat"; break; + case 267: return "readlinkat"; break; + case 268: return "fchmodat"; break; + case 269: return "faccessat"; break; + case 270: return "pselect6"; break; + case 271: return "ppoll"; break; + case 272: return "unshare"; break; + case 273: return "set_robust_list"; break; + case 274: return "get_robust_list"; break; + case 275: return "splice"; break; + case 276: return "tee"; break; + case 277: return "sync_file_range"; break; + case 278: return "vmsplice"; break; + case 279: return "move_pages"; break; + case 280: return "utimensat"; break; + case 281: return "epoll_pwait"; break; + case 282: return "signalfd"; break; + case 283: return "timerfd_create"; break; + case 284: return "eventfd"; break; + case 285: return "fallocate"; break; + case 286: return "timerfd_settime"; break; + case 287: return "timerfd_gettime"; break; + case 288: return "accept4"; break; + case 289: return "signalfd4"; break; + case 290: return "eventfd2"; break; + case 291: return "epoll_create1"; break; + case 292: return "dup3"; break; + case 293: return "pipe2"; break; + case 294: return "inotify_init1"; break; + case 295: return "preadv"; break; + case 296: return "pwritev"; break; + case 297: return "rt_tgsigqueueinfo"; break; + case 298: return "perf_event_open"; break; + default: return "UNKNOWN"; break; + } +}