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