17db96d56Sopenharmony_ci/* Authors: Gregory P. Smith & Jeffrey Yasskin */ 27db96d56Sopenharmony_ci#ifndef Py_BUILD_CORE_BUILTIN 37db96d56Sopenharmony_ci# define Py_BUILD_CORE_MODULE 1 47db96d56Sopenharmony_ci#endif 57db96d56Sopenharmony_ci 67db96d56Sopenharmony_ci#include "Python.h" 77db96d56Sopenharmony_ci#include "pycore_fileutils.h" 87db96d56Sopenharmony_ci#if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE) 97db96d56Sopenharmony_ci# define _GNU_SOURCE 107db96d56Sopenharmony_ci#endif 117db96d56Sopenharmony_ci#include <unistd.h> 127db96d56Sopenharmony_ci#include <fcntl.h> 137db96d56Sopenharmony_ci#ifdef HAVE_SYS_TYPES_H 147db96d56Sopenharmony_ci#include <sys/types.h> 157db96d56Sopenharmony_ci#endif 167db96d56Sopenharmony_ci#if defined(HAVE_SYS_STAT_H) 177db96d56Sopenharmony_ci#include <sys/stat.h> 187db96d56Sopenharmony_ci#endif 197db96d56Sopenharmony_ci#ifdef HAVE_SYS_SYSCALL_H 207db96d56Sopenharmony_ci#include <sys/syscall.h> 217db96d56Sopenharmony_ci#endif 227db96d56Sopenharmony_ci#if defined(HAVE_SYS_RESOURCE_H) 237db96d56Sopenharmony_ci#include <sys/resource.h> 247db96d56Sopenharmony_ci#endif 257db96d56Sopenharmony_ci#ifdef HAVE_DIRENT_H 267db96d56Sopenharmony_ci#include <dirent.h> 277db96d56Sopenharmony_ci#endif 287db96d56Sopenharmony_ci#ifdef HAVE_GRP_H 297db96d56Sopenharmony_ci#include <grp.h> 307db96d56Sopenharmony_ci#endif /* HAVE_GRP_H */ 317db96d56Sopenharmony_ci 327db96d56Sopenharmony_ci#include "posixmodule.h" 337db96d56Sopenharmony_ci 347db96d56Sopenharmony_ci#ifdef _Py_MEMORY_SANITIZER 357db96d56Sopenharmony_ci# include <sanitizer/msan_interface.h> 367db96d56Sopenharmony_ci#endif 377db96d56Sopenharmony_ci 387db96d56Sopenharmony_ci#if defined(__ANDROID__) && __ANDROID_API__ < 21 && !defined(SYS_getdents64) 397db96d56Sopenharmony_ci# include <sys/linux-syscalls.h> 407db96d56Sopenharmony_ci# define SYS_getdents64 __NR_getdents64 417db96d56Sopenharmony_ci#endif 427db96d56Sopenharmony_ci 437db96d56Sopenharmony_ci#if defined(__linux__) && defined(HAVE_VFORK) && defined(HAVE_SIGNAL_H) && \ 447db96d56Sopenharmony_ci defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK) 457db96d56Sopenharmony_ci/* If this is ever expanded to non-Linux platforms, verify what calls are 467db96d56Sopenharmony_ci * allowed after vfork(). Ex: setsid() may be disallowed on macOS? */ 477db96d56Sopenharmony_ci# include <signal.h> 487db96d56Sopenharmony_ci# define VFORK_USABLE 1 497db96d56Sopenharmony_ci#endif 507db96d56Sopenharmony_ci 517db96d56Sopenharmony_ci#if defined(__sun) && defined(__SVR4) 527db96d56Sopenharmony_ci/* readdir64 is used to work around Solaris 9 bug 6395699. */ 537db96d56Sopenharmony_ci# define readdir readdir64 547db96d56Sopenharmony_ci# define dirent dirent64 557db96d56Sopenharmony_ci# if !defined(HAVE_DIRFD) 567db96d56Sopenharmony_ci/* Some versions of Solaris lack dirfd(). */ 577db96d56Sopenharmony_ci# define dirfd(dirp) ((dirp)->dd_fd) 587db96d56Sopenharmony_ci# define HAVE_DIRFD 597db96d56Sopenharmony_ci# endif 607db96d56Sopenharmony_ci#endif 617db96d56Sopenharmony_ci 627db96d56Sopenharmony_ci#if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__DragonFly__) 637db96d56Sopenharmony_ci# define FD_DIR "/dev/fd" 647db96d56Sopenharmony_ci#else 657db96d56Sopenharmony_ci# define FD_DIR "/proc/self/fd" 667db96d56Sopenharmony_ci#endif 677db96d56Sopenharmony_ci 687db96d56Sopenharmony_ci#ifdef NGROUPS_MAX 697db96d56Sopenharmony_ci#define MAX_GROUPS NGROUPS_MAX 707db96d56Sopenharmony_ci#else 717db96d56Sopenharmony_ci#define MAX_GROUPS 64 727db96d56Sopenharmony_ci#endif 737db96d56Sopenharmony_ci 747db96d56Sopenharmony_ci#define POSIX_CALL(call) do { if ((call) == -1) goto error; } while (0) 757db96d56Sopenharmony_ci 767db96d56Sopenharmony_cistatic struct PyModuleDef _posixsubprocessmodule; 777db96d56Sopenharmony_ci 787db96d56Sopenharmony_ci/* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */ 797db96d56Sopenharmony_cistatic int 807db96d56Sopenharmony_ci_pos_int_from_ascii(const char *name) 817db96d56Sopenharmony_ci{ 827db96d56Sopenharmony_ci int num = 0; 837db96d56Sopenharmony_ci while (*name >= '0' && *name <= '9') { 847db96d56Sopenharmony_ci num = num * 10 + (*name - '0'); 857db96d56Sopenharmony_ci ++name; 867db96d56Sopenharmony_ci } 877db96d56Sopenharmony_ci if (*name) 887db96d56Sopenharmony_ci return -1; /* Non digit found, not a number. */ 897db96d56Sopenharmony_ci return num; 907db96d56Sopenharmony_ci} 917db96d56Sopenharmony_ci 927db96d56Sopenharmony_ci 937db96d56Sopenharmony_ci#if defined(__FreeBSD__) || defined(__DragonFly__) 947db96d56Sopenharmony_ci/* When /dev/fd isn't mounted it is often a static directory populated 957db96d56Sopenharmony_ci * with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD, OpenBSD and DragonFlyBSD. 967db96d56Sopenharmony_ci * NetBSD and OpenBSD have a /proc fs available (though not necessarily 977db96d56Sopenharmony_ci * mounted) and do not have fdescfs for /dev/fd. MacOS X has a devfs 987db96d56Sopenharmony_ci * that properly supports /dev/fd. 997db96d56Sopenharmony_ci */ 1007db96d56Sopenharmony_cistatic int 1017db96d56Sopenharmony_ci_is_fdescfs_mounted_on_dev_fd(void) 1027db96d56Sopenharmony_ci{ 1037db96d56Sopenharmony_ci struct stat dev_stat; 1047db96d56Sopenharmony_ci struct stat dev_fd_stat; 1057db96d56Sopenharmony_ci if (stat("/dev", &dev_stat) != 0) 1067db96d56Sopenharmony_ci return 0; 1077db96d56Sopenharmony_ci if (stat(FD_DIR, &dev_fd_stat) != 0) 1087db96d56Sopenharmony_ci return 0; 1097db96d56Sopenharmony_ci if (dev_stat.st_dev == dev_fd_stat.st_dev) 1107db96d56Sopenharmony_ci return 0; /* / == /dev == /dev/fd means it is static. #fail */ 1117db96d56Sopenharmony_ci return 1; 1127db96d56Sopenharmony_ci} 1137db96d56Sopenharmony_ci#endif 1147db96d56Sopenharmony_ci 1157db96d56Sopenharmony_ci 1167db96d56Sopenharmony_ci/* Returns 1 if there is a problem with fd_sequence, 0 otherwise. */ 1177db96d56Sopenharmony_cistatic int 1187db96d56Sopenharmony_ci_sanity_check_python_fd_sequence(PyObject *fd_sequence) 1197db96d56Sopenharmony_ci{ 1207db96d56Sopenharmony_ci Py_ssize_t seq_idx; 1217db96d56Sopenharmony_ci long prev_fd = -1; 1227db96d56Sopenharmony_ci for (seq_idx = 0; seq_idx < PyTuple_GET_SIZE(fd_sequence); ++seq_idx) { 1237db96d56Sopenharmony_ci PyObject* py_fd = PyTuple_GET_ITEM(fd_sequence, seq_idx); 1247db96d56Sopenharmony_ci long iter_fd; 1257db96d56Sopenharmony_ci if (!PyLong_Check(py_fd)) { 1267db96d56Sopenharmony_ci return 1; 1277db96d56Sopenharmony_ci } 1287db96d56Sopenharmony_ci iter_fd = PyLong_AsLong(py_fd); 1297db96d56Sopenharmony_ci if (iter_fd < 0 || iter_fd <= prev_fd || iter_fd > INT_MAX) { 1307db96d56Sopenharmony_ci /* Negative, overflow, unsorted, too big for a fd. */ 1317db96d56Sopenharmony_ci return 1; 1327db96d56Sopenharmony_ci } 1337db96d56Sopenharmony_ci prev_fd = iter_fd; 1347db96d56Sopenharmony_ci } 1357db96d56Sopenharmony_ci return 0; 1367db96d56Sopenharmony_ci} 1377db96d56Sopenharmony_ci 1387db96d56Sopenharmony_ci 1397db96d56Sopenharmony_ci/* Is fd found in the sorted Python Sequence? */ 1407db96d56Sopenharmony_cistatic int 1417db96d56Sopenharmony_ci_is_fd_in_sorted_fd_sequence(int fd, int *fd_sequence, 1427db96d56Sopenharmony_ci Py_ssize_t fd_sequence_len) 1437db96d56Sopenharmony_ci{ 1447db96d56Sopenharmony_ci /* Binary search. */ 1457db96d56Sopenharmony_ci Py_ssize_t search_min = 0; 1467db96d56Sopenharmony_ci Py_ssize_t search_max = fd_sequence_len - 1; 1477db96d56Sopenharmony_ci if (search_max < 0) 1487db96d56Sopenharmony_ci return 0; 1497db96d56Sopenharmony_ci do { 1507db96d56Sopenharmony_ci long middle = (search_min + search_max) / 2; 1517db96d56Sopenharmony_ci long middle_fd = fd_sequence[middle]; 1527db96d56Sopenharmony_ci if (fd == middle_fd) 1537db96d56Sopenharmony_ci return 1; 1547db96d56Sopenharmony_ci if (fd > middle_fd) 1557db96d56Sopenharmony_ci search_min = middle + 1; 1567db96d56Sopenharmony_ci else 1577db96d56Sopenharmony_ci search_max = middle - 1; 1587db96d56Sopenharmony_ci } while (search_min <= search_max); 1597db96d56Sopenharmony_ci return 0; 1607db96d56Sopenharmony_ci} 1617db96d56Sopenharmony_ci 1627db96d56Sopenharmony_ci/* 1637db96d56Sopenharmony_ci * Do all the Python C API calls in the parent process to turn the pass_fds 1647db96d56Sopenharmony_ci * "py_fds_to_keep" tuple into a C array. The caller owns allocation and 1657db96d56Sopenharmony_ci * freeing of the array. 1667db96d56Sopenharmony_ci * 1677db96d56Sopenharmony_ci * On error an unknown number of array elements may have been filled in. 1687db96d56Sopenharmony_ci * A Python exception has been set when an error is returned. 1697db96d56Sopenharmony_ci * 1707db96d56Sopenharmony_ci * Returns: -1 on error, 0 on success. 1717db96d56Sopenharmony_ci */ 1727db96d56Sopenharmony_cistatic int 1737db96d56Sopenharmony_ciconvert_fds_to_keep_to_c(PyObject *py_fds_to_keep, int *c_fds_to_keep) 1747db96d56Sopenharmony_ci{ 1757db96d56Sopenharmony_ci Py_ssize_t i, len; 1767db96d56Sopenharmony_ci 1777db96d56Sopenharmony_ci len = PyTuple_GET_SIZE(py_fds_to_keep); 1787db96d56Sopenharmony_ci for (i = 0; i < len; ++i) { 1797db96d56Sopenharmony_ci PyObject* fdobj = PyTuple_GET_ITEM(py_fds_to_keep, i); 1807db96d56Sopenharmony_ci long fd = PyLong_AsLong(fdobj); 1817db96d56Sopenharmony_ci if (fd == -1 && PyErr_Occurred()) { 1827db96d56Sopenharmony_ci return -1; 1837db96d56Sopenharmony_ci } 1847db96d56Sopenharmony_ci if (fd < 0 || fd > INT_MAX) { 1857db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, 1867db96d56Sopenharmony_ci "fd out of range in fds_to_keep."); 1877db96d56Sopenharmony_ci return -1; 1887db96d56Sopenharmony_ci } 1897db96d56Sopenharmony_ci c_fds_to_keep[i] = (int)fd; 1907db96d56Sopenharmony_ci } 1917db96d56Sopenharmony_ci return 0; 1927db96d56Sopenharmony_ci} 1937db96d56Sopenharmony_ci 1947db96d56Sopenharmony_ci 1957db96d56Sopenharmony_ci/* This function must be async-signal-safe as it is called from child_exec() 1967db96d56Sopenharmony_ci * after fork() or vfork(). 1977db96d56Sopenharmony_ci */ 1987db96d56Sopenharmony_cistatic int 1997db96d56Sopenharmony_cimake_inheritable(int *c_fds_to_keep, Py_ssize_t len, int errpipe_write) 2007db96d56Sopenharmony_ci{ 2017db96d56Sopenharmony_ci Py_ssize_t i; 2027db96d56Sopenharmony_ci 2037db96d56Sopenharmony_ci for (i = 0; i < len; ++i) { 2047db96d56Sopenharmony_ci int fd = c_fds_to_keep[i]; 2057db96d56Sopenharmony_ci if (fd == errpipe_write) { 2067db96d56Sopenharmony_ci /* errpipe_write is part of fds_to_keep. It must be closed at 2077db96d56Sopenharmony_ci exec(), but kept open in the child process until exec() is 2087db96d56Sopenharmony_ci called. */ 2097db96d56Sopenharmony_ci continue; 2107db96d56Sopenharmony_ci } 2117db96d56Sopenharmony_ci if (_Py_set_inheritable_async_safe(fd, 1, NULL) < 0) 2127db96d56Sopenharmony_ci return -1; 2137db96d56Sopenharmony_ci } 2147db96d56Sopenharmony_ci return 0; 2157db96d56Sopenharmony_ci} 2167db96d56Sopenharmony_ci 2177db96d56Sopenharmony_ci 2187db96d56Sopenharmony_ci/* Get the maximum file descriptor that could be opened by this process. 2197db96d56Sopenharmony_ci * This function is async signal safe for use between fork() and exec(). 2207db96d56Sopenharmony_ci */ 2217db96d56Sopenharmony_cistatic long 2227db96d56Sopenharmony_cisafe_get_max_fd(void) 2237db96d56Sopenharmony_ci{ 2247db96d56Sopenharmony_ci long local_max_fd; 2257db96d56Sopenharmony_ci#if defined(__NetBSD__) 2267db96d56Sopenharmony_ci local_max_fd = fcntl(0, F_MAXFD); 2277db96d56Sopenharmony_ci if (local_max_fd >= 0) 2287db96d56Sopenharmony_ci return local_max_fd; 2297db96d56Sopenharmony_ci#endif 2307db96d56Sopenharmony_ci#if defined(HAVE_SYS_RESOURCE_H) && defined(__OpenBSD__) 2317db96d56Sopenharmony_ci struct rlimit rl; 2327db96d56Sopenharmony_ci /* Not on the POSIX async signal safe functions list but likely 2337db96d56Sopenharmony_ci * safe. TODO - Someone should audit OpenBSD to make sure. */ 2347db96d56Sopenharmony_ci if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) 2357db96d56Sopenharmony_ci return (long) rl.rlim_max; 2367db96d56Sopenharmony_ci#endif 2377db96d56Sopenharmony_ci#ifdef _SC_OPEN_MAX 2387db96d56Sopenharmony_ci local_max_fd = sysconf(_SC_OPEN_MAX); 2397db96d56Sopenharmony_ci if (local_max_fd == -1) 2407db96d56Sopenharmony_ci#endif 2417db96d56Sopenharmony_ci local_max_fd = 256; /* Matches legacy Lib/subprocess.py behavior. */ 2427db96d56Sopenharmony_ci return local_max_fd; 2437db96d56Sopenharmony_ci} 2447db96d56Sopenharmony_ci 2457db96d56Sopenharmony_ci 2467db96d56Sopenharmony_ci/* Close all file descriptors in the given range except for those in 2477db96d56Sopenharmony_ci * fds_to_keep by invoking closer on each subrange. 2487db96d56Sopenharmony_ci * 2497db96d56Sopenharmony_ci * If end_fd == -1, it's guessed via safe_get_max_fd(), but it isn't 2507db96d56Sopenharmony_ci * possible to know for sure what the max fd to go up to is for 2517db96d56Sopenharmony_ci * processes with the capability of raising their maximum, or in case 2527db96d56Sopenharmony_ci * a process opened a high fd and then lowered its maximum. 2537db96d56Sopenharmony_ci */ 2547db96d56Sopenharmony_cistatic int 2557db96d56Sopenharmony_ci_close_range_except(int start_fd, 2567db96d56Sopenharmony_ci int end_fd, 2577db96d56Sopenharmony_ci int *fds_to_keep, 2587db96d56Sopenharmony_ci Py_ssize_t fds_to_keep_len, 2597db96d56Sopenharmony_ci int (*closer)(int, int)) 2607db96d56Sopenharmony_ci{ 2617db96d56Sopenharmony_ci if (end_fd == -1) { 2627db96d56Sopenharmony_ci end_fd = Py_MIN(safe_get_max_fd(), INT_MAX); 2637db96d56Sopenharmony_ci } 2647db96d56Sopenharmony_ci Py_ssize_t keep_seq_idx; 2657db96d56Sopenharmony_ci /* As fds_to_keep is sorted we can loop through the list closing 2667db96d56Sopenharmony_ci * fds in between any in the keep list falling within our range. */ 2677db96d56Sopenharmony_ci for (keep_seq_idx = 0; keep_seq_idx < fds_to_keep_len; ++keep_seq_idx) { 2687db96d56Sopenharmony_ci int keep_fd = fds_to_keep[keep_seq_idx]; 2697db96d56Sopenharmony_ci if (keep_fd < start_fd) 2707db96d56Sopenharmony_ci continue; 2717db96d56Sopenharmony_ci if (closer(start_fd, keep_fd - 1) != 0) 2727db96d56Sopenharmony_ci return -1; 2737db96d56Sopenharmony_ci start_fd = keep_fd + 1; 2747db96d56Sopenharmony_ci } 2757db96d56Sopenharmony_ci if (start_fd <= end_fd) { 2767db96d56Sopenharmony_ci if (closer(start_fd, end_fd) != 0) 2777db96d56Sopenharmony_ci return -1; 2787db96d56Sopenharmony_ci } 2797db96d56Sopenharmony_ci return 0; 2807db96d56Sopenharmony_ci} 2817db96d56Sopenharmony_ci 2827db96d56Sopenharmony_ci#if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H) 2837db96d56Sopenharmony_ci/* It doesn't matter if d_name has room for NAME_MAX chars; we're using this 2847db96d56Sopenharmony_ci * only to read a directory of short file descriptor number names. The kernel 2857db96d56Sopenharmony_ci * will return an error if we didn't give it enough space. Highly Unlikely. 2867db96d56Sopenharmony_ci * This structure is very old and stable: It will not change unless the kernel 2877db96d56Sopenharmony_ci * chooses to break compatibility with all existing binaries. Highly Unlikely. 2887db96d56Sopenharmony_ci */ 2897db96d56Sopenharmony_cistruct linux_dirent64 { 2907db96d56Sopenharmony_ci unsigned long long d_ino; 2917db96d56Sopenharmony_ci long long d_off; 2927db96d56Sopenharmony_ci unsigned short d_reclen; /* Length of this linux_dirent */ 2937db96d56Sopenharmony_ci unsigned char d_type; 2947db96d56Sopenharmony_ci char d_name[256]; /* Filename (null-terminated) */ 2957db96d56Sopenharmony_ci}; 2967db96d56Sopenharmony_ci 2977db96d56Sopenharmony_cistatic int 2987db96d56Sopenharmony_ci_brute_force_closer(int first, int last) 2997db96d56Sopenharmony_ci{ 3007db96d56Sopenharmony_ci for (int i = first; i <= last; i++) { 3017db96d56Sopenharmony_ci /* Ignore errors */ 3027db96d56Sopenharmony_ci (void)close(i); 3037db96d56Sopenharmony_ci } 3047db96d56Sopenharmony_ci return 0; 3057db96d56Sopenharmony_ci} 3067db96d56Sopenharmony_ci 3077db96d56Sopenharmony_ci/* Close all open file descriptors in the range from start_fd and higher 3087db96d56Sopenharmony_ci * Do not close any in the sorted fds_to_keep list. 3097db96d56Sopenharmony_ci * 3107db96d56Sopenharmony_ci * This version is async signal safe as it does not make any unsafe C library 3117db96d56Sopenharmony_ci * calls, malloc calls or handle any locks. It is _unfortunate_ to be forced 3127db96d56Sopenharmony_ci * to resort to making a kernel system call directly but this is the ONLY api 3137db96d56Sopenharmony_ci * available that does no harm. opendir/readdir/closedir perform memory 3147db96d56Sopenharmony_ci * allocation and locking so while they usually work they are not guaranteed 3157db96d56Sopenharmony_ci * to (especially if you have replaced your malloc implementation). A version 3167db96d56Sopenharmony_ci * of this function that uses those can be found in the _maybe_unsafe variant. 3177db96d56Sopenharmony_ci * 3187db96d56Sopenharmony_ci * This is Linux specific because that is all I am ready to test it on. It 3197db96d56Sopenharmony_ci * should be easy to add OS specific dirent or dirent64 structures and modify 3207db96d56Sopenharmony_ci * it with some cpp #define magic to work on other OSes as well if you want. 3217db96d56Sopenharmony_ci */ 3227db96d56Sopenharmony_cistatic void 3237db96d56Sopenharmony_ci_close_open_fds_safe(int start_fd, int *fds_to_keep, Py_ssize_t fds_to_keep_len) 3247db96d56Sopenharmony_ci{ 3257db96d56Sopenharmony_ci int fd_dir_fd; 3267db96d56Sopenharmony_ci 3277db96d56Sopenharmony_ci fd_dir_fd = _Py_open_noraise(FD_DIR, O_RDONLY); 3287db96d56Sopenharmony_ci if (fd_dir_fd == -1) { 3297db96d56Sopenharmony_ci /* No way to get a list of open fds. */ 3307db96d56Sopenharmony_ci _close_range_except(start_fd, -1, 3317db96d56Sopenharmony_ci fds_to_keep, fds_to_keep_len, 3327db96d56Sopenharmony_ci _brute_force_closer); 3337db96d56Sopenharmony_ci return; 3347db96d56Sopenharmony_ci } else { 3357db96d56Sopenharmony_ci char buffer[sizeof(struct linux_dirent64)]; 3367db96d56Sopenharmony_ci int bytes; 3377db96d56Sopenharmony_ci while ((bytes = syscall(SYS_getdents64, fd_dir_fd, 3387db96d56Sopenharmony_ci (struct linux_dirent64 *)buffer, 3397db96d56Sopenharmony_ci sizeof(buffer))) > 0) { 3407db96d56Sopenharmony_ci struct linux_dirent64 *entry; 3417db96d56Sopenharmony_ci int offset; 3427db96d56Sopenharmony_ci#ifdef _Py_MEMORY_SANITIZER 3437db96d56Sopenharmony_ci __msan_unpoison(buffer, bytes); 3447db96d56Sopenharmony_ci#endif 3457db96d56Sopenharmony_ci for (offset = 0; offset < bytes; offset += entry->d_reclen) { 3467db96d56Sopenharmony_ci int fd; 3477db96d56Sopenharmony_ci entry = (struct linux_dirent64 *)(buffer + offset); 3487db96d56Sopenharmony_ci if ((fd = _pos_int_from_ascii(entry->d_name)) < 0) 3497db96d56Sopenharmony_ci continue; /* Not a number. */ 3507db96d56Sopenharmony_ci if (fd != fd_dir_fd && fd >= start_fd && 3517db96d56Sopenharmony_ci !_is_fd_in_sorted_fd_sequence(fd, fds_to_keep, 3527db96d56Sopenharmony_ci fds_to_keep_len)) { 3537db96d56Sopenharmony_ci close(fd); 3547db96d56Sopenharmony_ci } 3557db96d56Sopenharmony_ci } 3567db96d56Sopenharmony_ci } 3577db96d56Sopenharmony_ci close(fd_dir_fd); 3587db96d56Sopenharmony_ci } 3597db96d56Sopenharmony_ci} 3607db96d56Sopenharmony_ci 3617db96d56Sopenharmony_ci#define _close_open_fds_fallback _close_open_fds_safe 3627db96d56Sopenharmony_ci 3637db96d56Sopenharmony_ci#else /* NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */ 3647db96d56Sopenharmony_ci 3657db96d56Sopenharmony_cistatic int 3667db96d56Sopenharmony_ci_unsafe_closer(int first, int last) 3677db96d56Sopenharmony_ci{ 3687db96d56Sopenharmony_ci _Py_closerange(first, last); 3697db96d56Sopenharmony_ci return 0; 3707db96d56Sopenharmony_ci} 3717db96d56Sopenharmony_ci 3727db96d56Sopenharmony_ci/* Close all open file descriptors from start_fd and higher. 3737db96d56Sopenharmony_ci * Do not close any in the sorted fds_to_keep tuple. 3747db96d56Sopenharmony_ci * 3757db96d56Sopenharmony_ci * This function violates the strict use of async signal safe functions. :( 3767db96d56Sopenharmony_ci * It calls opendir(), readdir() and closedir(). Of these, the one most 3777db96d56Sopenharmony_ci * likely to ever cause a problem is opendir() as it performs an internal 3787db96d56Sopenharmony_ci * malloc(). Practically this should not be a problem. The Java VM makes the 3797db96d56Sopenharmony_ci * same calls between fork and exec in its own UNIXProcess_md.c implementation. 3807db96d56Sopenharmony_ci * 3817db96d56Sopenharmony_ci * readdir_r() is not used because it provides no benefit. It is typically 3827db96d56Sopenharmony_ci * implemented as readdir() followed by memcpy(). See also: 3837db96d56Sopenharmony_ci * http://womble.decadent.org.uk/readdir_r-advisory.html 3847db96d56Sopenharmony_ci */ 3857db96d56Sopenharmony_cistatic void 3867db96d56Sopenharmony_ci_close_open_fds_maybe_unsafe(int start_fd, int *fds_to_keep, 3877db96d56Sopenharmony_ci Py_ssize_t fds_to_keep_len) 3887db96d56Sopenharmony_ci{ 3897db96d56Sopenharmony_ci DIR *proc_fd_dir; 3907db96d56Sopenharmony_ci#ifndef HAVE_DIRFD 3917db96d56Sopenharmony_ci while (_is_fd_in_sorted_fd_sequence(start_fd, fds_to_keep, 3927db96d56Sopenharmony_ci fds_to_keep_len)) { 3937db96d56Sopenharmony_ci ++start_fd; 3947db96d56Sopenharmony_ci } 3957db96d56Sopenharmony_ci /* Close our lowest fd before we call opendir so that it is likely to 3967db96d56Sopenharmony_ci * reuse that fd otherwise we might close opendir's file descriptor in 3977db96d56Sopenharmony_ci * our loop. This trick assumes that fd's are allocated on a lowest 3987db96d56Sopenharmony_ci * available basis. */ 3997db96d56Sopenharmony_ci close(start_fd); 4007db96d56Sopenharmony_ci ++start_fd; 4017db96d56Sopenharmony_ci#endif 4027db96d56Sopenharmony_ci 4037db96d56Sopenharmony_ci#if defined(__FreeBSD__) || defined(__DragonFly__) 4047db96d56Sopenharmony_ci if (!_is_fdescfs_mounted_on_dev_fd()) 4057db96d56Sopenharmony_ci proc_fd_dir = NULL; 4067db96d56Sopenharmony_ci else 4077db96d56Sopenharmony_ci#endif 4087db96d56Sopenharmony_ci proc_fd_dir = opendir(FD_DIR); 4097db96d56Sopenharmony_ci if (!proc_fd_dir) { 4107db96d56Sopenharmony_ci /* No way to get a list of open fds. */ 4117db96d56Sopenharmony_ci _close_range_except(start_fd, -1, fds_to_keep, fds_to_keep_len, 4127db96d56Sopenharmony_ci _unsafe_closer); 4137db96d56Sopenharmony_ci } else { 4147db96d56Sopenharmony_ci struct dirent *dir_entry; 4157db96d56Sopenharmony_ci#ifdef HAVE_DIRFD 4167db96d56Sopenharmony_ci int fd_used_by_opendir = dirfd(proc_fd_dir); 4177db96d56Sopenharmony_ci#else 4187db96d56Sopenharmony_ci int fd_used_by_opendir = start_fd - 1; 4197db96d56Sopenharmony_ci#endif 4207db96d56Sopenharmony_ci errno = 0; 4217db96d56Sopenharmony_ci while ((dir_entry = readdir(proc_fd_dir))) { 4227db96d56Sopenharmony_ci int fd; 4237db96d56Sopenharmony_ci if ((fd = _pos_int_from_ascii(dir_entry->d_name)) < 0) 4247db96d56Sopenharmony_ci continue; /* Not a number. */ 4257db96d56Sopenharmony_ci if (fd != fd_used_by_opendir && fd >= start_fd && 4267db96d56Sopenharmony_ci !_is_fd_in_sorted_fd_sequence(fd, fds_to_keep, 4277db96d56Sopenharmony_ci fds_to_keep_len)) { 4287db96d56Sopenharmony_ci close(fd); 4297db96d56Sopenharmony_ci } 4307db96d56Sopenharmony_ci errno = 0; 4317db96d56Sopenharmony_ci } 4327db96d56Sopenharmony_ci if (errno) { 4337db96d56Sopenharmony_ci /* readdir error, revert behavior. Highly Unlikely. */ 4347db96d56Sopenharmony_ci _close_range_except(start_fd, -1, fds_to_keep, fds_to_keep_len, 4357db96d56Sopenharmony_ci _unsafe_closer); 4367db96d56Sopenharmony_ci } 4377db96d56Sopenharmony_ci closedir(proc_fd_dir); 4387db96d56Sopenharmony_ci } 4397db96d56Sopenharmony_ci} 4407db96d56Sopenharmony_ci 4417db96d56Sopenharmony_ci#define _close_open_fds_fallback _close_open_fds_maybe_unsafe 4427db96d56Sopenharmony_ci 4437db96d56Sopenharmony_ci#endif /* else NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */ 4447db96d56Sopenharmony_ci 4457db96d56Sopenharmony_ci/* We can use close_range() library function only if it's known to be 4467db96d56Sopenharmony_ci * async-signal-safe. 4477db96d56Sopenharmony_ci * 4487db96d56Sopenharmony_ci * On Linux, glibc explicitly documents it to be a thin wrapper over 4497db96d56Sopenharmony_ci * the system call, and other C libraries are likely to follow glibc. 4507db96d56Sopenharmony_ci */ 4517db96d56Sopenharmony_ci#if defined(HAVE_CLOSE_RANGE) && \ 4527db96d56Sopenharmony_ci (defined(__linux__) || defined(__FreeBSD__)) 4537db96d56Sopenharmony_ci#define HAVE_ASYNC_SAFE_CLOSE_RANGE 4547db96d56Sopenharmony_ci 4557db96d56Sopenharmony_cistatic int 4567db96d56Sopenharmony_ci_close_range_closer(int first, int last) 4577db96d56Sopenharmony_ci{ 4587db96d56Sopenharmony_ci return close_range(first, last, 0); 4597db96d56Sopenharmony_ci} 4607db96d56Sopenharmony_ci#endif 4617db96d56Sopenharmony_ci 4627db96d56Sopenharmony_cistatic void 4637db96d56Sopenharmony_ci_close_open_fds(int start_fd, int *fds_to_keep, Py_ssize_t fds_to_keep_len) 4647db96d56Sopenharmony_ci{ 4657db96d56Sopenharmony_ci#ifdef HAVE_ASYNC_SAFE_CLOSE_RANGE 4667db96d56Sopenharmony_ci if (_close_range_except( 4677db96d56Sopenharmony_ci start_fd, INT_MAX, fds_to_keep, fds_to_keep_len, 4687db96d56Sopenharmony_ci _close_range_closer) == 0) { 4697db96d56Sopenharmony_ci return; 4707db96d56Sopenharmony_ci } 4717db96d56Sopenharmony_ci#endif 4727db96d56Sopenharmony_ci _close_open_fds_fallback(start_fd, fds_to_keep, fds_to_keep_len); 4737db96d56Sopenharmony_ci} 4747db96d56Sopenharmony_ci 4757db96d56Sopenharmony_ci#ifdef VFORK_USABLE 4767db96d56Sopenharmony_ci/* Reset dispositions for all signals to SIG_DFL except for ignored 4777db96d56Sopenharmony_ci * signals. This way we ensure that no signal handlers can run 4787db96d56Sopenharmony_ci * after we unblock signals in a child created by vfork(). 4797db96d56Sopenharmony_ci */ 4807db96d56Sopenharmony_cistatic void 4817db96d56Sopenharmony_cireset_signal_handlers(const sigset_t *child_sigmask) 4827db96d56Sopenharmony_ci{ 4837db96d56Sopenharmony_ci struct sigaction sa_dfl = {.sa_handler = SIG_DFL}; 4847db96d56Sopenharmony_ci for (int sig = 1; sig < _NSIG; sig++) { 4857db96d56Sopenharmony_ci /* Dispositions for SIGKILL and SIGSTOP can't be changed. */ 4867db96d56Sopenharmony_ci if (sig == SIGKILL || sig == SIGSTOP) { 4877db96d56Sopenharmony_ci continue; 4887db96d56Sopenharmony_ci } 4897db96d56Sopenharmony_ci 4907db96d56Sopenharmony_ci /* There is no need to reset the disposition of signals that will 4917db96d56Sopenharmony_ci * remain blocked across execve() since the kernel will do it. */ 4927db96d56Sopenharmony_ci if (sigismember(child_sigmask, sig) == 1) { 4937db96d56Sopenharmony_ci continue; 4947db96d56Sopenharmony_ci } 4957db96d56Sopenharmony_ci 4967db96d56Sopenharmony_ci struct sigaction sa; 4977db96d56Sopenharmony_ci /* C libraries usually return EINVAL for signals used 4987db96d56Sopenharmony_ci * internally (e.g. for thread cancellation), so simply 4997db96d56Sopenharmony_ci * skip errors here. */ 5007db96d56Sopenharmony_ci if (sigaction(sig, NULL, &sa) == -1) { 5017db96d56Sopenharmony_ci continue; 5027db96d56Sopenharmony_ci } 5037db96d56Sopenharmony_ci 5047db96d56Sopenharmony_ci /* void *h works as these fields are both pointer types already. */ 5057db96d56Sopenharmony_ci void *h = (sa.sa_flags & SA_SIGINFO ? (void *)sa.sa_sigaction : 5067db96d56Sopenharmony_ci (void *)sa.sa_handler); 5077db96d56Sopenharmony_ci if (h == SIG_IGN || h == SIG_DFL) { 5087db96d56Sopenharmony_ci continue; 5097db96d56Sopenharmony_ci } 5107db96d56Sopenharmony_ci 5117db96d56Sopenharmony_ci /* This call can't reasonably fail, but if it does, terminating 5127db96d56Sopenharmony_ci * the child seems to be too harsh, so ignore errors. */ 5137db96d56Sopenharmony_ci (void) sigaction(sig, &sa_dfl, NULL); 5147db96d56Sopenharmony_ci } 5157db96d56Sopenharmony_ci} 5167db96d56Sopenharmony_ci#endif /* VFORK_USABLE */ 5177db96d56Sopenharmony_ci 5187db96d56Sopenharmony_ci 5197db96d56Sopenharmony_ci/* 5207db96d56Sopenharmony_ci * This function is code executed in the child process immediately after 5217db96d56Sopenharmony_ci * (v)fork to set things up and call exec(). 5227db96d56Sopenharmony_ci * 5237db96d56Sopenharmony_ci * All of the code in this function must only use async-signal-safe functions, 5247db96d56Sopenharmony_ci * listed at `man 7 signal` or 5257db96d56Sopenharmony_ci * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html. 5267db96d56Sopenharmony_ci * 5277db96d56Sopenharmony_ci * This restriction is documented at 5287db96d56Sopenharmony_ci * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html. 5297db96d56Sopenharmony_ci * 5307db96d56Sopenharmony_ci * If this function is called after vfork(), even more care must be taken. 5317db96d56Sopenharmony_ci * The lack of preparations that C libraries normally take on fork(), 5327db96d56Sopenharmony_ci * as well as sharing the address space with the parent, might make even 5337db96d56Sopenharmony_ci * async-signal-safe functions vfork-unsafe. In particular, on Linux, 5347db96d56Sopenharmony_ci * set*id() and setgroups() library functions must not be called, since 5357db96d56Sopenharmony_ci * they have to interact with the library-level thread list and send 5367db96d56Sopenharmony_ci * library-internal signals to implement per-process credentials semantics 5377db96d56Sopenharmony_ci * required by POSIX but not supported natively on Linux. Another reason to 5387db96d56Sopenharmony_ci * avoid this family of functions is that sharing an address space between 5397db96d56Sopenharmony_ci * processes running with different privileges is inherently insecure. 5407db96d56Sopenharmony_ci * See bpo-35823 for further discussion and references. 5417db96d56Sopenharmony_ci * 5427db96d56Sopenharmony_ci * In some C libraries, setrlimit() has the same thread list/signalling 5437db96d56Sopenharmony_ci * behavior since resource limits were per-thread attributes before 5447db96d56Sopenharmony_ci * Linux 2.6.10. Musl, as of 1.2.1, is known to have this issue 5457db96d56Sopenharmony_ci * (https://www.openwall.com/lists/musl/2020/10/15/6). 5467db96d56Sopenharmony_ci * 5477db96d56Sopenharmony_ci * If vfork-unsafe functionality is desired after vfork(), consider using 5487db96d56Sopenharmony_ci * syscall() to obtain it. 5497db96d56Sopenharmony_ci */ 5507db96d56Sopenharmony_ciPy_NO_INLINE static void 5517db96d56Sopenharmony_cichild_exec(char *const exec_array[], 5527db96d56Sopenharmony_ci char *const argv[], 5537db96d56Sopenharmony_ci char *const envp[], 5547db96d56Sopenharmony_ci const char *cwd, 5557db96d56Sopenharmony_ci int p2cread, int p2cwrite, 5567db96d56Sopenharmony_ci int c2pread, int c2pwrite, 5577db96d56Sopenharmony_ci int errread, int errwrite, 5587db96d56Sopenharmony_ci int errpipe_read, int errpipe_write, 5597db96d56Sopenharmony_ci int close_fds, int restore_signals, 5607db96d56Sopenharmony_ci int call_setsid, pid_t pgid_to_set, 5617db96d56Sopenharmony_ci int call_setgid, gid_t gid, 5627db96d56Sopenharmony_ci int call_setgroups, size_t groups_size, const gid_t *groups, 5637db96d56Sopenharmony_ci int call_setuid, uid_t uid, int child_umask, 5647db96d56Sopenharmony_ci const void *child_sigmask, 5657db96d56Sopenharmony_ci int *fds_to_keep, Py_ssize_t fds_to_keep_len, 5667db96d56Sopenharmony_ci PyObject *preexec_fn, 5677db96d56Sopenharmony_ci PyObject *preexec_fn_args_tuple) 5687db96d56Sopenharmony_ci{ 5697db96d56Sopenharmony_ci int i, saved_errno, reached_preexec = 0; 5707db96d56Sopenharmony_ci PyObject *result; 5717db96d56Sopenharmony_ci const char* err_msg = ""; 5727db96d56Sopenharmony_ci /* Buffer large enough to hold a hex integer. We can't malloc. */ 5737db96d56Sopenharmony_ci char hex_errno[sizeof(saved_errno)*2+1]; 5747db96d56Sopenharmony_ci 5757db96d56Sopenharmony_ci if (make_inheritable(fds_to_keep, fds_to_keep_len, errpipe_write) < 0) 5767db96d56Sopenharmony_ci goto error; 5777db96d56Sopenharmony_ci 5787db96d56Sopenharmony_ci /* Close parent's pipe ends. */ 5797db96d56Sopenharmony_ci if (p2cwrite != -1) 5807db96d56Sopenharmony_ci POSIX_CALL(close(p2cwrite)); 5817db96d56Sopenharmony_ci if (c2pread != -1) 5827db96d56Sopenharmony_ci POSIX_CALL(close(c2pread)); 5837db96d56Sopenharmony_ci if (errread != -1) 5847db96d56Sopenharmony_ci POSIX_CALL(close(errread)); 5857db96d56Sopenharmony_ci POSIX_CALL(close(errpipe_read)); 5867db96d56Sopenharmony_ci 5877db96d56Sopenharmony_ci /* When duping fds, if there arises a situation where one of the fds is 5887db96d56Sopenharmony_ci either 0, 1 or 2, it is possible that it is overwritten (#12607). */ 5897db96d56Sopenharmony_ci if (c2pwrite == 0) { 5907db96d56Sopenharmony_ci POSIX_CALL(c2pwrite = dup(c2pwrite)); 5917db96d56Sopenharmony_ci /* issue32270 */ 5927db96d56Sopenharmony_ci if (_Py_set_inheritable_async_safe(c2pwrite, 0, NULL) < 0) { 5937db96d56Sopenharmony_ci goto error; 5947db96d56Sopenharmony_ci } 5957db96d56Sopenharmony_ci } 5967db96d56Sopenharmony_ci while (errwrite == 0 || errwrite == 1) { 5977db96d56Sopenharmony_ci POSIX_CALL(errwrite = dup(errwrite)); 5987db96d56Sopenharmony_ci /* issue32270 */ 5997db96d56Sopenharmony_ci if (_Py_set_inheritable_async_safe(errwrite, 0, NULL) < 0) { 6007db96d56Sopenharmony_ci goto error; 6017db96d56Sopenharmony_ci } 6027db96d56Sopenharmony_ci } 6037db96d56Sopenharmony_ci 6047db96d56Sopenharmony_ci /* Dup fds for child. 6057db96d56Sopenharmony_ci dup2() removes the CLOEXEC flag but we must do it ourselves if dup2() 6067db96d56Sopenharmony_ci would be a no-op (issue #10806). */ 6077db96d56Sopenharmony_ci if (p2cread == 0) { 6087db96d56Sopenharmony_ci if (_Py_set_inheritable_async_safe(p2cread, 1, NULL) < 0) 6097db96d56Sopenharmony_ci goto error; 6107db96d56Sopenharmony_ci } 6117db96d56Sopenharmony_ci else if (p2cread != -1) 6127db96d56Sopenharmony_ci POSIX_CALL(dup2(p2cread, 0)); /* stdin */ 6137db96d56Sopenharmony_ci 6147db96d56Sopenharmony_ci if (c2pwrite == 1) { 6157db96d56Sopenharmony_ci if (_Py_set_inheritable_async_safe(c2pwrite, 1, NULL) < 0) 6167db96d56Sopenharmony_ci goto error; 6177db96d56Sopenharmony_ci } 6187db96d56Sopenharmony_ci else if (c2pwrite != -1) 6197db96d56Sopenharmony_ci POSIX_CALL(dup2(c2pwrite, 1)); /* stdout */ 6207db96d56Sopenharmony_ci 6217db96d56Sopenharmony_ci if (errwrite == 2) { 6227db96d56Sopenharmony_ci if (_Py_set_inheritable_async_safe(errwrite, 1, NULL) < 0) 6237db96d56Sopenharmony_ci goto error; 6247db96d56Sopenharmony_ci } 6257db96d56Sopenharmony_ci else if (errwrite != -1) 6267db96d56Sopenharmony_ci POSIX_CALL(dup2(errwrite, 2)); /* stderr */ 6277db96d56Sopenharmony_ci 6287db96d56Sopenharmony_ci /* We no longer manually close p2cread, c2pwrite, and errwrite here as 6297db96d56Sopenharmony_ci * _close_open_fds takes care when it is not already non-inheritable. */ 6307db96d56Sopenharmony_ci 6317db96d56Sopenharmony_ci if (cwd) 6327db96d56Sopenharmony_ci POSIX_CALL(chdir(cwd)); 6337db96d56Sopenharmony_ci 6347db96d56Sopenharmony_ci if (child_umask >= 0) 6357db96d56Sopenharmony_ci umask(child_umask); /* umask() always succeeds. */ 6367db96d56Sopenharmony_ci 6377db96d56Sopenharmony_ci if (restore_signals) 6387db96d56Sopenharmony_ci _Py_RestoreSignals(); 6397db96d56Sopenharmony_ci 6407db96d56Sopenharmony_ci#ifdef VFORK_USABLE 6417db96d56Sopenharmony_ci if (child_sigmask) { 6427db96d56Sopenharmony_ci reset_signal_handlers(child_sigmask); 6437db96d56Sopenharmony_ci if ((errno = pthread_sigmask(SIG_SETMASK, child_sigmask, NULL))) { 6447db96d56Sopenharmony_ci goto error; 6457db96d56Sopenharmony_ci } 6467db96d56Sopenharmony_ci } 6477db96d56Sopenharmony_ci#endif 6487db96d56Sopenharmony_ci 6497db96d56Sopenharmony_ci#ifdef HAVE_SETSID 6507db96d56Sopenharmony_ci if (call_setsid) 6517db96d56Sopenharmony_ci POSIX_CALL(setsid()); 6527db96d56Sopenharmony_ci#endif 6537db96d56Sopenharmony_ci 6547db96d56Sopenharmony_ci#ifdef HAVE_SETPGID 6557db96d56Sopenharmony_ci if (pgid_to_set >= 0) 6567db96d56Sopenharmony_ci POSIX_CALL(setpgid(0, pgid_to_set)); 6577db96d56Sopenharmony_ci#endif 6587db96d56Sopenharmony_ci 6597db96d56Sopenharmony_ci#ifdef HAVE_SETGROUPS 6607db96d56Sopenharmony_ci if (call_setgroups) 6617db96d56Sopenharmony_ci POSIX_CALL(setgroups(groups_size, groups)); 6627db96d56Sopenharmony_ci#endif /* HAVE_SETGROUPS */ 6637db96d56Sopenharmony_ci 6647db96d56Sopenharmony_ci#ifdef HAVE_SETREGID 6657db96d56Sopenharmony_ci if (call_setgid) 6667db96d56Sopenharmony_ci POSIX_CALL(setregid(gid, gid)); 6677db96d56Sopenharmony_ci#endif /* HAVE_SETREGID */ 6687db96d56Sopenharmony_ci 6697db96d56Sopenharmony_ci#ifdef HAVE_SETREUID 6707db96d56Sopenharmony_ci if (call_setuid) 6717db96d56Sopenharmony_ci POSIX_CALL(setreuid(uid, uid)); 6727db96d56Sopenharmony_ci#endif /* HAVE_SETREUID */ 6737db96d56Sopenharmony_ci 6747db96d56Sopenharmony_ci 6757db96d56Sopenharmony_ci reached_preexec = 1; 6767db96d56Sopenharmony_ci if (preexec_fn != Py_None && preexec_fn_args_tuple) { 6777db96d56Sopenharmony_ci /* This is where the user has asked us to deadlock their program. */ 6787db96d56Sopenharmony_ci result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL); 6797db96d56Sopenharmony_ci if (result == NULL) { 6807db96d56Sopenharmony_ci /* Stringifying the exception or traceback would involve 6817db96d56Sopenharmony_ci * memory allocation and thus potential for deadlock. 6827db96d56Sopenharmony_ci * We've already faced potential deadlock by calling back 6837db96d56Sopenharmony_ci * into Python in the first place, so it probably doesn't 6847db96d56Sopenharmony_ci * matter but we avoid it to minimize the possibility. */ 6857db96d56Sopenharmony_ci err_msg = "Exception occurred in preexec_fn."; 6867db96d56Sopenharmony_ci errno = 0; /* We don't want to report an OSError. */ 6877db96d56Sopenharmony_ci goto error; 6887db96d56Sopenharmony_ci } 6897db96d56Sopenharmony_ci /* Py_DECREF(result); - We're about to exec so why bother? */ 6907db96d56Sopenharmony_ci } 6917db96d56Sopenharmony_ci 6927db96d56Sopenharmony_ci /* close FDs after executing preexec_fn, which might open FDs */ 6937db96d56Sopenharmony_ci if (close_fds) { 6947db96d56Sopenharmony_ci /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */ 6957db96d56Sopenharmony_ci _close_open_fds(3, fds_to_keep, fds_to_keep_len); 6967db96d56Sopenharmony_ci } 6977db96d56Sopenharmony_ci 6987db96d56Sopenharmony_ci /* This loop matches the Lib/os.py _execvpe()'s PATH search when */ 6997db96d56Sopenharmony_ci /* given the executable_list generated by Lib/subprocess.py. */ 7007db96d56Sopenharmony_ci saved_errno = 0; 7017db96d56Sopenharmony_ci for (i = 0; exec_array[i] != NULL; ++i) { 7027db96d56Sopenharmony_ci const char *executable = exec_array[i]; 7037db96d56Sopenharmony_ci if (envp) { 7047db96d56Sopenharmony_ci execve(executable, argv, envp); 7057db96d56Sopenharmony_ci } else { 7067db96d56Sopenharmony_ci execv(executable, argv); 7077db96d56Sopenharmony_ci } 7087db96d56Sopenharmony_ci if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) { 7097db96d56Sopenharmony_ci saved_errno = errno; 7107db96d56Sopenharmony_ci } 7117db96d56Sopenharmony_ci } 7127db96d56Sopenharmony_ci /* Report the first exec error, not the last. */ 7137db96d56Sopenharmony_ci if (saved_errno) 7147db96d56Sopenharmony_ci errno = saved_errno; 7157db96d56Sopenharmony_ci 7167db96d56Sopenharmony_cierror: 7177db96d56Sopenharmony_ci saved_errno = errno; 7187db96d56Sopenharmony_ci /* Report the posix error to our parent process. */ 7197db96d56Sopenharmony_ci /* We ignore all write() return values as the total size of our writes is 7207db96d56Sopenharmony_ci less than PIPEBUF and we cannot do anything about an error anyways. 7217db96d56Sopenharmony_ci Use _Py_write_noraise() to retry write() if it is interrupted by a 7227db96d56Sopenharmony_ci signal (fails with EINTR). */ 7237db96d56Sopenharmony_ci if (saved_errno) { 7247db96d56Sopenharmony_ci char *cur; 7257db96d56Sopenharmony_ci _Py_write_noraise(errpipe_write, "OSError:", 8); 7267db96d56Sopenharmony_ci cur = hex_errno + sizeof(hex_errno); 7277db96d56Sopenharmony_ci while (saved_errno != 0 && cur != hex_errno) { 7287db96d56Sopenharmony_ci *--cur = Py_hexdigits[saved_errno % 16]; 7297db96d56Sopenharmony_ci saved_errno /= 16; 7307db96d56Sopenharmony_ci } 7317db96d56Sopenharmony_ci _Py_write_noraise(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur); 7327db96d56Sopenharmony_ci _Py_write_noraise(errpipe_write, ":", 1); 7337db96d56Sopenharmony_ci if (!reached_preexec) { 7347db96d56Sopenharmony_ci /* Indicate to the parent that the error happened before exec(). */ 7357db96d56Sopenharmony_ci _Py_write_noraise(errpipe_write, "noexec", 6); 7367db96d56Sopenharmony_ci } 7377db96d56Sopenharmony_ci /* We can't call strerror(saved_errno). It is not async signal safe. 7387db96d56Sopenharmony_ci * The parent process will look the error message up. */ 7397db96d56Sopenharmony_ci } else { 7407db96d56Sopenharmony_ci _Py_write_noraise(errpipe_write, "SubprocessError:0:", 18); 7417db96d56Sopenharmony_ci _Py_write_noraise(errpipe_write, err_msg, strlen(err_msg)); 7427db96d56Sopenharmony_ci } 7437db96d56Sopenharmony_ci} 7447db96d56Sopenharmony_ci 7457db96d56Sopenharmony_ci 7467db96d56Sopenharmony_ci/* The main purpose of this wrapper function is to isolate vfork() from both 7477db96d56Sopenharmony_ci * subprocess_fork_exec() and child_exec(). A child process created via 7487db96d56Sopenharmony_ci * vfork() executes on the same stack as the parent process while the latter is 7497db96d56Sopenharmony_ci * suspended, so this function should not be inlined to avoid compiler bugs 7507db96d56Sopenharmony_ci * that might clobber data needed by the parent later. Additionally, 7517db96d56Sopenharmony_ci * child_exec() should not be inlined to avoid spurious -Wclobber warnings from 7527db96d56Sopenharmony_ci * GCC (see bpo-35823). 7537db96d56Sopenharmony_ci */ 7547db96d56Sopenharmony_ciPy_NO_INLINE static pid_t 7557db96d56Sopenharmony_cido_fork_exec(char *const exec_array[], 7567db96d56Sopenharmony_ci char *const argv[], 7577db96d56Sopenharmony_ci char *const envp[], 7587db96d56Sopenharmony_ci const char *cwd, 7597db96d56Sopenharmony_ci int p2cread, int p2cwrite, 7607db96d56Sopenharmony_ci int c2pread, int c2pwrite, 7617db96d56Sopenharmony_ci int errread, int errwrite, 7627db96d56Sopenharmony_ci int errpipe_read, int errpipe_write, 7637db96d56Sopenharmony_ci int close_fds, int restore_signals, 7647db96d56Sopenharmony_ci int call_setsid, pid_t pgid_to_set, 7657db96d56Sopenharmony_ci int call_setgid, gid_t gid, 7667db96d56Sopenharmony_ci int call_setgroups, size_t groups_size, const gid_t *groups, 7677db96d56Sopenharmony_ci int call_setuid, uid_t uid, int child_umask, 7687db96d56Sopenharmony_ci const void *child_sigmask, 7697db96d56Sopenharmony_ci int *fds_to_keep, Py_ssize_t fds_to_keep_len, 7707db96d56Sopenharmony_ci PyObject *preexec_fn, 7717db96d56Sopenharmony_ci PyObject *preexec_fn_args_tuple) 7727db96d56Sopenharmony_ci{ 7737db96d56Sopenharmony_ci 7747db96d56Sopenharmony_ci pid_t pid; 7757db96d56Sopenharmony_ci 7767db96d56Sopenharmony_ci#ifdef VFORK_USABLE 7777db96d56Sopenharmony_ci if (child_sigmask) { 7787db96d56Sopenharmony_ci /* These are checked by our caller; verify them in debug builds. */ 7797db96d56Sopenharmony_ci assert(!call_setuid); 7807db96d56Sopenharmony_ci assert(!call_setgid); 7817db96d56Sopenharmony_ci assert(!call_setgroups); 7827db96d56Sopenharmony_ci assert(preexec_fn == Py_None); 7837db96d56Sopenharmony_ci 7847db96d56Sopenharmony_ci pid = vfork(); 7857db96d56Sopenharmony_ci if (pid == -1) { 7867db96d56Sopenharmony_ci /* If vfork() fails, fall back to using fork(). When it isn't 7877db96d56Sopenharmony_ci * allowed in a process by the kernel, vfork can return -1 7887db96d56Sopenharmony_ci * with errno EINVAL. https://bugs.python.org/issue47151. */ 7897db96d56Sopenharmony_ci pid = fork(); 7907db96d56Sopenharmony_ci } 7917db96d56Sopenharmony_ci } else 7927db96d56Sopenharmony_ci#endif 7937db96d56Sopenharmony_ci { 7947db96d56Sopenharmony_ci pid = fork(); 7957db96d56Sopenharmony_ci } 7967db96d56Sopenharmony_ci 7977db96d56Sopenharmony_ci if (pid != 0) { 7987db96d56Sopenharmony_ci return pid; 7997db96d56Sopenharmony_ci } 8007db96d56Sopenharmony_ci 8017db96d56Sopenharmony_ci /* Child process. 8027db96d56Sopenharmony_ci * See the comment above child_exec() for restrictions imposed on 8037db96d56Sopenharmony_ci * the code below. 8047db96d56Sopenharmony_ci */ 8057db96d56Sopenharmony_ci 8067db96d56Sopenharmony_ci if (preexec_fn != Py_None) { 8077db96d56Sopenharmony_ci /* We'll be calling back into Python later so we need to do this. 8087db96d56Sopenharmony_ci * This call may not be async-signal-safe but neither is calling 8097db96d56Sopenharmony_ci * back into Python. The user asked us to use hope as a strategy 8107db96d56Sopenharmony_ci * to avoid deadlock... */ 8117db96d56Sopenharmony_ci PyOS_AfterFork_Child(); 8127db96d56Sopenharmony_ci } 8137db96d56Sopenharmony_ci 8147db96d56Sopenharmony_ci child_exec(exec_array, argv, envp, cwd, 8157db96d56Sopenharmony_ci p2cread, p2cwrite, c2pread, c2pwrite, 8167db96d56Sopenharmony_ci errread, errwrite, errpipe_read, errpipe_write, 8177db96d56Sopenharmony_ci close_fds, restore_signals, call_setsid, pgid_to_set, 8187db96d56Sopenharmony_ci call_setgid, gid, call_setgroups, groups_size, groups, 8197db96d56Sopenharmony_ci call_setuid, uid, child_umask, child_sigmask, 8207db96d56Sopenharmony_ci fds_to_keep, fds_to_keep_len, 8217db96d56Sopenharmony_ci preexec_fn, preexec_fn_args_tuple); 8227db96d56Sopenharmony_ci _exit(255); 8237db96d56Sopenharmony_ci return 0; /* Dead code to avoid a potential compiler warning. */ 8247db96d56Sopenharmony_ci} 8257db96d56Sopenharmony_ci 8267db96d56Sopenharmony_ci 8277db96d56Sopenharmony_cistatic PyObject * 8287db96d56Sopenharmony_cisubprocess_fork_exec(PyObject *module, PyObject *args) 8297db96d56Sopenharmony_ci{ 8307db96d56Sopenharmony_ci PyObject *gc_module = NULL; 8317db96d56Sopenharmony_ci PyObject *executable_list, *py_fds_to_keep; 8327db96d56Sopenharmony_ci PyObject *env_list, *preexec_fn; 8337db96d56Sopenharmony_ci PyObject *process_args, *converted_args = NULL, *fast_args = NULL; 8347db96d56Sopenharmony_ci PyObject *preexec_fn_args_tuple = NULL; 8357db96d56Sopenharmony_ci PyObject *groups_list; 8367db96d56Sopenharmony_ci PyObject *uid_object, *gid_object; 8377db96d56Sopenharmony_ci int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite; 8387db96d56Sopenharmony_ci int errpipe_read, errpipe_write, close_fds, restore_signals; 8397db96d56Sopenharmony_ci int call_setsid; 8407db96d56Sopenharmony_ci pid_t pgid_to_set = -1; 8417db96d56Sopenharmony_ci int call_setgid = 0, call_setgroups = 0, call_setuid = 0; 8427db96d56Sopenharmony_ci uid_t uid; 8437db96d56Sopenharmony_ci gid_t gid, *groups = NULL; 8447db96d56Sopenharmony_ci int child_umask; 8457db96d56Sopenharmony_ci PyObject *cwd_obj, *cwd_obj2 = NULL; 8467db96d56Sopenharmony_ci const char *cwd; 8477db96d56Sopenharmony_ci pid_t pid = -1; 8487db96d56Sopenharmony_ci int need_to_reenable_gc = 0; 8497db96d56Sopenharmony_ci char *const *exec_array, *const *argv = NULL, *const *envp = NULL; 8507db96d56Sopenharmony_ci Py_ssize_t arg_num, num_groups = 0; 8517db96d56Sopenharmony_ci int need_after_fork = 0; 8527db96d56Sopenharmony_ci int saved_errno = 0; 8537db96d56Sopenharmony_ci int allow_vfork; 8547db96d56Sopenharmony_ci int *c_fds_to_keep = NULL; 8557db96d56Sopenharmony_ci 8567db96d56Sopenharmony_ci if (!PyArg_ParseTuple( 8577db96d56Sopenharmony_ci args, "OOpO!OOiiiiiiiiii" _Py_PARSE_PID "OOOiOp:fork_exec", 8587db96d56Sopenharmony_ci &process_args, &executable_list, 8597db96d56Sopenharmony_ci &close_fds, &PyTuple_Type, &py_fds_to_keep, 8607db96d56Sopenharmony_ci &cwd_obj, &env_list, 8617db96d56Sopenharmony_ci &p2cread, &p2cwrite, &c2pread, &c2pwrite, 8627db96d56Sopenharmony_ci &errread, &errwrite, &errpipe_read, &errpipe_write, 8637db96d56Sopenharmony_ci &restore_signals, &call_setsid, &pgid_to_set, 8647db96d56Sopenharmony_ci &gid_object, &groups_list, &uid_object, &child_umask, 8657db96d56Sopenharmony_ci &preexec_fn, &allow_vfork)) 8667db96d56Sopenharmony_ci return NULL; 8677db96d56Sopenharmony_ci 8687db96d56Sopenharmony_ci if ((preexec_fn != Py_None) && 8697db96d56Sopenharmony_ci (PyInterpreterState_Get() != PyInterpreterState_Main())) { 8707db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 8717db96d56Sopenharmony_ci "preexec_fn not supported within subinterpreters"); 8727db96d56Sopenharmony_ci return NULL; 8737db96d56Sopenharmony_ci } 8747db96d56Sopenharmony_ci 8757db96d56Sopenharmony_ci if (close_fds && errpipe_write < 3) { /* precondition */ 8767db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3"); 8777db96d56Sopenharmony_ci return NULL; 8787db96d56Sopenharmony_ci } 8797db96d56Sopenharmony_ci if (_sanity_check_python_fd_sequence(py_fds_to_keep)) { 8807db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "bad value(s) in fds_to_keep"); 8817db96d56Sopenharmony_ci return NULL; 8827db96d56Sopenharmony_ci } 8837db96d56Sopenharmony_ci 8847db96d56Sopenharmony_ci PyInterpreterState *interp = PyInterpreterState_Get(); 8857db96d56Sopenharmony_ci const PyConfig *config = _PyInterpreterState_GetConfig(interp); 8867db96d56Sopenharmony_ci if (config->_isolated_interpreter) { 8877db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, 8887db96d56Sopenharmony_ci "subprocess not supported for isolated subinterpreters"); 8897db96d56Sopenharmony_ci return NULL; 8907db96d56Sopenharmony_ci } 8917db96d56Sopenharmony_ci 8927db96d56Sopenharmony_ci /* We need to call gc.disable() when we'll be calling preexec_fn */ 8937db96d56Sopenharmony_ci if (preexec_fn != Py_None) { 8947db96d56Sopenharmony_ci need_to_reenable_gc = PyGC_Disable(); 8957db96d56Sopenharmony_ci } 8967db96d56Sopenharmony_ci 8977db96d56Sopenharmony_ci exec_array = _PySequence_BytesToCharpArray(executable_list); 8987db96d56Sopenharmony_ci if (!exec_array) 8997db96d56Sopenharmony_ci goto cleanup; 9007db96d56Sopenharmony_ci 9017db96d56Sopenharmony_ci /* Convert args and env into appropriate arguments for exec() */ 9027db96d56Sopenharmony_ci /* These conversions are done in the parent process to avoid allocating 9037db96d56Sopenharmony_ci or freeing memory in the child process. */ 9047db96d56Sopenharmony_ci if (process_args != Py_None) { 9057db96d56Sopenharmony_ci Py_ssize_t num_args; 9067db96d56Sopenharmony_ci /* Equivalent to: */ 9077db96d56Sopenharmony_ci /* tuple(PyUnicode_FSConverter(arg) for arg in process_args) */ 9087db96d56Sopenharmony_ci fast_args = PySequence_Fast(process_args, "argv must be a tuple"); 9097db96d56Sopenharmony_ci if (fast_args == NULL) 9107db96d56Sopenharmony_ci goto cleanup; 9117db96d56Sopenharmony_ci num_args = PySequence_Fast_GET_SIZE(fast_args); 9127db96d56Sopenharmony_ci converted_args = PyTuple_New(num_args); 9137db96d56Sopenharmony_ci if (converted_args == NULL) 9147db96d56Sopenharmony_ci goto cleanup; 9157db96d56Sopenharmony_ci for (arg_num = 0; arg_num < num_args; ++arg_num) { 9167db96d56Sopenharmony_ci PyObject *borrowed_arg, *converted_arg; 9177db96d56Sopenharmony_ci if (PySequence_Fast_GET_SIZE(fast_args) != num_args) { 9187db96d56Sopenharmony_ci PyErr_SetString(PyExc_RuntimeError, "args changed during iteration"); 9197db96d56Sopenharmony_ci goto cleanup; 9207db96d56Sopenharmony_ci } 9217db96d56Sopenharmony_ci borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num); 9227db96d56Sopenharmony_ci if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0) 9237db96d56Sopenharmony_ci goto cleanup; 9247db96d56Sopenharmony_ci PyTuple_SET_ITEM(converted_args, arg_num, converted_arg); 9257db96d56Sopenharmony_ci } 9267db96d56Sopenharmony_ci 9277db96d56Sopenharmony_ci argv = _PySequence_BytesToCharpArray(converted_args); 9287db96d56Sopenharmony_ci Py_CLEAR(converted_args); 9297db96d56Sopenharmony_ci Py_CLEAR(fast_args); 9307db96d56Sopenharmony_ci if (!argv) 9317db96d56Sopenharmony_ci goto cleanup; 9327db96d56Sopenharmony_ci } 9337db96d56Sopenharmony_ci 9347db96d56Sopenharmony_ci if (env_list != Py_None) { 9357db96d56Sopenharmony_ci envp = _PySequence_BytesToCharpArray(env_list); 9367db96d56Sopenharmony_ci if (!envp) 9377db96d56Sopenharmony_ci goto cleanup; 9387db96d56Sopenharmony_ci } 9397db96d56Sopenharmony_ci 9407db96d56Sopenharmony_ci if (cwd_obj != Py_None) { 9417db96d56Sopenharmony_ci if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0) 9427db96d56Sopenharmony_ci goto cleanup; 9437db96d56Sopenharmony_ci cwd = PyBytes_AsString(cwd_obj2); 9447db96d56Sopenharmony_ci } else { 9457db96d56Sopenharmony_ci cwd = NULL; 9467db96d56Sopenharmony_ci } 9477db96d56Sopenharmony_ci 9487db96d56Sopenharmony_ci if (groups_list != Py_None) { 9497db96d56Sopenharmony_ci#ifdef HAVE_SETGROUPS 9507db96d56Sopenharmony_ci Py_ssize_t i; 9517db96d56Sopenharmony_ci gid_t gid; 9527db96d56Sopenharmony_ci 9537db96d56Sopenharmony_ci if (!PyList_Check(groups_list)) { 9547db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 9557db96d56Sopenharmony_ci "setgroups argument must be a list"); 9567db96d56Sopenharmony_ci goto cleanup; 9577db96d56Sopenharmony_ci } 9587db96d56Sopenharmony_ci num_groups = PySequence_Size(groups_list); 9597db96d56Sopenharmony_ci 9607db96d56Sopenharmony_ci if (num_groups < 0) 9617db96d56Sopenharmony_ci goto cleanup; 9627db96d56Sopenharmony_ci 9637db96d56Sopenharmony_ci if (num_groups > MAX_GROUPS) { 9647db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "too many groups"); 9657db96d56Sopenharmony_ci goto cleanup; 9667db96d56Sopenharmony_ci } 9677db96d56Sopenharmony_ci 9687db96d56Sopenharmony_ci if ((groups = PyMem_RawMalloc(num_groups * sizeof(gid_t))) == NULL) { 9697db96d56Sopenharmony_ci PyErr_SetString(PyExc_MemoryError, 9707db96d56Sopenharmony_ci "failed to allocate memory for group list"); 9717db96d56Sopenharmony_ci goto cleanup; 9727db96d56Sopenharmony_ci } 9737db96d56Sopenharmony_ci 9747db96d56Sopenharmony_ci for (i = 0; i < num_groups; i++) { 9757db96d56Sopenharmony_ci PyObject *elem; 9767db96d56Sopenharmony_ci elem = PySequence_GetItem(groups_list, i); 9777db96d56Sopenharmony_ci if (!elem) 9787db96d56Sopenharmony_ci goto cleanup; 9797db96d56Sopenharmony_ci if (!PyLong_Check(elem)) { 9807db96d56Sopenharmony_ci PyErr_SetString(PyExc_TypeError, 9817db96d56Sopenharmony_ci "groups must be integers"); 9827db96d56Sopenharmony_ci Py_DECREF(elem); 9837db96d56Sopenharmony_ci goto cleanup; 9847db96d56Sopenharmony_ci } else { 9857db96d56Sopenharmony_ci if (!_Py_Gid_Converter(elem, &gid)) { 9867db96d56Sopenharmony_ci Py_DECREF(elem); 9877db96d56Sopenharmony_ci PyErr_SetString(PyExc_ValueError, "invalid group id"); 9887db96d56Sopenharmony_ci goto cleanup; 9897db96d56Sopenharmony_ci } 9907db96d56Sopenharmony_ci groups[i] = gid; 9917db96d56Sopenharmony_ci } 9927db96d56Sopenharmony_ci Py_DECREF(elem); 9937db96d56Sopenharmony_ci } 9947db96d56Sopenharmony_ci call_setgroups = 1; 9957db96d56Sopenharmony_ci 9967db96d56Sopenharmony_ci#else /* HAVE_SETGROUPS */ 9977db96d56Sopenharmony_ci PyErr_BadInternalCall(); 9987db96d56Sopenharmony_ci goto cleanup; 9997db96d56Sopenharmony_ci#endif /* HAVE_SETGROUPS */ 10007db96d56Sopenharmony_ci } 10017db96d56Sopenharmony_ci 10027db96d56Sopenharmony_ci if (gid_object != Py_None) { 10037db96d56Sopenharmony_ci#ifdef HAVE_SETREGID 10047db96d56Sopenharmony_ci if (!_Py_Gid_Converter(gid_object, &gid)) 10057db96d56Sopenharmony_ci goto cleanup; 10067db96d56Sopenharmony_ci 10077db96d56Sopenharmony_ci call_setgid = 1; 10087db96d56Sopenharmony_ci 10097db96d56Sopenharmony_ci#else /* HAVE_SETREGID */ 10107db96d56Sopenharmony_ci PyErr_BadInternalCall(); 10117db96d56Sopenharmony_ci goto cleanup; 10127db96d56Sopenharmony_ci#endif /* HAVE_SETREUID */ 10137db96d56Sopenharmony_ci } 10147db96d56Sopenharmony_ci 10157db96d56Sopenharmony_ci if (uid_object != Py_None) { 10167db96d56Sopenharmony_ci#ifdef HAVE_SETREUID 10177db96d56Sopenharmony_ci if (!_Py_Uid_Converter(uid_object, &uid)) 10187db96d56Sopenharmony_ci goto cleanup; 10197db96d56Sopenharmony_ci 10207db96d56Sopenharmony_ci call_setuid = 1; 10217db96d56Sopenharmony_ci 10227db96d56Sopenharmony_ci#else /* HAVE_SETREUID */ 10237db96d56Sopenharmony_ci PyErr_BadInternalCall(); 10247db96d56Sopenharmony_ci goto cleanup; 10257db96d56Sopenharmony_ci#endif /* HAVE_SETREUID */ 10267db96d56Sopenharmony_ci } 10277db96d56Sopenharmony_ci 10287db96d56Sopenharmony_ci Py_ssize_t fds_to_keep_len = PyTuple_GET_SIZE(py_fds_to_keep); 10297db96d56Sopenharmony_ci c_fds_to_keep = PyMem_Malloc(fds_to_keep_len * sizeof(int)); 10307db96d56Sopenharmony_ci if (c_fds_to_keep == NULL) { 10317db96d56Sopenharmony_ci PyErr_SetString(PyExc_MemoryError, "failed to malloc c_fds_to_keep"); 10327db96d56Sopenharmony_ci goto cleanup; 10337db96d56Sopenharmony_ci } 10347db96d56Sopenharmony_ci if (convert_fds_to_keep_to_c(py_fds_to_keep, c_fds_to_keep) < 0) { 10357db96d56Sopenharmony_ci goto cleanup; 10367db96d56Sopenharmony_ci } 10377db96d56Sopenharmony_ci 10387db96d56Sopenharmony_ci /* This must be the last thing done before fork() because we do not 10397db96d56Sopenharmony_ci * want to call PyOS_BeforeFork() if there is any chance of another 10407db96d56Sopenharmony_ci * error leading to the cleanup: code without calling fork(). */ 10417db96d56Sopenharmony_ci if (preexec_fn != Py_None) { 10427db96d56Sopenharmony_ci preexec_fn_args_tuple = PyTuple_New(0); 10437db96d56Sopenharmony_ci if (!preexec_fn_args_tuple) 10447db96d56Sopenharmony_ci goto cleanup; 10457db96d56Sopenharmony_ci PyOS_BeforeFork(); 10467db96d56Sopenharmony_ci need_after_fork = 1; 10477db96d56Sopenharmony_ci } 10487db96d56Sopenharmony_ci 10497db96d56Sopenharmony_ci /* NOTE: When old_sigmask is non-NULL, do_fork_exec() may use vfork(). */ 10507db96d56Sopenharmony_ci const void *old_sigmask = NULL; 10517db96d56Sopenharmony_ci#ifdef VFORK_USABLE 10527db96d56Sopenharmony_ci /* Use vfork() only if it's safe. See the comment above child_exec(). */ 10537db96d56Sopenharmony_ci sigset_t old_sigs; 10547db96d56Sopenharmony_ci if (preexec_fn == Py_None && allow_vfork && 10557db96d56Sopenharmony_ci !call_setuid && !call_setgid && !call_setgroups) { 10567db96d56Sopenharmony_ci /* Block all signals to ensure that no signal handlers are run in the 10577db96d56Sopenharmony_ci * child process while it shares memory with us. Note that signals 10587db96d56Sopenharmony_ci * used internally by C libraries won't be blocked by 10597db96d56Sopenharmony_ci * pthread_sigmask(), but signal handlers installed by C libraries 10607db96d56Sopenharmony_ci * normally service only signals originating from *within the process*, 10617db96d56Sopenharmony_ci * so it should be sufficient to consider any library function that 10627db96d56Sopenharmony_ci * might send such a signal to be vfork-unsafe and do not call it in 10637db96d56Sopenharmony_ci * the child. 10647db96d56Sopenharmony_ci */ 10657db96d56Sopenharmony_ci sigset_t all_sigs; 10667db96d56Sopenharmony_ci sigfillset(&all_sigs); 10677db96d56Sopenharmony_ci if ((saved_errno = pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs))) { 10687db96d56Sopenharmony_ci goto cleanup; 10697db96d56Sopenharmony_ci } 10707db96d56Sopenharmony_ci old_sigmask = &old_sigs; 10717db96d56Sopenharmony_ci } 10727db96d56Sopenharmony_ci#endif 10737db96d56Sopenharmony_ci 10747db96d56Sopenharmony_ci pid = do_fork_exec(exec_array, argv, envp, cwd, 10757db96d56Sopenharmony_ci p2cread, p2cwrite, c2pread, c2pwrite, 10767db96d56Sopenharmony_ci errread, errwrite, errpipe_read, errpipe_write, 10777db96d56Sopenharmony_ci close_fds, restore_signals, call_setsid, pgid_to_set, 10787db96d56Sopenharmony_ci call_setgid, gid, call_setgroups, num_groups, groups, 10797db96d56Sopenharmony_ci call_setuid, uid, child_umask, old_sigmask, 10807db96d56Sopenharmony_ci c_fds_to_keep, fds_to_keep_len, 10817db96d56Sopenharmony_ci preexec_fn, preexec_fn_args_tuple); 10827db96d56Sopenharmony_ci 10837db96d56Sopenharmony_ci /* Parent (original) process */ 10847db96d56Sopenharmony_ci if (pid == -1) { 10857db96d56Sopenharmony_ci /* Capture errno for the exception. */ 10867db96d56Sopenharmony_ci saved_errno = errno; 10877db96d56Sopenharmony_ci } 10887db96d56Sopenharmony_ci 10897db96d56Sopenharmony_ci#ifdef VFORK_USABLE 10907db96d56Sopenharmony_ci if (old_sigmask) { 10917db96d56Sopenharmony_ci /* vfork() semantics guarantees that the parent is blocked 10927db96d56Sopenharmony_ci * until the child performs _exit() or execve(), so it is safe 10937db96d56Sopenharmony_ci * to unblock signals once we're here. 10947db96d56Sopenharmony_ci * Note that in environments where vfork() is implemented as fork(), 10957db96d56Sopenharmony_ci * such as QEMU user-mode emulation, the parent won't be blocked, 10967db96d56Sopenharmony_ci * but it won't share the address space with the child, 10977db96d56Sopenharmony_ci * so it's still safe to unblock the signals. 10987db96d56Sopenharmony_ci * 10997db96d56Sopenharmony_ci * We don't handle errors here because this call can't fail 11007db96d56Sopenharmony_ci * if valid arguments are given, and because there is no good 11017db96d56Sopenharmony_ci * way for the caller to deal with a failure to restore 11027db96d56Sopenharmony_ci * the thread signal mask. */ 11037db96d56Sopenharmony_ci (void) pthread_sigmask(SIG_SETMASK, old_sigmask, NULL); 11047db96d56Sopenharmony_ci } 11057db96d56Sopenharmony_ci#endif 11067db96d56Sopenharmony_ci 11077db96d56Sopenharmony_ci if (need_after_fork) 11087db96d56Sopenharmony_ci PyOS_AfterFork_Parent(); 11097db96d56Sopenharmony_ci 11107db96d56Sopenharmony_cicleanup: 11117db96d56Sopenharmony_ci if (c_fds_to_keep != NULL) { 11127db96d56Sopenharmony_ci PyMem_Free(c_fds_to_keep); 11137db96d56Sopenharmony_ci } 11147db96d56Sopenharmony_ci 11157db96d56Sopenharmony_ci if (saved_errno != 0) { 11167db96d56Sopenharmony_ci errno = saved_errno; 11177db96d56Sopenharmony_ci /* We can't call this above as PyOS_AfterFork_Parent() calls back 11187db96d56Sopenharmony_ci * into Python code which would see the unreturned error. */ 11197db96d56Sopenharmony_ci PyErr_SetFromErrno(PyExc_OSError); 11207db96d56Sopenharmony_ci } 11217db96d56Sopenharmony_ci 11227db96d56Sopenharmony_ci Py_XDECREF(preexec_fn_args_tuple); 11237db96d56Sopenharmony_ci PyMem_RawFree(groups); 11247db96d56Sopenharmony_ci Py_XDECREF(cwd_obj2); 11257db96d56Sopenharmony_ci if (envp) 11267db96d56Sopenharmony_ci _Py_FreeCharPArray(envp); 11277db96d56Sopenharmony_ci Py_XDECREF(converted_args); 11287db96d56Sopenharmony_ci Py_XDECREF(fast_args); 11297db96d56Sopenharmony_ci if (argv) 11307db96d56Sopenharmony_ci _Py_FreeCharPArray(argv); 11317db96d56Sopenharmony_ci if (exec_array) 11327db96d56Sopenharmony_ci _Py_FreeCharPArray(exec_array); 11337db96d56Sopenharmony_ci 11347db96d56Sopenharmony_ci if (need_to_reenable_gc) { 11357db96d56Sopenharmony_ci PyGC_Enable(); 11367db96d56Sopenharmony_ci } 11377db96d56Sopenharmony_ci Py_XDECREF(gc_module); 11387db96d56Sopenharmony_ci 11397db96d56Sopenharmony_ci return pid == -1 ? NULL : PyLong_FromPid(pid); 11407db96d56Sopenharmony_ci} 11417db96d56Sopenharmony_ci 11427db96d56Sopenharmony_ci 11437db96d56Sopenharmony_ciPyDoc_STRVAR(subprocess_fork_exec_doc, 11447db96d56Sopenharmony_ci"fork_exec(args, executable_list, close_fds, pass_fds, cwd, env,\n\ 11457db96d56Sopenharmony_ci p2cread, p2cwrite, c2pread, c2pwrite,\n\ 11467db96d56Sopenharmony_ci errread, errwrite, errpipe_read, errpipe_write,\n\ 11477db96d56Sopenharmony_ci restore_signals, call_setsid, pgid_to_set,\n\ 11487db96d56Sopenharmony_ci gid, groups_list, uid,\n\ 11497db96d56Sopenharmony_ci preexec_fn)\n\ 11507db96d56Sopenharmony_ci\n\ 11517db96d56Sopenharmony_ciForks a child process, closes parent file descriptors as appropriate in the\n\ 11527db96d56Sopenharmony_cichild and dups the few that are needed before calling exec() in the child\n\ 11537db96d56Sopenharmony_ciprocess.\n\ 11547db96d56Sopenharmony_ci\n\ 11557db96d56Sopenharmony_ciIf close_fds is true, close file descriptors 3 and higher, except those listed\n\ 11567db96d56Sopenharmony_ciin the sorted tuple pass_fds.\n\ 11577db96d56Sopenharmony_ci\n\ 11587db96d56Sopenharmony_ciThe preexec_fn, if supplied, will be called immediately before closing file\n\ 11597db96d56Sopenharmony_cidescriptors and exec.\n\ 11607db96d56Sopenharmony_ciWARNING: preexec_fn is NOT SAFE if your application uses threads.\n\ 11617db96d56Sopenharmony_ci It may trigger infrequent, difficult to debug deadlocks.\n\ 11627db96d56Sopenharmony_ci\n\ 11637db96d56Sopenharmony_ciIf an error occurs in the child process before the exec, it is\n\ 11647db96d56Sopenharmony_ciserialized and written to the errpipe_write fd per subprocess.py.\n\ 11657db96d56Sopenharmony_ci\n\ 11667db96d56Sopenharmony_ciReturns: the child process's PID.\n\ 11677db96d56Sopenharmony_ci\n\ 11687db96d56Sopenharmony_ciRaises: Only on an error in the parent process.\n\ 11697db96d56Sopenharmony_ci"); 11707db96d56Sopenharmony_ci 11717db96d56Sopenharmony_ci/* module level code ********************************************************/ 11727db96d56Sopenharmony_ci 11737db96d56Sopenharmony_ciPyDoc_STRVAR(module_doc, 11747db96d56Sopenharmony_ci"A POSIX helper for the subprocess module."); 11757db96d56Sopenharmony_ci 11767db96d56Sopenharmony_cistatic PyMethodDef module_methods[] = { 11777db96d56Sopenharmony_ci {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc}, 11787db96d56Sopenharmony_ci {NULL, NULL} /* sentinel */ 11797db96d56Sopenharmony_ci}; 11807db96d56Sopenharmony_ci 11817db96d56Sopenharmony_cistatic PyModuleDef_Slot _posixsubprocess_slots[] = { 11827db96d56Sopenharmony_ci {0, NULL} 11837db96d56Sopenharmony_ci}; 11847db96d56Sopenharmony_ci 11857db96d56Sopenharmony_cistatic struct PyModuleDef _posixsubprocessmodule = { 11867db96d56Sopenharmony_ci PyModuleDef_HEAD_INIT, 11877db96d56Sopenharmony_ci .m_name = "_posixsubprocess", 11887db96d56Sopenharmony_ci .m_doc = module_doc, 11897db96d56Sopenharmony_ci .m_size = 0, 11907db96d56Sopenharmony_ci .m_methods = module_methods, 11917db96d56Sopenharmony_ci .m_slots = _posixsubprocess_slots, 11927db96d56Sopenharmony_ci}; 11937db96d56Sopenharmony_ci 11947db96d56Sopenharmony_ciPyMODINIT_FUNC 11957db96d56Sopenharmony_ciPyInit__posixsubprocess(void) 11967db96d56Sopenharmony_ci{ 11977db96d56Sopenharmony_ci return PyModuleDef_Init(&_posixsubprocessmodule); 11987db96d56Sopenharmony_ci} 1199