1 2 /*--------------------------------------------------------------------*/ 3 /*--- User-mode execve(), and other stuff shared between stage1 ---*/ 4 /*--- and stage2. m_ume.c ---*/ 5 /*--------------------------------------------------------------------*/ 6 7 /* 8 This file is part of Valgrind, a dynamic binary instrumentation 9 framework. 10 11 Copyright (C) 2000-2012 Julian Seward 12 jseward (at) acm.org 13 14 This program is free software; you can redistribute it and/or 15 modify it under the terms of the GNU General Public License as 16 published by the Free Software Foundation; either version 2 of the 17 License, or (at your option) any later version. 18 19 This program is distributed in the hope that it will be useful, but 20 WITHOUT ANY WARRANTY; without even the implied warranty of 21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 22 General Public License for more details. 23 24 You should have received a copy of the GNU General Public License 25 along with this program; if not, write to the Free Software 26 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 27 02111-1307, USA. 28 29 The GNU General Public License is contained in the file COPYING. 30 */ 31 32 33 #include "pub_core_basics.h" 34 #include "pub_core_vki.h" 35 36 #include "pub_core_libcbase.h" 37 #include "pub_core_libcassert.h" // VG_(exit), vg_assert 38 #include "pub_core_libcfile.h" // VG_(close) et al 39 #include "pub_core_libcprint.h" // VG_(message) 40 #include "pub_core_mallocfree.h" // VG_(strdup) 41 #include "pub_core_syscall.h" // VG_(mk_SysRes_Error) 42 #include "pub_core_options.h" // VG_(clo_xml) 43 #include "pub_core_ume.h" // self 44 45 #include "priv_ume.h" 46 47 48 typedef struct { 49 Bool (*match_fn)(Char *hdr, Int len); 50 Int (*load_fn)(Int fd, const HChar *name, ExeInfo *info); 51 } ExeHandler; 52 53 static ExeHandler exe_handlers[] = { 54 # if defined(VGO_linux) 55 { VG_(match_ELF), VG_(load_ELF) }, 56 # elif defined(VGO_darwin) 57 { VG_(match_macho), VG_(load_macho) }, 58 # else 59 # error "unknown OS" 60 # endif 61 { VG_(match_script), VG_(load_script) }, 62 }; 63 #define EXE_HANDLER_COUNT (sizeof(exe_handlers)/sizeof(exe_handlers[0])) 64 65 66 // Check the file looks executable. 67 SysRes 68 VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid) 69 { 70 Int fd, ret, i; 71 SysRes res; 72 Char buf[4096]; 73 SizeT bufsz = 4096, fsz; 74 Bool is_setuid = False; 75 76 // Check it's readable 77 res = VG_(open)(exe_name, VKI_O_RDONLY, 0); 78 if (sr_isError(res)) { 79 return res; 80 } 81 fd = sr_Res(res); 82 83 // Check we have execute permissions 84 ret = VG_(check_executable)(&is_setuid, (HChar*)exe_name, allow_setuid); 85 if (0 != ret) { 86 VG_(close)(fd); 87 if (is_setuid && !VG_(clo_xml)) { 88 VG_(message)(Vg_UserMsg, "\n"); 89 VG_(message)(Vg_UserMsg, 90 "Warning: Can't execute setuid/setgid executable: %s\n", 91 exe_name); 92 VG_(message)(Vg_UserMsg, "Possible workaround: remove " 93 "--trace-children=yes, if in effect\n"); 94 VG_(message)(Vg_UserMsg, "\n"); 95 } 96 return VG_(mk_SysRes_Error)(ret); 97 } 98 99 fsz = (SizeT)VG_(fsize)(fd); 100 if (fsz < bufsz) 101 bufsz = fsz; 102 103 res = VG_(pread)(fd, buf, bufsz, 0); 104 if (sr_isError(res) || sr_Res(res) != bufsz) { 105 VG_(close)(fd); 106 return VG_(mk_SysRes_Error)(VKI_EACCES); 107 } 108 bufsz = sr_Res(res); 109 110 // Look for a matching executable format 111 for (i = 0; i < EXE_HANDLER_COUNT; i++) { 112 if ((*exe_handlers[i].match_fn)(buf, bufsz)) { 113 res = VG_(mk_SysRes_Success)(i); 114 break; 115 } 116 } 117 if (i == EXE_HANDLER_COUNT) { 118 // Rejected by all executable format handlers. 119 res = VG_(mk_SysRes_Error)(VKI_ENOEXEC); 120 } 121 122 // Write the 'out_fd' param if necessary, or close the file. 123 if (!sr_isError(res) && out_fd) { 124 *out_fd = fd; 125 } else { 126 VG_(close)(fd); 127 } 128 129 return res; 130 } 131 132 // returns: 0 = success, non-0 is failure 133 // 134 // We can execute only binaries (ELF, etc) or scripts that begin with "#!". 135 // (Not, for example, scripts that don't begin with "#!"; see the 136 // VG_(do_exec)() invocation from m_main.c for how that's handled.) 137 Int VG_(do_exec_inner)(const HChar* exe, ExeInfo* info) 138 { 139 SysRes res; 140 Int fd; 141 Int ret; 142 143 res = VG_(pre_exec_check)(exe, &fd, False/*allow_setuid*/); 144 if (sr_isError(res)) 145 return sr_Err(res); 146 147 vg_assert2(sr_Res(res) >= 0 && sr_Res(res) < EXE_HANDLER_COUNT, 148 "invalid VG_(pre_exec_check) result"); 149 150 ret = (*exe_handlers[sr_Res(res)].load_fn)(fd, exe, info); 151 152 VG_(close)(fd); 153 154 return ret; 155 } 156 157 158 static Bool is_hash_bang_file(Char* f) 159 { 160 SysRes res = VG_(open)(f, VKI_O_RDONLY, 0); 161 if (!sr_isError(res)) { 162 Char buf[3] = {0,0,0}; 163 Int fd = sr_Res(res); 164 Int n = VG_(read)(fd, buf, 2); 165 if (n == 2 && VG_STREQ("#!", buf)) 166 return True; 167 } 168 return False; 169 } 170 171 // Look at the first 80 chars, and if any are greater than 127, it's binary. 172 // This is crude, but should be good enough. Note that it fails on a 173 // zero-length file, as we want. 174 static Bool is_binary_file(Char* f) 175 { 176 SysRes res = VG_(open)(f, VKI_O_RDONLY, 0); 177 if (!sr_isError(res)) { 178 UChar buf[80]; 179 Int fd = sr_Res(res); 180 Int n = VG_(read)(fd, buf, 80); 181 Int i; 182 for (i = 0; i < n; i++) { 183 if (buf[i] > 127) 184 return True; // binary char found 185 } 186 return False; 187 } else { 188 // Something went wrong. This will only happen if we earlier 189 // succeeded in opening the file but fail here (eg. the file was 190 // deleted between then and now). 191 VG_(fmsg)("%s: unknown error\n", f); 192 VG_(exit)(126); // 126 == NOEXEC 193 } 194 } 195 196 // If the do_exec fails we try to emulate what the shell does (I used 197 // bash as a guide). It's worth noting that the shell can execute some 198 // things that VG_(do_exec)() (which subsitutes for the kernel's exec()) 199 // will refuse to (eg. scripts lacking a "#!" prefix). 200 static Int do_exec_shell_followup(Int ret, HChar* exe_name, ExeInfo* info) 201 { 202 # if defined(VGPV_arm_linux_android) || defined(VGPV_x86_linux_android) 203 Char* default_interp_name = "/system/bin/sh"; 204 # else 205 Char* default_interp_name = "/bin/sh"; 206 # endif 207 208 SysRes res; 209 struct vg_stat st; 210 211 if (VKI_ENOEXEC == ret) { 212 // It was an executable file, but in an unacceptable format. Probably 213 // is a shell script lacking the "#!" prefix; try to execute it so. 214 215 // Is it a binary file? 216 if (is_binary_file(exe_name)) { 217 VG_(fmsg)("%s: cannot execute binary file\n", exe_name); 218 VG_(exit)(126); // 126 == NOEXEC 219 } 220 221 // Looks like a script. Run it with /bin/sh. This includes 222 // zero-length files. 223 224 info->interp_name = VG_(strdup)("ume.desf.1", default_interp_name); 225 info->interp_args = NULL; 226 if (info->argv && info->argv[0] != NULL) 227 info->argv[0] = (char *)exe_name; 228 229 ret = VG_(do_exec_inner)(info->interp_name, info); 230 231 if (0 != ret) { 232 // Something went wrong with executing the default interpreter 233 VG_(fmsg)("%s: bad interpreter (%s): %s\n", 234 exe_name, info->interp_name, VG_(strerror)(ret)); 235 VG_(exit)(126); // 126 == NOEXEC 236 } 237 238 } else if (0 != ret) { 239 // Something else went wrong. Try to make the error more specific, 240 // and then print a message and abort. 241 242 // Was it a directory? 243 res = VG_(stat)(exe_name, &st); 244 if (!sr_isError(res) && VKI_S_ISDIR(st.mode)) { 245 VG_(fmsg)("%s: is a directory\n", exe_name); 246 247 // Was it not executable? 248 } else if (0 != VG_(check_executable)(NULL, exe_name, 249 False/*allow_setuid*/)) { 250 VG_(fmsg)("%s: %s\n", exe_name, VG_(strerror)(ret)); 251 252 // Did it start with "#!"? If so, it must have been a bad interpreter. 253 } else if (is_hash_bang_file(exe_name)) { 254 VG_(fmsg)("%s: bad interpreter: %s\n", exe_name, VG_(strerror)(ret)); 255 256 // Otherwise it was something else. 257 } else { 258 VG_(fmsg)("%s: %s\n", exe_name, VG_(strerror)(ret)); 259 } 260 // 126 means NOEXEC; I think this is Posix, and that in some cases we 261 // should be returning 127, meaning NOTFOUND. Oh well. 262 VG_(exit)(126); 263 } 264 return ret; 265 } 266 267 268 // This emulates the kernel's exec(). If it fails, it then emulates the 269 // shell's handling of the situation. 270 // See ume.h for an indication of which entries of 'info' are inputs, which 271 // are outputs, and which are both. 272 /* returns: 0 = success, non-0 is failure */ 273 Int VG_(do_exec)(const HChar* exe_name, ExeInfo* info) 274 { 275 Int ret; 276 277 info->interp_name = NULL; 278 info->interp_args = NULL; 279 280 ret = VG_(do_exec_inner)(exe_name, info); 281 282 if (0 != ret) { 283 Char* exe_name_casted = (Char*)exe_name; 284 ret = do_exec_shell_followup(ret, exe_name_casted, info); 285 } 286 return ret; 287 } 288 289 /*--------------------------------------------------------------------*/ 290 /*--- end ---*/ 291 /*--------------------------------------------------------------------*/ 292