1 2 /*--------------------------------------------------------------------*/ 3 /*--- User-mode execve() for #! scripts. m_ume_script.c ---*/ 4 /*--------------------------------------------------------------------*/ 5 6 /* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2013 Julian Seward 11 jseward (at) acm.org 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29 */ 30 31 #include "pub_core_basics.h" 32 #include "pub_core_vki.h" 33 34 #include "pub_core_libcbase.h" 35 #include "pub_core_libcassert.h" // VG_(exit), vg_assert 36 #include "pub_core_libcfile.h" // VG_(close) et al 37 #include "pub_core_libcprint.h" 38 #include "pub_core_xarray.h" 39 #include "pub_core_clientstate.h" 40 #include "pub_core_mallocfree.h" // VG_(strdup) 41 #include "pub_core_ume.h" // self 42 43 #include "priv_ume.h" 44 45 Bool VG_(match_script)(const void *hdr, Int len) 46 { 47 const HChar* script = hdr; 48 const HChar* end = script + len; 49 const HChar* interp = script + 2; 50 51 // len < 4: need '#', '!', plus at least a '/' and one more char 52 if (len < 4) return False; 53 if (0 != VG_(memcmp)(hdr, "#!", 2)) return False; 54 55 // Find interpreter name, make sure it's an absolute path (starts with 56 // '/') and has at least one more char. First, skip over any space 57 // between the #! and the start of the interpreter name 58 while (interp < end && VG_(isspace)(*interp)) interp++; 59 60 // overrun? 61 if (interp >= end) return False; // can't find start of interp name 62 63 // interp should now point at the / 64 if (*interp != '/') return False; // absolute path only for interpreter 65 66 // check for something plausible after the / 67 interp++; 68 if (interp >= end) return False; 69 if (VG_(isspace)(*interp)) return False; 70 71 // Here we should get the full interpreter name and check it with 72 // check_executable(). See the "EXEC FAILED" failure when running shell 73 // for an example. 74 75 return True; // looks like a #! script 76 } 77 78 79 /* returns: 0 = success, non-0 is failure */ 80 Int VG_(load_script)(Int fd, const HChar* name, ExeInfo* info) 81 { 82 HChar hdr[4096]; 83 Int len = 4096; 84 Int eol; 85 HChar* interp; 86 HChar* end; 87 HChar* cp; 88 HChar* arg = NULL; 89 SysRes res; 90 91 // Read the first part of the file. 92 res = VG_(pread)(fd, hdr, len, 0); 93 if (sr_isError(res)) { 94 VG_(close)(fd); 95 return VKI_EACCES; 96 } else { 97 len = sr_Res(res); 98 } 99 100 vg_assert('#' == hdr[0] && '!' == hdr[1]); 101 102 end = hdr + len; 103 interp = hdr + 2; 104 while (interp < end && VG_(isspace)(*interp)) 105 interp++; 106 107 vg_assert(*interp == '/'); /* absolute path only for interpreter */ 108 109 /* skip over interpreter name */ 110 for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++) 111 ; 112 113 eol = (*cp == '\n'); 114 115 *cp++ = '\0'; 116 117 if (!eol && cp < end) { 118 /* skip space before arg */ 119 while (cp < end && VG_(isspace)(*cp) && *cp != '\n') 120 cp++; 121 122 /* arg is from here to eol */ 123 arg = cp; 124 while (cp < end && *cp != '\n') 125 cp++; 126 *cp = '\0'; 127 } 128 129 info->interp_name = VG_(strdup)("ume.ls.1", interp); 130 vg_assert(NULL != info->interp_name); 131 if (arg != NULL && *arg != '\0') { 132 info->interp_args = VG_(strdup)("ume.ls.2", arg); 133 vg_assert(NULL != info->interp_args); 134 } 135 136 if (info->argv && info->argv[0] != NULL) 137 info->argv[0] = name; 138 139 VG_(args_the_exename) = name; 140 141 if (0) 142 VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n", 143 info->interp_name, info->interp_args); 144 145 return VG_(do_exec_inner)(interp, info); 146 } 147 148 /*--------------------------------------------------------------------*/ 149 /*--- end ---*/ 150 /*--------------------------------------------------------------------*/ 151