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-2011 Julian Seward
12      jseward@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
48typedef struct {
49   Bool (*match_fn)(Char *hdr, Int len);
50   Int  (*load_fn)(Int fd, const HChar *name, ExeInfo *info);
51} ExeHandler;
52
53static 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.
67SysRes
68VG_(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.)
137Int 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
158static 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.
174static 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).
200static Int do_exec_shell_followup(Int ret, HChar* exe_name, ExeInfo* info)
201{
202#  if defined(VGPV_arm_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 */
273Int 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