1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved. 2 * 3 * Permission is hereby granted, free of charge, to any person obtaining a copy 4 * of this software and associated documentation files (the "Software"), to 5 * deal in the Software without restriction, including without limitation the 6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 7 * sell copies of the Software, and to permit persons to whom the Software is 8 * furnished to do so, subject to the following conditions: 9 * 10 * The above copyright notice and this permission notice shall be included in 11 * all copies or substantial portions of the Software. 12 * 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 19 * IN THE SOFTWARE. 20 */ 21 22 #include "uv.h" 23 #include "internal.h" 24 25 #include <stdio.h> 26 #include <stdlib.h> 27 #include <assert.h> 28 #include <errno.h> 29 #include <signal.h> 30 #include <string.h> 31 32 #include <sys/types.h> 33 #include <sys/wait.h> 34 #include <unistd.h> 35 #include <fcntl.h> 36 #include <poll.h> 37 38 #if defined(__APPLE__) 39 # include <spawn.h> 40 # include <paths.h> 41 # include <sys/kauth.h> 42 # include <sys/types.h> 43 # include <sys/sysctl.h> 44 # include <dlfcn.h> 45 # include <crt_externs.h> 46 # include <xlocale.h> 47 # define environ (*_NSGetEnviron()) 48 49 /* macOS 10.14 back does not define this constant */ 50 # ifndef POSIX_SPAWN_SETSID 51 # define POSIX_SPAWN_SETSID 1024 52 # endif 53 54 #else 55 extern char **environ; 56 #endif 57 58 #if defined(__linux__) || defined(__GLIBC__) 59 # include <grp.h> 60 #endif 61 62 #if defined(__MVS__) 63 # include "zos-base.h" 64 #endif 65 66 #if defined(__APPLE__) || \ 67 defined(__DragonFly__) || \ 68 defined(__FreeBSD__) || \ 69 defined(__NetBSD__) || \ 70 defined(__OpenBSD__) 71 #include <sys/event.h> 72 #else 73 #define UV_USE_SIGCHLD 74 #endif 75 76 77 #ifdef UV_USE_SIGCHLD 78 static void uv__chld(uv_signal_t* handle, int signum) { 79 assert(signum == SIGCHLD); 80 uv__wait_children(handle->loop); 81 } 82 #endif 83 84 void uv__wait_children(uv_loop_t* loop) { 85 uv_process_t* process; 86 int exit_status; 87 int term_signal; 88 int status; 89 int options; 90 pid_t pid; 91 QUEUE pending; 92 QUEUE* q; 93 QUEUE* h; 94 95 QUEUE_INIT(&pending); 96 97 h = &loop->process_handles; 98 q = QUEUE_HEAD(h); 99 while (q != h) { 100 process = QUEUE_DATA(q, uv_process_t, queue); 101 q = QUEUE_NEXT(q); 102 103 #ifndef UV_USE_SIGCHLD 104 if ((process->flags & UV_HANDLE_REAP) == 0) 105 continue; 106 options = 0; 107 process->flags &= ~UV_HANDLE_REAP; 108 #else 109 options = WNOHANG; 110 #endif 111 112 do 113 pid = waitpid(process->pid, &status, options); 114 while (pid == -1 && errno == EINTR); 115 116 #ifdef UV_USE_SIGCHLD 117 if (pid == 0) /* Not yet exited */ 118 continue; 119 #endif 120 121 if (pid == -1) { 122 if (errno != ECHILD) 123 abort(); 124 /* The child died, and we missed it. This probably means someone else 125 * stole the waitpid from us. Handle this by not handling it at all. */ 126 continue; 127 } 128 129 assert(pid == process->pid); 130 process->status = status; 131 QUEUE_REMOVE(&process->queue); 132 QUEUE_INSERT_TAIL(&pending, &process->queue); 133 } 134 135 h = &pending; 136 q = QUEUE_HEAD(h); 137 while (q != h) { 138 process = QUEUE_DATA(q, uv_process_t, queue); 139 q = QUEUE_NEXT(q); 140 141 QUEUE_REMOVE(&process->queue); 142 QUEUE_INIT(&process->queue); 143 uv__handle_stop(process); 144 145 if (process->exit_cb == NULL) 146 continue; 147 148 exit_status = 0; 149 if (WIFEXITED(process->status)) 150 exit_status = WEXITSTATUS(process->status); 151 152 term_signal = 0; 153 if (WIFSIGNALED(process->status)) 154 term_signal = WTERMSIG(process->status); 155 156 process->exit_cb(process, exit_status, term_signal); 157 } 158 assert(QUEUE_EMPTY(&pending)); 159 } 160 161 /* 162 * Used for initializing stdio streams like options.stdin_stream. Returns 163 * zero on success. See also the cleanup section in uv_spawn(). 164 */ 165 static int uv__process_init_stdio(uv_stdio_container_t* container, int fds[2]) { 166 int mask; 167 int fd; 168 169 mask = UV_IGNORE | UV_CREATE_PIPE | UV_INHERIT_FD | UV_INHERIT_STREAM; 170 171 switch (container->flags & mask) { 172 case UV_IGNORE: 173 return 0; 174 175 case UV_CREATE_PIPE: 176 assert(container->data.stream != NULL); 177 if (container->data.stream->type != UV_NAMED_PIPE) 178 return UV_EINVAL; 179 else 180 return uv_socketpair(SOCK_STREAM, 0, fds, 0, 0); 181 182 case UV_INHERIT_FD: 183 case UV_INHERIT_STREAM: 184 if (container->flags & UV_INHERIT_FD) 185 fd = container->data.fd; 186 else 187 fd = uv__stream_fd(container->data.stream); 188 189 if (fd == -1) 190 return UV_EINVAL; 191 192 fds[1] = fd; 193 return 0; 194 195 default: 196 assert(0 && "Unexpected flags"); 197 return UV_EINVAL; 198 } 199 } 200 201 202 static int uv__process_open_stream(uv_stdio_container_t* container, 203 int pipefds[2]) { 204 int flags; 205 int err; 206 207 if (!(container->flags & UV_CREATE_PIPE) || pipefds[0] < 0) 208 return 0; 209 210 err = uv__close(pipefds[1]); 211 if (err != 0) 212 abort(); 213 214 pipefds[1] = -1; 215 uv__nonblock(pipefds[0], 1); 216 217 flags = 0; 218 if (container->flags & UV_WRITABLE_PIPE) 219 flags |= UV_HANDLE_READABLE; 220 if (container->flags & UV_READABLE_PIPE) 221 flags |= UV_HANDLE_WRITABLE; 222 223 return uv__stream_open(container->data.stream, pipefds[0], flags); 224 } 225 226 227 static void uv__process_close_stream(uv_stdio_container_t* container) { 228 if (!(container->flags & UV_CREATE_PIPE)) return; 229 uv__stream_close(container->data.stream); 230 } 231 232 233 static void uv__write_int(int fd, int val) { 234 ssize_t n; 235 236 do 237 n = write(fd, &val, sizeof(val)); 238 while (n == -1 && errno == EINTR); 239 240 /* The write might have failed (e.g. if the parent process has died), 241 * but we have nothing left but to _exit ourself now too. */ 242 _exit(127); 243 } 244 245 246 static void uv__write_errno(int error_fd) { 247 uv__write_int(error_fd, UV__ERR(errno)); 248 } 249 250 251 #if !(defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH)) 252 /* execvp is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED, so must be 253 * avoided. Since this isn't called on those targets, the function 254 * doesn't even need to be defined for them. 255 */ 256 static void uv__process_child_init(const uv_process_options_t* options, 257 int stdio_count, 258 int (*pipes)[2], 259 int error_fd) { 260 sigset_t signewset; 261 int close_fd; 262 int use_fd; 263 int fd; 264 int n; 265 266 /* Reset signal disposition first. Use a hard-coded limit because NSIG is not 267 * fixed on Linux: it's either 32, 34 or 64, depending on whether RT signals 268 * are enabled. We are not allowed to touch RT signal handlers, glibc uses 269 * them internally. 270 */ 271 for (n = 1; n < 32; n += 1) { 272 if (n == SIGKILL || n == SIGSTOP) 273 continue; /* Can't be changed. */ 274 275 #if defined(__HAIKU__) 276 if (n == SIGKILLTHR) 277 continue; /* Can't be changed. */ 278 #endif 279 280 if (SIG_ERR != signal(n, SIG_DFL)) 281 continue; 282 283 uv__write_errno(error_fd); 284 } 285 286 if (options->flags & UV_PROCESS_DETACHED) 287 setsid(); 288 289 /* First duplicate low numbered fds, since it's not safe to duplicate them, 290 * they could get replaced. Example: swapping stdout and stderr; without 291 * this fd 2 (stderr) would be duplicated into fd 1, thus making both 292 * stdout and stderr go to the same fd, which was not the intention. */ 293 for (fd = 0; fd < stdio_count; fd++) { 294 use_fd = pipes[fd][1]; 295 if (use_fd < 0 || use_fd >= fd) 296 continue; 297 #ifdef F_DUPFD_CLOEXEC /* POSIX 2008 */ 298 pipes[fd][1] = fcntl(use_fd, F_DUPFD_CLOEXEC, stdio_count); 299 #else 300 pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count); 301 #endif 302 if (pipes[fd][1] == -1) 303 uv__write_errno(error_fd); 304 #ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */ 305 n = uv__cloexec(pipes[fd][1], 1); 306 if (n) 307 uv__write_int(error_fd, n); 308 #endif 309 } 310 311 for (fd = 0; fd < stdio_count; fd++) { 312 close_fd = -1; 313 use_fd = pipes[fd][1]; 314 315 if (use_fd < 0) { 316 if (fd >= 3) 317 continue; 318 else { 319 /* Redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is 320 * set. */ 321 uv__close_nocheckstdio(fd); /* Free up fd, if it happens to be open. */ 322 use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR); 323 close_fd = use_fd; 324 325 if (use_fd < 0) 326 uv__write_errno(error_fd); 327 } 328 } 329 330 if (fd == use_fd) { 331 if (close_fd == -1) { 332 n = uv__cloexec(use_fd, 0); 333 if (n) 334 uv__write_int(error_fd, n); 335 } 336 } 337 else { 338 fd = dup2(use_fd, fd); 339 } 340 341 if (fd == -1) 342 uv__write_errno(error_fd); 343 344 if (fd <= 2 && close_fd == -1) 345 uv__nonblock_fcntl(fd, 0); 346 347 if (close_fd >= stdio_count) 348 uv__close(close_fd); 349 } 350 351 if (options->cwd != NULL && chdir(options->cwd)) 352 uv__write_errno(error_fd); 353 354 if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { 355 /* When dropping privileges from root, the `setgroups` call will 356 * remove any extraneous groups. If we don't call this, then 357 * even though our uid has dropped, we may still have groups 358 * that enable us to do super-user things. This will fail if we 359 * aren't root, so don't bother checking the return value, this 360 * is just done as an optimistic privilege dropping function. 361 */ 362 SAVE_ERRNO(setgroups(0, NULL)); 363 } 364 365 if ((options->flags & UV_PROCESS_SETGID) && setgid(options->gid)) 366 uv__write_errno(error_fd); 367 368 if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid)) 369 uv__write_errno(error_fd); 370 371 if (options->env != NULL) 372 environ = options->env; 373 374 /* Reset signal mask just before exec. */ 375 sigemptyset(&signewset); 376 if (sigprocmask(SIG_SETMASK, &signewset, NULL) != 0) 377 abort(); 378 379 #ifdef __MVS__ 380 execvpe(options->file, options->args, environ); 381 #else 382 execvp(options->file, options->args); 383 #endif 384 385 uv__write_errno(error_fd); 386 } 387 #endif 388 389 390 #if defined(__APPLE__) 391 typedef struct uv__posix_spawn_fncs_tag { 392 struct { 393 int (*addchdir_np)(const posix_spawn_file_actions_t *, const char *); 394 } file_actions; 395 } uv__posix_spawn_fncs_t; 396 397 398 static uv_once_t posix_spawn_init_once = UV_ONCE_INIT; 399 static uv__posix_spawn_fncs_t posix_spawn_fncs; 400 static int posix_spawn_can_use_setsid; 401 402 403 static void uv__spawn_init_posix_spawn_fncs(void) { 404 /* Try to locate all non-portable functions at runtime */ 405 posix_spawn_fncs.file_actions.addchdir_np = 406 dlsym(RTLD_DEFAULT, "posix_spawn_file_actions_addchdir_np"); 407 } 408 409 410 static void uv__spawn_init_can_use_setsid(void) { 411 int which[] = {CTL_KERN, KERN_OSRELEASE}; 412 unsigned major; 413 unsigned minor; 414 unsigned patch; 415 char buf[256]; 416 size_t len; 417 418 len = sizeof(buf); 419 if (sysctl(which, ARRAY_SIZE(which), buf, &len, NULL, 0)) 420 return; 421 422 /* NULL specifies to use LC_C_LOCALE */ 423 if (3 != sscanf_l(buf, NULL, "%u.%u.%u", &major, &minor, &patch)) 424 return; 425 426 posix_spawn_can_use_setsid = (major >= 19); /* macOS Catalina */ 427 } 428 429 430 static void uv__spawn_init_posix_spawn(void) { 431 /* Init handles to all potentially non-defined functions */ 432 uv__spawn_init_posix_spawn_fncs(); 433 434 /* Init feature detection for POSIX_SPAWN_SETSID flag */ 435 uv__spawn_init_can_use_setsid(); 436 } 437 438 439 static int uv__spawn_set_posix_spawn_attrs( 440 posix_spawnattr_t* attrs, 441 const uv__posix_spawn_fncs_t* posix_spawn_fncs, 442 const uv_process_options_t* options) { 443 int err; 444 unsigned int flags; 445 sigset_t signal_set; 446 447 err = posix_spawnattr_init(attrs); 448 if (err != 0) { 449 /* If initialization fails, no need to de-init, just return */ 450 return err; 451 } 452 453 if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) { 454 /* kauth_cred_issuser currently requires exactly uid == 0 for these 455 * posixspawn_attrs (set_groups_np, setuid_np, setgid_np), which deviates 456 * from the normal specification of setuid (which also uses euid), and they 457 * are also undocumented syscalls, so we do not use them. */ 458 err = ENOSYS; 459 goto error; 460 } 461 462 /* Set flags for spawn behavior 463 * 1) POSIX_SPAWN_CLOEXEC_DEFAULT: (Apple Extension) All descriptors in the 464 * parent will be treated as if they had been created with O_CLOEXEC. The 465 * only fds that will be passed on to the child are those manipulated by 466 * the file actions 467 * 2) POSIX_SPAWN_SETSIGDEF: Signals mentioned in spawn-sigdefault in the 468 * spawn attributes will be reset to behave as their default 469 * 3) POSIX_SPAWN_SETSIGMASK: Signal mask will be set to the value of 470 * spawn-sigmask in attributes 471 * 4) POSIX_SPAWN_SETSID: Make the process a new session leader if a detached 472 * session was requested. */ 473 flags = POSIX_SPAWN_CLOEXEC_DEFAULT | 474 POSIX_SPAWN_SETSIGDEF | 475 POSIX_SPAWN_SETSIGMASK; 476 if (options->flags & UV_PROCESS_DETACHED) { 477 /* If running on a version of macOS where this flag is not supported, 478 * revert back to the fork/exec flow. Otherwise posix_spawn will 479 * silently ignore the flag. */ 480 if (!posix_spawn_can_use_setsid) { 481 err = ENOSYS; 482 goto error; 483 } 484 485 flags |= POSIX_SPAWN_SETSID; 486 } 487 err = posix_spawnattr_setflags(attrs, flags); 488 if (err != 0) 489 goto error; 490 491 /* Reset all signal the child to their default behavior */ 492 sigfillset(&signal_set); 493 err = posix_spawnattr_setsigdefault(attrs, &signal_set); 494 if (err != 0) 495 goto error; 496 497 /* Reset the signal mask for all signals */ 498 sigemptyset(&signal_set); 499 err = posix_spawnattr_setsigmask(attrs, &signal_set); 500 if (err != 0) 501 goto error; 502 503 return err; 504 505 error: 506 (void) posix_spawnattr_destroy(attrs); 507 return err; 508 } 509 510 511 static int uv__spawn_set_posix_spawn_file_actions( 512 posix_spawn_file_actions_t* actions, 513 const uv__posix_spawn_fncs_t* posix_spawn_fncs, 514 const uv_process_options_t* options, 515 int stdio_count, 516 int (*pipes)[2]) { 517 int fd; 518 int fd2; 519 int use_fd; 520 int err; 521 522 err = posix_spawn_file_actions_init(actions); 523 if (err != 0) { 524 /* If initialization fails, no need to de-init, just return */ 525 return err; 526 } 527 528 /* Set the current working directory if requested */ 529 if (options->cwd != NULL) { 530 if (posix_spawn_fncs->file_actions.addchdir_np == NULL) { 531 err = ENOSYS; 532 goto error; 533 } 534 535 err = posix_spawn_fncs->file_actions.addchdir_np(actions, options->cwd); 536 if (err != 0) 537 goto error; 538 } 539 540 /* Do not return ENOSYS after this point, as we may mutate pipes. */ 541 542 /* First duplicate low numbered fds, since it's not safe to duplicate them, 543 * they could get replaced. Example: swapping stdout and stderr; without 544 * this fd 2 (stderr) would be duplicated into fd 1, thus making both 545 * stdout and stderr go to the same fd, which was not the intention. */ 546 for (fd = 0; fd < stdio_count; fd++) { 547 use_fd = pipes[fd][1]; 548 if (use_fd < 0 || use_fd >= fd) 549 continue; 550 use_fd = stdio_count; 551 for (fd2 = 0; fd2 < stdio_count; fd2++) { 552 /* If we were not setting POSIX_SPAWN_CLOEXEC_DEFAULT, we would need to 553 * also consider whether fcntl(fd, F_GETFD) returned without the 554 * FD_CLOEXEC flag set. */ 555 if (pipes[fd2][1] == use_fd) { 556 use_fd++; 557 fd2 = 0; 558 } 559 } 560 err = posix_spawn_file_actions_adddup2( 561 actions, 562 pipes[fd][1], 563 use_fd); 564 assert(err != ENOSYS); 565 if (err != 0) 566 goto error; 567 pipes[fd][1] = use_fd; 568 } 569 570 /* Second, move the descriptors into their respective places */ 571 for (fd = 0; fd < stdio_count; fd++) { 572 use_fd = pipes[fd][1]; 573 if (use_fd < 0) { 574 if (fd >= 3) 575 continue; 576 else { 577 /* If ignored, redirect to (or from) /dev/null, */ 578 err = posix_spawn_file_actions_addopen( 579 actions, 580 fd, 581 "/dev/null", 582 fd == 0 ? O_RDONLY : O_RDWR, 583 0); 584 assert(err != ENOSYS); 585 if (err != 0) 586 goto error; 587 continue; 588 } 589 } 590 591 if (fd == use_fd) 592 err = posix_spawn_file_actions_addinherit_np(actions, fd); 593 else 594 err = posix_spawn_file_actions_adddup2(actions, use_fd, fd); 595 assert(err != ENOSYS); 596 if (err != 0) 597 goto error; 598 599 /* Make sure the fd is marked as non-blocking (state shared between child 600 * and parent). */ 601 uv__nonblock_fcntl(use_fd, 0); 602 } 603 604 /* Finally, close all the superfluous descriptors */ 605 for (fd = 0; fd < stdio_count; fd++) { 606 use_fd = pipes[fd][1]; 607 if (use_fd < stdio_count) 608 continue; 609 610 /* Check if we already closed this. */ 611 for (fd2 = 0; fd2 < fd; fd2++) { 612 if (pipes[fd2][1] == use_fd) 613 break; 614 } 615 if (fd2 < fd) 616 continue; 617 618 err = posix_spawn_file_actions_addclose(actions, use_fd); 619 assert(err != ENOSYS); 620 if (err != 0) 621 goto error; 622 } 623 624 return 0; 625 626 error: 627 (void) posix_spawn_file_actions_destroy(actions); 628 return err; 629 } 630 631 char* uv__spawn_find_path_in_env(char** env) { 632 char** env_iterator; 633 const char path_var[] = "PATH="; 634 635 /* Look for an environment variable called PATH in the 636 * provided env array, and return its value if found */ 637 for (env_iterator = env; *env_iterator != NULL; env_iterator++) { 638 if (strncmp(*env_iterator, path_var, sizeof(path_var) - 1) == 0) { 639 /* Found "PATH=" at the beginning of the string */ 640 return *env_iterator + sizeof(path_var) - 1; 641 } 642 } 643 644 return NULL; 645 } 646 647 648 static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options, 649 posix_spawnattr_t* attrs, 650 posix_spawn_file_actions_t* actions, 651 pid_t* pid) { 652 const char *p; 653 const char *z; 654 const char *path; 655 size_t l; 656 size_t k; 657 int err; 658 int seen_eacces; 659 660 path = NULL; 661 err = -1; 662 seen_eacces = 0; 663 664 /* Short circuit for erroneous case */ 665 if (options->file == NULL) 666 return ENOENT; 667 668 /* The environment for the child process is that of the parent unless overriden 669 * by options->env */ 670 char** env = environ; 671 if (options->env != NULL) 672 env = options->env; 673 674 /* If options->file contains a slash, posix_spawn/posix_spawnp should behave 675 * the same, and do not involve PATH resolution at all. The libc 676 * `posix_spawnp` provided by Apple is buggy (since 10.15), so we now emulate it 677 * here, per https://github.com/libuv/libuv/pull/3583. */ 678 if (strchr(options->file, '/') != NULL) { 679 do 680 err = posix_spawn(pid, options->file, actions, attrs, options->args, env); 681 while (err == EINTR); 682 return err; 683 } 684 685 /* Look for the definition of PATH in the provided env */ 686 path = uv__spawn_find_path_in_env(env); 687 688 /* The following resolution logic (execvpe emulation) is copied from 689 * https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c 690 * and adapted to work for our specific usage */ 691 692 /* If no path was provided in env, use the default value 693 * to look for the executable */ 694 if (path == NULL) 695 path = _PATH_DEFPATH; 696 697 k = strnlen(options->file, NAME_MAX + 1); 698 if (k > NAME_MAX) 699 return ENAMETOOLONG; 700 701 l = strnlen(path, PATH_MAX - 1) + 1; 702 703 for (p = path;; p = z) { 704 /* Compose the new process file from the entry in the PATH 705 * environment variable and the actual file name */ 706 char b[PATH_MAX + NAME_MAX]; 707 z = strchr(p, ':'); 708 if (!z) 709 z = p + strlen(p); 710 if ((size_t)(z - p) >= l) { 711 if (!*z++) 712 break; 713 714 continue; 715 } 716 memcpy(b, p, z - p); 717 b[z - p] = '/'; 718 memcpy(b + (z - p) + (z > p), options->file, k + 1); 719 720 /* Try to spawn the new process file. If it fails with ENOENT, the 721 * new process file is not in this PATH entry, continue with the next 722 * PATH entry. */ 723 do 724 err = posix_spawn(pid, b, actions, attrs, options->args, env); 725 while (err == EINTR); 726 727 switch (err) { 728 case EACCES: 729 seen_eacces = 1; 730 break; /* continue search */ 731 case ENOENT: 732 case ENOTDIR: 733 break; /* continue search */ 734 default: 735 return err; 736 } 737 738 if (!*z++) 739 break; 740 } 741 742 if (seen_eacces) 743 return EACCES; 744 return err; 745 } 746 747 748 static int uv__spawn_and_init_child_posix_spawn( 749 const uv_process_options_t* options, 750 int stdio_count, 751 int (*pipes)[2], 752 pid_t* pid, 753 const uv__posix_spawn_fncs_t* posix_spawn_fncs) { 754 int err; 755 posix_spawnattr_t attrs; 756 posix_spawn_file_actions_t actions; 757 758 err = uv__spawn_set_posix_spawn_attrs(&attrs, posix_spawn_fncs, options); 759 if (err != 0) 760 goto error; 761 762 /* This may mutate pipes. */ 763 err = uv__spawn_set_posix_spawn_file_actions(&actions, 764 posix_spawn_fncs, 765 options, 766 stdio_count, 767 pipes); 768 if (err != 0) { 769 (void) posix_spawnattr_destroy(&attrs); 770 goto error; 771 } 772 773 /* Try to spawn options->file resolving in the provided environment 774 * if any */ 775 err = uv__spawn_resolve_and_spawn(options, &attrs, &actions, pid); 776 assert(err != ENOSYS); 777 778 /* Destroy the actions/attributes */ 779 (void) posix_spawn_file_actions_destroy(&actions); 780 (void) posix_spawnattr_destroy(&attrs); 781 782 error: 783 /* In an error situation, the attributes and file actions are 784 * already destroyed, only the happy path requires cleanup */ 785 return UV__ERR(err); 786 } 787 #endif 788 789 static int uv__spawn_and_init_child_fork(const uv_process_options_t* options, 790 int stdio_count, 791 int (*pipes)[2], 792 int error_fd, 793 pid_t* pid) { 794 sigset_t signewset; 795 sigset_t sigoldset; 796 797 /* Start the child with most signals blocked, to avoid any issues before we 798 * can reset them, but allow program failures to exit (and not hang). */ 799 sigfillset(&signewset); 800 sigdelset(&signewset, SIGKILL); 801 sigdelset(&signewset, SIGSTOP); 802 sigdelset(&signewset, SIGTRAP); 803 sigdelset(&signewset, SIGSEGV); 804 sigdelset(&signewset, SIGBUS); 805 sigdelset(&signewset, SIGILL); 806 sigdelset(&signewset, SIGSYS); 807 sigdelset(&signewset, SIGABRT); 808 if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0) 809 abort(); 810 811 *pid = fork(); 812 813 if (*pid == 0) { 814 /* Fork succeeded, in the child process */ 815 uv__process_child_init(options, stdio_count, pipes, error_fd); 816 abort(); 817 } 818 819 if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0) 820 abort(); 821 822 if (*pid == -1) 823 /* Failed to fork */ 824 return UV__ERR(errno); 825 826 /* Fork succeeded, in the parent process */ 827 return 0; 828 } 829 830 static int uv__spawn_and_init_child( 831 uv_loop_t* loop, 832 const uv_process_options_t* options, 833 int stdio_count, 834 int (*pipes)[2], 835 pid_t* pid) { 836 int signal_pipe[2] = { -1, -1 }; 837 int status; 838 int err; 839 int exec_errorno; 840 ssize_t r; 841 842 #if defined(__APPLE__) 843 uv_once(&posix_spawn_init_once, uv__spawn_init_posix_spawn); 844 845 /* Special child process spawn case for macOS Big Sur (11.0) onwards 846 * 847 * Big Sur introduced a significant performance degradation on a call to 848 * fork/exec when the process has many pages mmaped in with MAP_JIT, like, say 849 * a javascript interpreter. Electron-based applications, for example, 850 * are impacted; though the magnitude of the impact depends on how much the 851 * app relies on subprocesses. 852 * 853 * On macOS, though, posix_spawn is implemented in a way that does not 854 * exhibit the problem. This block implements the forking and preparation 855 * logic with posix_spawn and its related primitives. It also takes advantage of 856 * the macOS extension POSIX_SPAWN_CLOEXEC_DEFAULT that makes impossible to 857 * leak descriptors to the child process. */ 858 err = uv__spawn_and_init_child_posix_spawn(options, 859 stdio_count, 860 pipes, 861 pid, 862 &posix_spawn_fncs); 863 864 /* The posix_spawn flow will return UV_ENOSYS if any of the posix_spawn_x_np 865 * non-standard functions is both _needed_ and _undefined_. In those cases, 866 * default back to the fork/execve strategy. For all other errors, just fail. */ 867 if (err != UV_ENOSYS) 868 return err; 869 870 #endif 871 872 /* This pipe is used by the parent to wait until 873 * the child has called `execve()`. We need this 874 * to avoid the following race condition: 875 * 876 * if ((pid = fork()) > 0) { 877 * kill(pid, SIGTERM); 878 * } 879 * else if (pid == 0) { 880 * execve("/bin/cat", argp, envp); 881 * } 882 * 883 * The parent sends a signal immediately after forking. 884 * Since the child may not have called `execve()` yet, 885 * there is no telling what process receives the signal, 886 * our fork or /bin/cat. 887 * 888 * To avoid ambiguity, we create a pipe with both ends 889 * marked close-on-exec. Then, after the call to `fork()`, 890 * the parent polls the read end until it EOFs or errors with EPIPE. 891 */ 892 err = uv__make_pipe(signal_pipe, 0); 893 if (err) 894 return err; 895 896 /* Acquire write lock to prevent opening new fds in worker threads */ 897 uv_rwlock_wrlock(&loop->cloexec_lock); 898 899 err = uv__spawn_and_init_child_fork(options, stdio_count, pipes, signal_pipe[1], pid); 900 901 /* Release lock in parent process */ 902 uv_rwlock_wrunlock(&loop->cloexec_lock); 903 904 uv__close(signal_pipe[1]); 905 906 if (err == 0) { 907 do 908 r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno)); 909 while (r == -1 && errno == EINTR); 910 911 if (r == 0) 912 ; /* okay, EOF */ 913 else if (r == sizeof(exec_errorno)) { 914 do 915 err = waitpid(*pid, &status, 0); /* okay, read errorno */ 916 while (err == -1 && errno == EINTR); 917 assert(err == *pid); 918 err = exec_errorno; 919 } else if (r == -1 && errno == EPIPE) { 920 /* Something unknown happened to our child before spawn */ 921 do 922 err = waitpid(*pid, &status, 0); /* okay, got EPIPE */ 923 while (err == -1 && errno == EINTR); 924 assert(err == *pid); 925 err = UV_EPIPE; 926 } else 927 abort(); 928 } 929 930 uv__close_nocheckstdio(signal_pipe[0]); 931 932 return err; 933 } 934 935 int uv_spawn(uv_loop_t* loop, 936 uv_process_t* process, 937 const uv_process_options_t* options) { 938 #if defined(__APPLE__) && (TARGET_OS_TV || TARGET_OS_WATCH) 939 /* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */ 940 return UV_ENOSYS; 941 #else 942 int pipes_storage[8][2]; 943 int (*pipes)[2]; 944 int stdio_count; 945 pid_t pid; 946 int err; 947 int exec_errorno; 948 int i; 949 950 assert(options->file != NULL); 951 assert(!(options->flags & ~(UV_PROCESS_DETACHED | 952 UV_PROCESS_SETGID | 953 UV_PROCESS_SETUID | 954 UV_PROCESS_WINDOWS_HIDE | 955 UV_PROCESS_WINDOWS_HIDE_CONSOLE | 956 UV_PROCESS_WINDOWS_HIDE_GUI | 957 UV_PROCESS_WINDOWS_VERBATIM_ARGUMENTS))); 958 959 uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS); 960 QUEUE_INIT(&process->queue); 961 process->status = 0; 962 963 stdio_count = options->stdio_count; 964 if (stdio_count < 3) 965 stdio_count = 3; 966 967 err = UV_ENOMEM; 968 pipes = pipes_storage; 969 if (stdio_count > (int) ARRAY_SIZE(pipes_storage)) 970 pipes = uv__malloc(stdio_count * sizeof(*pipes)); 971 972 if (pipes == NULL) 973 goto error; 974 975 for (i = 0; i < stdio_count; i++) { 976 pipes[i][0] = -1; 977 pipes[i][1] = -1; 978 } 979 980 for (i = 0; i < options->stdio_count; i++) { 981 err = uv__process_init_stdio(options->stdio + i, pipes[i]); 982 if (err) 983 goto error; 984 } 985 986 #ifdef UV_USE_SIGCHLD 987 uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD); 988 #endif 989 990 /* Spawn the child */ 991 exec_errorno = uv__spawn_and_init_child(loop, options, stdio_count, pipes, &pid); 992 993 #if 0 994 /* This runs into a nodejs issue (it expects initialized streams, even if the 995 * exec failed). 996 * See https://github.com/libuv/libuv/pull/3107#issuecomment-782482608 */ 997 if (exec_errorno != 0) 998 goto error; 999 #endif 1000 1001 /* Activate this handle if exec() happened successfully, even if we later 1002 * fail to open a stdio handle. This ensures we can eventually reap the child 1003 * with waitpid. */ 1004 if (exec_errorno == 0) { 1005 #ifndef UV_USE_SIGCHLD 1006 struct kevent event; 1007 EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0); 1008 if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL)) { 1009 if (errno != ESRCH) 1010 abort(); 1011 /* Process already exited. Call waitpid on the next loop iteration. */ 1012 process->flags |= UV_HANDLE_REAP; 1013 loop->flags |= UV_LOOP_REAP_CHILDREN; 1014 } 1015 #endif 1016 1017 process->pid = pid; 1018 process->exit_cb = options->exit_cb; 1019 QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue); 1020 uv__handle_start(process); 1021 } 1022 1023 for (i = 0; i < options->stdio_count; i++) { 1024 err = uv__process_open_stream(options->stdio + i, pipes[i]); 1025 if (err == 0) 1026 continue; 1027 1028 while (i--) 1029 uv__process_close_stream(options->stdio + i); 1030 1031 goto error; 1032 } 1033 1034 if (pipes != pipes_storage) 1035 uv__free(pipes); 1036 1037 return exec_errorno; 1038 1039 error: 1040 if (pipes != NULL) { 1041 for (i = 0; i < stdio_count; i++) { 1042 if (i < options->stdio_count) 1043 if (options->stdio[i].flags & (UV_INHERIT_FD | UV_INHERIT_STREAM)) 1044 continue; 1045 if (pipes[i][0] != -1) 1046 uv__close_nocheckstdio(pipes[i][0]); 1047 if (pipes[i][1] != -1) 1048 uv__close_nocheckstdio(pipes[i][1]); 1049 } 1050 1051 if (pipes != pipes_storage) 1052 uv__free(pipes); 1053 } 1054 1055 return err; 1056 #endif 1057 } 1058 1059 1060 int uv_process_kill(uv_process_t* process, int signum) { 1061 return uv_kill(process->pid, signum); 1062 } 1063 1064 1065 int uv_kill(int pid, int signum) { 1066 if (kill(pid, signum)) { 1067 #if defined(__MVS__) 1068 /* EPERM is returned if the process is a zombie. */ 1069 siginfo_t infop; 1070 if (errno == EPERM && 1071 waitid(P_PID, pid, &infop, WNOHANG | WNOWAIT | WEXITED) == 0) 1072 return 0; 1073 #endif 1074 return UV__ERR(errno); 1075 } else 1076 return 0; 1077 } 1078 1079 1080 void uv__process_close(uv_process_t* handle) { 1081 QUEUE_REMOVE(&handle->queue); 1082 uv__handle_stop(handle); 1083 if (QUEUE_EMPTY(&handle->loop->process_handles)) 1084 uv_signal_stop(&handle->loop->child_watcher); 1085 } 1086