drd/drd_pthread_intercepts: Add a workaround for what is probably a compiler bug
[valgrind.git] / coregrind / m_ume / main.c
blobd917fb596895ff8bc47bc3fb214ad59a24e65cc5
2 /*--------------------------------------------------------------------*/
3 /*--- User-mode execve(), and other stuff shared between stage1 ---*/
4 /*--- and stage2. m_ume.c ---*/
5 /*--------------------------------------------------------------------*/
7 /*
8 This file is part of Valgrind, a dynamic binary instrumentation
9 framework.
11 Copyright (C) 2000-2017 Julian Seward
12 jseward@acm.org
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.
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.
24 You should have received a copy of the GNU General Public License
25 along with this program; if not, see <http://www.gnu.org/licenses/>.
27 The GNU General Public License is contained in the file COPYING.
31 #include "pub_core_basics.h"
32 #include "pub_core_vki.h"
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" // VG_(message)
38 #include "pub_core_mallocfree.h" // VG_(strdup)
39 #include "pub_core_syscall.h" // VG_(mk_SysRes_Error)
40 #include "pub_core_options.h" // VG_(clo_xml)
41 #include "pub_core_ume.h" // self
43 #include "priv_ume.h"
46 typedef struct {
47 Bool (*match_fn)(const void *hdr, SizeT len);
48 Int (*load_fn)(Int fd, const HChar *name, ExeInfo *info);
49 } ExeHandler;
51 static ExeHandler exe_handlers[] = {
52 # if defined(VGO_linux) || defined(VGO_solaris)
53 { VG_(match_ELF), VG_(load_ELF) },
54 # elif defined(VGO_darwin)
55 { VG_(match_macho), VG_(load_macho) },
56 # else
57 # error "unknown OS"
58 # endif
59 { VG_(match_script), VG_(load_script) },
61 #define EXE_HANDLER_COUNT (sizeof(exe_handlers)/sizeof(exe_handlers[0]))
64 // Check the file looks executable.
65 SysRes
66 VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid)
68 Int fd, ret, i;
69 SysRes res;
70 Char buf[4096];
71 SizeT bufsz = sizeof buf, fsz;
72 Bool is_setuid = False;
74 // Check it's readable
75 res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
76 if (sr_isError(res)) {
77 return res;
79 fd = sr_Res(res);
81 // Check we have execute permissions
82 ret = VG_(check_executable)(&is_setuid, exe_name, allow_setuid);
83 if (0 != ret) {
84 VG_(close)(fd);
85 if (is_setuid && !VG_(clo_xml)) {
86 VG_(message)(Vg_UserMsg, "\n");
87 VG_(message)(Vg_UserMsg,
88 "Warning: Can't execute setuid/setgid/setcap executable: %s\n",
89 exe_name);
90 VG_(message)(Vg_UserMsg, "Possible workaround: remove "
91 "--trace-children=yes, if in effect\n");
92 VG_(message)(Vg_UserMsg, "\n");
94 return VG_(mk_SysRes_Error)(ret);
97 fsz = (SizeT)VG_(fsize)(fd);
98 if (fsz < bufsz)
99 bufsz = fsz;
101 res = VG_(pread)(fd, buf, bufsz, 0);
102 if (sr_isError(res) || sr_Res(res) != bufsz) {
103 VG_(close)(fd);
104 return VG_(mk_SysRes_Error)(VKI_EACCES);
106 bufsz = sr_Res(res);
108 // Look for a matching executable format
109 for (i = 0; i < EXE_HANDLER_COUNT; i++) {
110 if ((*exe_handlers[i].match_fn)(buf, bufsz)) {
111 res = VG_(mk_SysRes_Success)(i);
112 break;
115 if (i == EXE_HANDLER_COUNT) {
116 // Rejected by all executable format handlers.
117 res = VG_(mk_SysRes_Error)(VKI_ENOEXEC);
120 // Write the 'out_fd' param if necessary, or close the file.
121 if (!sr_isError(res) && out_fd) {
122 *out_fd = fd;
123 } else {
124 VG_(close)(fd);
127 return res;
130 // returns: 0 = success, non-0 is failure
132 // We can execute only binaries (ELF, etc) or scripts that begin with "#!".
133 // (Not, for example, scripts that don't begin with "#!"; see
134 // do_exec_shell_followup for how that's handled.)
135 Int VG_(do_exec_inner)(const HChar* exe, ExeInfo* info)
137 SysRes res;
138 Int fd;
139 Int ret;
141 res = VG_(pre_exec_check)(exe, &fd, False/*allow_setuid*/);
142 if (sr_isError(res))
143 return sr_Err(res);
145 vg_assert2(sr_Res(res) >= 0 && sr_Res(res) < EXE_HANDLER_COUNT,
146 "invalid VG_(pre_exec_check) result");
148 ret = (*exe_handlers[sr_Res(res)].load_fn)(fd, exe, info);
150 VG_(close)(fd);
152 return ret;
156 static Bool is_hash_bang_file(const HChar* f)
158 SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
159 if (!sr_isError(res)) {
160 HChar buf[3] = {0,0,0};
161 Int fd = sr_Res(res);
162 Int n = VG_(read)(fd, buf, 2);
163 if (n == 2 && VG_STREQ("#!", buf))
164 return True;
166 return False;
169 // Look at the first 80 chars, and if any are greater than 127, it's binary.
170 // This is crude, but should be good enough. Note that it fails on a
171 // zero-length file, as we want.
172 static Bool is_binary_file(const HChar* f)
174 SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
175 if (!sr_isError(res)) {
176 UChar buf[80];
177 Int fd = sr_Res(res);
178 Int n = VG_(read)(fd, buf, 80);
179 Int i;
180 for (i = 0; i < n; i++) {
181 if (buf[i] > 127)
182 return True; // binary char found
184 return False;
185 } else {
186 // Something went wrong. This will only happen if we earlier
187 // succeeded in opening the file but fail here (eg. the file was
188 // deleted between then and now).
189 VG_(fmsg)("%s: unknown error\n", f);
190 VG_(exit)(126); // 126 == NOEXEC
194 // If the do_exec fails we try to emulate what the shell does (I used
195 // bash as a guide). It's worth noting that the shell can execute some
196 // things that VG_(do_exec)() (which subsitutes for the kernel's exec())
197 // will refuse to (eg. scripts lacking a "#!" prefix).
198 static Int do_exec_shell_followup(Int ret, const HChar* exe_name, ExeInfo* info)
200 # if defined(VGPV_arm_linux_android) \
201 || defined(VGPV_x86_linux_android) \
202 || defined(VGPV_mips32_linux_android) \
203 || defined(VGPV_arm64_linux_android)
204 const HChar* default_interp_name = "/system/bin/sh";
205 # else
206 const HChar* default_interp_name = "/bin/sh";
207 # endif
209 SysRes res;
210 struct vg_stat st;
212 if (VKI_ENOEXEC == ret) {
213 // It was an executable file, but in an unacceptable format. Probably
214 // is a shell script lacking the "#!" prefix; try to execute it so.
216 // Is it a binary file?
217 if (is_binary_file(exe_name)) {
218 VG_(fmsg)("%s: cannot execute binary file\n", exe_name);
219 VG_(exit)(126); // 126 == NOEXEC
222 // Looks like a script. Run it with /bin/sh. This includes
223 // zero-length files.
224 VG_(free)(info->interp_name);
225 info->interp_name = VG_(strdup)("ume.desf.1", default_interp_name);
226 VG_(free)(info->interp_args); info->interp_args = NULL;
227 if (info->argv && info->argv[0] != NULL)
228 info->argv[0] = exe_name;
230 ret = VG_(do_exec_inner)(info->interp_name, info);
232 if (0 != ret) {
233 // Something went wrong with executing the default interpreter
234 VG_(fmsg)("%s: bad interpreter (%s): %s\n",
235 exe_name, info->interp_name, VG_(strerror)(ret));
236 VG_(exit)(126); // 126 == NOEXEC
239 } else if (0 != ret) {
240 // Something else went wrong. Try to make the error more specific,
241 // and then print a message and abort.
242 Int exit_code = 126; // 126 == NOEXEC (bash)
244 res = VG_(stat)(exe_name, &st);
246 // Does the file exist ?
247 if (sr_isError(res) && sr_Err(res) == VKI_ENOENT) {
248 VG_(fmsg)("%s: %s\n", exe_name, VG_(strerror)(ret));
249 exit_code = 127; // 127 == NOTFOUND (bash)
251 // Was it a directory?
252 } else if (!sr_isError(res) && VKI_S_ISDIR(st.mode)) {
253 VG_(fmsg)("%s: is a directory\n", exe_name);
255 // Was it not executable?
256 } else if (0 != VG_(check_executable)(NULL, exe_name,
257 False/*allow_setuid*/)) {
258 VG_(fmsg)("%s: %s\n", exe_name, VG_(strerror)(ret));
260 // Did it start with "#!"? If so, it must have been a bad interpreter.
261 } else if (is_hash_bang_file(exe_name)) {
262 VG_(fmsg)("%s: bad interpreter: %s\n", exe_name, VG_(strerror)(ret));
264 // Otherwise it was something else.
265 } else {
266 VG_(fmsg)("%s: %s\n", exe_name, VG_(strerror)(ret));
268 VG_(exit)(exit_code);
270 return ret;
274 // This emulates the kernel's exec(). If it fails, it then emulates the
275 // shell's handling of the situation.
276 // See pub_core_ume.h for an indication of which entries of 'info' are
277 // inputs, which are outputs, and which are both.
278 /* returns: 0 = success, non-0 is failure */
279 Int VG_(do_exec)(const HChar* exe_name, ExeInfo* info)
281 Int ret;
283 VG_(free)(info->interp_name); info->interp_name = NULL;
284 VG_(free)(info->interp_args); info->interp_args = NULL;
286 ret = VG_(do_exec_inner)(exe_name, info);
288 if (0 != ret) {
289 ret = do_exec_shell_followup(ret, exe_name, info);
291 return ret;
294 /*--------------------------------------------------------------------*/
295 /*--- end ---*/
296 /*--------------------------------------------------------------------*/