LCOV - code coverage report
Current view: top level - Modules - _posixsubprocess.c (source / functions) Hit Total Coverage
Test: CPython 3.12 LCOV report [commit acb105a7c1f] Lines: 289 347 83.3 %
Date: 2022-07-20 13:12:14 Functions: 13 15 86.7 %
Branches: 231 312 74.0 %

           Branch data     Line data    Source code
       1                 :            : /* Authors: Gregory P. Smith & Jeffrey Yasskin */
       2                 :            : #ifndef Py_BUILD_CORE_BUILTIN
       3                 :            : #  define Py_BUILD_CORE_MODULE 1
       4                 :            : #endif
       5                 :            : 
       6                 :            : #include "Python.h"
       7                 :            : #include "pycore_fileutils.h"
       8                 :            : #if defined(HAVE_PIPE2) && !defined(_GNU_SOURCE)
       9                 :            : # define _GNU_SOURCE
      10                 :            : #endif
      11                 :            : #include <unistd.h>
      12                 :            : #include <fcntl.h>
      13                 :            : #ifdef HAVE_SYS_TYPES_H
      14                 :            : #include <sys/types.h>
      15                 :            : #endif
      16                 :            : #if defined(HAVE_SYS_STAT_H)
      17                 :            : #include <sys/stat.h>
      18                 :            : #endif
      19                 :            : #ifdef HAVE_SYS_SYSCALL_H
      20                 :            : #include <sys/syscall.h>
      21                 :            : #endif
      22                 :            : #if defined(HAVE_SYS_RESOURCE_H)
      23                 :            : #include <sys/resource.h>
      24                 :            : #endif
      25                 :            : #ifdef HAVE_DIRENT_H
      26                 :            : #include <dirent.h>
      27                 :            : #endif
      28                 :            : #ifdef HAVE_GRP_H
      29                 :            : #include <grp.h>
      30                 :            : #endif /* HAVE_GRP_H */
      31                 :            : 
      32                 :            : #include "posixmodule.h"
      33                 :            : 
      34                 :            : #ifdef _Py_MEMORY_SANITIZER
      35                 :            : # include <sanitizer/msan_interface.h>
      36                 :            : #endif
      37                 :            : 
      38                 :            : #if defined(__ANDROID__) && __ANDROID_API__ < 21 && !defined(SYS_getdents64)
      39                 :            : # include <sys/linux-syscalls.h>
      40                 :            : # define SYS_getdents64  __NR_getdents64
      41                 :            : #endif
      42                 :            : 
      43                 :            : #if defined(__linux__) && defined(HAVE_VFORK) && defined(HAVE_SIGNAL_H) && \
      44                 :            :     defined(HAVE_PTHREAD_SIGMASK) && !defined(HAVE_BROKEN_PTHREAD_SIGMASK)
      45                 :            : /* If this is ever expanded to non-Linux platforms, verify what calls are
      46                 :            :  * allowed after vfork(). Ex: setsid() may be disallowed on macOS? */
      47                 :            : # include <signal.h>
      48                 :            : # define VFORK_USABLE 1
      49                 :            : #endif
      50                 :            : 
      51                 :            : #if defined(__sun) && defined(__SVR4)
      52                 :            : /* readdir64 is used to work around Solaris 9 bug 6395699. */
      53                 :            : # define readdir readdir64
      54                 :            : # define dirent dirent64
      55                 :            : # if !defined(HAVE_DIRFD)
      56                 :            : /* Some versions of Solaris lack dirfd(). */
      57                 :            : #  define dirfd(dirp) ((dirp)->dd_fd)
      58                 :            : #  define HAVE_DIRFD
      59                 :            : # endif
      60                 :            : #endif
      61                 :            : 
      62                 :            : #if defined(__FreeBSD__) || (defined(__APPLE__) && defined(__MACH__)) || defined(__DragonFly__)
      63                 :            : # define FD_DIR "/dev/fd"
      64                 :            : #else
      65                 :            : # define FD_DIR "/proc/self/fd"
      66                 :            : #endif
      67                 :            : 
      68                 :            : #ifdef NGROUPS_MAX
      69                 :            : #define MAX_GROUPS NGROUPS_MAX
      70                 :            : #else
      71                 :            : #define MAX_GROUPS 64
      72                 :            : #endif
      73                 :            : 
      74                 :            : #define POSIX_CALL(call)   do { if ((call) == -1) goto error; } while (0)
      75                 :            : 
      76                 :            : static struct PyModuleDef _posixsubprocessmodule;
      77                 :            : 
      78                 :            : /* Convert ASCII to a positive int, no libc call. no overflow. -1 on error. */
      79                 :            : static int
      80                 :       8475 : _pos_int_from_ascii(const char *name)
      81                 :            : {
      82                 :       8475 :     int num = 0;
      83   [ +  +  +  - ]:      19254 :     while (*name >= '0' && *name <= '9') {
      84                 :      10779 :         num = num * 10 + (*name - '0');
      85                 :      10779 :         ++name;
      86                 :            :     }
      87         [ +  + ]:       8475 :     if (*name)
      88                 :       1002 :         return -1;  /* Non digit found, not a number. */
      89                 :       7473 :     return num;
      90                 :            : }
      91                 :            : 
      92                 :            : 
      93                 :            : #if defined(__FreeBSD__) || defined(__DragonFly__)
      94                 :            : /* When /dev/fd isn't mounted it is often a static directory populated
      95                 :            :  * with 0 1 2 or entries for 0 .. 63 on FreeBSD, NetBSD, OpenBSD and DragonFlyBSD.
      96                 :            :  * NetBSD and OpenBSD have a /proc fs available (though not necessarily
      97                 :            :  * mounted) and do not have fdescfs for /dev/fd.  MacOS X has a devfs
      98                 :            :  * that properly supports /dev/fd.
      99                 :            :  */
     100                 :            : static int
     101                 :            : _is_fdescfs_mounted_on_dev_fd(void)
     102                 :            : {
     103                 :            :     struct stat dev_stat;
     104                 :            :     struct stat dev_fd_stat;
     105                 :            :     if (stat("/dev", &dev_stat) != 0)
     106                 :            :         return 0;
     107                 :            :     if (stat(FD_DIR, &dev_fd_stat) != 0)
     108                 :            :         return 0;
     109                 :            :     if (dev_stat.st_dev == dev_fd_stat.st_dev)
     110                 :            :         return 0;  /* / == /dev == /dev/fd means it is static. #fail */
     111                 :            :     return 1;
     112                 :            : }
     113                 :            : #endif
     114                 :            : 
     115                 :            : 
     116                 :            : /* Returns 1 if there is a problem with fd_sequence, 0 otherwise. */
     117                 :            : static int
     118                 :       5613 : _sanity_check_python_fd_sequence(PyObject *fd_sequence)
     119                 :            : {
     120                 :            :     Py_ssize_t seq_idx;
     121                 :       5613 :     long prev_fd = -1;
     122         [ +  + ]:      13635 :     for (seq_idx = 0; seq_idx < PyTuple_GET_SIZE(fd_sequence); ++seq_idx) {
     123                 :       8028 :         PyObject* py_fd = PyTuple_GET_ITEM(fd_sequence, seq_idx);
     124                 :            :         long iter_fd;
     125         [ +  + ]:       8028 :         if (!PyLong_Check(py_fd)) {
     126                 :          2 :             return 1;
     127                 :            :         }
     128                 :       8026 :         iter_fd = PyLong_AsLong(py_fd);
     129   [ +  +  +  +  :       8026 :         if (iter_fd < 0 || iter_fd <= prev_fd || iter_fd > INT_MAX) {
                   -  + ]
     130                 :            :             /* Negative, overflow, unsorted, too big for a fd. */
     131                 :          4 :             return 1;
     132                 :            :         }
     133                 :       8022 :         prev_fd = iter_fd;
     134                 :            :     }
     135                 :       5607 :     return 0;
     136                 :            : }
     137                 :            : 
     138                 :            : 
     139                 :            : /* Is fd found in the sorted Python Sequence? */
     140                 :            : static int
     141                 :       5469 : _is_fd_in_sorted_fd_sequence(int fd, PyObject *fd_sequence)
     142                 :            : {
     143                 :            :     /* Binary search. */
     144                 :       5469 :     Py_ssize_t search_min = 0;
     145                 :       5469 :     Py_ssize_t search_max = PyTuple_GET_SIZE(fd_sequence) - 1;
     146         [ -  + ]:       5469 :     if (search_max < 0)
     147                 :          0 :         return 0;
     148                 :            :     do {
     149                 :      13914 :         long middle = (search_min + search_max) / 2;
     150                 :      13914 :         long middle_fd = PyLong_AsLong(PyTuple_GET_ITEM(fd_sequence, middle));
     151         [ +  + ]:      13914 :         if (fd == middle_fd)
     152                 :       2610 :             return 1;
     153         [ +  + ]:      11304 :         if (fd > middle_fd)
     154                 :       7776 :             search_min = middle + 1;
     155                 :            :         else
     156                 :       3528 :             search_max = middle - 1;
     157         [ +  + ]:      11304 :     } while (search_min <= search_max);
     158                 :       2859 :     return 0;
     159                 :            : }
     160                 :            : 
     161                 :            : static int
     162                 :       5564 : make_inheritable(PyObject *py_fds_to_keep, int errpipe_write)
     163                 :            : {
     164                 :            :     Py_ssize_t i, len;
     165                 :            : 
     166                 :       5564 :     len = PyTuple_GET_SIZE(py_fds_to_keep);
     167         [ +  + ]:      13538 :     for (i = 0; i < len; ++i) {
     168                 :       7974 :         PyObject* fdobj = PyTuple_GET_ITEM(py_fds_to_keep, i);
     169                 :       7974 :         long fd = PyLong_AsLong(fdobj);
     170                 :            :         assert(!PyErr_Occurred());
     171                 :            :         assert(0 <= fd && fd <= INT_MAX);
     172         [ +  + ]:       7974 :         if (fd == errpipe_write) {
     173                 :            :             /* errpipe_write is part of py_fds_to_keep. It must be closed at
     174                 :            :                exec(), but kept open in the child process until exec() is
     175                 :            :                called. */
     176                 :       4933 :             continue;
     177                 :            :         }
     178         [ -  + ]:       3041 :         if (_Py_set_inheritable_async_safe((int)fd, 1, NULL) < 0)
     179                 :          0 :             return -1;
     180                 :            :     }
     181                 :       5564 :     return 0;
     182                 :            : }
     183                 :            : 
     184                 :            : 
     185                 :            : /* Get the maximum file descriptor that could be opened by this process.
     186                 :            :  * This function is async signal safe for use between fork() and exec().
     187                 :            :  */
     188                 :            : static long
     189                 :          0 : safe_get_max_fd(void)
     190                 :            : {
     191                 :            :     long local_max_fd;
     192                 :            : #if defined(__NetBSD__)
     193                 :            :     local_max_fd = fcntl(0, F_MAXFD);
     194                 :            :     if (local_max_fd >= 0)
     195                 :            :         return local_max_fd;
     196                 :            : #endif
     197                 :            : #if defined(HAVE_SYS_RESOURCE_H) && defined(__OpenBSD__)
     198                 :            :     struct rlimit rl;
     199                 :            :     /* Not on the POSIX async signal safe functions list but likely
     200                 :            :      * safe.  TODO - Someone should audit OpenBSD to make sure. */
     201                 :            :     if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
     202                 :            :         return (long) rl.rlim_max;
     203                 :            : #endif
     204                 :            : #ifdef _SC_OPEN_MAX
     205                 :          0 :     local_max_fd = sysconf(_SC_OPEN_MAX);
     206         [ #  # ]:          0 :     if (local_max_fd == -1)
     207                 :            : #endif
     208                 :          0 :         local_max_fd = 256;  /* Matches legacy Lib/subprocess.py behavior. */
     209                 :          0 :     return local_max_fd;
     210                 :            : }
     211                 :            : 
     212                 :            : 
     213                 :            : /* Close all file descriptors in the given range except for those in
     214                 :            :  * py_fds_to_keep by invoking closer on each subrange.
     215                 :            :  *
     216                 :            :  * If end_fd == -1, it's guessed via safe_get_max_fd(), but it isn't
     217                 :            :  * possible to know for sure what the max fd to go up to is for
     218                 :            :  * processes with the capability of raising their maximum, or in case
     219                 :            :  * a process opened a high fd and then lowered its maximum.
     220                 :            :  */
     221                 :            : static int
     222                 :       5561 : _close_range_except(int start_fd,
     223                 :            :                     int end_fd,
     224                 :            :                     PyObject *py_fds_to_keep,
     225                 :            :                     int (*closer)(int, int))
     226                 :            : {
     227         [ -  + ]:       5561 :     if (end_fd == -1) {
     228         [ #  # ]:          0 :         end_fd = Py_MIN(safe_get_max_fd(), INT_MAX);
     229                 :            :     }
     230                 :       5561 :     Py_ssize_t num_fds_to_keep = PyTuple_GET_SIZE(py_fds_to_keep);
     231                 :            :     Py_ssize_t keep_seq_idx;
     232                 :            :     /* As py_fds_to_keep is sorted we can loop through the list closing
     233                 :            :      * fds in between any in the keep list falling within our range. */
     234         [ +  + ]:      11461 :     for (keep_seq_idx = 0; keep_seq_idx < num_fds_to_keep; ++keep_seq_idx) {
     235                 :       6401 :         PyObject* py_keep_fd = PyTuple_GET_ITEM(py_fds_to_keep, keep_seq_idx);
     236                 :       6401 :         int keep_fd = PyLong_AsLong(py_keep_fd);
     237         [ +  + ]:       6401 :         if (keep_fd < start_fd)
     238                 :         57 :             continue;
     239         [ +  + ]:       6344 :         if (closer(start_fd, keep_fd - 1) != 0)
     240                 :        501 :             return -1;
     241                 :       5843 :         start_fd = keep_fd + 1;
     242                 :            :     }
     243         [ +  - ]:       5060 :     if (start_fd <= end_fd) {
     244         [ -  + ]:       5060 :         if (closer(start_fd, end_fd) != 0)
     245                 :          0 :             return -1;
     246                 :            :     }
     247                 :       5060 :     return 0;
     248                 :            : }
     249                 :            : 
     250                 :            : #if defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)
     251                 :            : /* It doesn't matter if d_name has room for NAME_MAX chars; we're using this
     252                 :            :  * only to read a directory of short file descriptor number names.  The kernel
     253                 :            :  * will return an error if we didn't give it enough space.  Highly Unlikely.
     254                 :            :  * This structure is very old and stable: It will not change unless the kernel
     255                 :            :  * chooses to break compatibility with all existing binaries.  Highly Unlikely.
     256                 :            :  */
     257                 :            : struct linux_dirent64 {
     258                 :            :    unsigned long long d_ino;
     259                 :            :    long long d_off;
     260                 :            :    unsigned short d_reclen;     /* Length of this linux_dirent */
     261                 :            :    unsigned char  d_type;
     262                 :            :    char           d_name[256];  /* Filename (null-terminated) */
     263                 :            : };
     264                 :            : 
     265                 :            : static int
     266                 :          0 : _brute_force_closer(int first, int last)
     267                 :            : {
     268         [ #  # ]:          0 :     for (int i = first; i <= last; i++) {
     269                 :            :         /* Ignore errors */
     270                 :          0 :         (void)close(i);
     271                 :            :     }
     272                 :          0 :     return 0;
     273                 :            : }
     274                 :            : 
     275                 :            : /* Close all open file descriptors in the range from start_fd and higher
     276                 :            :  * Do not close any in the sorted py_fds_to_keep list.
     277                 :            :  *
     278                 :            :  * This version is async signal safe as it does not make any unsafe C library
     279                 :            :  * calls, malloc calls or handle any locks.  It is _unfortunate_ to be forced
     280                 :            :  * to resort to making a kernel system call directly but this is the ONLY api
     281                 :            :  * available that does no harm.  opendir/readdir/closedir perform memory
     282                 :            :  * allocation and locking so while they usually work they are not guaranteed
     283                 :            :  * to (especially if you have replaced your malloc implementation).  A version
     284                 :            :  * of this function that uses those can be found in the _maybe_unsafe variant.
     285                 :            :  *
     286                 :            :  * This is Linux specific because that is all I am ready to test it on.  It
     287                 :            :  * should be easy to add OS specific dirent or dirent64 structures and modify
     288                 :            :  * it with some cpp #define magic to work on other OSes as well if you want.
     289                 :            :  */
     290                 :            : static void
     291                 :        501 : _close_open_fds_safe(int start_fd, PyObject* py_fds_to_keep)
     292                 :            : {
     293                 :            :     int fd_dir_fd;
     294                 :            : 
     295                 :        501 :     fd_dir_fd = _Py_open_noraise(FD_DIR, O_RDONLY);
     296         [ -  + ]:        501 :     if (fd_dir_fd == -1) {
     297                 :            :         /* No way to get a list of open fds. */
     298                 :          0 :         _close_range_except(start_fd, -1, py_fds_to_keep, _brute_force_closer);
     299                 :          0 :         return;
     300                 :            :     } else {
     301                 :            :         char buffer[sizeof(struct linux_dirent64)];
     302                 :            :         int bytes;
     303                 :       1507 :         while ((bytes = syscall(SYS_getdents64, fd_dir_fd,
     304                 :            :                                 (struct linux_dirent64 *)buffer,
     305         [ +  + ]:       1507 :                                 sizeof(buffer))) > 0) {
     306                 :            :             struct linux_dirent64 *entry;
     307                 :            :             int offset;
     308                 :            : #ifdef _Py_MEMORY_SANITIZER
     309                 :            :             __msan_unpoison(buffer, bytes);
     310                 :            : #endif
     311         [ +  + ]:       9481 :             for (offset = 0; offset < bytes; offset += entry->d_reclen) {
     312                 :            :                 int fd;
     313                 :       8475 :                 entry = (struct linux_dirent64 *)(buffer + offset);
     314         [ +  + ]:       8475 :                 if ((fd = _pos_int_from_ascii(entry->d_name)) < 0)
     315                 :       1002 :                     continue;  /* Not a number. */
     316   [ +  +  +  +  :      12942 :                 if (fd != fd_dir_fd && fd >= start_fd &&
                   +  + ]
     317                 :       5469 :                     !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) {
     318                 :       2859 :                     close(fd);
     319                 :            :                 }
     320                 :            :             }
     321                 :            :         }
     322                 :        501 :         close(fd_dir_fd);
     323                 :            :     }
     324                 :            : }
     325                 :            : 
     326                 :            : #define _close_open_fds_fallback _close_open_fds_safe
     327                 :            : 
     328                 :            : #else  /* NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */
     329                 :            : 
     330                 :            : static int
     331                 :            : _unsafe_closer(int first, int last)
     332                 :            : {
     333                 :            :     _Py_closerange(first, last);
     334                 :            :     return 0;
     335                 :            : }
     336                 :            : 
     337                 :            : /* Close all open file descriptors from start_fd and higher.
     338                 :            :  * Do not close any in the sorted py_fds_to_keep tuple.
     339                 :            :  *
     340                 :            :  * This function violates the strict use of async signal safe functions. :(
     341                 :            :  * It calls opendir(), readdir() and closedir().  Of these, the one most
     342                 :            :  * likely to ever cause a problem is opendir() as it performs an internal
     343                 :            :  * malloc().  Practically this should not be a problem.  The Java VM makes the
     344                 :            :  * same calls between fork and exec in its own UNIXProcess_md.c implementation.
     345                 :            :  *
     346                 :            :  * readdir_r() is not used because it provides no benefit.  It is typically
     347                 :            :  * implemented as readdir() followed by memcpy().  See also:
     348                 :            :  *   http://womble.decadent.org.uk/readdir_r-advisory.html
     349                 :            :  */
     350                 :            : static void
     351                 :            : _close_open_fds_maybe_unsafe(int start_fd, PyObject* py_fds_to_keep)
     352                 :            : {
     353                 :            :     DIR *proc_fd_dir;
     354                 :            : #ifndef HAVE_DIRFD
     355                 :            :     while (_is_fd_in_sorted_fd_sequence(start_fd, py_fds_to_keep)) {
     356                 :            :         ++start_fd;
     357                 :            :     }
     358                 :            :     /* Close our lowest fd before we call opendir so that it is likely to
     359                 :            :      * reuse that fd otherwise we might close opendir's file descriptor in
     360                 :            :      * our loop.  This trick assumes that fd's are allocated on a lowest
     361                 :            :      * available basis. */
     362                 :            :     close(start_fd);
     363                 :            :     ++start_fd;
     364                 :            : #endif
     365                 :            : 
     366                 :            : #if defined(__FreeBSD__) || defined(__DragonFly__)
     367                 :            :     if (!_is_fdescfs_mounted_on_dev_fd())
     368                 :            :         proc_fd_dir = NULL;
     369                 :            :     else
     370                 :            : #endif
     371                 :            :         proc_fd_dir = opendir(FD_DIR);
     372                 :            :     if (!proc_fd_dir) {
     373                 :            :         /* No way to get a list of open fds. */
     374                 :            :         _close_range_except(start_fd, -1, py_fds_to_keep, _unsafe_closer);
     375                 :            :     } else {
     376                 :            :         struct dirent *dir_entry;
     377                 :            : #ifdef HAVE_DIRFD
     378                 :            :         int fd_used_by_opendir = dirfd(proc_fd_dir);
     379                 :            : #else
     380                 :            :         int fd_used_by_opendir = start_fd - 1;
     381                 :            : #endif
     382                 :            :         errno = 0;
     383                 :            :         while ((dir_entry = readdir(proc_fd_dir))) {
     384                 :            :             int fd;
     385                 :            :             if ((fd = _pos_int_from_ascii(dir_entry->d_name)) < 0)
     386                 :            :                 continue;  /* Not a number. */
     387                 :            :             if (fd != fd_used_by_opendir && fd >= start_fd &&
     388                 :            :                 !_is_fd_in_sorted_fd_sequence(fd, py_fds_to_keep)) {
     389                 :            :                 close(fd);
     390                 :            :             }
     391                 :            :             errno = 0;
     392                 :            :         }
     393                 :            :         if (errno) {
     394                 :            :             /* readdir error, revert behavior. Highly Unlikely. */
     395                 :            :             _close_range_except(start_fd, -1, py_fds_to_keep, _unsafe_closer);
     396                 :            :         }
     397                 :            :         closedir(proc_fd_dir);
     398                 :            :     }
     399                 :            : }
     400                 :            : 
     401                 :            : #define _close_open_fds_fallback _close_open_fds_maybe_unsafe
     402                 :            : 
     403                 :            : #endif  /* else NOT (defined(__linux__) && defined(HAVE_SYS_SYSCALL_H)) */
     404                 :            : 
     405                 :            : /* We can use close_range() library function only if it's known to be
     406                 :            :  * async-signal-safe.
     407                 :            :  *
     408                 :            :  * On Linux, glibc explicitly documents it to be a thin wrapper over
     409                 :            :  * the system call, and other C libraries are likely to follow glibc.
     410                 :            :  */
     411                 :            : #if defined(HAVE_CLOSE_RANGE) && \
     412                 :            :     (defined(__linux__) || defined(__FreeBSD__))
     413                 :            : #define HAVE_ASYNC_SAFE_CLOSE_RANGE
     414                 :            : 
     415                 :            : static int
     416                 :      11404 : _close_range_closer(int first, int last)
     417                 :            : {
     418                 :      11404 :     return close_range(first, last, 0);
     419                 :            : }
     420                 :            : #endif
     421                 :            : 
     422                 :            : static void
     423                 :       5561 : _close_open_fds(int start_fd, PyObject* py_fds_to_keep)
     424                 :            : {
     425                 :            : #ifdef HAVE_ASYNC_SAFE_CLOSE_RANGE
     426         [ +  + ]:       5561 :     if (_close_range_except(
     427                 :            :             start_fd, INT_MAX, py_fds_to_keep,
     428                 :            :             _close_range_closer) == 0) {
     429                 :       5060 :         return;
     430                 :            :     }
     431                 :            : #endif
     432                 :        501 :     _close_open_fds_fallback(start_fd, py_fds_to_keep);
     433                 :            : }
     434                 :            : 
     435                 :            : #ifdef VFORK_USABLE
     436                 :            : /* Reset dispositions for all signals to SIG_DFL except for ignored
     437                 :            :  * signals. This way we ensure that no signal handlers can run
     438                 :            :  * after we unblock signals in a child created by vfork().
     439                 :            :  */
     440                 :            : static void
     441                 :       5561 : reset_signal_handlers(const sigset_t *child_sigmask)
     442                 :            : {
     443                 :       5561 :     struct sigaction sa_dfl = {.sa_handler = SIG_DFL};
     444         [ +  + ]:     361465 :     for (int sig = 1; sig < _NSIG; sig++) {
     445                 :            :         /* Dispositions for SIGKILL and SIGSTOP can't be changed. */
     446   [ +  +  +  + ]:     355904 :         if (sig == SIGKILL || sig == SIGSTOP) {
     447                 :     314659 :             continue;
     448                 :            :         }
     449                 :            : 
     450                 :            :         /* There is no need to reset the disposition of signals that will
     451                 :            :          * remain blocked across execve() since the kernel will do it. */
     452         [ +  + ]:     344782 :         if (sigismember(child_sigmask, sig) == 1) {
     453                 :        116 :             continue;
     454                 :            :         }
     455                 :            : 
     456                 :            :         struct sigaction sa;
     457                 :            :         /* C libraries usually return EINVAL for signals used
     458                 :            :          * internally (e.g. for thread cancellation), so simply
     459                 :            :          * skip errors here. */
     460         [ +  + ]:     344666 :         if (sigaction(sig, NULL, &sa) == -1) {
     461                 :      11122 :             continue;
     462                 :            :         }
     463                 :            : 
     464                 :            :         /* void *h works as these fields are both pointer types already. */
     465         [ -  + ]:     333544 :         void *h = (sa.sa_flags & SA_SIGINFO ? (void *)sa.sa_sigaction :
     466                 :            :                                               (void *)sa.sa_handler);
     467   [ +  +  +  + ]:     333544 :         if (h == SIG_IGN || h == SIG_DFL) {
     468                 :     292299 :             continue;
     469                 :            :         }
     470                 :            : 
     471                 :            :         /* This call can't reasonably fail, but if it does, terminating
     472                 :            :          * the child seems to be too harsh, so ignore errors. */
     473                 :      41245 :         (void) sigaction(sig, &sa_dfl, NULL);
     474                 :            :     }
     475                 :       5561 : }
     476                 :            : #endif /* VFORK_USABLE */
     477                 :            : 
     478                 :            : 
     479                 :            : /*
     480                 :            :  * This function is code executed in the child process immediately after
     481                 :            :  * (v)fork to set things up and call exec().
     482                 :            :  *
     483                 :            :  * All of the code in this function must only use async-signal-safe functions,
     484                 :            :  * listed at `man 7 signal` or
     485                 :            :  * http://www.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html.
     486                 :            :  *
     487                 :            :  * This restriction is documented at
     488                 :            :  * http://www.opengroup.org/onlinepubs/009695399/functions/fork.html.
     489                 :            :  *
     490                 :            :  * If this function is called after vfork(), even more care must be taken.
     491                 :            :  * The lack of preparations that C libraries normally take on fork(),
     492                 :            :  * as well as sharing the address space with the parent, might make even
     493                 :            :  * async-signal-safe functions vfork-unsafe. In particular, on Linux,
     494                 :            :  * set*id() and setgroups() library functions must not be called, since
     495                 :            :  * they have to interact with the library-level thread list and send
     496                 :            :  * library-internal signals to implement per-process credentials semantics
     497                 :            :  * required by POSIX but not supported natively on Linux. Another reason to
     498                 :            :  * avoid this family of functions is that sharing an address space between
     499                 :            :  * processes running with different privileges is inherently insecure.
     500                 :            :  * See bpo-35823 for further discussion and references.
     501                 :            :  *
     502                 :            :  * In some C libraries, setrlimit() has the same thread list/signalling
     503                 :            :  * behavior since resource limits were per-thread attributes before
     504                 :            :  * Linux 2.6.10. Musl, as of 1.2.1, is known to have this issue
     505                 :            :  * (https://www.openwall.com/lists/musl/2020/10/15/6).
     506                 :            :  *
     507                 :            :  * If vfork-unsafe functionality is desired after vfork(), consider using
     508                 :            :  * syscall() to obtain it.
     509                 :            :  */
     510                 :            : Py_NO_INLINE static void
     511                 :       5564 : child_exec(char *const exec_array[],
     512                 :            :            char *const argv[],
     513                 :            :            char *const envp[],
     514                 :            :            const char *cwd,
     515                 :            :            int p2cread, int p2cwrite,
     516                 :            :            int c2pread, int c2pwrite,
     517                 :            :            int errread, int errwrite,
     518                 :            :            int errpipe_read, int errpipe_write,
     519                 :            :            int close_fds, int restore_signals,
     520                 :            :            int call_setsid, pid_t pgid_to_set,
     521                 :            :            int call_setgid, gid_t gid,
     522                 :            :            int call_setgroups, size_t groups_size, const gid_t *groups,
     523                 :            :            int call_setuid, uid_t uid, int child_umask,
     524                 :            :            const void *child_sigmask,
     525                 :            :            PyObject *py_fds_to_keep,
     526                 :            :            PyObject *preexec_fn,
     527                 :            :            PyObject *preexec_fn_args_tuple)
     528                 :            : {
     529                 :       5564 :     int i, saved_errno, reached_preexec = 0;
     530                 :            :     PyObject *result;
     531                 :       5564 :     const char* err_msg = "";
     532                 :            :     /* Buffer large enough to hold a hex integer.  We can't malloc. */
     533                 :            :     char hex_errno[sizeof(saved_errno)*2+1];
     534                 :            : 
     535         [ -  + ]:       5564 :     if (make_inheritable(py_fds_to_keep, errpipe_write) < 0)
     536                 :          0 :         goto error;
     537                 :            : 
     538                 :            :     /* Close parent's pipe ends. */
     539         [ +  + ]:       5564 :     if (p2cwrite != -1)
     540         [ -  + ]:       1421 :         POSIX_CALL(close(p2cwrite));
     541         [ +  + ]:       5564 :     if (c2pread != -1)
     542         [ -  + ]:       3988 :         POSIX_CALL(close(c2pread));
     543         [ +  + ]:       5564 :     if (errread != -1)
     544         [ -  + ]:       3494 :         POSIX_CALL(close(errread));
     545         [ -  + ]:       5564 :     POSIX_CALL(close(errpipe_read));
     546                 :            : 
     547                 :            :     /* When duping fds, if there arises a situation where one of the fds is
     548                 :            :        either 0, 1 or 2, it is possible that it is overwritten (#12607). */
     549         [ +  + ]:       5564 :     if (c2pwrite == 0) {
     550         [ -  + ]:          6 :         POSIX_CALL(c2pwrite = dup(c2pwrite));
     551                 :            :         /* issue32270 */
     552         [ -  + ]:          6 :         if (_Py_set_inheritable_async_safe(c2pwrite, 0, NULL) < 0) {
     553                 :          0 :             goto error;
     554                 :            :         }
     555                 :            :     }
     556   [ +  +  +  + ]:       5582 :     while (errwrite == 0 || errwrite == 1) {
     557         [ -  + ]:         18 :         POSIX_CALL(errwrite = dup(errwrite));
     558                 :            :         /* issue32270 */
     559         [ -  + ]:         18 :         if (_Py_set_inheritable_async_safe(errwrite, 0, NULL) < 0) {
     560                 :          0 :             goto error;
     561                 :            :         }
     562                 :            :     }
     563                 :            : 
     564                 :            :     /* Dup fds for child.
     565                 :            :        dup2() removes the CLOEXEC flag but we must do it ourselves if dup2()
     566                 :            :        would be a no-op (issue #10806). */
     567         [ +  + ]:       5564 :     if (p2cread == 0) {
     568         [ -  + ]:          9 :         if (_Py_set_inheritable_async_safe(p2cread, 1, NULL) < 0)
     569                 :          0 :             goto error;
     570                 :            :     }
     571         [ +  + ]:       5555 :     else if (p2cread != -1)
     572         [ -  + ]:       1528 :         POSIX_CALL(dup2(p2cread, 0));  /* stdin */
     573                 :            : 
     574         [ +  + ]:       5564 :     if (c2pwrite == 1) {
     575         [ -  + ]:         12 :         if (_Py_set_inheritable_async_safe(c2pwrite, 1, NULL) < 0)
     576                 :          0 :             goto error;
     577                 :            :     }
     578         [ +  + ]:       5552 :     else if (c2pwrite != -1)
     579         [ -  + ]:       4498 :         POSIX_CALL(dup2(c2pwrite, 1));  /* stdout */
     580                 :            : 
     581         [ +  + ]:       5564 :     if (errwrite == 2) {
     582         [ -  + ]:          9 :         if (_Py_set_inheritable_async_safe(errwrite, 1, NULL) < 0)
     583                 :          0 :             goto error;
     584                 :            :     }
     585         [ +  + ]:       5555 :     else if (errwrite != -1)
     586         [ -  + ]:       4297 :         POSIX_CALL(dup2(errwrite, 2));  /* stderr */
     587                 :            : 
     588                 :            :     /* We no longer manually close p2cread, c2pwrite, and errwrite here as
     589                 :            :      * _close_open_fds takes care when it is not already non-inheritable. */
     590                 :            : 
     591         [ +  + ]:       5564 :     if (cwd)
     592         [ +  + ]:        534 :         POSIX_CALL(chdir(cwd));
     593                 :            : 
     594         [ +  + ]:       5561 :     if (child_umask >= 0)
     595                 :          1 :         umask(child_umask);  /* umask() always succeeds. */
     596                 :            : 
     597         [ +  + ]:       5561 :     if (restore_signals)
     598                 :       4929 :         _Py_RestoreSignals();
     599                 :            : 
     600                 :            : #ifdef VFORK_USABLE
     601         [ +  - ]:       5561 :     if (child_sigmask) {
     602                 :       5561 :         reset_signal_handlers(child_sigmask);
     603         [ -  + ]:       5561 :         if ((errno = pthread_sigmask(SIG_SETMASK, child_sigmask, NULL))) {
     604                 :          0 :             goto error;
     605                 :            :         }
     606                 :            :     }
     607                 :            : #endif
     608                 :            : 
     609                 :            : #ifdef HAVE_SETSID
     610         [ +  + ]:       5561 :     if (call_setsid)
     611         [ -  + ]:        478 :         POSIX_CALL(setsid());
     612                 :            : #endif
     613                 :            : 
     614                 :            : #ifdef HAVE_SETPGID
     615                 :            :     static_assert(_Py_IS_TYPE_SIGNED(pid_t), "pid_t is unsigned");
     616         [ +  + ]:       5561 :     if (pgid_to_set >= 0) {
     617         [ -  + ]:          1 :         POSIX_CALL(setpgid(0, pgid_to_set));
     618                 :            :     }
     619                 :            : #endif
     620                 :            : 
     621                 :            : #ifdef HAVE_SETGROUPS
     622         [ -  + ]:       5561 :     if (call_setgroups)
     623         [ #  # ]:          0 :         POSIX_CALL(setgroups(groups_size, groups));
     624                 :            : #endif /* HAVE_SETGROUPS */
     625                 :            : 
     626                 :            : #ifdef HAVE_SETREGID
     627         [ -  + ]:       5561 :     if (call_setgid)
     628         [ #  # ]:          0 :         POSIX_CALL(setregid(gid, gid));
     629                 :            : #endif /* HAVE_SETREGID */
     630                 :            : 
     631                 :            : #ifdef HAVE_SETREUID
     632         [ -  + ]:       5561 :     if (call_setuid)
     633         [ #  # ]:          0 :         POSIX_CALL(setreuid(uid, uid));
     634                 :            : #endif /* HAVE_SETREUID */
     635                 :            : 
     636                 :            : 
     637                 :       5561 :     reached_preexec = 1;
     638   [ -  +  -  - ]:       5561 :     if (preexec_fn != Py_None && preexec_fn_args_tuple) {
     639                 :            :         /* This is where the user has asked us to deadlock their program. */
     640                 :          0 :         result = PyObject_Call(preexec_fn, preexec_fn_args_tuple, NULL);
     641         [ #  # ]:          0 :         if (result == NULL) {
     642                 :            :             /* Stringifying the exception or traceback would involve
     643                 :            :              * memory allocation and thus potential for deadlock.
     644                 :            :              * We've already faced potential deadlock by calling back
     645                 :            :              * into Python in the first place, so it probably doesn't
     646                 :            :              * matter but we avoid it to minimize the possibility. */
     647                 :          0 :             err_msg = "Exception occurred in preexec_fn.";
     648                 :          0 :             errno = 0;  /* We don't want to report an OSError. */
     649                 :          0 :             goto error;
     650                 :            :         }
     651                 :            :         /* Py_DECREF(result); - We're about to exec so why bother? */
     652                 :            :     }
     653                 :            : 
     654                 :            :     /* close FDs after executing preexec_fn, which might open FDs */
     655         [ +  - ]:       5561 :     if (close_fds) {
     656                 :            :         /* TODO HP-UX could use pstat_getproc() if anyone cares about it. */
     657                 :       5561 :         _close_open_fds(3, py_fds_to_keep);
     658                 :            :     }
     659                 :            : 
     660                 :            :     /* This loop matches the Lib/os.py _execvpe()'s PATH search when */
     661                 :            :     /* given the executable_list generated by Lib/subprocess.py.     */
     662                 :       5561 :     saved_errno = 0;
     663         [ +  + ]:      22645 :     for (i = 0; exec_array[i] != NULL; ++i) {
     664                 :      20574 :         const char *executable = exec_array[i];
     665         [ +  + ]:      20574 :         if (envp) {
     666                 :       2186 :             execve(executable, argv, envp);
     667                 :            :         } else {
     668                 :      18388 :             execv(executable, argv);
     669                 :            :         }
     670   [ -  +  -  -  :      17084 :         if (errno != ENOENT && errno != ENOTDIR && saved_errno == 0) {
                   -  - ]
     671                 :          0 :             saved_errno = errno;
     672                 :            :         }
     673                 :            :     }
     674                 :            :     /* Report the first exec error, not the last. */
     675         [ +  - ]:       2071 :     if (saved_errno)
     676                 :          0 :         errno = saved_errno;
     677                 :            : 
     678                 :       2071 : error:
     679                 :       2074 :     saved_errno = errno;
     680                 :            :     /* Report the posix error to our parent process. */
     681                 :            :     /* We ignore all write() return values as the total size of our writes is
     682                 :            :        less than PIPEBUF and we cannot do anything about an error anyways.
     683                 :            :        Use _Py_write_noraise() to retry write() if it is interrupted by a
     684                 :            :        signal (fails with EINTR). */
     685         [ +  - ]:       2074 :     if (saved_errno) {
     686                 :            :         char *cur;
     687                 :       2074 :         _Py_write_noraise(errpipe_write, "OSError:", 8);
     688                 :       2074 :         cur = hex_errno + sizeof(hex_errno);
     689   [ +  +  +  - ]:       4148 :         while (saved_errno != 0 && cur != hex_errno) {
     690                 :       2074 :             *--cur = Py_hexdigits[saved_errno % 16];
     691                 :       2074 :             saved_errno /= 16;
     692                 :            :         }
     693                 :       2074 :         _Py_write_noraise(errpipe_write, cur, hex_errno + sizeof(hex_errno) - cur);
     694                 :       2074 :         _Py_write_noraise(errpipe_write, ":", 1);
     695         [ +  + ]:       2074 :         if (!reached_preexec) {
     696                 :            :             /* Indicate to the parent that the error happened before exec(). */
     697                 :          3 :             _Py_write_noraise(errpipe_write, "noexec", 6);
     698                 :            :         }
     699                 :            :         /* We can't call strerror(saved_errno).  It is not async signal safe.
     700                 :            :          * The parent process will look the error message up. */
     701                 :            :     } else {
     702                 :          0 :         _Py_write_noraise(errpipe_write, "SubprocessError:0:", 18);
     703                 :          0 :         _Py_write_noraise(errpipe_write, err_msg, strlen(err_msg));
     704                 :            :     }
     705                 :       2074 : }
     706                 :            : 
     707                 :            : 
     708                 :            : /* The main purpose of this wrapper function is to isolate vfork() from both
     709                 :            :  * subprocess_fork_exec() and child_exec(). A child process created via
     710                 :            :  * vfork() executes on the same stack as the parent process while the latter is
     711                 :            :  * suspended, so this function should not be inlined to avoid compiler bugs
     712                 :            :  * that might clobber data needed by the parent later. Additionally,
     713                 :            :  * child_exec() should not be inlined to avoid spurious -Wclobber warnings from
     714                 :            :  * GCC (see bpo-35823).
     715                 :            :  */
     716                 :            : Py_NO_INLINE static pid_t
     717                 :       5589 : do_fork_exec(char *const exec_array[],
     718                 :            :              char *const argv[],
     719                 :            :              char *const envp[],
     720                 :            :              const char *cwd,
     721                 :            :              int p2cread, int p2cwrite,
     722                 :            :              int c2pread, int c2pwrite,
     723                 :            :              int errread, int errwrite,
     724                 :            :              int errpipe_read, int errpipe_write,
     725                 :            :              int close_fds, int restore_signals,
     726                 :            :              int call_setsid, pid_t pgid_to_set,
     727                 :            :              int call_setgid, gid_t gid,
     728                 :            :              int call_setgroups, size_t groups_size, const gid_t *groups,
     729                 :            :              int call_setuid, uid_t uid, int child_umask,
     730                 :            :              const void *child_sigmask,
     731                 :            :              PyObject *py_fds_to_keep,
     732                 :            :              PyObject *preexec_fn,
     733                 :            :              PyObject *preexec_fn_args_tuple)
     734                 :            : {
     735                 :            : 
     736                 :            :     pid_t pid;
     737                 :            : 
     738                 :            : #ifdef VFORK_USABLE
     739         [ +  + ]:       5589 :     if (child_sigmask) {
     740                 :            :         /* These are checked by our caller; verify them in debug builds. */
     741                 :            :         assert(!call_setuid);
     742                 :            :         assert(!call_setgid);
     743                 :            :         assert(!call_setgroups);
     744                 :            :         assert(preexec_fn == Py_None);
     745                 :            : 
     746                 :       5564 :         pid = vfork();
     747         [ -  + ]:      11128 :         if (pid == -1) {
     748                 :            :             /* If vfork() fails, fall back to using fork(). When it isn't
     749                 :            :              * allowed in a process by the kernel, vfork can return -1
     750                 :            :              * with errno EINVAL. https://bugs.python.org/issue47151. */
     751                 :          0 :             pid = fork();
     752                 :            :         }
     753                 :            :     } else
     754                 :            : #endif
     755                 :            :     {
     756                 :         25 :         pid = fork();
     757                 :            :     }
     758                 :            : 
     759         [ +  + ]:      11153 :     if (pid != 0) {
     760                 :       5589 :         return pid;
     761                 :            :     }
     762                 :            : 
     763                 :            :     /* Child process.
     764                 :            :      * See the comment above child_exec() for restrictions imposed on
     765                 :            :      * the code below.
     766                 :            :      */
     767                 :            : 
     768         [ -  + ]:       5564 :     if (preexec_fn != Py_None) {
     769                 :            :         /* We'll be calling back into Python later so we need to do this.
     770                 :            :          * This call may not be async-signal-safe but neither is calling
     771                 :            :          * back into Python.  The user asked us to use hope as a strategy
     772                 :            :          * to avoid deadlock... */
     773                 :          0 :         PyOS_AfterFork_Child();
     774                 :            :     }
     775                 :            : 
     776                 :       5564 :     child_exec(exec_array, argv, envp, cwd,
     777                 :            :                p2cread, p2cwrite, c2pread, c2pwrite,
     778                 :            :                errread, errwrite, errpipe_read, errpipe_write,
     779                 :            :                close_fds, restore_signals, call_setsid, pgid_to_set,
     780                 :            :                call_setgid, gid, call_setgroups, groups_size, groups,
     781                 :            :                call_setuid, uid, child_umask, child_sigmask,
     782                 :            :                py_fds_to_keep, preexec_fn, preexec_fn_args_tuple);
     783                 :       2074 :     _exit(255);
     784                 :            :     return 0;  /* Dead code to avoid a potential compiler warning. */
     785                 :            : }
     786                 :            : 
     787                 :            : 
     788                 :            : static PyObject *
     789                 :       5613 : subprocess_fork_exec(PyObject *module, PyObject *args)
     790                 :            : {
     791                 :       5613 :     PyObject *gc_module = NULL;
     792                 :            :     PyObject *executable_list, *py_fds_to_keep;
     793                 :            :     PyObject *env_list, *preexec_fn;
     794                 :       5613 :     PyObject *process_args, *converted_args = NULL, *fast_args = NULL;
     795                 :       5613 :     PyObject *preexec_fn_args_tuple = NULL;
     796                 :            :     PyObject *groups_list;
     797                 :            :     PyObject *uid_object, *gid_object;
     798                 :            :     int p2cread, p2cwrite, c2pread, c2pwrite, errread, errwrite;
     799                 :            :     int errpipe_read, errpipe_write, close_fds, restore_signals;
     800                 :            :     int call_setsid;
     801                 :       5613 :     pid_t pgid_to_set = -1;
     802                 :       5613 :     int call_setgid = 0, call_setgroups = 0, call_setuid = 0;
     803                 :            :     uid_t uid;
     804                 :       5613 :     gid_t gid, *groups = NULL;
     805                 :            :     int child_umask;
     806                 :       5613 :     PyObject *cwd_obj, *cwd_obj2 = NULL;
     807                 :            :     const char *cwd;
     808                 :       5613 :     pid_t pid = -1;
     809                 :       5613 :     int need_to_reenable_gc = 0;
     810                 :       5613 :     char *const *exec_array, *const *argv = NULL, *const *envp = NULL;
     811                 :       5613 :     Py_ssize_t arg_num, num_groups = 0;
     812                 :       5613 :     int need_after_fork = 0;
     813                 :       5613 :     int saved_errno = 0;
     814                 :            :     int allow_vfork;
     815                 :            : 
     816         [ -  + ]:       5613 :     if (!PyArg_ParseTuple(
     817                 :            :             args, "OOpO!OOiiiiiiiiii" _Py_PARSE_PID "OOOiOp:fork_exec",
     818                 :            :             &process_args, &executable_list,
     819                 :            :             &close_fds, &PyTuple_Type, &py_fds_to_keep,
     820                 :            :             &cwd_obj, &env_list,
     821                 :            :             &p2cread, &p2cwrite, &c2pread, &c2pwrite,
     822                 :            :             &errread, &errwrite, &errpipe_read, &errpipe_write,
     823                 :            :             &restore_signals, &call_setsid, &pgid_to_set,
     824                 :            :             &gid_object, &groups_list, &uid_object, &child_umask,
     825                 :            :             &preexec_fn, &allow_vfork))
     826                 :          0 :         return NULL;
     827                 :            : 
     828   [ +  +  -  + ]:       5632 :     if ((preexec_fn != Py_None) &&
     829                 :         19 :             (PyInterpreterState_Get() != PyInterpreterState_Main())) {
     830                 :          0 :         PyErr_SetString(PyExc_RuntimeError,
     831                 :            :                         "preexec_fn not supported within subinterpreters");
     832                 :          0 :         return NULL;
     833                 :            :     }
     834                 :            : 
     835   [ +  +  -  + ]:       5613 :     if (close_fds && errpipe_write < 3) {  /* precondition */
     836                 :          0 :         PyErr_SetString(PyExc_ValueError, "errpipe_write must be >= 3");
     837                 :          0 :         return NULL;
     838                 :            :     }
     839         [ +  + ]:       5613 :     if (_sanity_check_python_fd_sequence(py_fds_to_keep)) {
     840                 :          6 :         PyErr_SetString(PyExc_ValueError, "bad value(s) in fds_to_keep");
     841                 :          6 :         return NULL;
     842                 :            :     }
     843                 :            : 
     844                 :       5607 :     PyInterpreterState *interp = PyInterpreterState_Get();
     845                 :       5607 :     const PyConfig *config = _PyInterpreterState_GetConfig(interp);
     846         [ -  + ]:       5607 :     if (config->_isolated_interpreter) {
     847                 :          0 :         PyErr_SetString(PyExc_RuntimeError,
     848                 :            :                         "subprocess not supported for isolated subinterpreters");
     849                 :          0 :         return NULL;
     850                 :            :     }
     851                 :            : 
     852                 :            :     /* We need to call gc.disable() when we'll be calling preexec_fn */
     853         [ +  + ]:       5607 :     if (preexec_fn != Py_None) {
     854                 :         19 :         need_to_reenable_gc = PyGC_Disable();
     855                 :            :     }
     856                 :            : 
     857                 :       5607 :     exec_array = _PySequence_BytesToCharpArray(executable_list);
     858         [ +  + ]:       5607 :     if (!exec_array)
     859                 :          5 :         goto cleanup;
     860                 :            : 
     861                 :            :     /* Convert args and env into appropriate arguments for exec() */
     862                 :            :     /* These conversions are done in the parent process to avoid allocating
     863                 :            :        or freeing memory in the child process. */
     864         [ +  - ]:       5602 :     if (process_args != Py_None) {
     865                 :            :         Py_ssize_t num_args;
     866                 :            :         /* Equivalent to:  */
     867                 :            :         /*  tuple(PyUnicode_FSConverter(arg) for arg in process_args)  */
     868                 :       5602 :         fast_args = PySequence_Fast(process_args, "argv must be a tuple");
     869         [ +  + ]:       5602 :         if (fast_args == NULL)
     870                 :          2 :             goto cleanup;
     871         [ +  - ]:       5600 :         num_args = PySequence_Fast_GET_SIZE(fast_args);
     872                 :       5600 :         converted_args = PyTuple_New(num_args);
     873         [ -  + ]:       5600 :         if (converted_args == NULL)
     874                 :          0 :             goto cleanup;
     875         [ +  + ]:      31313 :         for (arg_num = 0; arg_num < num_args; ++arg_num) {
     876                 :            :             PyObject *borrowed_arg, *converted_arg;
     877   [ +  -  -  + ]:      25715 :             if (PySequence_Fast_GET_SIZE(fast_args) != num_args) {
     878                 :          0 :                 PyErr_SetString(PyExc_RuntimeError, "args changed during iteration");
     879                 :          2 :                 goto cleanup;
     880                 :            :             }
     881         [ +  - ]:      25715 :             borrowed_arg = PySequence_Fast_GET_ITEM(fast_args, arg_num);
     882         [ +  + ]:      25715 :             if (PyUnicode_FSConverter(borrowed_arg, &converted_arg) == 0)
     883                 :          2 :                 goto cleanup;
     884                 :      25713 :             PyTuple_SET_ITEM(converted_args, arg_num, converted_arg);
     885                 :            :         }
     886                 :            : 
     887                 :       5598 :         argv = _PySequence_BytesToCharpArray(converted_args);
     888         [ +  - ]:       5598 :         Py_CLEAR(converted_args);
     889         [ +  - ]:       5598 :         Py_CLEAR(fast_args);
     890         [ -  + ]:       5598 :         if (!argv)
     891                 :          0 :             goto cleanup;
     892                 :            :     }
     893                 :            : 
     894         [ +  + ]:       5598 :     if (env_list != Py_None) {
     895                 :       1820 :         envp = _PySequence_BytesToCharpArray(env_list);
     896         [ +  + ]:       1820 :         if (!envp)
     897                 :          5 :             goto cleanup;
     898                 :            :     }
     899                 :            : 
     900         [ +  + ]:       5593 :     if (cwd_obj != Py_None) {
     901         [ +  + ]:        538 :         if (PyUnicode_FSConverter(cwd_obj, &cwd_obj2) == 0)
     902                 :          1 :             goto cleanup;
     903                 :        537 :         cwd = PyBytes_AsString(cwd_obj2);
     904                 :            :     } else {
     905                 :       5055 :         cwd = NULL;
     906                 :            :     }
     907                 :            : 
     908         [ +  + ]:       5592 :     if (groups_list != Py_None) {
     909                 :            : #ifdef HAVE_SETGROUPS
     910                 :            :         Py_ssize_t i;
     911                 :            :         gid_t gid;
     912                 :            : 
     913         [ -  + ]:          2 :         if (!PyList_Check(groups_list)) {
     914                 :          0 :             PyErr_SetString(PyExc_TypeError,
     915                 :            :                     "setgroups argument must be a list");
     916                 :          1 :             goto cleanup;
     917                 :            :         }
     918                 :          2 :         num_groups = PySequence_Size(groups_list);
     919                 :            : 
     920         [ -  + ]:          2 :         if (num_groups < 0)
     921                 :          0 :             goto cleanup;
     922                 :            : 
     923         [ -  + ]:          2 :         if (num_groups > MAX_GROUPS) {
     924                 :          0 :             PyErr_SetString(PyExc_ValueError, "too many groups");
     925                 :          0 :             goto cleanup;
     926                 :            :         }
     927                 :            : 
     928         [ -  + ]:          2 :         if ((groups = PyMem_RawMalloc(num_groups * sizeof(gid_t))) == NULL) {
     929                 :          0 :             PyErr_SetString(PyExc_MemoryError,
     930                 :            :                     "failed to allocate memory for group list");
     931                 :          0 :             goto cleanup;
     932                 :            :         }
     933                 :            : 
     934         [ +  + ]:          4 :         for (i = 0; i < num_groups; i++) {
     935                 :            :             PyObject *elem;
     936                 :          3 :             elem = PySequence_GetItem(groups_list, i);
     937         [ -  + ]:          3 :             if (!elem)
     938                 :          0 :                 goto cleanup;
     939         [ -  + ]:          3 :             if (!PyLong_Check(elem)) {
     940                 :          0 :                 PyErr_SetString(PyExc_TypeError,
     941                 :            :                                 "groups must be integers");
     942                 :          0 :                 Py_DECREF(elem);
     943                 :          0 :                 goto cleanup;
     944                 :            :             } else {
     945         [ +  + ]:          3 :                 if (!_Py_Gid_Converter(elem, &gid)) {
     946                 :          1 :                     Py_DECREF(elem);
     947                 :          1 :                     PyErr_SetString(PyExc_ValueError, "invalid group id");
     948                 :          1 :                     goto cleanup;
     949                 :            :                 }
     950                 :          2 :                 groups[i] = gid;
     951                 :            :             }
     952                 :          2 :             Py_DECREF(elem);
     953                 :            :         }
     954                 :          1 :         call_setgroups = 1;
     955                 :            : 
     956                 :            : #else /* HAVE_SETGROUPS */
     957                 :            :         PyErr_BadInternalCall();
     958                 :            :         goto cleanup;
     959                 :            : #endif /* HAVE_SETGROUPS */
     960                 :            :     }
     961                 :            : 
     962         [ +  + ]:       5591 :     if (gid_object != Py_None) {
     963                 :            : #ifdef HAVE_SETREGID
     964         [ +  + ]:          7 :         if (!_Py_Gid_Converter(gid_object, &gid))
     965                 :          1 :             goto cleanup;
     966                 :            : 
     967                 :          6 :         call_setgid = 1;
     968                 :            : 
     969                 :            : #else /* HAVE_SETREGID */
     970                 :            :         PyErr_BadInternalCall();
     971                 :            :         goto cleanup;
     972                 :            : #endif /* HAVE_SETREUID */
     973                 :            :     }
     974                 :            : 
     975         [ +  + ]:       5590 :     if (uid_object != Py_None) {
     976                 :            : #ifdef HAVE_SETREUID
     977         [ +  + ]:          7 :         if (!_Py_Uid_Converter(uid_object, &uid))
     978                 :          1 :             goto cleanup;
     979                 :            : 
     980                 :          6 :         call_setuid = 1;
     981                 :            : 
     982                 :            : #else /* HAVE_SETREUID */
     983                 :            :         PyErr_BadInternalCall();
     984                 :            :         goto cleanup;
     985                 :            : #endif /* HAVE_SETREUID */
     986                 :            :     }
     987                 :            : 
     988                 :            :     /* This must be the last thing done before fork() because we do not
     989                 :            :      * want to call PyOS_BeforeFork() if there is any chance of another
     990                 :            :      * error leading to the cleanup: code without calling fork(). */
     991         [ +  + ]:       5589 :     if (preexec_fn != Py_None) {
     992                 :         12 :         preexec_fn_args_tuple = PyTuple_New(0);
     993         [ -  + ]:         12 :         if (!preexec_fn_args_tuple)
     994                 :          0 :             goto cleanup;
     995                 :         12 :         PyOS_BeforeFork();
     996                 :         12 :         need_after_fork = 1;
     997                 :            :     }
     998                 :            : 
     999                 :            :     /* NOTE: When old_sigmask is non-NULL, do_fork_exec() may use vfork(). */
    1000                 :       5589 :     const void *old_sigmask = NULL;
    1001                 :            : #ifdef VFORK_USABLE
    1002                 :            :     /* Use vfork() only if it's safe. See the comment above child_exec(). */
    1003                 :            :     sigset_t old_sigs;
    1004   [ +  +  +  -  :       5589 :     if (preexec_fn == Py_None && allow_vfork &&
                   +  + ]
    1005   [ +  +  +  + ]:       5571 :         !call_setuid && !call_setgid && !call_setgroups) {
    1006                 :            :         /* Block all signals to ensure that no signal handlers are run in the
    1007                 :            :          * child process while it shares memory with us. Note that signals
    1008                 :            :          * used internally by C libraries won't be blocked by
    1009                 :            :          * pthread_sigmask(), but signal handlers installed by C libraries
    1010                 :            :          * normally service only signals originating from *within the process*,
    1011                 :            :          * so it should be sufficient to consider any library function that
    1012                 :            :          * might send such a signal to be vfork-unsafe and do not call it in
    1013                 :            :          * the child.
    1014                 :            :          */
    1015                 :            :         sigset_t all_sigs;
    1016                 :       5564 :         sigfillset(&all_sigs);
    1017         [ -  + ]:       5564 :         if ((saved_errno = pthread_sigmask(SIG_BLOCK, &all_sigs, &old_sigs))) {
    1018                 :          0 :             goto cleanup;
    1019                 :            :         }
    1020                 :       5564 :         old_sigmask = &old_sigs;
    1021                 :            :     }
    1022                 :            : #endif
    1023                 :            : 
    1024                 :       5589 :     pid = do_fork_exec(exec_array, argv, envp, cwd,
    1025                 :            :                        p2cread, p2cwrite, c2pread, c2pwrite,
    1026                 :            :                        errread, errwrite, errpipe_read, errpipe_write,
    1027                 :            :                        close_fds, restore_signals, call_setsid, pgid_to_set,
    1028                 :            :                        call_setgid, gid, call_setgroups, num_groups, groups,
    1029                 :            :                        call_setuid, uid, child_umask, old_sigmask,
    1030                 :            :                        py_fds_to_keep, preexec_fn, preexec_fn_args_tuple);
    1031                 :            : 
    1032                 :            :     /* Parent (original) process */
    1033         [ +  + ]:       5589 :     if (pid == -1) {
    1034                 :            :         /* Capture errno for the exception. */
    1035                 :          1 :         saved_errno = errno;
    1036                 :            :     }
    1037                 :            : 
    1038                 :            : #ifdef VFORK_USABLE
    1039         [ +  + ]:       5589 :     if (old_sigmask) {
    1040                 :            :         /* vfork() semantics guarantees that the parent is blocked
    1041                 :            :          * until the child performs _exit() or execve(), so it is safe
    1042                 :            :          * to unblock signals once we're here.
    1043                 :            :          * Note that in environments where vfork() is implemented as fork(),
    1044                 :            :          * such as QEMU user-mode emulation, the parent won't be blocked,
    1045                 :            :          * but it won't share the address space with the child,
    1046                 :            :          * so it's still safe to unblock the signals.
    1047                 :            :          *
    1048                 :            :          * We don't handle errors here because this call can't fail
    1049                 :            :          * if valid arguments are given, and because there is no good
    1050                 :            :          * way for the caller to deal with a failure to restore
    1051                 :            :          * the thread signal mask. */
    1052                 :       5564 :         (void) pthread_sigmask(SIG_SETMASK, old_sigmask, NULL);
    1053                 :            :     }
    1054                 :            : #endif
    1055                 :            : 
    1056         [ +  + ]:       5589 :     if (need_after_fork)
    1057                 :         12 :         PyOS_AfterFork_Parent();
    1058                 :            : 
    1059                 :       5577 : cleanup:
    1060         [ +  + ]:       5607 :     if (saved_errno != 0) {
    1061                 :          1 :         errno = saved_errno;
    1062                 :            :         /* We can't call this above as PyOS_AfterFork_Parent() calls back
    1063                 :            :          * into Python code which would see the unreturned error. */
    1064                 :          1 :         PyErr_SetFromErrno(PyExc_OSError);
    1065                 :            :     }
    1066                 :            : 
    1067                 :       5607 :     Py_XDECREF(preexec_fn_args_tuple);
    1068                 :       5607 :     PyMem_RawFree(groups);
    1069                 :       5607 :     Py_XDECREF(cwd_obj2);
    1070         [ +  + ]:       5607 :     if (envp)
    1071                 :       1815 :         _Py_FreeCharPArray(envp);
    1072                 :       5607 :     Py_XDECREF(converted_args);
    1073                 :       5607 :     Py_XDECREF(fast_args);
    1074         [ +  + ]:       5607 :     if (argv)
    1075                 :       5598 :         _Py_FreeCharPArray(argv);
    1076         [ +  + ]:       5607 :     if (exec_array)
    1077                 :       5602 :         _Py_FreeCharPArray(exec_array);
    1078                 :            : 
    1079         [ +  + ]:       5607 :     if (need_to_reenable_gc) {
    1080                 :         18 :         PyGC_Enable();
    1081                 :            :     }
    1082                 :       5607 :     Py_XDECREF(gc_module);
    1083                 :            : 
    1084         [ +  + ]:       5607 :     return pid == -1 ? NULL : PyLong_FromPid(pid);
    1085                 :            : }
    1086                 :            : 
    1087                 :            : 
    1088                 :            : PyDoc_STRVAR(subprocess_fork_exec_doc,
    1089                 :            : "fork_exec(args, executable_list, close_fds, pass_fds, cwd, env,\n\
    1090                 :            :           p2cread, p2cwrite, c2pread, c2pwrite,\n\
    1091                 :            :           errread, errwrite, errpipe_read, errpipe_write,\n\
    1092                 :            :           restore_signals, call_setsid, pgid_to_set,\n\
    1093                 :            :           gid, groups_list, uid,\n\
    1094                 :            :           preexec_fn)\n\
    1095                 :            : \n\
    1096                 :            : Forks a child process, closes parent file descriptors as appropriate in the\n\
    1097                 :            : child and dups the few that are needed before calling exec() in the child\n\
    1098                 :            : process.\n\
    1099                 :            : \n\
    1100                 :            : If close_fds is true, close file descriptors 3 and higher, except those listed\n\
    1101                 :            : in the sorted tuple pass_fds.\n\
    1102                 :            : \n\
    1103                 :            : The preexec_fn, if supplied, will be called immediately before closing file\n\
    1104                 :            : descriptors and exec.\n\
    1105                 :            : WARNING: preexec_fn is NOT SAFE if your application uses threads.\n\
    1106                 :            :          It may trigger infrequent, difficult to debug deadlocks.\n\
    1107                 :            : \n\
    1108                 :            : If an error occurs in the child process before the exec, it is\n\
    1109                 :            : serialized and written to the errpipe_write fd per subprocess.py.\n\
    1110                 :            : \n\
    1111                 :            : Returns: the child process's PID.\n\
    1112                 :            : \n\
    1113                 :            : Raises: Only on an error in the parent process.\n\
    1114                 :            : ");
    1115                 :            : 
    1116                 :            : /* module level code ********************************************************/
    1117                 :            : 
    1118                 :            : PyDoc_STRVAR(module_doc,
    1119                 :            : "A POSIX helper for the subprocess module.");
    1120                 :            : 
    1121                 :            : static PyMethodDef module_methods[] = {
    1122                 :            :     {"fork_exec", subprocess_fork_exec, METH_VARARGS, subprocess_fork_exec_doc},
    1123                 :            :     {NULL, NULL}  /* sentinel */
    1124                 :            : };
    1125                 :            : 
    1126                 :            : static PyModuleDef_Slot _posixsubprocess_slots[] = {
    1127                 :            :     {0, NULL}
    1128                 :            : };
    1129                 :            : 
    1130                 :            : static struct PyModuleDef _posixsubprocessmodule = {
    1131                 :            :         PyModuleDef_HEAD_INIT,
    1132                 :            :         .m_name = "_posixsubprocess",
    1133                 :            :         .m_doc = module_doc,
    1134                 :            :         .m_size = 0,
    1135                 :            :         .m_methods = module_methods,
    1136                 :            :         .m_slots = _posixsubprocess_slots,
    1137                 :            : };
    1138                 :            : 
    1139                 :            : PyMODINIT_FUNC
    1140                 :       1198 : PyInit__posixsubprocess(void)
    1141                 :            : {
    1142                 :       1198 :     return PyModuleDef_Init(&_posixsubprocessmodule);
    1143                 :            : }

Generated by: LCOV version 1.14