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