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