This is the mail archive of the libc-alpha@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2 2/5] posix: Add posix_spawn_file_actions_closefrom


Ping.

On 31/07/2019 15:31, Adhemerval Zanella wrote:
> Changes from previous version:
> 
>   - Remove __spawn_valid_fd check on posix_spawn_file_actions_addclosefrom.
> 
>   - Rename __SUPPORT_SPAWN_CLOSEFROM macro to __SPAWN_SUPPORT_CLOSEFROM.
> 
>   - Use getdents64 instead of changing add internal __opendir_inplace.
> 
> Regarding the lseek to reset the descriptor offset after each file removal,
> I think that by iteracting the descriptor based on getdents64 results there
> is no real need for it.  The kernel returns the fds sequentially and there
> is no open operations done concurrently, so both my expectations and the
> tests result is getdents returns an updated version after a close() call.
> 
> --
> 
> This patch adds a way to close a range of file descriptors on posix_spawn
> as a new file action.  The API is similar to the one provided by Solaris
> 11 [1], where the file action causes the all open file descriptors greater
> than or equal to input on to be closed when the new process is spawned.
> 
> There are some discussions on BZ#10353 [2], although the bug itself asks
> for a generic solution (similar to the closeall provided by some BSD).
> The posix_spawn is safe to be implemented by interacting over /proc/self/fd,
> the Linux spawni.c does not use CLONE_FILES, so the helper process has its
> own file descriptor table and any failure (in /proc operation) aborts the
> process creation and returns an error to the caller.
> 
> I am aware that this file action might be redundant to the current approach
> of POSIX in promoting O_CLOEXEC in more interfaces. However O_CLOEXEC is still
> not the default and for some specific usages, the caller needs to close all
> possible file descriptors to avoid them leaking.  Some examples are CPython
> (discussed in BZ#10353) and OpenJDK jspawnhelper [3] (where OpenJDK spawns a
> helper process to exactly closes all file descriptors).  Most likely any
> environment which calls functions that might open file descriptor under the
> hood and aim to use posix_spawn might face the same requirement.
> 
> Checked on x86_64-linux-gnu, i686-linux-gnu, powerpc64le-linux-gnu, and
> aarch64-linux-gnu.
> 
> 	* posix/Makefile (routines): Add spawn_faction_addclosefrom.
> 	(tests): Add tst-spawn5.
> 	(tst-spawn5-ARGS): New rule.
> 	* posix/Versions [GLIBC_2.30] (libc): Add
> 	posix_spawn_file_actions_addclosefrom_np.
> 	* posix/spawn.h (posix_spawn_file_actions_addclosefrom_np): New
> 	prototype.
> 	* posix/spawn_faction_addclosefrom.c: New file
> 	* posix/spawn_faction_destroy.c (__posix_spawn_file_actions_destroy):
> 	Handle spawn_do_closefrom.
> 	* posix/spawn_int.h (__spawn_action): Add closefrom_action and
> 	spawn_do_closefrom.
> 	* posix/spawn_int_abi.h: New file.
> 	* sysdeps/unix/sysv/linux/spawn_int_abi.h: Likewise.
> 	* posix/tst-spawn5.c: Likewise.
> 	* sysdeps/mach/hurd/spawni.c (__spawni, __spawni_child): Handle
> 	spawn_do_closefrom.
> 	* sysdeps/posix/spawni.c (__spawni_child): Likewise.
> 	* sysdeps/unix/sysv/linux/spawni.c (__spawni_child, __spawnix):
> 	Likewise.
> 	(spawn_closefrom): New function.
> 	* sysdeps/mach/hurd/i386/libc.abilist (2.30): Add
> 	posix_spawn_file_actions_addclosefrom_np.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/csky/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
> ---
>  posix/Makefile                                |   5 +-
>  posix/Versions                                |   1 +
>  posix/spawn.h                                 |   7 +
>  posix/spawn_faction_addclosefrom.c            |  58 +++++
>  posix/spawn_faction_destroy.c                 |   1 +
>  posix/spawn_int.h                             |   6 +
>  posix/spawn_int_abi.h                         |  27 +++
>  posix/tst-spawn5.c                            | 210 ++++++++++++++++++
>  sysdeps/mach/hurd/i386/libc.abilist           |   1 +
>  sysdeps/mach/hurd/spawni.c                    |   4 +
>  sysdeps/posix/spawni.c                        |   4 +
>  sysdeps/unix/sysv/linux/aarch64/libc.abilist  |   1 +
>  sysdeps/unix/sysv/linux/alpha/libc.abilist    |   1 +
>  sysdeps/unix/sysv/linux/arm/libc.abilist      |   1 +
>  sysdeps/unix/sysv/linux/csky/libc.abilist     |   1 +
>  sysdeps/unix/sysv/linux/hppa/libc.abilist     |   1 +
>  sysdeps/unix/sysv/linux/i386/libc.abilist     |   1 +
>  sysdeps/unix/sysv/linux/ia64/libc.abilist     |   1 +
>  .../sysv/linux/m68k/coldfire/libc.abilist     |   1 +
>  .../unix/sysv/linux/m68k/m680x0/libc.abilist  |   1 +
>  .../unix/sysv/linux/microblaze/libc.abilist   |   1 +
>  .../sysv/linux/mips/mips32/fpu/libc.abilist   |   1 +
>  .../sysv/linux/mips/mips32/nofpu/libc.abilist |   1 +
>  .../sysv/linux/mips/mips64/n32/libc.abilist   |   1 +
>  .../sysv/linux/mips/mips64/n64/libc.abilist   |   1 +
>  sysdeps/unix/sysv/linux/nios2/libc.abilist    |   1 +
>  .../linux/powerpc/powerpc32/fpu/libc.abilist  |   1 +
>  .../linux/powerpc/powerpc64/be/libc.abilist   |   1 +
>  .../linux/powerpc/powerpc64/le/libc.abilist   |   1 +
>  .../unix/sysv/linux/riscv/rv64/libc.abilist   |   1 +
>  .../unix/sysv/linux/s390/s390-32/libc.abilist |   1 +
>  .../unix/sysv/linux/s390/s390-64/libc.abilist |   1 +
>  sysdeps/unix/sysv/linux/sh/libc.abilist       |   1 +
>  .../sysv/linux/sparc/sparc32/libc.abilist     |   1 +
>  .../sysv/linux/sparc/sparc64/libc.abilist     |   1 +
>  sysdeps/unix/sysv/linux/spawn_int_abi.h       |  25 +++
>  sysdeps/unix/sysv/linux/spawni.c              |  62 +++++-
>  .../unix/sysv/linux/x86_64/64/libc.abilist    |   1 +
>  .../unix/sysv/linux/x86_64/x32/libc.abilist   |   1 +
>  39 files changed, 425 insertions(+), 12 deletions(-)
>  create mode 100644 posix/spawn_faction_addclosefrom.c
>  create mode 100644 posix/spawn_int_abi.h
>  create mode 100644 posix/tst-spawn5.c
>  create mode 100644 sysdeps/unix/sysv/linux/spawn_int_abi.h
> 
> diff --git a/posix/Makefile b/posix/Makefile
> index 8ac6743ad7..1ac41ad85a 100644
> --- a/posix/Makefile
> +++ b/posix/Makefile
> @@ -57,6 +57,7 @@ routines :=								      \
>  	spawn_faction_init spawn_faction_destroy spawn_faction_addclose	      \
>  	spawn_faction_addopen spawn_faction_adddup2 spawn_valid_fd	      \
>  	spawn_faction_addchdir spawn_faction_addfchdir			      \
> +	spawn_faction_addclosefrom					      \
>  	spawnattr_init spawnattr_destroy				      \
>  	spawnattr_getdefault spawnattr_setdefault			      \
>  	spawnattr_getflags spawnattr_setflags				      \
> @@ -100,7 +101,8 @@ tests		:= test-errno tstgetopt testfnm runtests runptests \
>  		   tst-posix_fadvise tst-posix_fadvise64 \
>  		   tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
>  		   tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
> -		   bug-regex38 tst-regcomp-truncated tst-spawn-chdir
> +		   bug-regex38 tst-regcomp-truncated tst-spawn-chdir \
> +		   tst-spawn5
>  tests-internal	:= bug-regex5 bug-regex20 bug-regex33 \
>  		   tst-rfc3484 tst-rfc3484-2 tst-rfc3484-3 \
>  		   tst-glob_lstat_compat tst-spawn4-compat
> @@ -254,6 +256,7 @@ tst-exec-static-ARGS = $(tst-exec-ARGS)
>  tst-execvpe5-ARGS = -- $(host-test-program-cmd)
>  tst-spawn-ARGS = -- $(host-test-program-cmd)
>  tst-spawn-static-ARGS = $(tst-spawn-ARGS)
> +tst-spawn5-ARGS = -- $(host-test-program-cmd)
>  tst-dir-ARGS = `pwd` `cd $(common-objdir)/$(subdir); pwd` `cd $(common-objdir); pwd` $(objpfx)tst-dir
>  tst-chmod-ARGS = $(objdir)
>  tst-vfork3-ARGS = --test-dir=$(objpfx)
> diff --git a/posix/Versions b/posix/Versions
> index 7d06a6d0c0..c8268e5996 100644
> --- a/posix/Versions
> +++ b/posix/Versions
> @@ -146,6 +146,7 @@ libc {
>      posix_spawn_file_actions_addfchdir_np;
>    }
>    GLIBC_2.30 {
> +    posix_spawn_file_actions_addclosefrom_np;
>    }
>    GLIBC_PRIVATE {
>      __libc_fork; __libc_pread; __libc_pwrite;
> diff --git a/posix/spawn.h b/posix/spawn.h
> index 471dbea022..773f416b2e 100644
> --- a/posix/spawn.h
> +++ b/posix/spawn.h
> @@ -213,6 +213,13 @@ extern int posix_spawn_file_actions_addchdir_np (posix_spawn_file_actions_t *
>  extern int posix_spawn_file_actions_addfchdir_np (posix_spawn_file_actions_t *,
>  						  int __fd)
>       __THROW __nonnull ((1));
> +
> +/* Add an action to close all file descriptor greater than FROM during
> +   spawn.  This affects the subsequent file actions.  */
> +extern int posix_spawn_file_actions_addclosefrom_np (posix_spawn_file_actions_t *,
> +						     int __from)
> +     __THROW __nonnull ((1));
> +
>  #endif
>  
>  __END_DECLS
> diff --git a/posix/spawn_faction_addclosefrom.c b/posix/spawn_faction_addclosefrom.c
> new file mode 100644
> index 0000000000..52e949c8b3
> --- /dev/null
> +++ b/posix/spawn_faction_addclosefrom.c
> @@ -0,0 +1,58 @@
> +/* Add a closefrom to a file action list for posix_spawn.
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <errno.h>
> +#include <spawn.h>
> +#include <unistd.h>
> +#include <spawn_int.h>
> +
> +int
> +__posix_spawn_file_actions_addclosefrom (posix_spawn_file_actions_t
> +					 *file_actions, int from)
> +{
> +#if __SPAWN_SUPPORT_CLOSEFROM
> +  struct __spawn_action *rec;
> +
> +  if (fd < 0)
> +    return EBADF;
> +
> +  /* Allocate more memory if needed.  */
> +  if (file_actions->__used == file_actions->__allocated
> +      && __posix_spawn_file_actions_realloc (file_actions) != 0)
> +    /* This can only mean we ran out of memory.  */
> +    return ENOMEM;
> +
> +  /* Add the new value.  */
> +  rec = &file_actions->__actions[file_actions->__used];
> +  rec->tag = spawn_do_closefrom;
> +  rec->action.closefrom_action.from = from;
> +
> +  /* Account for the new entry.  */
> +  ++file_actions->__used;
> +
> +  return 0;
> +#else
> +  __set_errno (EINVAL);
> +  return -1;
> +#endif
> +}
> +weak_alias (__posix_spawn_file_actions_addclosefrom,
> +	    posix_spawn_file_actions_addclosefrom_np)
> +#if !__SPAWN_SUPPORT_CLOSEFROM
> +stub_warning (posix_spawn_file_actions_addclosefrom_np)
> +#endif
> diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c
> index 51fab13585..b45d1cd889 100644
> --- a/posix/spawn_faction_destroy.c
> +++ b/posix/spawn_faction_destroy.c
> @@ -39,6 +39,7 @@ __posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
>  	case spawn_do_close:
>  	case spawn_do_dup2:
>  	case spawn_do_fchdir:
> +	case spawn_do_closefrom:
>  	  /* No cleanup required.  */
>  	  break;
>  	}
> diff --git a/posix/spawn_int.h b/posix/spawn_int.h
> index 93b7597f90..0bc29226e4 100644
> --- a/posix/spawn_int.h
> +++ b/posix/spawn_int.h
> @@ -20,6 +20,7 @@
>  #define _SPAWN_INT_H
>  
>  #include <spawn.h>
> +#include <spawn_int_abi.h>
>  #include <stdbool.h>
>  
>  /* Data structure to contain the action information.  */
> @@ -32,6 +33,7 @@ struct __spawn_action
>      spawn_do_open,
>      spawn_do_chdir,
>      spawn_do_fchdir,
> +    spawn_do_closefrom,
>    } tag;
>  
>    union
> @@ -60,6 +62,10 @@ struct __spawn_action
>      {
>        int fd;
>      } fchdir_action;
> +    struct
> +    {
> +      int from;
> +    } closefrom_action;
>    } action;
>  };
>  
> diff --git a/posix/spawn_int_abi.h b/posix/spawn_int_abi.h
> new file mode 100644
> index 0000000000..142efed339
> --- /dev/null
> +++ b/posix/spawn_int_abi.h
> @@ -0,0 +1,27 @@
> +/* Internal ABI specific for posix_spawn functionality.  Generic version.
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SPAWN_INT_ABI_H
> +#define _SPAWN_INT_ABI_H
> +
> +/* The closefrom file actions requires either a syscall or an arch-specific
> +   way to interact over all file descriptors and act uppon them (such
> +   /proc/self/fd on Linux).  */
> +#define __SPAWN_SUPPOR_CLOSEFROM 0
> +
> +#endif /* _SPAWN_INT_H */
> diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c
> new file mode 100644
> index 0000000000..7af33a4dbe
> --- /dev/null
> +++ b/posix/tst-spawn5.c
> @@ -0,0 +1,210 @@
> +/* Tests for posix_spawn signal handling.
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <getopt.h>
> +#include <spawn.h>
> +#include <fcntl.h>
> +#include <sys/wait.h>
> +#include <dirent.h>
> +#include <stdbool.h>
> +#include <errno.h>
> +#include <limits.h>
> +
> +#include <support/check.h>
> +#include <support/xunistd.h>
> +#include <support/support.h>
> +#include <array_length.h>
> +
> +/* Nonzero if the program gets called via `exec'.  */
> +static int restart;
> +#define CMDLINE_OPTIONS \
> +  { "restart", no_argument, &restart, 1 },
> +
> +/* Called on process re-execution.  */
> +static int
> +handle_restart (int from)
> +{
> +  DIR *fds = opendir ("/proc/self/fd");
> +  if (fds == NULL)
> +    FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m");
> +
> +  while (true)
> +    {
> +      errno = 0;
> +      struct dirent64 *e = readdir64 (fds);
> +      if (e == NULL)
> +        {
> +          if (errno != 0)
> +            FAIL_EXIT1 ("readdir: %m");
> +          break;
> +        }
> +
> +      if (e->d_name[0] == '.')
> +        continue;
> +
> +      char *endptr;
> +      long int fd = strtol (e->d_name, &endptr, 10);
> +      if (*endptr != '\0' || fd < 0 || fd > INT_MAX)
> +        FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s",
> +                    e->d_name);
> +
> +      /* Skip the descriptor which is used to enumerate the
> +         descriptors.  */
> +      if (fd == dirfd (fds))
> +        continue;
> +
> +      struct stat64 st;
> +      if (fstat64 (fd, &st) != 0)
> +        FAIL_EXIT1 ("readdir: fstat64 (%ld) failed: %m", fd);
> +
> +      if (fd >= from)
> +	FAIL_EXIT1 ("error: fd (%ld) greater than from (%d)", fd, from);
> +    }
> +
> +  closedir (fds);
> +
> +  return 0;
> +}
> +
> +/* Common argument used for process re-execution.  */
> +static char *initial_spargv[5];
> +static size_t initial_spargv_size;
> +
> +/* Re-execute the test process with both '--direct', '--restart', and the
> +   TEST (as integer value) as arguments.  */
> +static void
> +reexecute (int fd, const posix_spawn_file_actions_t *fa)
> +{
> +  char *spargv[8];
> +  int i;
> +
> +  for (i = 0; i < initial_spargv_size; i++)
> +    spargv[i] = initial_spargv[i];
> +  /* Three digits per byte plus null terminator.  */
> +  char teststr[3 * sizeof (fd) + 1];
> +  snprintf (teststr, array_length (teststr), "%d", fd);
> +  spargv[i++] = teststr;
> +  spargv[i] = NULL;
> +  TEST_VERIFY (i < 8);
> +
> +  pid_t pid;
> +  int status;
> +
> +  TEST_COMPARE (posix_spawn (&pid, spargv[0], fa, NULL, spargv, environ),
> +		0);
> +  TEST_COMPARE (xwaitpid (pid, &status, 0), pid);
> +  TEST_VERIFY (WIFEXITED (status));
> +  TEST_VERIFY (!WIFSIGNALED (status));
> +  TEST_COMPARE (WEXITSTATUS (status), 0);
> +}
> +
> +static void
> +do_test_closefrom (int num_fd_to_open)
> +{
> +  int *fds = xmalloc (num_fd_to_open * sizeof (int));
> +  for (int i = 0; i < num_fd_to_open; i++)
> +    fds[i] = xopen ("/dev/null", O_WRONLY, 0);
> +
> +  posix_spawn_file_actions_t fa;
> +  /* posix_spawn_file_actions_init does not fail.  */
> +  posix_spawn_file_actions_init (&fa);
> +
> +  {
> +    int ret = posix_spawn_file_actions_addclosefrom_np (&fa, fds[0]);
> +    if (ret == -1)
> +      {
> +	if (errno == ENOSYS)
> +	  /* Hurd currently does not support closefrom fileaction.  */
> +	  FAIL_UNSUPPORTED ("posix_spawn_file_actions_addclosefrom_np unsupported");
> +        else
> +	  FAIL_EXIT1 ("posix_spawn_file_actions_addclosefrom_np failed");
> +      }
> +  }
> +
> +  /* Default check, all file descriptor from [fd[0], fd[1]) are opened.  */
> +  reexecute (fds[0], &fa);
> +
> +  /* Add a gap in the range.  */
> +  xclose (fds[num_fd_to_open/2]);
> +  xclose (fds[num_fd_to_open/2 + 1]);
> +  reexecute (fds[0], &fa);
> +
> +  /* Add another gap, at the beginning.  */
> +  xclose (fds[0]);
> +  xclose (fds[1]);
> +  reexecute (fds[0], &fa);
> +
> +  /* Add another gap, now at the end.  */
> +  xclose (fds[num_fd_to_open-1]);
> +  xclose (fds[num_fd_to_open-2]);
> +  reexecute (fds[0], &fa);
> +
> +  /* Open some more files, filling the gaps.  */
> +  for (int i = 0; i < 6; i++)
> +    xopen ("/dev/null", O_WRONLY, 0);
> +  reexecute (fds[0], &fa);
> +
> +  /* Open some more, but with O_CLOEXEC.  */
> +  for (int i = 0; i < num_fd_to_open/2; i++)
> +    xopen ("/dev/null", O_WRONLY | O_CLOEXEC, 0);
> +
> +  free (fds);
> +}
> +
> +
> +static int
> +do_test (int argc, char *argv[])
> +{
> +  /* We must have one or four parameters left if called initially:
> +       + path for ld.so		optional
> +       + "--library-path"	optional
> +       + the library path	optional
> +       + the application name
> +
> +     Plus one parameter to indicate which test to execute through
> +     re-execution.
> +
> +     So for default usage without --enable-hardcoded-path-in-tests, it
> +     will be called initially with 5 arguments and later with 2.  For
> +     --enable-hardcoded-path-in-tests it will be called with 2 arguments
> +     regardless.  */
> +
> +  if (argc != (restart ? 2 : 5) && argc != 2)
> +    FAIL_EXIT1 ("wrong number of arguments (%d)", argc);
> +
> +  if (restart)
> +    return handle_restart (atoi (argv[1]));
> +
> +  /* Respawn using the same arguments.  */
> +  for (initial_spargv_size = 0;
> +       initial_spargv_size < (argc == 5 ? 4 : 1);
> +       initial_spargv_size++)
> +    initial_spargv[initial_spargv_size] = argv[initial_spargv_size + 1];
> +  initial_spargv[initial_spargv_size++] = (char *) "--direct";
> +  initial_spargv[initial_spargv_size++] = (char *) "--restart";
> +
> +  do_test_closefrom (10);
> +  do_test_closefrom (100);
> +
> +  return 0;
> +}
> +
> +#define TEST_FUNCTION_ARGV do_test
> +#include <support/test-driver.c>
> diff --git a/sysdeps/mach/hurd/i386/libc.abilist b/sysdeps/mach/hurd/i386/libc.abilist
> index 1fc7ab2433..fcf957cfc6 100644
> --- a/sysdeps/mach/hurd/i386/libc.abilist
> +++ b/sysdeps/mach/hurd/i386/libc.abilist
> @@ -2175,6 +2175,7 @@ GLIBC_2.3.4 setipv4sourcefilter F
>  GLIBC_2.3.4 setsourcefilter F
>  GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
>  GLIBC_2.4 __fgets_chk F
> diff --git a/sysdeps/mach/hurd/spawni.c b/sysdeps/mach/hurd/spawni.c
> index e8024a2679..720e56ffb3 100644
> --- a/sysdeps/mach/hurd/spawni.c
> +++ b/sysdeps/mach/hurd/spawni.c
> @@ -597,6 +597,10 @@ __spawni (pid_t *pid, const char *file,
>  	  case spawn_do_fchdir:
>  	    err = child_fchdir (action->action.fchdir_action.fd);
>  	    break;
> +
> +	  case spawn_do_closefrom:
> +	    err = EINVAL;
> +	    break;
>  	  }
>  
>  	if (err)
> diff --git a/sysdeps/posix/spawni.c b/sysdeps/posix/spawni.c
> index a5913feb14..3beaba91db 100644
> --- a/sysdeps/posix/spawni.c
> +++ b/sysdeps/posix/spawni.c
> @@ -231,6 +231,10 @@ __spawni_child (void *arguments)
>  	      if (__fchdir (action->action.fchdir_action.fd) != 0)
>  		goto fail;
>  	      break;
> +
> +	    case spawn_do_closefrom:
> +	      __set_errno (EINVAL);
> +	      goto fail;
>  	    }
>  	}
>      }
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index a4c31932cb..e1e793b348 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2143,5 +2143,6 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index fe85a35620..735e54f433 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2218,6 +2218,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index bc3df8dcea..a3b9db6efa 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -128,6 +128,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _Exit F
> diff --git a/sysdeps/unix/sysv/linux/csky/libc.abilist b/sysdeps/unix/sysv/linux/csky/libc.abilist
> index 9b3cee65bb..88d112b9b1 100644
> --- a/sysdeps/unix/sysv/linux/csky/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/csky/libc.abilist
> @@ -2087,5 +2087,6 @@ GLIBC_2.29 xprt_register F
>  GLIBC_2.29 xprt_unregister F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 75edece94a..2925c96183 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -2039,6 +2039,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index edeaf8e722..9fd8ceb639 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2205,6 +2205,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index b5d460eeb2..37d817eeb3 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -2071,6 +2071,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 05633b3cb8..e81ab1f0bf 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -129,6 +129,7 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _Exit F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 47eb7b4608..cd5742bf63 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -2148,6 +2148,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index f7ced487f7..957b14d992 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2135,5 +2135,6 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index e49dc4272e..b8ffdea448 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -2122,6 +2122,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index daa3b60c5b..e1c861720a 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -2120,6 +2120,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index 457ce0b6f2..88fe3f4d26 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -2128,6 +2128,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index 63d5c03bfb..7c6dafa818 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -2122,6 +2122,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 7fec0c9670..487b005070 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2176,5 +2176,6 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 9200a54309..db81db978a 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -2178,6 +2178,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> index 2860df8ebc..06dfdf1fed 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/libc.abilist
> @@ -2041,6 +2041,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> index 2229a1dcc0..eb0532937e 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/libc.abilist
> @@ -2245,5 +2245,6 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> index 31010e6cf7..4985fa93e3 100644
> --- a/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/riscv/rv64/libc.abilist
> @@ -2105,5 +2105,6 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 576295deff..1ef1b9d4cc 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -2173,6 +2173,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index abf0473683..f9d9fe68ca 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -2077,6 +2077,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 41977f6e9c..1b12384dd1 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -2043,6 +2043,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 3d2f00ca52..a7c244cb56 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -2167,6 +2167,7 @@ GLIBC_2.30 __nldbl_warn F
>  GLIBC_2.30 __nldbl_warnx F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 _IO_fprintf F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index 2f20643e8e..a71facfb43 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -2094,6 +2094,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/spawn_int_abi.h b/sysdeps/unix/sysv/linux/spawn_int_abi.h
> new file mode 100644
> index 0000000000..9c4b31ccae
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/spawn_int_abi.h
> @@ -0,0 +1,25 @@
> +/* Internal ABI specific for posix_spawn functionality.  Linux version.
> +   Copyright (C) 2019 Free Software Foundation, Inc.
> +   This file is part of the GNU C Library.
> +
> +   The GNU C Library is free software; you can redistribute it and/or
> +   modify it under the terms of the GNU Lesser General Public
> +   License as published by the Free Software Foundation; either
> +   version 2.1 of the License, or (at your option) any later version.
> +
> +   The GNU C Library is distributed in the hope that it will be useful,
> +   but WITHOUT ANY WARRANTY; without even the implied warranty of
> +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> +   Lesser General Public License for more details.
> +
> +   You should have received a copy of the GNU Lesser General Public
> +   License along with the GNU C Library; if not, see
> +   <http://www.gnu.org/licenses/>.  */
> +
> +#ifndef _SPAWN_INT_ABI_H
> +#define _SPAWN_INT_ABI_H
> +
> +/* spawni.c implements closefrom by interacting over /proc/self/fd.  */
> +#define __SPAWN_SUPPORT_CLOSEFROM 1
> +
> +#endif /* _SPAWN_INT_H */
> diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
> index c1abf3f960..ca7bf99825 100644
> --- a/sysdeps/unix/sysv/linux/spawni.c
> +++ b/sysdeps/unix/sysv/linux/spawni.c
> @@ -17,20 +17,16 @@
>     <http://www.gnu.org/licenses/>.  */
>  
>  #include <spawn.h>
> -#include <fcntl.h>
>  #include <paths.h>
> -#include <string.h>
> +#include <dirent.h>
>  #include <sys/resource.h>
> -#include <sys/wait.h>
> -#include <sys/param.h>
> -#include <sys/mman.h>
>  #include <not-cancel.h>
>  #include <local-setxid.h>
>  #include <shlib-compat.h>
> -#include <nptl/pthreadP.h>
> -#include <dl-sysdep.h>
> -#include <libc-pointer-arith.h>
> +#include <sigsetops.h>
> +#include <internal-signals.h>
>  #include <ldsodefs.h>
> +#include <ctype.h>
>  #include "spawn_int.h"
>  
>  /* The Linux implementation of posix_spawn{p} uses the clone syscall directly
> @@ -114,6 +110,44 @@ maybe_script_execute (struct posix_spawn_args *args)
>      }
>  }
>  
> +/* Close all file descriptor up to FROM by interacting /proc/self/fd.  */
> +static bool
> +spawn_closefrom (int from)
> +{
> +  struct dirent64 entries[1024 / sizeof (struct dirent64)];
> +
> +  int dirfd = __open ("/proc/self/fd", O_RDONLY | O_DIRECTORY, 0);
> +  if (dirfd == -1)
> +    return false;
> +
> +  ssize_t r;
> +  while ((r = __getdents64 (dirfd, entries, sizeof (entries))) > 0)
> +    {
> +      struct dirent64 *dp = entries;
> +      struct dirent64 *edp = (void *)((uintptr_t) dp + r);
> +
> +      for (struct dirent64 *dp = entries; dp < edp;
> +	   dp = (void *)((uintptr_t) dp + dp->d_reclen))
> +	{
> +	  int fd = 0;
> +
> +	  if (dp->d_name[0] == '.')
> +	    continue;
> +
> +	  for (const char *s = dp->d_name; isdigit (*s); s++)
> +	    fd = 10 * fd + (*s - '0');
> +
> +	  if (fd == dirfd || fd < from)
> +	    continue;
> +
> +	  __close_nocancel (fd);
> +	}
> +    }
> +
> +  __close_nocancel (dirfd);
> +  return true;
> +}
> +
>  /* Function used in the clone call to setup the signals mask, posix_spawn
>     attributes, and file actions.  It run on its own stack (provided by the
>     posix_spawn call).  */
> @@ -280,6 +314,11 @@ __spawni_child (void *arguments)
>  	      if (__fchdir (action->action.fchdir_action.fd) != 0)
>  		goto fail;
>  	      break;
> +
> +	    case spawn_do_closefrom:
> +	      if (!spawn_closefrom (action->action.closefrom_action.from))
> +		goto fail;
> +	      break;
>  	    }
>  	}
>      }
> @@ -339,12 +378,13 @@ __spawnix (pid_t * pid, const char *file,
>    int prot = (PROT_READ | PROT_WRITE
>  	     | ((GL (dl_stack_flags) & PF_X) ? PROT_EXEC : 0));
>  
> -  /* Add a slack area for child's stack.  */
> -  size_t argv_size = (argc * sizeof (void *)) + 512;
> +  size_t argv_size = (argc * sizeof (void *));
>    /* We need at least a few pages in case the compiler's stack checking is
>       enabled.  In some configs, it is known to use at least 24KiB.  We use
>       32KiB to be "safe" from anything the compiler might do.  Besides, the
> -     extra pages won't actually be allocated unless they get used.  */
> +     extra pages won't actually be allocated unless they get used.
> +     It also acts the slack for spawn_closefrom (including MIPS64 getdents64
> +     where it might use about 1k extra stack space.  */
>    argv_size += (32 * 1024);
>    size_t stack_size = ALIGN_UP (argv_size, GLRO(dl_pagesize));
>    void *stack = __mmap (NULL, stack_size, prot,
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index 59f85d9373..78a43f5851 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -2052,6 +2052,7 @@ GLIBC_2.3.4 xdr_quad_t F
>  GLIBC_2.3.4 xdr_u_quad_t F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
>  GLIBC_2.4 __confstr_chk F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index 67a4e238d6..b83897ddbf 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2151,5 +2151,6 @@ GLIBC_2.29 posix_spawn_file_actions_addchdir_np F
>  GLIBC_2.29 posix_spawn_file_actions_addfchdir_np F
>  GLIBC_2.30 getdents64 F
>  GLIBC_2.30 gettid F
> +GLIBC_2.30 posix_spawn_file_actions_addclosefrom_np F
>  GLIBC_2.30 tgkill F
>  GLIBC_2.30 twalk_r F
> 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]