fix(guile-2.2.4): harden scm_system execvp(sh) path and preserve wait-status semantics

This commit is contained in:
vxtls 2026-03-18 21:10:56 -04:00
parent 8bed6f4e32
commit 6a5ba94f81

View file

@ -12,7 +12,7 @@
#include <unistd.h> /* for _exit */ #include <unistd.h> /* for _exit */
#include "libguile/_scm.h" #include "libguile/_scm.h"
@@ -48,7 +51,10 @@ @@ -48,7 +51,11 @@
"indicating whether the command processor is available.") "indicating whether the command processor is available.")
#define FUNC_NAME s_scm_system #define FUNC_NAME s_scm_system
{ {
@ -20,17 +20,20 @@
+ int rv, eno, child_errno = 0; + int rv, eno, child_errno = 0;
+ int status; + int status;
+ int errpipe[2]; + int errpipe[2];
+ ssize_t nread;
+ pid_t pid; + pid_t pid;
char *c_cmd; char *c_cmd;
if (SCM_UNBNDP (cmd)) if (SCM_UNBNDP (cmd))
@@ -59,11 +65,67 @@ @@ -59,11 +66,78 @@
SCM_VALIDATE_STRING (1, cmd); SCM_VALIDATE_STRING (1, cmd);
errno = 0; errno = 0;
c_cmd = scm_to_locale_string (cmd); c_cmd = scm_to_locale_string (cmd);
- rv = system (c_cmd); - rv = system (c_cmd);
- eno = errno; free (c_cmd); errno = eno; - eno = errno; free (c_cmd); errno = eno;
- if (rv == -1 || (rv == 127 && errno != 0)) - if (rv == -1 || (rv == 127 && errno != 0))
- SCM_SYSERROR;
- return scm_from_int (rv);
+ +
+ if (pipe (errpipe) < 0) + if (pipe (errpipe) < 0)
+ { + {
@ -70,21 +73,31 @@
+ } + }
+ +
+ close (errpipe[1]); + close (errpipe[1]);
+ while ((rv = waitpid (pid, &status, 0)) == -1 && errno == EINTR) + while ((nread = read (errpipe[0], &child_errno, sizeof (child_errno))) == -1
+ ;
+
+ while (read (errpipe[0], &child_errno, sizeof (child_errno)) == -1
+ && errno == EINTR) + && errno == EINTR)
+ ; + ;
+ close (errpipe[0]); + close (errpipe[0]);
+ if (nread == -1)
+ {
+ eno = errno;
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+ if (nread != sizeof (child_errno))
+ child_errno = 0;
+ +
+ eno = errno; + while ((rv = waitpid (pid, &status, 0)) == -1 && errno == EINTR)
+ free (c_cmd); + ;
+ errno = eno;
+
+ if (rv == -1) + if (rv == -1)
SCM_SYSERROR; + {
- return scm_from_int (rv); + eno = errno;
+ free (c_cmd);
+ errno = eno;
+ SCM_SYSERROR;
+ }
+
+ free (c_cmd);
+ +
+ if (child_errno != 0) + if (child_errno != 0)
+ { + {