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-2012 Julian Seward 11 jseward@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 45Bool VG_(match_script)(Char *hdr, Int len) 46{ 47 Char* end = hdr + len; 48 Char* interp = hdr + 2; 49 50 // len < 4: need '#', '!', plus at least a '/' and one more char 51 if (len < 4) return False; 52 if (0 != VG_(memcmp)(hdr, "#!", 2)) return False; 53 54 // Find interpreter name, make sure it's an absolute path (starts with 55 // '/') and has at least one more char. First, skip over any space 56 // between the #! and the start of the interpreter name 57 while (interp < end && VG_(isspace)(*interp)) interp++; 58 59 // overrun? 60 if (interp >= end) return False; // can't find start of interp name 61 62 // interp should now point at the / 63 if (*interp != '/') return False; // absolute path only for interpreter 64 65 // check for something plausible after the / 66 interp++; 67 if (interp >= end) return False; 68 if (VG_(isspace)(*interp)) return False; 69 70 // Here we should get the full interpreter name and check it with 71 // check_executable(). See the "EXEC FAILED" failure when running shell 72 // for an example. 73 74 return True; // looks like a #! script 75} 76 77 78/* returns: 0 = success, non-0 is failure */ 79Int VG_(load_script)(Int fd, const HChar* name, ExeInfo* info) 80{ 81 Char hdr[4096]; 82 Int len = 4096; 83 Int eol; 84 Char* interp; 85 Char* end; 86 Char* cp; 87 Char* arg = NULL; 88 SysRes res; 89 90 // Read the first part of the file. 91 res = VG_(pread)(fd, hdr, len, 0); 92 if (sr_isError(res)) { 93 VG_(close)(fd); 94 return VKI_EACCES; 95 } else { 96 len = sr_Res(res); 97 } 98 99 vg_assert('#' == hdr[0] && '!' == hdr[1]); 100 101 end = hdr + len; 102 interp = hdr + 2; 103 while (interp < end && VG_(isspace)(*interp)) 104 interp++; 105 106 vg_assert(*interp == '/'); /* absolute path only for interpreter */ 107 108 /* skip over interpreter name */ 109 for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++) 110 ; 111 112 eol = (*cp == '\n'); 113 114 *cp++ = '\0'; 115 116 if (!eol && cp < end) { 117 /* skip space before arg */ 118 while (cp < end && VG_(isspace)(*cp) && *cp != '\n') 119 cp++; 120 121 /* arg is from here to eol */ 122 arg = cp; 123 while (cp < end && *cp != '\n') 124 cp++; 125 *cp = '\0'; 126 } 127 128 info->interp_name = VG_(strdup)("ume.ls.1", interp); 129 vg_assert(NULL != info->interp_name); 130 if (arg != NULL && *arg != '\0') { 131 info->interp_args = VG_(strdup)("ume.ls.2", arg); 132 vg_assert(NULL != info->interp_args); 133 } 134 135 if (info->argv && info->argv[0] != NULL) 136 info->argv[0] = (char *)name; 137 138 VG_(args_the_exename) = name; 139 140 if (0) 141 VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n", 142 info->interp_name, info->interp_args); 143 144 return VG_(do_exec_inner)(interp, info); 145} 146 147/*--------------------------------------------------------------------*/ 148/*--- end ---*/ 149/*--------------------------------------------------------------------*/ 150