xref: /freebsd/lib/libc/gen/exec.c (revision 702423e864a5a297713566ea74a62723a9c68a72)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1991, 1993
5  *	The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31 
32 #include "namespace.h"
33 #include <sys/param.h>
34 #include <sys/stat.h>
35 #include <assert.h>
36 #include <errno.h>
37 #include <unistd.h>
38 #include <stdbool.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <stdio.h>
42 #include <paths.h>
43 
44 #include <stdarg.h>
45 #include "un-namespace.h"
46 #include "libc_private.h"
47 
48 static const char execvPe_err_preamble[] = "execvP: ";
49 static const char execvPe_err_trailer[] = ": path too long\n";
50 
51 int
execl(const char * name,const char * arg,...)52 execl(const char *name, const char *arg, ...)
53 {
54 	va_list ap;
55 	const char **argv;
56 	int n;
57 
58 	va_start(ap, arg);
59 	n = 1;
60 	while (va_arg(ap, char *) != NULL)
61 		n++;
62 	va_end(ap);
63 	argv = alloca((n + 1) * sizeof(*argv));
64 	if (argv == NULL) {
65 		errno = ENOMEM;
66 		return (-1);
67 	}
68 	va_start(ap, arg);
69 	n = 1;
70 	argv[0] = arg;
71 	while ((argv[n] = va_arg(ap, char *)) != NULL)
72 		n++;
73 	va_end(ap);
74 	return (_execve(name, __DECONST(char **, argv), environ));
75 }
76 
77 int
execle(const char * name,const char * arg,...)78 execle(const char *name, const char *arg, ...)
79 {
80 	va_list ap;
81 	const char **argv;
82 	char **envp;
83 	int n;
84 
85 	va_start(ap, arg);
86 	n = 1;
87 	while (va_arg(ap, char *) != NULL)
88 		n++;
89 	va_end(ap);
90 	argv = alloca((n + 1) * sizeof(*argv));
91 	if (argv == NULL) {
92 		errno = ENOMEM;
93 		return (-1);
94 	}
95 	va_start(ap, arg);
96 	n = 1;
97 	argv[0] = arg;
98 	while ((argv[n] = va_arg(ap, char *)) != NULL)
99 		n++;
100 	envp = va_arg(ap, char **);
101 	va_end(ap);
102 	return (_execve(name, __DECONST(char **, argv), envp));
103 }
104 
105 int
execlp(const char * name,const char * arg,...)106 execlp(const char *name, const char *arg, ...)
107 {
108 	va_list ap;
109 	const char **argv;
110 	int n;
111 
112 	va_start(ap, arg);
113 	n = 1;
114 	while (va_arg(ap, char *) != NULL)
115 		n++;
116 	va_end(ap);
117 	argv = alloca((n + 1) * sizeof(*argv));
118 	if (argv == NULL) {
119 		errno = ENOMEM;
120 		return (-1);
121 	}
122 	va_start(ap, arg);
123 	n = 1;
124 	argv[0] = arg;
125 	while ((argv[n] = va_arg(ap, char *)) != NULL)
126 		n++;
127 	va_end(ap);
128 	return (execvp(name, __DECONST(char **, argv)));
129 }
130 
131 int
execv(const char * name,char * const * argv)132 execv(const char *name, char * const *argv)
133 {
134 	(void)_execve(name, argv, environ);
135 	return (-1);
136 }
137 
138 int
execvp(const char * name,char * const * argv)139 execvp(const char *name, char * const *argv)
140 {
141 	return (__libc_execvpe(name, argv, environ));
142 }
143 
144 /*
145  * Returns 0 if we don't consider this a terminal condition, -1 if we do.
146  */
147 static int
execvPe_prog(const char * path,char * const * argv,char * const * envp)148 execvPe_prog(const char *path, char * const *argv, char * const *envp)
149 {
150 	struct stat sb;
151 	const char **memp;
152 	size_t cnt;
153 	int save_errno;
154 
155 	(void)_execve(path, argv, envp);
156 	/* Grouped roughly by never terminal vs. usually terminal conditions */
157 	switch (errno) {
158 	case ELOOP:
159 	case ENAMETOOLONG:
160 	case ENOENT:
161 	case ENOTDIR:
162 		/* Non-terminal: property of the path we're trying */
163 		break;
164 	case ENOEXEC:
165 		 /*
166 		  * Failures here are considered terminal because we must handle
167 		  * this via the ENOEXEC fallback path; doing any further
168 		  * searching would be categorically incorrect.
169 		  */
170 
171 		for (cnt = 0; argv[cnt] != NULL; ++cnt)
172 			;
173 
174 		/*
175 		 * cnt may be 0 above; always allocate at least
176 		 * 3 entries so that we can at least fit "sh", path, and
177 		 * the NULL terminator.  We can rely on cnt to take into
178 		 * account the NULL terminator in all other scenarios,
179 		 * as we drop argv[0].
180 		 */
181 		memp = alloca(MAX(3, cnt + 2) * sizeof(char *));
182 		assert(memp != NULL);
183 		if (cnt > 0) {
184 			memp[0] = argv[0];
185 			memp[1] = path;
186 			memcpy(&memp[2], &argv[1], cnt * sizeof(char *));
187 		} else {
188 			memp[0] = "sh";
189 			memp[1] = path;
190 			memp[2] = NULL;
191 		}
192 
193 		(void)_execve(_PATH_BSHELL, __DECONST(char **, memp), envp);
194 		return (-1);
195 	case ENOMEM:
196 	case E2BIG:
197 		/* Terminal: persistent condition */
198 		return (-1);
199 	case ETXTBSY:
200 		/*
201 		 * Terminal: we used to retry here, but sh(1) doesn't.
202 		 */
203 		return (-1);
204 	default:
205 		/*
206 		 * EACCES may be for an inaccessible directory or
207 		 * a non-executable file.  Call stat() to decide
208 		 * which.  This also handles ambiguities for EFAULT
209 		 * and EIO, and undocumented errors like ESTALE.
210 		 * We hope that the race for a stat() is unimportant.
211 		 */
212 		save_errno = errno;
213 		if (stat(path, &sb) == -1) {
214 			/*
215 			 * We force errno to ENOENT here to disambiguate the
216 			 * EACCESS case; the results of execve(2) are somewhat
217 			 * inconclusive because either the file did not exist or
218 			 * we just don't have search permissions, but the caller
219 			 * only really wants to see EACCES if the file did exist
220 			 * but was not accessible.
221 			 */
222 			if (save_errno == EACCES)
223 				errno = ENOENT;
224 			break;
225 		}
226 
227 		errno = save_errno;
228 
229 		/*
230 		 * Non-terminal: the file did exist and we just didn't have
231 		 * access to it, so we surface the EACCES and let the search
232 		 * continue for a candidate that we do have access to.
233 		 */
234 		if (errno == EACCES)
235 			break;
236 
237 		/*
238 		 * All other errors here are terminal, as prescribed by exec(3).
239 		 */
240 		return (-1);
241 	}
242 
243 	return (0);
244 }
245 
246 static int
execvPe(const char * name,const char * path,char * const * argv,char * const * envp)247 execvPe(const char *name, const char *path, char * const *argv,
248     char * const *envp)
249 {
250 	char buf[MAXPATHLEN];
251 	size_t ln, lp;
252 	const char *np, *op, *p;
253 	bool eacces;
254 
255 	eacces = false;
256 
257 	/* If it's an absolute or relative path name, it's easy. */
258 	if (strchr(name, '/') != NULL) {
259 		/*
260 		 * We ignore non-terminal conditions because we don't have any
261 		 * further paths to try -- we can just bubble up the errno from
262 		 * execve(2) here.
263 		 */
264 		(void)execvPe_prog(name, argv, envp);
265 		return (-1);
266 	}
267 
268 	/* If it's an empty path name, fail in the usual POSIX way. */
269 	if (*name == '\0') {
270 		errno = ENOENT;
271 		return (-1);
272 	}
273 
274 	op = path;
275 	ln = strlen(name);
276 	while (op != NULL) {
277 		np = strchrnul(op, ':');
278 
279 		/*
280 		 * It's a SHELL path -- double, leading and trailing colons
281 		 * mean the current directory.
282 		 */
283 		if (np == op) {
284 			/* Empty component. */
285 			p = ".";
286 			lp = 1;
287 		} else {
288 			/* Non-empty component. */
289 			p = op;
290 			lp = np - op;
291 		}
292 
293 		/* Advance to the next component or terminate after this. */
294 		if (*np == '\0')
295 			op = NULL;
296 		else
297 			op = np + 1;
298 
299 		/*
300 		 * If the path is too long, then complain.  This is a possible
301 		 * security issue: given a way to make the path too long, the
302 		 * user may execute the wrong program.
303 		 *
304 		 * Remember to exercise caution here with assembling our final
305 		 * buf and any output, as we may be running in a vfork() context
306 		 * via posix_spawnp().
307 		 */
308 		if (lp + ln + 2 > sizeof(buf)) {
309 			(void)_write(STDERR_FILENO, execvPe_err_preamble,
310 			    sizeof(execvPe_err_preamble) - 1);
311 			(void)_write(STDERR_FILENO, p, lp);
312 			(void)_write(STDERR_FILENO, execvPe_err_trailer,
313 			    sizeof(execvPe_err_trailer) - 1);
314 
315 			continue;
316 		}
317 
318 		memcpy(&buf[0], p, lp);
319 		buf[lp] = '/';
320 		memcpy(&buf[lp + 1], name, ln);
321 		buf[lp + ln + 1] = '\0';
322 
323 		/*
324 		 * For terminal conditions we can just return immediately.  If
325 		 * it was non-terminal, we just need to note if we had an
326 		 * EACCES -- execvPe_prog would do a stat(2) and leave us with
327 		 * an errno of EACCES only if the file did exist; otherwise it
328 		 * would coerce it to an ENOENT because we may not know if a
329 		 * file actually existed there or not.
330 		 */
331 		if (execvPe_prog(buf, argv, envp) == -1)
332 			return (-1);
333 		if (errno == EACCES)
334 			eacces = true;
335 	}
336 
337 	/*
338 	 * We don't often preserve errors encountering during the PATH search,
339 	 * so we override it here.  ENOENT would be misleading if we found a
340 	 * candidate but couldn't access it, but most of the other conditions
341 	 * are either terminal or indicate that nothing was there.
342 	 */
343 	if (eacces)
344 		errno = EACCES;
345 	else
346 		errno = ENOENT;
347 
348 	return (-1);
349 }
350 
351 int
execvP(const char * name,const char * path,char * const argv[])352 execvP(const char *name, const char *path, char * const argv[])
353 {
354 	return execvPe(name, path, argv, environ);
355 }
356 
357 int
__libc_execvpe(const char * name,char * const argv[],char * const envp[])358 __libc_execvpe(const char *name, char * const argv[], char * const envp[])
359 {
360 	const char *path;
361 
362 	/* Get the path we're searching. */
363 	if ((path = getenv("PATH")) == NULL)
364 		path = _PATH_DEFPATH;
365 
366 	return (execvPe(name, path, argv, envp));
367 }
368 
369 __weak_reference(__libc_execvpe, execvpe);
370