xref: /freebsd/lib/libc/gen/posix_spawn.c (revision 535af610)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
5  * 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  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31 
32 #include "namespace.h"
33 #include <sys/param.h>
34 #include <sys/queue.h>
35 #include <sys/wait.h>
36 
37 #include <errno.h>
38 #include <fcntl.h>
39 #include <sched.h>
40 #include <spawn.h>
41 #include <signal.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45 #include "un-namespace.h"
46 #include "libc_private.h"
47 
48 struct __posix_spawnattr {
49 	short			sa_flags;
50 	pid_t			sa_pgroup;
51 	struct sched_param	sa_schedparam;
52 	int			sa_schedpolicy;
53 	sigset_t		sa_sigdefault;
54 	sigset_t		sa_sigmask;
55 };
56 
57 struct __posix_spawn_file_actions {
58 	STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list;
59 };
60 
61 typedef struct __posix_spawn_file_actions_entry {
62 	STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list;
63 	enum {
64 		FAE_OPEN,
65 		FAE_DUP2,
66 		FAE_CLOSE,
67 		FAE_CHDIR,
68 		FAE_FCHDIR,
69 		FAE_CLOSEFROM,
70 	} fae_action;
71 
72 	int fae_fildes;
73 	union {
74 		struct {
75 			char *path;
76 #define fae_path	fae_data.open.path
77 			int oflag;
78 #define fae_oflag	fae_data.open.oflag
79 			mode_t mode;
80 #define fae_mode	fae_data.open.mode
81 		} open;
82 		struct {
83 			int newfildes;
84 #define fae_newfildes	fae_data.dup2.newfildes
85 		} dup2;
86 	} fae_data;
87 } posix_spawn_file_actions_entry_t;
88 
89 /*
90  * Spawn routines
91  */
92 
93 static int
94 process_spawnattr(const posix_spawnattr_t sa)
95 {
96 	struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL };
97 	int i;
98 
99 	/*
100 	 * POSIX doesn't really describe in which order everything
101 	 * should be set. We'll just set them in the order in which they
102 	 * are mentioned.
103 	 */
104 
105 	/* Set process group */
106 	if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) {
107 		if (setpgid(0, sa->sa_pgroup) != 0)
108 			return (errno);
109 	}
110 
111 	/* Set scheduler policy */
112 	if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) {
113 		if (sched_setscheduler(0, sa->sa_schedpolicy,
114 		    &sa->sa_schedparam) != 0)
115 			return (errno);
116 	} else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) {
117 		if (sched_setparam(0, &sa->sa_schedparam) != 0)
118 			return (errno);
119 	}
120 
121 	/* Reset user ID's */
122 	if (sa->sa_flags & POSIX_SPAWN_RESETIDS) {
123 		if (setegid(getgid()) != 0)
124 			return (errno);
125 		if (seteuid(getuid()) != 0)
126 			return (errno);
127 	}
128 
129 	/*
130 	 * Set signal masks/defaults.
131 	 * Use unwrapped syscall, libthr is in undefined state after vfork().
132 	 */
133 	if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) {
134 		__sys_sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL);
135 	}
136 
137 	if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) {
138 		for (i = 1; i <= _SIG_MAXSIG; i++) {
139 			if (sigismember(&sa->sa_sigdefault, i))
140 				if (__sys_sigaction(i, &sigact, NULL) != 0)
141 					return (errno);
142 		}
143 	}
144 
145 	return (0);
146 }
147 
148 static int
149 process_file_actions_entry(posix_spawn_file_actions_entry_t *fae)
150 {
151 	int fd, saved_errno;
152 
153 	switch (fae->fae_action) {
154 	case FAE_OPEN:
155 		/* Perform an open(), make it use the right fd */
156 		fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode);
157 		if (fd < 0)
158 			return (errno);
159 		if (fd != fae->fae_fildes) {
160 			if (_dup2(fd, fae->fae_fildes) == -1) {
161 				saved_errno = errno;
162 				(void)_close(fd);
163 				return (saved_errno);
164 			}
165 			if (_close(fd) != 0) {
166 				if (errno == EBADF)
167 					return (EBADF);
168 			}
169 		}
170 		if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1)
171 			return (errno);
172 		break;
173 	case FAE_DUP2:
174 		/* Perform a dup2() */
175 		if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1)
176 			return (errno);
177 		if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1)
178 			return (errno);
179 		break;
180 	case FAE_CLOSE:
181 		/* Perform a close(), do not fail if already closed */
182 		(void)_close(fae->fae_fildes);
183 		break;
184 	case FAE_CHDIR:
185 		if (chdir(fae->fae_path) != 0)
186 			return (errno);
187 		break;
188 	case FAE_FCHDIR:
189 		if (fchdir(fae->fae_fildes) != 0)
190 			return (errno);
191 		break;
192 	case FAE_CLOSEFROM:
193 		closefrom(fae->fae_fildes);
194 		break;
195 	}
196 	return (0);
197 }
198 
199 static int
200 process_file_actions(const posix_spawn_file_actions_t fa)
201 {
202 	posix_spawn_file_actions_entry_t *fae;
203 	int error;
204 
205 	/* Replay all file descriptor modifications */
206 	STAILQ_FOREACH(fae, &fa->fa_list, fae_list) {
207 		error = process_file_actions_entry(fae);
208 		if (error)
209 			return (error);
210 	}
211 	return (0);
212 }
213 
214 struct posix_spawn_args {
215 	const char *path;
216 	const posix_spawn_file_actions_t *fa;
217 	const posix_spawnattr_t *sa;
218 	char * const * argv;
219 	char * const * envp;
220 	int use_env_path;
221 	volatile int error;
222 };
223 
224 #define	PSPAWN_STACK_ALIGNMENT	16
225 #define	PSPAWN_STACK_ALIGNBYTES	(PSPAWN_STACK_ALIGNMENT - 1)
226 #define	PSPAWN_STACK_ALIGN(sz) \
227 	(((sz) + PSPAWN_STACK_ALIGNBYTES) & ~PSPAWN_STACK_ALIGNBYTES)
228 
229 #if defined(__i386__) || defined(__amd64__)
230 /*
231  * Below we'll assume that _RFORK_THREAD_STACK_SIZE is appropriately aligned for
232  * the posix_spawn() case where we do not end up calling _execvpe and won't ever
233  * try to allocate space on the stack for argv[].
234  */
235 #define	_RFORK_THREAD_STACK_SIZE	4096
236 _Static_assert((_RFORK_THREAD_STACK_SIZE % PSPAWN_STACK_ALIGNMENT) == 0,
237     "Inappropriate stack size alignment");
238 #endif
239 
240 static int
241 _posix_spawn_thr(void *data)
242 {
243 	struct posix_spawn_args *psa;
244 	char * const *envp;
245 
246 	psa = data;
247 	if (psa->sa != NULL) {
248 		psa->error = process_spawnattr(*psa->sa);
249 		if (psa->error)
250 			_exit(127);
251 	}
252 	if (psa->fa != NULL) {
253 		psa->error = process_file_actions(*psa->fa);
254 		if (psa->error)
255 			_exit(127);
256 	}
257 	envp = psa->envp != NULL ? psa->envp : environ;
258 	if (psa->use_env_path)
259 		_execvpe(psa->path, psa->argv, envp);
260 	else
261 		_execve(psa->path, psa->argv, envp);
262 	psa->error = errno;
263 
264 	/* This is called in such a way that it must not exit. */
265 	_exit(127);
266 }
267 
268 static int
269 do_posix_spawn(pid_t *pid, const char *path,
270     const posix_spawn_file_actions_t *fa,
271     const posix_spawnattr_t *sa,
272     char * const argv[], char * const envp[], int use_env_path)
273 {
274 	struct posix_spawn_args psa;
275 	pid_t p;
276 #ifdef _RFORK_THREAD_STACK_SIZE
277 	char *stack;
278 	size_t cnt, stacksz;
279 
280 	stacksz = _RFORK_THREAD_STACK_SIZE;
281 	if (use_env_path) {
282 		/*
283 		 * We need to make sure we have enough room on the stack for the
284 		 * potential alloca() in execvPe if it gets kicked back an
285 		 * ENOEXEC from execve(2), plus the original buffer we gave
286 		 * ourselves; this protects us in the event that the caller
287 		 * intentionally or inadvertently supplies enough arguments to
288 		 * make us blow past the stack we've allocated from it.
289 		 */
290 		for (cnt = 0; argv[cnt] != NULL; ++cnt)
291 			;
292 		stacksz += MAX(3, cnt + 2) * sizeof(char *);
293 		stacksz = PSPAWN_STACK_ALIGN(stacksz);
294 	}
295 
296 	/*
297 	 * aligned_alloc is not safe to use here, because we can't guarantee
298 	 * that aligned_alloc and free will be provided by the same
299 	 * implementation.  We've actively hit at least one application that
300 	 * will provide its own malloc/free but not aligned_alloc leading to
301 	 * a free by the wrong allocator.
302 	 */
303 	stack = malloc(stacksz);
304 	if (stack == NULL)
305 		return (ENOMEM);
306 	stacksz = (((uintptr_t)stack + stacksz) & ~PSPAWN_STACK_ALIGNBYTES) -
307 	    (uintptr_t)stack;
308 #endif
309 	psa.path = path;
310 	psa.fa = fa;
311 	psa.sa = sa;
312 	psa.argv = argv;
313 	psa.envp = envp;
314 	psa.use_env_path = use_env_path;
315 	psa.error = 0;
316 
317 	/*
318 	 * Passing RFSPAWN to rfork(2) gives us effectively a vfork that drops
319 	 * non-ignored signal handlers.  We'll fall back to the slightly less
320 	 * ideal vfork(2) if we get an EINVAL from rfork -- this should only
321 	 * happen with newer libc on older kernel that doesn't accept
322 	 * RFSPAWN.
323 	 */
324 #ifdef _RFORK_THREAD_STACK_SIZE
325 	/*
326 	 * x86 stores the return address on the stack, so rfork(2) cannot work
327 	 * as-is because the child would clobber the return address om the
328 	 * parent.  Because of this, we must use rfork_thread instead while
329 	 * almost every other arch stores the return address in a register.
330 	 */
331 	p = rfork_thread(RFSPAWN, stack + stacksz, _posix_spawn_thr, &psa);
332 	free(stack);
333 #else
334 	p = rfork(RFSPAWN);
335 	if (p == 0)
336 		/* _posix_spawn_thr does not return */
337 		_posix_spawn_thr(&psa);
338 #endif
339 	/*
340 	 * The above block should leave us in a state where we've either
341 	 * succeeded and we're ready to process the results, or we need to
342 	 * fallback to vfork() if the kernel didn't like RFSPAWN.
343 	 */
344 
345 	if (p == -1 && errno == EINVAL) {
346 		p = vfork();
347 		if (p == 0)
348 			/* _posix_spawn_thr does not return */
349 			_posix_spawn_thr(&psa);
350 	}
351 	if (p == -1)
352 		return (errno);
353 	if (psa.error != 0)
354 		/* Failed; ready to reap */
355 		_waitpid(p, NULL, WNOHANG);
356 	else if (pid != NULL)
357 		/* exec succeeded */
358 		*pid = p;
359 	return (psa.error);
360 }
361 
362 int
363 posix_spawn(pid_t *pid, const char *path,
364     const posix_spawn_file_actions_t *fa,
365     const posix_spawnattr_t *sa,
366     char * const argv[], char * const envp[])
367 {
368 	return (do_posix_spawn(pid, path, fa, sa, argv, envp, 0));
369 }
370 
371 int
372 posix_spawnp(pid_t *pid, const char *path,
373     const posix_spawn_file_actions_t *fa,
374     const posix_spawnattr_t *sa,
375     char * const argv[], char * const envp[])
376 {
377 	return (do_posix_spawn(pid, path, fa, sa, argv, envp, 1));
378 }
379 
380 /*
381  * File descriptor actions
382  */
383 
384 int
385 posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret)
386 {
387 	posix_spawn_file_actions_t fa;
388 
389 	fa = malloc(sizeof(struct __posix_spawn_file_actions));
390 	if (fa == NULL)
391 		return (-1);
392 
393 	STAILQ_INIT(&fa->fa_list);
394 	*ret = fa;
395 	return (0);
396 }
397 
398 int
399 posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa)
400 {
401 	posix_spawn_file_actions_entry_t *fae;
402 
403 	while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) {
404 		/* Remove file action entry from the queue */
405 		STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list);
406 
407 		/* Deallocate file action entry */
408 		if (fae->fae_action == FAE_OPEN ||
409 		    fae->fae_action == FAE_CHDIR)
410 			free(fae->fae_path);
411 		free(fae);
412 	}
413 
414 	free(*fa);
415 	return (0);
416 }
417 
418 int
419 posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,
420     int fildes, const char * __restrict path, int oflag, mode_t mode)
421 {
422 	posix_spawn_file_actions_entry_t *fae;
423 	int error;
424 
425 	if (fildes < 0)
426 		return (EBADF);
427 
428 	/* Allocate object */
429 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
430 	if (fae == NULL)
431 		return (errno);
432 
433 	/* Set values and store in queue */
434 	fae->fae_action = FAE_OPEN;
435 	fae->fae_path = strdup(path);
436 	if (fae->fae_path == NULL) {
437 		error = errno;
438 		free(fae);
439 		return (error);
440 	}
441 	fae->fae_fildes = fildes;
442 	fae->fae_oflag = oflag;
443 	fae->fae_mode = mode;
444 
445 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
446 	return (0);
447 }
448 
449 int
450 posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa,
451     int fildes, int newfildes)
452 {
453 	posix_spawn_file_actions_entry_t *fae;
454 
455 	if (fildes < 0 || newfildes < 0)
456 		return (EBADF);
457 
458 	/* Allocate object */
459 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
460 	if (fae == NULL)
461 		return (errno);
462 
463 	/* Set values and store in queue */
464 	fae->fae_action = FAE_DUP2;
465 	fae->fae_fildes = fildes;
466 	fae->fae_newfildes = newfildes;
467 
468 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
469 	return (0);
470 }
471 
472 int
473 posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa,
474     int fildes)
475 {
476 	posix_spawn_file_actions_entry_t *fae;
477 
478 	if (fildes < 0)
479 		return (EBADF);
480 
481 	/* Allocate object */
482 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
483 	if (fae == NULL)
484 		return (errno);
485 
486 	/* Set values and store in queue */
487 	fae->fae_action = FAE_CLOSE;
488 	fae->fae_fildes = fildes;
489 
490 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
491 	return (0);
492 }
493 
494 int
495 posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *
496     __restrict fa, const char *__restrict path)
497 {
498 	posix_spawn_file_actions_entry_t *fae;
499 	int error;
500 
501 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
502 	if (fae == NULL)
503 		return (errno);
504 
505 	fae->fae_action = FAE_CHDIR;
506 	fae->fae_path = strdup(path);
507 	if (fae->fae_path == NULL) {
508 		error = errno;
509 		free(fae);
510 		return (error);
511 	}
512 
513 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
514 	return (0);
515 }
516 
517 int
518 posix_spawn_file_actions_addfchdir_np(posix_spawn_file_actions_t *__restrict fa,
519     int fildes)
520 {
521 	posix_spawn_file_actions_entry_t *fae;
522 
523 	if (fildes < 0)
524 		return (EBADF);
525 
526 	/* Allocate object */
527 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
528 	if (fae == NULL)
529 		return (errno);
530 
531 	fae->fae_action = FAE_FCHDIR;
532 	fae->fae_fildes = fildes;
533 
534 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
535 	return (0);
536 }
537 
538 int
539 posix_spawn_file_actions_addclosefrom_np (posix_spawn_file_actions_t *
540     __restrict fa, int from)
541 {
542 	posix_spawn_file_actions_entry_t *fae;
543 
544 	if (from < 0)
545 		return (EBADF);
546 
547 	/* Allocate object */
548 	fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
549 	if (fae == NULL)
550 		return (errno);
551 
552 	fae->fae_action = FAE_CLOSEFROM;
553 	fae->fae_fildes = from;
554 
555 	STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
556 	return (0);
557 }
558 
559 /*
560  * Spawn attributes
561  */
562 
563 int
564 posix_spawnattr_init(posix_spawnattr_t *ret)
565 {
566 	posix_spawnattr_t sa;
567 
568 	sa = calloc(1, sizeof(struct __posix_spawnattr));
569 	if (sa == NULL)
570 		return (errno);
571 
572 	/* Set defaults as specified by POSIX, cleared above */
573 	*ret = sa;
574 	return (0);
575 }
576 
577 int
578 posix_spawnattr_destroy(posix_spawnattr_t *sa)
579 {
580 	free(*sa);
581 	return (0);
582 }
583 
584 int
585 posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa,
586     short * __restrict flags)
587 {
588 	*flags = (*sa)->sa_flags;
589 	return (0);
590 }
591 
592 int
593 posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa,
594     pid_t * __restrict pgroup)
595 {
596 	*pgroup = (*sa)->sa_pgroup;
597 	return (0);
598 }
599 
600 int
601 posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa,
602     struct sched_param * __restrict schedparam)
603 {
604 	*schedparam = (*sa)->sa_schedparam;
605 	return (0);
606 }
607 
608 int
609 posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa,
610     int * __restrict schedpolicy)
611 {
612 	*schedpolicy = (*sa)->sa_schedpolicy;
613 	return (0);
614 }
615 
616 int
617 posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa,
618     sigset_t * __restrict sigdefault)
619 {
620 	*sigdefault = (*sa)->sa_sigdefault;
621 	return (0);
622 }
623 
624 int
625 posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa,
626     sigset_t * __restrict sigmask)
627 {
628 	*sigmask = (*sa)->sa_sigmask;
629 	return (0);
630 }
631 
632 int
633 posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags)
634 {
635 	(*sa)->sa_flags = flags;
636 	return (0);
637 }
638 
639 int
640 posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup)
641 {
642 	(*sa)->sa_pgroup = pgroup;
643 	return (0);
644 }
645 
646 int
647 posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa,
648     const struct sched_param * __restrict schedparam)
649 {
650 	(*sa)->sa_schedparam = *schedparam;
651 	return (0);
652 }
653 
654 int
655 posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy)
656 {
657 	(*sa)->sa_schedpolicy = schedpolicy;
658 	return (0);
659 }
660 
661 int
662 posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa,
663     const sigset_t * __restrict sigdefault)
664 {
665 	(*sa)->sa_sigdefault = *sigdefault;
666 	return (0);
667 }
668 
669 int
670 posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa,
671     const sigset_t * __restrict sigmask)
672 {
673 	(*sa)->sa_sigmask = *sigmask;
674 	return (0);
675 }
676