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