> 2025-11-07 Bruno Haible <[email protected]> > > posix_spawn-internal: Fix use of vfork on SPARC and PowerPC platforms. > Reported by Pádraig Brady <[email protected]> in > <https://lists.gnu.org/archive/html/coreutils/2025-11/msg00052.html>. > * lib/spawni.c (__spawni): Revert last change. Do the stack allocations > with alloca() in the parent process, not in the child process.
And this patch adds a corresponding unit test. Without the fix, it crashes on Linux/SPARC, Linux/ppc64, Linux/ppc64le, Solaris/SPARC. 2025-11-10 Bruno Haible <[email protected]> posix_spawnp tests: Add test against previous bug. * tests/test-posix_spawnp-vfork.c: New file, based on tests/test-posix_spawnp-script.c. * modules/posix_spawnp-tests (Files): Add it. (Makefile.am): Arrange to compile and test test-posix_spawnp-vfork.
>From 7b98e50eee2d301fc8b126bfc394f9aa6e92099e Mon Sep 17 00:00:00 2001 From: Bruno Haible <[email protected]> Date: Mon, 10 Nov 2025 10:28:28 +0100 Subject: [PATCH] posix_spawnp tests: Add test against previous bug. * tests/test-posix_spawnp-vfork.c: New file, based on tests/test-posix_spawnp-script.c. * modules/posix_spawnp-tests (Files): Add it. (Makefile.am): Arrange to compile and test test-posix_spawnp-vfork. --- ChangeLog | 8 +++ modules/posix_spawnp-tests | 7 ++- tests/test-posix_spawnp-vfork.c | 106 ++++++++++++++++++++++++++++++++ 3 files changed, 119 insertions(+), 2 deletions(-) create mode 100644 tests/test-posix_spawnp-vfork.c diff --git a/ChangeLog b/ChangeLog index 3b1613fb0d..04e61f8506 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2025-11-10 Bruno Haible <[email protected]> + + posix_spawnp tests: Add test against previous bug. + * tests/test-posix_spawnp-vfork.c: New file, based on + tests/test-posix_spawnp-script.c. + * modules/posix_spawnp-tests (Files): Add it. + (Makefile.am): Arrange to compile and test test-posix_spawnp-vfork. + 2025-11-08 Paul Eggert <[email protected]> gendocs: port better to texi2html 5.0 diff --git a/modules/posix_spawnp-tests b/modules/posix_spawnp-tests index 11a36b3b68..39f591cb10 100644 --- a/modules/posix_spawnp-tests +++ b/modules/posix_spawnp-tests @@ -4,6 +4,7 @@ tests/test-posix_spawn-dup2-stdout.in.sh tests/test-posix_spawn-dup2-stdin.c tests/test-posix_spawn-dup2-stdin.in.sh tests/test-posix_spawnp-script.c +tests/test-posix_spawnp-vfork.c tests/executable-script tests/executable-script.sh tests/executable-shell-script @@ -35,11 +36,13 @@ Makefile.am: TESTS += \ test-posix_spawn-dup2-stdout \ test-posix_spawn-dup2-stdin \ - test-posix_spawnp-script + test-posix_spawnp-script \ + test-posix_spawnp-vfork check_PROGRAMS += \ test-posix_spawn-dup2-stdout \ test-posix_spawn-dup2-stdin \ - test-posix_spawnp-script + test-posix_spawnp-script \ + test-posix_spawnp-vfork BUILT_SOURCES += test-posix_spawn-dup2-stdout.sh test-posix_spawn-dup2-stdout.sh: test-posix_spawn-dup2-stdout.in.sh diff --git a/tests/test-posix_spawnp-vfork.c b/tests/test-posix_spawnp-vfork.c new file mode 100644 index 0000000000..633f8e73de --- /dev/null +++ b/tests/test-posix_spawnp-vfork.c @@ -0,0 +1,106 @@ +/* Test of posix_spawnp() function. + Copyright (C) 2020-2025 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3, or (at your option) + any later version. + + This program 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, see <https://www.gnu.org/licenses/>. */ + +#include <config.h> + +#include <spawn.h> + +#include <errno.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/wait.h> + +#include "macros.h" + +/* Check an invocation via vfork() with a large $PATH (ca. 4 KB). + When configured with gl_cv_func_posix_spawnp_secure_exec=no, this test used + to crash on Linux/SPARC, Linux/ppc64, Linux/ppc64le, and Solaris/SPARC. */ + +int +main () +{ +#if defined _WIN32 && !defined __CYGWIN__ + /* There is no 'false' program on this platform, but no vfork() either. */ + fprintf (stderr, "Skipping test: no vfork() on this platform.\n"); + return 77; +#else + + /* Components of file names are limited to ca. 255 characters on most + platforms. (Cf. NAME_MAX in <limits.h>.) + Here is one with 250 characters. */ +# define OOO "oooooooooooooooooooooooooooooooooooooooooooooooooo" \ + "oooooooooooooooooooooooooooooooooooooooooooooooooo" \ + "oooooooooooooooooooooooooooooooooooooooooooooooooo" \ + "oooooooooooooooooooooooooooooooooooooooooooooooooo" \ + "oooooooooooooooooooooooooooooooooooooooooooooooooo" + /* File names are limited to ca. 1024 characters on many platforms, + to ca. 4096 characters only on Linux and Cygwin, and unlimited only + on GNU/Hurd. (Cf. PATH_MAX in <limits.h>.) + We prepend several directory names below this 1024 limit. */ +# define ADD "/usr/bin/p" OOO "/" OOO "/" OOO "/" OOO ":" \ + "/usr/bin/q" OOO "/" OOO "/" OOO "/" OOO ":" \ + "/usr/bin/r" OOO "/" OOO "/" OOO "/" OOO ":" \ + "/usr/bin/s" OOO "/" OOO "/" OOO "/" OOO ":" + const char *old_path = getenv ("PATH"); + char *new_path = (char *) malloc (strlen (ADD) + strlen (old_path) + 1); + ASSERT (new_path != NULL); + memcpy (new_path, ADD, strlen (ADD)); + strcpy (new_path + strlen (ADD), old_path); + ASSERT (setenv ("PATH", new_path, 1) == 0); + + posix_spawnattr_t attr; + ASSERT (posix_spawnattr_init (&attr) == 0); + ASSERT (posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK) == 0); + + if (test_exit_status != EXIT_SUCCESS) + return test_exit_status; + + /* Can't use 'false' here, because its exit status is only guaranteed to be + non-zero, and is in fact 255 on Solaris. */ + const char *prog = "sh"; + const char *prog_argv[4] = { prog, "-c", "exit 1", NULL }; + pid_t child; + int err = posix_spawnp (&child, prog, NULL, &attr, (char **) prog_argv, environ); + if (err != 0) + { + errno = err; + perror ("posix_spawn"); + return 1; + } + + /* Wait for child. */ + int status = 0; + while (waitpid (child, &status, 0) != child) + ; + if (!WIFEXITED (status)) + { + fprintf (stderr, "subprocess terminated with unexpected wait status %d\n", status); + return 1; + } + int exitstatus = WEXITSTATUS (status); + if (exitstatus != 1) + { + fprintf (stderr, "subprocess terminated with unexpected exit status %d\n", exitstatus); + return 1; + } + + return test_exit_status; + +#endif +} -- 2.51.0
