Message ID | 20190731183136.21545-2-adhemerval.zanella@linaro.org |
---|---|
State | New |
Headers | show |
Series | [v2,1/5] mips: Do not malloc on getdents64 fallback | expand |
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 >
This needs symbol version updates for 2.31. -- Joseph S. Myers joseph@codesourcery.com
On 28/08/2019 14:21, Joseph Myers wrote: > This needs symbol version updates for 2.31. > Ack, I will update is and re-send it.
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