On 07/11/2025 15:42, Pádraig Brady wrote:
On 07/11/2025 12:22, Bruno Haible wrote:
I wrote:
    $ ./configure gl_cv_func_posix_spawnp_secure_exec=no --quiet

I reproduce it. Smaller reproducer:
    $ cd src
    $ mkdir subdir
    $ ./ginstall -s -c -m 555 dd subdir

It crashes if and only if $PATH is long enough:

I can force the crash using the attached testcase.sh, that sets
a PATH of size ca. 4 KB, on
    - Linux/SPARC
    - Linux/ppc64, Linux/ppc64le
    - Solaris 10 and 11 / SPARC

I'm committing this fix, which fixes the problem on all these platforms.

Excellent.
The code looks good to me.

I'll add the following to our test script:

+# Ensure there are no issues with posix_spawnp() and large $PATHs
+# which we saw when initially changing from execvp() to posix_spawnp().
+PATH=$(printf '%4001s' '' | sed 's/\(.\{79\}\)./\1:/g'):$PATH \
+  ginstall $strip -c -m 555 $dd $dir || fail=1

Note the sed above that splits the long path
into acceptable length components shouldn't be needed ideally.
Each $PATH component needs to be <= $NAME_MAX:

  $ getconf -a | grep -E '^(NAME|PATH)_MAX'
  NAME_MAX                           255
  PATH_MAX                           4096

I won't change the test script, but it does
seem like gnulib's posix_spawnp() could deal with that,
especially given that it doesn't apply any NAME_MAX or PATH_MAX
limit checks before passing onto execve().

  $ PATH=$(printf '%256s' ''):$PATH src/ginstall -s -c -m 555 dd dir
  ginstall: strip process terminated abnormally

With the attached, the problematic path is skipped and strip is run.

Note the $NAME_MAX limit is also in glibc's execvp:

  PATH=$(printf '%256s' ''):$PATH install -s -c -m 555 /bin/ls /tmp
  install: cannot run 'strip': File name too long

I'll send a proposal to glibc to make the same adjustment there.

Note ELOOP might also be considered skippable,
but the kernel can give that for limits in the shebang resolving,
so I thought it best to leave that for now.

cheers,
Padraig
From 86faf1ebe4c3a6c5f3cf6da971b73a8457f0a640 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?P=C3=A1draig=20Brady?= <[email protected]>
Date: Sat, 8 Nov 2025 11:04:05 +0000
Subject: [PATCH] posix_spawn-internal: skip $PATH components that are too long

* lib/spawni.c (__spawni): Skip path components for
which execve returns ENAMETOOLONG.
---
 ChangeLog    | 6 ++++++
 lib/spawni.c | 1 +
 2 files changed, 7 insertions(+)

diff --git a/ChangeLog b/ChangeLog
index 5b31898d06..03cd375ec7 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2025-11-08  Pádraig Brady  <[email protected]>
+
+	posix_spawn-internal: skip $PATH components that are too long
+	* lib/spawni.c (__spawni): Skip path components for
+	which execve returns ENAMETOOLONG.
+
 2025-11-06  Collin Funk  <[email protected]>
 
 	renameat, renameatu: Work around GNU/Hurd bugs.
diff --git a/lib/spawni.c b/lib/spawni.c
index 3f81d95697..18319dc828 100644
--- a/lib/spawni.c
+++ b/lib/spawni.c
@@ -1091,6 +1091,7 @@ __spawni (pid_t *pid, const char *file,
         case ENOENT:
         case ESTALE:
         case ENOTDIR:
+        case ENAMETOOLONG:
           /* Those errors indicate the file is missing or not executable
              by us, in which case we want to just try the next path
              directory.  */
-- 
2.51.1

Reply via email to