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