[PATCH] xargs: make errno handling after execvp failure more robust
Bernhard Voelker <[email protected]> Mon, 23 Feb 2026 23:06:33 +0100
| Newsgroups | gmane.comp.gnu.findutils.bugs,gmane.comp.gnu.findutils.patches |
|---|---|
| Message-ID | <[email protected]> |
I don't have a reproducer, but by reading of the code it was clear that write() and close() before error() could eventually clobber the errno value from execvp(). Pushed the attached. Have a nice day, Berny
0001-xargs-make-errno-handling-after-execvp-failure-more-.patch
(text/x-patch, 2.2 KB)
From dd594fe7b83f4d0096a3d9a903b3abe6a3f4fb2e Mon Sep 17 00:00:00 2001 From: Bernhard Voelker <[email protected]> Date: Mon, 23 Feb 2026 23:02:08 +0100 Subject: [PATCH] xargs: make errno handling after execvp failure more robust * xargs/xargs.c (xargs_do_exec): Save errno in a new variable to avoid that write() or close() clobber it before its value is used in error(). --- xargs/xargs.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/xargs/xargs.c b/xargs/xargs.c index 262a64cf..b7f8f1e8 100644 --- a/xargs/xargs.c +++ b/xargs/xargs.c @@ -1348,7 +1348,8 @@ xargs_do_exec (struct buildcmd_control *ctl, void *usercontext, int argc, char * errno = E2BIG; else execvp (argv[0], argv); - if (errno) + int saved_errno = errno; + if (saved_errno) { /* Write errno value to parent. We do this even if * the error was not E2BIG, because we need to @@ -1362,19 +1363,21 @@ xargs_do_exec (struct buildcmd_control *ctl, void *usercontext, int argc, char * * utility if we run it, for POSIX compliance on the * handling of exit values. */ - write (fd[1], &errno, sizeof (int)); + write (fd[1], &saved_errno, sizeof (int)); } close (fd[1]); - if (E2BIG != errno) + if (E2BIG != saved_errno) { - error (0, errno, _("failed to run command %s"), + error (0, saved_errno, _("failed to run command %s"), quotearg_n_style (0, locale_quoting_style, argv[0])); } /* The actual value returned here should be irrelevant, * because the parent will test our value of errno. */ - _exit (errno == ENOENT ? XARGS_EXIT_COMMAND_NOT_FOUND : XARGS_EXIT_COMMAND_CANNOT_BE_RUN); + _exit (saved_errno == ENOENT + ? XARGS_EXIT_COMMAND_NOT_FOUND + : XARGS_EXIT_COMMAND_CANNOT_BE_RUN); /*NOTREACHED*/ } /* child */ -- 2.52.0