import glibc-2.28-199.el8

This commit is contained in:
CentOS Sources 2022-04-30 08:10:38 +00:00 committed by Stepan Oksanichenko
parent 45c1bfee5b
commit 4b137de5ff
15 changed files with 1786 additions and 1 deletions

View File

@ -0,0 +1,253 @@
commit 2a973ab7f1a6f6cd9be1c7257fd7b5d331515eab
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Sep 12 10:30:46 2018 -0300
posix: Add internal symbols for posix_spawn interface
This patch adds internal hidden definition for mostly of the posix_spawn
function so it can be used internally on both popen and system
implementations.
Checked on x86_64-linux-gnu.
* include/spawn.h (__posix_spawn, posix_spawn_file_actions_addclose,
__posix_spawn_file_actions_adddup2, __posix_spawn_file_actions_destroy,
__posix_spawn_file_actions_init, __posix_spawnattr_init,
__posix_spawnattr_destroy, __posix_spawnattr_setflags,
__posix_spawnattr_setsigdefault, __posix_spawnattr_setsigmask): New
prototype.
* posix/spawn.c (__posix_spawn): Add libc_hidden_def.
* posix/spawn_faction_addclose.c
(__posix_spawn_file_actions_addclose): Add hidden definition.
* posix/spawn_faction_adddup2.c
(__posix_spawn_file_actions_adddup2): Likewise.
* posix/spawn_faction_destroy.c
(__posix_spawn_file_actions_destroy): Likewise.
* posix/spawn_faction_init.c (__posix_spawn_file_actions_init):
Likewise.
* posix/spawnattr_destroy.c (__posix_spawnattr_destroy): Likewise.
* posix/spawnattr_init.c (__posix_spawnattr_init): Likewise.
* posix/spawnattr_setdefault.c (__posix_spawnattr_setsigdefault):
Likewise.
* posix/spawnattr_setflags.c (__posix_spawnattr_setflags): Likewise.
* posix/spawnattr_setsigmask.c (__posix_spawnattr_setsigmask):
Likewise.
diff --git a/include/spawn.h b/include/spawn.h
index a6c7a8adc361927e..7fdd965bd780f8de 100644
--- a/include/spawn.h
+++ b/include/spawn.h
@@ -1 +1,36 @@
+#ifndef _SPAWN_H
#include <posix/spawn.h>
+
+# ifndef _ISOMAC
+__typeof (posix_spawn) __posix_spawn;
+libc_hidden_proto (__posix_spawn)
+
+__typeof (posix_spawn_file_actions_addclose)
+ __posix_spawn_file_actions_addclose attribute_hidden;
+
+__typeof (posix_spawn_file_actions_adddup2)
+ __posix_spawn_file_actions_adddup2 attribute_hidden;
+
+__typeof (posix_spawn_file_actions_destroy)
+ __posix_spawn_file_actions_destroy attribute_hidden;
+
+__typeof (posix_spawn_file_actions_init) __posix_spawn_file_actions_init
+ attribute_hidden;
+
+__typeof (posix_spawnattr_init) __posix_spawnattr_init
+ attribute_hidden;
+
+__typeof (posix_spawnattr_destroy) __posix_spawnattr_destroy
+ attribute_hidden;
+
+__typeof (posix_spawnattr_setflags) __posix_spawnattr_setflags
+ attribute_hidden;
+
+__typeof (posix_spawnattr_setsigdefault) __posix_spawnattr_setsigdefault
+ attribute_hidden;
+
+__typeof (posix_spawnattr_setsigmask) __posix_spawnattr_setsigmask
+ attribute_hidden;
+
+# endif /* !_ISOMAC */
+#endif /* spawn.h */
diff --git a/posix/spawn.c b/posix/spawn.c
index 51f67b2755bd4949..a82f1c84e299f018 100644
--- a/posix/spawn.c
+++ b/posix/spawn.c
@@ -30,6 +30,7 @@ __posix_spawn (pid_t *pid, const char *path,
return __spawni (pid, path, file_actions, attrp, argv, envp, 0);
}
versioned_symbol (libc, __posix_spawn, posix_spawn, GLIBC_2_15);
+libc_hidden_def (__posix_spawn)
#if SHLIB_COMPAT (libc, GLIBC_2_2, GLIBC_2_15)
diff --git a/posix/spawn_faction_addclose.c b/posix/spawn_faction_addclose.c
index 21081e19b55db44c..e1fafe438cf15c91 100644
--- a/posix/spawn_faction_addclose.c
+++ b/posix/spawn_faction_addclose.c
@@ -24,8 +24,8 @@
/* Add an action to FILE-ACTIONS which tells the implementation to call
`close' for the given file descriptor during the `spawn' call. */
int
-posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions,
- int fd)
+__posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions,
+ int fd)
{
struct __spawn_action *rec;
@@ -48,3 +48,5 @@ posix_spawn_file_actions_addclose (posix_spawn_file_actions_t *file_actions,
return 0;
}
+weak_alias (__posix_spawn_file_actions_addclose,
+ posix_spawn_file_actions_addclose)
diff --git a/posix/spawn_faction_adddup2.c b/posix/spawn_faction_adddup2.c
index 363bc29ae502bd60..371b1de3e6f1979a 100644
--- a/posix/spawn_faction_adddup2.c
+++ b/posix/spawn_faction_adddup2.c
@@ -24,8 +24,8 @@
/* Add an action to FILE-ACTIONS which tells the implementation to call
`dup2' for the given file descriptors during the `spawn' call. */
int
-posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions,
- int fd, int newfd)
+__posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions,
+ int fd, int newfd)
{
struct __spawn_action *rec;
@@ -49,3 +49,5 @@ posix_spawn_file_actions_adddup2 (posix_spawn_file_actions_t *file_actions,
return 0;
}
+weak_alias (__posix_spawn_file_actions_adddup2,
+ posix_spawn_file_actions_adddup2)
diff --git a/posix/spawn_faction_destroy.c b/posix/spawn_faction_destroy.c
index 46061ee3473d4475..2a2de4e41d6bd6d0 100644
--- a/posix/spawn_faction_destroy.c
+++ b/posix/spawn_faction_destroy.c
@@ -22,7 +22,7 @@
/* Deallocate the file actions. */
int
-posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
+__posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
{
/* Free the paths in the open actions. */
for (int i = 0; i < file_actions->__used; ++i)
@@ -44,3 +44,5 @@ posix_spawn_file_actions_destroy (posix_spawn_file_actions_t *file_actions)
free (file_actions->__actions);
return 0;
}
+weak_alias (__posix_spawn_file_actions_destroy,
+ posix_spawn_file_actions_destroy)
diff --git a/posix/spawn_faction_init.c b/posix/spawn_faction_init.c
index ddb42e6a77ba41ec..98432067c645021e 100644
--- a/posix/spawn_faction_init.c
+++ b/posix/spawn_faction_init.c
@@ -45,9 +45,10 @@ __posix_spawn_file_actions_realloc (posix_spawn_file_actions_t *file_actions)
/* Initialize data structure for file attribute for `spawn' call. */
int
-posix_spawn_file_actions_init (posix_spawn_file_actions_t *file_actions)
+__posix_spawn_file_actions_init (posix_spawn_file_actions_t *file_actions)
{
/* Simply clear all the elements. */
memset (file_actions, '\0', sizeof (*file_actions));
return 0;
}
+weak_alias (__posix_spawn_file_actions_init, posix_spawn_file_actions_init)
diff --git a/posix/spawnattr_destroy.c b/posix/spawnattr_destroy.c
index 603e00fffefae2bf..043386778588913a 100644
--- a/posix/spawnattr_destroy.c
+++ b/posix/spawnattr_destroy.c
@@ -19,8 +19,9 @@
/* Initialize data structure for file attribute for `spawn' call. */
int
-posix_spawnattr_destroy (posix_spawnattr_t *attr)
+__posix_spawnattr_destroy (posix_spawnattr_t *attr)
{
/* Nothing to do in the moment. */
return 0;
}
+weak_alias (__posix_spawnattr_destroy, posix_spawnattr_destroy)
diff --git a/posix/spawnattr_init.c b/posix/spawnattr_init.c
index bab464e62bdf7889..4e1218ab44e3f779 100644
--- a/posix/spawnattr_init.c
+++ b/posix/spawnattr_init.c
@@ -20,7 +20,7 @@
/* Initialize data structure for file attribute for `spawn' call. */
int
-posix_spawnattr_init (posix_spawnattr_t *attr)
+__posix_spawnattr_init (posix_spawnattr_t *attr)
{
/* All elements have to be initialized to the default values which
is generally zero. */
@@ -28,3 +28,4 @@ posix_spawnattr_init (posix_spawnattr_t *attr)
return 0;
}
+weak_alias (__posix_spawnattr_init, posix_spawnattr_init)
diff --git a/posix/spawnattr_setdefault.c b/posix/spawnattr_setdefault.c
index c77cda59be3dda20..174bcfa423dc5666 100644
--- a/posix/spawnattr_setdefault.c
+++ b/posix/spawnattr_setdefault.c
@@ -20,11 +20,12 @@
/* Set signal mask for signals with default handling in ATTR to SIGDEFAULT. */
int
-posix_spawnattr_setsigdefault (posix_spawnattr_t *attr,
- const sigset_t *sigdefault)
+__posix_spawnattr_setsigdefault (posix_spawnattr_t *attr,
+ const sigset_t *sigdefault)
{
/* Copy the sigset_t data to the user buffer. */
memcpy (&attr->__sd, sigdefault, sizeof (sigset_t));
return 0;
}
+weak_alias (__posix_spawnattr_setsigdefault, posix_spawnattr_setsigdefault)
diff --git a/posix/spawnattr_setflags.c b/posix/spawnattr_setflags.c
index cf9a60181dc91ccd..0a42e94770224a94 100644
--- a/posix/spawnattr_setflags.c
+++ b/posix/spawnattr_setflags.c
@@ -30,7 +30,7 @@
/* Store flags in the attribute structure. */
int
-posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags)
+__posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags)
{
/* Check no invalid bits are set. */
if (flags & ~ALL_FLAGS)
@@ -41,3 +41,4 @@ posix_spawnattr_setflags (posix_spawnattr_t *attr, short int flags)
return 0;
}
+weak_alias (__posix_spawnattr_setflags, posix_spawnattr_setflags)
diff --git a/posix/spawnattr_setsigmask.c b/posix/spawnattr_setsigmask.c
index 7ae81ad47025db6f..12c0111af441dd13 100644
--- a/posix/spawnattr_setsigmask.c
+++ b/posix/spawnattr_setsigmask.c
@@ -20,7 +20,7 @@
/* Set signal mask for the new process in ATTR to SIGMASK. */
int
-posix_spawnattr_setsigmask (posix_spawnattr_t *attr,
+__posix_spawnattr_setsigmask (posix_spawnattr_t *attr,
const sigset_t *sigmask)
{
/* Copy the sigset_t data to the user buffer. */
@@ -28,3 +28,4 @@ posix_spawnattr_setsigmask (posix_spawnattr_t *attr,
return 0;
}
+weak_alias (__posix_spawnattr_setsigmask, posix_spawnattr_setsigmask)

View File

@ -0,0 +1,21 @@
commit 5fce0e095bc413f908f472074c2235198cd76bf4
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Mar 24 15:36:23 2020 -0300
support/shell-container.c: Return 127 if execve fails
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/support/shell-container.c b/support/shell-container.c
index e87ac5cf1baa84e5..e9eea64bca7e949d 100644
--- a/support/shell-container.c
+++ b/support/shell-container.c
@@ -238,7 +238,7 @@ run_command_array (char **argv)
fprintf (stderr, "sh: execing %s failed: %s",
argv[0], strerror (errno));
- exit (1);
+ exit (127);
}
waitpid (pid, &status, 0);

View File

@ -0,0 +1,39 @@
commit 5a5a3a3234bc220a5192d620e0cbc5360da46f14
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Mar 24 15:40:36 2020 -0300
support/shell-container.c: Add builtin exit
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/support/shell-container.c b/support/shell-container.c
index e9eea64bca7e949d..aeaf6d2733abce61 100644
--- a/support/shell-container.c
+++ b/support/shell-container.c
@@ -135,6 +135,18 @@ copy_func (char **argv)
}
+/* Emulate the 'exit' builtin. The exit value is optional. */
+static int
+exit_func (char **argv)
+{
+ int exit_val = 0;
+
+ if (argv[0] != 0)
+ exit_val = atoi (argv[0]) & 0xff;
+ exit (exit_val);
+ return 0;
+}
+
/* This is a list of all the built-in commands we understand. */
static struct {
const char *name;
@@ -143,6 +155,7 @@ static struct {
{ "true", true_func },
{ "echo", echo_func },
{ "cp", copy_func },
+ { "exit", exit_func },
{ NULL, NULL }
};

View File

@ -0,0 +1,60 @@
commit 1c17100c43c0913ec94f3bcc966bf3792236c690
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Mar 24 15:47:13 2020 -0300
support/shell-container.c: Add builtin kill
No options supported.
Reviewed-by: DJ Delorie <dj@redhat.com>
diff --git a/support/shell-container.c b/support/shell-container.c
index aeaf6d2733abce61..3869e14683fb74dd 100644
--- a/support/shell-container.c
+++ b/support/shell-container.c
@@ -147,6 +147,25 @@ exit_func (char **argv)
return 0;
}
+/* Emulate the "/bin/kill" command. Options are ignored. */
+static int
+kill_func (char **argv)
+{
+ int signum = SIGTERM;
+ int i;
+
+ for (i = 0; argv[i]; i++)
+ {
+ pid_t pid;
+ if (strcmp (argv[i], "$$") == 0)
+ pid = getpid ();
+ else
+ pid = atoi (argv[i]);
+ kill (pid, signum);
+ }
+ return 0;
+}
+
/* This is a list of all the built-in commands we understand. */
static struct {
const char *name;
@@ -156,6 +175,7 @@ static struct {
{ "echo", echo_func },
{ "cp", copy_func },
{ "exit", exit_func },
+ { "kill", kill_func },
{ NULL, NULL }
};
@@ -264,6 +284,11 @@ run_command_array (char **argv)
if (rv)
exit (rv);
}
+ else if (WIFSIGNALED (status))
+ {
+ int sig = WTERMSIG (status);
+ raise (sig);
+ }
else
exit (1);
}

View File

@ -0,0 +1,66 @@
commit 75fe6d1a1620d84e0e487868feba9b2c0f109610
Author: Siddhesh Poyarekar <siddhesh@sourceware.org>
Date: Wed May 12 10:13:41 2021 +0530
support: Close fds in copy_func
copy_func may leave file descriptors open on error, so close them on
function exit.
diff --git a/support/shell-container.c b/support/shell-container.c
index 3869e14683fb74dd..f0a9814ae230d167 100644
--- a/support/shell-container.c
+++ b/support/shell-container.c
@@ -93,8 +93,9 @@ copy_func (char **argv)
{
char *sname = argv[0];
char *dname = argv[1];
- int sfd, dfd;
+ int sfd = -1, dfd = -1;
struct stat st;
+ int ret = 1;
sfd = open (sname, O_RDONLY);
if (sfd < 0)
@@ -108,7 +109,7 @@ copy_func (char **argv)
{
fprintf (stderr, "cp: unable to fstat %s: %s\n",
sname, strerror (errno));
- return 1;
+ goto out;
}
dfd = open (dname, O_WRONLY | O_TRUNC | O_CREAT, 0600);
@@ -116,22 +117,26 @@ copy_func (char **argv)
{
fprintf (stderr, "cp: unable to open %s for writing: %s\n",
dname, strerror (errno));
- return 1;
+ goto out;
}
if (support_copy_file_range (sfd, 0, dfd, 0, st.st_size, 0) != st.st_size)
{
fprintf (stderr, "cp: cannot copy file %s to %s: %s\n",
sname, dname, strerror (errno));
- return 1;
+ goto out;
}
- close (sfd);
- close (dfd);
-
+ ret = 0;
chmod (dname, st.st_mode & 0777);
- return 0;
+out:
+ if (sfd >= 0)
+ close (sfd);
+ if (dfd >= 0)
+ close (dfd);
+
+ return ret;
}

View File

@ -0,0 +1,231 @@
commit 14d0e87d9b8caaa2eca7ca81f1189596671fe4fb
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Sep 12 10:32:05 2018 -0300
posix: Use posix_spawn on popen
This patch uses posix_spawn on popen instead of fork and execl. On Linux
this has the advantage of much lower memory consumption (usually 32 Kb
minimum for the mmap stack area).
Two issues are also fixed with this change:
* BZ#17490: although POSIX pthread_atfork description only list 'fork'
as the function that should execute the atfork handlers, popen
description states that:
'[...] shall be *as if* a child process were created within the popen()
call using the fork() function [...]'
Other libc/system seems to follow the idea atfork handlers should not be
executed for popen:
libc/system | run atfork handles | notes
------------|----------------------|---------------------------------------
Freebsd | no | uses vfork
Solaris 11 | no |
MacOSX 11 | no | implemented through posix_spawn syscall
------------|----------------------|----------------------------------------
Similar to posix_spawn and system, popen idea is to spawn a different
binary so all the POSIX rationale to run the atfork handlers to avoid
internal process inconsistency is not really required and in some cases
might be unsafe.
* BZ#22834: the described scenario, where the forked process might access
invalid memory due an inconsistent state in multithreaded environment,
should not happen because posix_spawn does not access the affected
data structure (proc_file_chain).
Checked on x86_64-linux-gnu and i686-linux-gnu.
[BZ #22834]
[BZ #17490]
* NEWS: Add new semantic for atfork with popen and system.
* libio/iopopen.c (_IO_new_proc_open): use posix_spawn instead of
fork and execl.
diff --git a/libio/iopopen.c b/libio/iopopen.c
index 2eff45b4c80b5cd6..c768295180fdf809 100644
--- a/libio/iopopen.c
+++ b/libio/iopopen.c
@@ -34,7 +34,8 @@
#include <not-cancel.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <kernel-features.h>
+#include <spawn.h>
+#include <paths.h>
struct _IO_proc_file
{
@@ -59,13 +60,60 @@ unlock (void *not_used)
}
#endif
+/* POSIX states popen shall ensure that any streams from previous popen()
+ calls that remain open in the parent process should be closed in the new
+ child process.
+ To avoid a race-condition between checking which file descriptors need to
+ be close (by transversing the proc_file_chain list) and the insertion of a
+ new one after a successful posix_spawn this function should be called
+ with proc_file_chain_lock acquired. */
+static bool
+spawn_process (posix_spawn_file_actions_t *fa, FILE *fp, const char *command,
+ int do_cloexec, int pipe_fds[2], int parent_end, int child_end,
+ int child_pipe_fd)
+{
+
+ for (struct _IO_proc_file *p = proc_file_chain; p; p = p->next)
+ {
+ int fd = _IO_fileno ((FILE *) p);
+
+ /* If any stream from previous popen() calls has fileno
+ child_pipe_fd, it has been already closed by the adddup2 action
+ above. */
+ if (fd != child_pipe_fd
+ && __posix_spawn_file_actions_addclose (fa, fd) != 0)
+ return false;
+ }
+
+ if (__posix_spawn (&((_IO_proc_file *) fp)->pid, _PATH_BSHELL, fa, 0,
+ (char *const[]){ (char*) "sh", (char*) "-c",
+ (char *) command, NULL }, __environ) != 0)
+ return false;
+
+ __close_nocancel (pipe_fds[child_end]);
+
+ if (!do_cloexec)
+ /* Undo the effects of the pipe2 call which set the
+ close-on-exec flag. */
+ __fcntl (pipe_fds[parent_end], F_SETFD, 0);
+
+ _IO_fileno (fp) = pipe_fds[parent_end];
+
+ ((_IO_proc_file *) fp)->next = proc_file_chain;
+ proc_file_chain = (_IO_proc_file *) fp;
+
+ return true;
+}
+
FILE *
_IO_new_proc_open (FILE *fp, const char *command, const char *mode)
{
int read_or_write;
+ /* These are indexes for pipe_fds. */
int parent_end, child_end;
int pipe_fds[2];
- pid_t child_pid;
+ int child_pipe_fd;
+ bool spawn_ok;
int do_read = 0;
int do_write = 0;
@@ -108,72 +156,62 @@ _IO_new_proc_open (FILE *fp, const char *command, const char *mode)
if (do_read)
{
- parent_end = pipe_fds[0];
- child_end = pipe_fds[1];
+ parent_end = 0;
+ child_end = 1;
read_or_write = _IO_NO_WRITES;
+ child_pipe_fd = 1;
}
else
{
- parent_end = pipe_fds[1];
- child_end = pipe_fds[0];
+ parent_end = 1;
+ child_end = 0;
read_or_write = _IO_NO_READS;
+ child_pipe_fd = 0;
}
- ((_IO_proc_file *) fp)->pid = child_pid = __fork ();
- if (child_pid == 0)
- {
- int child_std_end = do_read ? 1 : 0;
- struct _IO_proc_file *p;
-
- if (child_end != child_std_end)
- __dup2 (child_end, child_std_end);
- else
- /* The descriptor is already the one we will use. But it must
- not be marked close-on-exec. Undo the effects. */
- __fcntl (child_end, F_SETFD, 0);
- /* POSIX.2: "popen() shall ensure that any streams from previous
- popen() calls that remain open in the parent process are closed
- in the new child process." */
- for (p = proc_file_chain; p; p = p->next)
- {
- int fd = _IO_fileno ((FILE *) p);
+ posix_spawn_file_actions_t fa;
+ /* posix_spawn_file_actions_init does not fail. */
+ __posix_spawn_file_actions_init (&fa);
- /* If any stream from previous popen() calls has fileno
- child_std_end, it has been already closed by the dup2 syscall
- above. */
- if (fd != child_std_end)
- __close_nocancel (fd);
- }
-
- execl ("/bin/sh", "sh", "-c", command, (char *) 0);
- _exit (127);
- }
- __close_nocancel (child_end);
- if (child_pid < 0)
+ /* The descriptor is already the one the child will use. In this case
+ it must be moved to another one otherwise, there is no safe way to
+ remove the close-on-exec flag in the child without creating a FD leak
+ race in the parent. */
+ if (pipe_fds[child_end] == child_pipe_fd)
{
- __close_nocancel (parent_end);
- return NULL;
+ int tmp = __fcntl (child_pipe_fd, F_DUPFD_CLOEXEC, 0);
+ if (tmp < 0)
+ goto spawn_failure;
+ __close_nocancel (pipe_fds[child_end]);
+ pipe_fds[child_end] = tmp;
}
- if (!do_cloexec)
- /* Undo the effects of the pipe2 call which set the
- close-on-exec flag. */
- __fcntl (parent_end, F_SETFD, 0);
+ if (__posix_spawn_file_actions_adddup2 (&fa, pipe_fds[child_end],
+ child_pipe_fd) != 0)
+ goto spawn_failure;
- _IO_fileno (fp) = parent_end;
-
- /* Link into proc_file_chain. */
#ifdef _IO_MTSAFE_IO
_IO_cleanup_region_start_noarg (unlock);
_IO_lock_lock (proc_file_chain_lock);
#endif
- ((_IO_proc_file *) fp)->next = proc_file_chain;
- proc_file_chain = (_IO_proc_file *) fp;
+ spawn_ok = spawn_process (&fa, fp, command, do_cloexec, pipe_fds,
+ parent_end, child_end, child_pipe_fd);
#ifdef _IO_MTSAFE_IO
_IO_lock_unlock (proc_file_chain_lock);
_IO_cleanup_region_end (0);
#endif
+ __posix_spawn_file_actions_destroy (&fa);
+
+ if (!spawn_ok)
+ {
+ spawn_failure:
+ __close_nocancel (pipe_fds[child_end]);
+ __close_nocancel (pipe_fds[parent_end]);
+ __set_errno (ENOMEM);
+ return NULL;
+ }
+
_IO_mask_flags (fp, read_or_write, _IO_NO_READS|_IO_NO_WRITES);
return fp;
}

View File

@ -0,0 +1,527 @@
commit 5fb7fc96350575c9adb1316833e48ca11553be49
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Wed Oct 24 16:29:38 2018 -0300
posix: Use posix_spawn on system
This patch uses posix_spawn on system implementation. On Linux this has
the advantage of much lower memory consumption (usually 32 Kb minimum for
the mmap stack area).
Although POSIX does not require, glibc system implementation aims to be
thread and cancellation safe. The cancellation code is moved to generic
implementation and enabled iff SIGCANCEL is defined (similar on how the
cancellation handler is enabled on nptl-init.c).
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, and powerpc64le-linux-gnu.
* sysdeps/unix/sysv/linux/spawni.c (__spawni_child): Use
__sigismember instead of sigismember.
* sysdeps/posix/system.c [SIGCANCEL] (cancel_handler_args,
cancel_handler): New definitions.
(CLEANUP_HANDLER, CLEANUP_RESET): Likewise.
(DO_LOCK, DO_UNLOCK, INIT_LOCK, ADD_REF, SUB_REF): Remove.
(do_system): Use posix_spawn instead of fork and execl and remove
reentracy code.
* sysdeps/generic/not-errno.h (__kill_noerrno): New prototype.
* sysdeps/unix/sysv/linux/not-errno.h (__kill_noerrno): Likewise.
* sysdeps/unix/sysv/linux/ia64/system.c: Remove file.
* sysdeps/unix/sysv/linux/s390/system.c: Likewise.
* sysdeps/unix/sysv/linux/sparc/system.c: Likewise.
* sysdeps/unix/sysv/linux/system.c: Likewise.
diff --git a/sysdeps/generic/not-errno.h b/sysdeps/generic/not-errno.h
index 93617a3266fd4aad..0fd66b5c5ed82315 100644
--- a/sysdeps/generic/not-errno.h
+++ b/sysdeps/generic/not-errno.h
@@ -17,3 +17,5 @@
<http://www.gnu.org/licenses/>. */
extern __typeof (__access) __access_noerrno attribute_hidden;
+
+extern __typeof (__kill) __kill_noerrno attribute_hidden;
diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c
index d7594436ed59906f..8a51a6b9919ec39b 100644
--- a/sysdeps/posix/system.c
+++ b/sysdeps/posix/system.c
@@ -17,20 +17,36 @@
#include <errno.h>
#include <signal.h>
-#include <stddef.h>
#include <stdlib.h>
#include <unistd.h>
+#include <sigsetops.h>
+#include <spawn.h>
+#include <pthread.h>
#include <sys/types.h>
#include <sys/wait.h>
-#include <libc-lock.h>
-#include <sysdep-cancel.h>
-#include <sigsetops.h>
+#include <stdio.h>
+#include <libc-lock.h>
+#include <not-errno.h>
+#include <not-cancel.h>
+#include <internal-signals.h>
#define SHELL_PATH "/bin/sh" /* Path of the shell. */
#define SHELL_NAME "sh" /* Name to give it. */
+/* This system implementation aims to be thread-safe, which requires to
+ restore the signal dispositions for SIGINT and SIGQUIT correctly and to
+ deal with cancellation by terminating the child process.
+
+ The signal disposition restoration on the single-thread case is
+ straighfoward. For multithreaded case, a reference-counter with a lock
+ is used, so the first thread will set the SIGINT/SIGQUIT dispositions and
+ last thread will restore them.
+
+ Cancellation handling is done with thread cancellation clean-up handlers
+ on waitpid call. */
+
#ifdef _LIBC_REENTRANT
static struct sigaction intr, quit;
static int sa_refcntr;
@@ -50,17 +66,45 @@ __libc_lock_define_initialized (static, lock);
#endif
+#if defined(_LIBC_REENTRANT) && defined(SIGCANCEL)
+struct cancel_handler_args
+{
+ struct sigaction *quit;
+ struct sigaction *intr;
+ pid_t pid;
+};
+
+static void
+cancel_handler (void *arg)
+{
+ struct cancel_handler_args *args = (struct cancel_handler_args *) (arg);
+
+ __kill_noerrno (args->pid, SIGKILL);
+
+ TEMP_FAILURE_RETRY (__waitpid_nocancel (args->pid, NULL, 0));
+
+ DO_LOCK ();
+ if (SUB_REF () == 0)
+ {
+ __sigaction (SIGQUIT, args->quit, NULL);
+ __sigaction (SIGINT, args->intr, NULL);
+ }
+ DO_UNLOCK ();
+}
+#endif
+
/* Execute LINE as a shell command, returning its status. */
static int
do_system (const char *line)
{
- int status, save;
+ int status;
pid_t pid;
struct sigaction sa;
#ifndef _LIBC_REENTRANT
struct sigaction intr, quit;
#endif
sigset_t omask;
+ sigset_t reset;
sa.sa_handler = SIG_IGN;
sa.sa_flags = 0;
@@ -69,105 +113,72 @@ do_system (const char *line)
DO_LOCK ();
if (ADD_REF () == 0)
{
- if (__sigaction (SIGINT, &sa, &intr) < 0)
- {
- (void) SUB_REF ();
- goto out;
- }
- if (__sigaction (SIGQUIT, &sa, &quit) < 0)
- {
- save = errno;
- (void) SUB_REF ();
- goto out_restore_sigint;
- }
+ /* sigaction can not fail with SIGINT/SIGQUIT used with SIG_IGN. */
+ __sigaction (SIGINT, &sa, &intr);
+ __sigaction (SIGQUIT, &sa, &quit);
}
DO_UNLOCK ();
- /* We reuse the bitmap in the 'sa' structure. */
__sigaddset (&sa.sa_mask, SIGCHLD);
- save = errno;
- if (__sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask) < 0)
+ /* sigprocmask can not fail with SIG_BLOCK used with valid input
+ arguments. */
+ __sigprocmask (SIG_BLOCK, &sa.sa_mask, &omask);
+
+ __sigemptyset (&reset);
+ if (intr.sa_handler != SIG_IGN)
+ __sigaddset(&reset, SIGINT);
+ if (quit.sa_handler != SIG_IGN)
+ __sigaddset(&reset, SIGQUIT);
+
+ posix_spawnattr_t spawn_attr;
+ /* None of the posix_spawnattr_* function returns an error, including
+ posix_spawnattr_setflags for the follow specific usage (using valid
+ flags). */
+ __posix_spawnattr_init (&spawn_attr);
+ __posix_spawnattr_setsigmask (&spawn_attr, &omask);
+ __posix_spawnattr_setsigdefault (&spawn_attr, &reset);
+ __posix_spawnattr_setflags (&spawn_attr,
+ POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK);
+
+ status = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr,
+ (char *const[]){ (char*) SHELL_NAME,
+ (char*) "-c",
+ (char *) line, NULL },
+ __environ);
+ __posix_spawnattr_destroy (&spawn_attr);
+
+ if (status == 0)
{
-#ifndef _LIBC
- if (errno == ENOSYS)
- __set_errno (save);
- else
-#endif
- {
- DO_LOCK ();
- if (SUB_REF () == 0)
- {
- save = errno;
- (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
- out_restore_sigint:
- (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
- __set_errno (save);
- }
- out:
- DO_UNLOCK ();
- return -1;
- }
- }
-
-#ifdef CLEANUP_HANDLER
- CLEANUP_HANDLER;
-#endif
-
-#ifdef FORK
- pid = FORK ();
-#else
- pid = __fork ();
+ /* Cancellation results in cleanup handlers running as exceptions in
+ the block where they were installed, so it is safe to reference
+ stack variable allocate in the broader scope. */
+#if defined(_LIBC_REENTRANT) && defined(SIGCANCEL)
+ struct cancel_handler_args cancel_args =
+ {
+ .quit = &quit,
+ .intr = &intr,
+ .pid = pid
+ };
+ __libc_cleanup_region_start (1, cancel_handler, &cancel_args);
#endif
- if (pid == (pid_t) 0)
- {
- /* Child side. */
- const char *new_argv[4];
- new_argv[0] = SHELL_NAME;
- new_argv[1] = "-c";
- new_argv[2] = line;
- new_argv[3] = NULL;
-
- /* Restore the signals. */
- (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
- (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
- (void) __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL);
- INIT_LOCK ();
-
- /* Exec the shell. */
- (void) __execve (SHELL_PATH, (char *const *) new_argv, __environ);
- _exit (127);
- }
- else if (pid < (pid_t) 0)
- /* The fork failed. */
- status = -1;
- else
- /* Parent side. */
- {
/* Note the system() is a cancellation point. But since we call
waitpid() which itself is a cancellation point we do not
have to do anything here. */
if (TEMP_FAILURE_RETRY (__waitpid (pid, &status, 0)) != pid)
status = -1;
- }
-
-#ifdef CLEANUP_HANDLER
- CLEANUP_RESET;
+#if defined(_LIBC_REENTRANT) && defined(SIGCANCEL)
+ __libc_cleanup_region_end (0);
#endif
+ }
- save = errno;
DO_LOCK ();
- if ((SUB_REF () == 0
- && (__sigaction (SIGINT, &intr, (struct sigaction *) NULL)
- | __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL)) != 0)
- || __sigprocmask (SIG_SETMASK, &omask, (sigset_t *) NULL) != 0)
+ if (SUB_REF () == 0)
{
-#ifndef _LIBC
- /* glibc cannot be used on systems without waitpid. */
- if (errno == ENOSYS)
- __set_errno (save);
- else
-#endif
- status = -1;
+ /* sigaction can not fail with SIGINT/SIGQUIT used with old
+ disposition. Same applies for sigprocmask. */
+ __sigaction (SIGINT, &intr, NULL);
+ __sigaction (SIGQUIT, &quit, NULL);
+ __sigprocmask (SIG_SETMASK, &omask, NULL);
}
DO_UNLOCK ();
diff --git a/sysdeps/unix/sysv/linux/ia64/system.c b/sysdeps/unix/sysv/linux/ia64/system.c
deleted file mode 100644
index d09fefefe64753ab..0000000000000000
--- a/sysdeps/unix/sysv/linux/ia64/system.c
+++ /dev/null
@@ -1,30 +0,0 @@
-/* Copyright (C) 2002-2018 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/>. */
-
-/* We have to and actually can handle cancelable system(). The big
- problem: we have to kill the child process if necessary. To do
- this a cleanup handler has to be registered and is has to be able
- to find the PID of the child. The main problem is to reliable have
- the PID when needed. It is not necessary for the parent thread to
- return. It might still be in the kernel when the cancellation
- request comes. Therefore we have to use the clone() calls ability
- to have the kernel write the PID into the user-level variable. */
-#define FORK() \
- INLINE_SYSCALL (clone2, 6, CLONE_PARENT_SETTID | SIGCHLD, NULL, 0, \
- &pid, NULL, NULL)
-
-#include <sysdeps/unix/sysv/linux/system.c>
diff --git a/sysdeps/unix/sysv/linux/not-errno.h b/sysdeps/unix/sysv/linux/not-errno.h
index 106ba5c72e3d7dda..b2f72cfb3d412c56 100644
--- a/sysdeps/unix/sysv/linux/not-errno.h
+++ b/sysdeps/unix/sysv/linux/not-errno.h
@@ -16,6 +16,9 @@
License along with the GNU C Library; if not, see
<http://www.gnu.org/licenses/>. */
+#include <sysdep.h>
+#include <fcntl.h>
+
/* This function is used on maybe_enable_malloc_check (elf/dl-tunables.c)
and to avoid having to build/use multiple versions if stack protection
in enabled it is defined as inline. */
@@ -33,3 +36,14 @@ __access_noerrno (const char *pathname, int mode)
return INTERNAL_SYSCALL_ERRNO (res, err);
return 0;
}
+
+static inline int
+__kill_noerrno (pid_t pid, int sig)
+{
+ int res;
+ INTERNAL_SYSCALL_DECL (err);
+ res = INTERNAL_SYSCALL_CALL (kill, err, pid, sig);
+ if (INTERNAL_SYSCALL_ERROR_P (res, err))
+ return INTERNAL_SYSCALL_ERRNO (res, err);
+ return 0;
+}
diff --git a/sysdeps/unix/sysv/linux/s390/system.c b/sysdeps/unix/sysv/linux/s390/system.c
deleted file mode 100644
index d8ef46133419dd89..0000000000000000
--- a/sysdeps/unix/sysv/linux/s390/system.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (C) 2003-2018 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/>. */
-
-/* We have to and actually can handle cancelable system(). The big
- problem: we have to kill the child process if necessary. To do
- this a cleanup handler has to be registered and is has to be able
- to find the PID of the child. The main problem is to reliable have
- the PID when needed. It is not necessary for the parent thread to
- return. It might still be in the kernel when the cancellation
- request comes. Therefore we have to use the clone() calls ability
- to have the kernel write the PID into the user-level variable. */
-#define FORK() \
- INLINE_SYSCALL (clone, 3, 0, CLONE_PARENT_SETTID | SIGCHLD, &pid)
-
-#include "../system.c"
diff --git a/sysdeps/unix/sysv/linux/sparc/system.c b/sysdeps/unix/sysv/linux/sparc/system.c
deleted file mode 100644
index 1f65c83399f920d6..0000000000000000
--- a/sysdeps/unix/sysv/linux/sparc/system.c
+++ /dev/null
@@ -1,29 +0,0 @@
-/* Copyright (C) 2003-2018 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/>. */
-
-/* We have to and actually can handle cancelable system(). The big
- problem: we have to kill the child process if necessary. To do
- this a cleanup handler has to be registered and is has to be able
- to find the PID of the child. The main problem is to reliable have
- the PID when needed. It is not necessary for the parent thread to
- return. It might still be in the kernel when the cancellation
- request comes. Therefore we have to use the clone() calls ability
- to have the kernel write the PID into the user-level variable. */
-#define FORK() \
- INLINE_CLONE_SYSCALL (CLONE_PARENT_SETTID | SIGCHLD, 0, &pid, NULL, NULL)
-
-#include "../system.c"
diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
index 85239cedbf2a5ab5..6a8bd2ed2e1c29b7 100644
--- a/sysdeps/unix/sysv/linux/spawni.c
+++ b/sysdeps/unix/sysv/linux/spawni.c
@@ -138,11 +138,11 @@ __spawni_child (void *arguments)
for (int sig = 1; sig < _NSIG; ++sig)
{
if ((attr->__flags & POSIX_SPAWN_SETSIGDEF)
- && sigismember (&attr->__sd, sig))
+ && __sigismember (&attr->__sd, sig))
{
sa.sa_handler = SIG_DFL;
}
- else if (sigismember (&hset, sig))
+ else if (__sigismember (&hset, sig))
{
if (__is_internal_signal (sig))
sa.sa_handler = SIG_IGN;
diff --git a/sysdeps/unix/sysv/linux/system.c b/sysdeps/unix/sysv/linux/system.c
deleted file mode 100644
index 7cc68a1528ee8f99..0000000000000000
--- a/sysdeps/unix/sysv/linux/system.c
+++ /dev/null
@@ -1,76 +0,0 @@
-/* Copyright (C) 2002-2018 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 <sched.h>
-#include <signal.h>
-#include <string.h> /* For the real memset prototype. */
-#include <sysdep.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <libc-lock.h>
-
-/* We have to and actually can handle cancelable system(). The big
- problem: we have to kill the child process if necessary. To do
- this a cleanup handler has to be registered and is has to be able
- to find the PID of the child. The main problem is to reliable have
- the PID when needed. It is not necessary for the parent thread to
- return. It might still be in the kernel when the cancellation
- request comes. Therefore we have to use the clone() calls ability
- to have the kernel write the PID into the user-level variable. */
-#ifndef FORK
-# define FORK() \
- INLINE_SYSCALL (clone, 3, CLONE_PARENT_SETTID | SIGCHLD, 0, &pid)
-#endif
-
-#ifdef _LIBC_REENTRANT
-static void cancel_handler (void *arg);
-
-# define CLEANUP_HANDLER \
- __libc_cleanup_region_start (1, cancel_handler, &pid)
-
-# define CLEANUP_RESET \
- __libc_cleanup_region_end (0)
-#endif
-
-
-/* Linux has waitpid(), so override the generic unix version. */
-#include <sysdeps/posix/system.c>
-
-
-#ifdef _LIBC_REENTRANT
-/* The cancellation handler. */
-static void
-cancel_handler (void *arg)
-{
- pid_t child = *(pid_t *) arg;
-
- INTERNAL_SYSCALL_DECL (err);
- INTERNAL_SYSCALL (kill, err, 2, child, SIGKILL);
-
- TEMP_FAILURE_RETRY (__waitpid (child, NULL, 0));
-
- DO_LOCK ();
-
- if (SUB_REF () == 0)
- {
- (void) __sigaction (SIGQUIT, &quit, (struct sigaction *) NULL);
- (void) __sigaction (SIGINT, &intr, (struct sigaction *) NULL);
- }
-
- DO_UNLOCK ();
-}
-#endif

View File

@ -0,0 +1,194 @@
commit f09542c584b121da0322fde4b55306d512b85d93
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Mar 23 15:23:20 2020 -0300
posix: Fix system error return value [BZ #25715]
It fixes 5fb7fc9635 when posix_spawn fails.
Checked on x86_64-linux-gnu and i686-linux-gnu.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c
index d14839f3ec3a7bad..b61bd347df7ec46a 100644
--- a/stdlib/tst-system.c
+++ b/stdlib/tst-system.c
@@ -17,14 +17,128 @@
<http://www.gnu.org/licenses/>. */
#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <paths.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/temp_file.h>
+#include <support/support.h>
+
+static char *tmpdir;
+static long int namemax;
+
+static void
+do_prepare (int argc, char *argv[])
+{
+ tmpdir = support_create_temp_directory ("tst-system-");
+ /* Include the last '/0'. */
+ namemax = pathconf (tmpdir, _PC_NAME_MAX) + 1;
+ TEST_VERIFY_EXIT (namemax != -1);
+}
+#define PREPARE do_prepare
+
+struct args
+{
+ const char *command;
+ int exit_status;
+ int term_sig;
+ const char *path;
+};
+
+static void
+call_system (void *closure)
+{
+ struct args *args = (struct args *) closure;
+ int ret;
+
+ if (args->path != NULL)
+ TEST_COMPARE (setenv ("PATH", args->path, 1), 0);
+ ret = system (args->command);
+ if (args->term_sig == 0)
+ {
+ /* Expect regular termination. */
+ TEST_VERIFY (WIFEXITED (ret) != 0);
+ TEST_COMPARE (WEXITSTATUS (ret), args->exit_status);
+ }
+ else
+ {
+ /* status_or_signal < 0. Expect termination by signal. */
+ TEST_VERIFY (WIFSIGNALED (ret) != 0);
+ TEST_COMPARE (WTERMSIG (ret), args->term_sig);
+ }
+}
static int
do_test (void)
{
- return system (":");
-}
+ TEST_VERIFY (system (NULL) != 0);
+ {
+ char cmd[namemax];
+ memset (cmd, 'a', sizeof(cmd));
+ cmd[sizeof(cmd) - 1] = '\0';
+
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ cmd, 127, 0, tmpdir
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
+
+ char *returnerr = xasprintf ("%s: 1: %s: not found\n",
+ basename(_PATH_BSHELL), cmd);
+ TEST_COMPARE_STRING (result.err.buffer, returnerr);
+ free (returnerr);
+ }
+
+ {
+ char cmd[namemax + 1];
+ memset (cmd, 'a', sizeof(cmd));
+ cmd[sizeof(cmd) - 1] = '\0';
+
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ cmd, 127, 0, tmpdir
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
+
+ char *returnerr = xasprintf ("%s: 1: %s: File name too long\n",
+ basename(_PATH_BSHELL), cmd);
+ TEST_COMPARE_STRING (result.err.buffer, returnerr);
+ free (returnerr);
+ }
+
+ {
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ "kill -USR1 $$", 0, SIGUSR1
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
+ }
+
+ {
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) { "echo ...", 0 });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_stdout);
+ TEST_COMPARE_STRING (result.out.buffer, "...\n");
+ }
+
+ {
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) { "exit 1", 1 });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
+ }
+
+ TEST_COMPARE (system (":"), 0);
+
+ return 0;
+}
-#define TEST_FUNCTION do_test ()
-#include "../test-skeleton.c"
+#include <support/test-driver.c>
diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c
index 8a51a6b9919ec39b..7db09a05c3fbca43 100644
--- a/sysdeps/posix/system.c
+++ b/sysdeps/posix/system.c
@@ -97,7 +97,8 @@ cancel_handler (void *arg)
static int
do_system (const char *line)
{
- int status;
+ int status = -1;
+ int ret;
pid_t pid;
struct sigaction sa;
#ifndef _LIBC_REENTRANT
@@ -140,14 +141,14 @@ do_system (const char *line)
__posix_spawnattr_setflags (&spawn_attr,
POSIX_SPAWN_SETSIGDEF | POSIX_SPAWN_SETSIGMASK);
- status = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr,
- (char *const[]){ (char*) SHELL_NAME,
- (char*) "-c",
- (char *) line, NULL },
- __environ);
+ ret = __posix_spawn (&pid, SHELL_PATH, 0, &spawn_attr,
+ (char *const[]){ (char *) SHELL_NAME,
+ (char *) "-c",
+ (char *) line, NULL },
+ __environ);
__posix_spawnattr_destroy (&spawn_attr);
- if (status == 0)
+ if (ret == 0)
{
/* Cancellation results in cleanup handlers running as exceptions in
the block where they were installed, so it is safe to reference
@@ -182,6 +183,9 @@ do_system (const char *line)
}
DO_UNLOCK ();
+ if (ret != 0)
+ __set_errno (ret);
+
return status;
}

View File

@ -0,0 +1,64 @@
commit 7a7226543611897103c7483bec160547294dcf0d
Author: Alexandra Hájková <ahajkova@redhat.com>
Date: Sat Dec 26 20:44:34 2020 +0100
Add xfchmod to libsupport
diff --git a/support/Makefile b/support/Makefile
index d2b95539403e416c..4875f52495ef292d 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -91,6 +91,7 @@ libsupport-routines = \
xdlfcn \
xdlmopen \
xdup2 \
+ xfchmod \
xfclose \
xfopen \
xfork \
diff --git a/support/xfchmod.c b/support/xfchmod.c
new file mode 100644
index 0000000000000000..4323b9ca8e078c98
--- /dev/null
+++ b/support/xfchmod.c
@@ -0,0 +1,28 @@
+/* fchmod with error checking.
+ Copyright (C) 2021 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xunistd.h>
+#include <sys/stat.h>
+
+void
+xfchmod (int fd, mode_t mode)
+{
+ if (fchmod (fd, mode) != 0)
+ FAIL_EXIT1 ("fchmod (%d, 0%o): %m", fd, mode);
+}
diff --git a/support/xunistd.h b/support/xunistd.h
index 74fd2771d12c36fe..ced8cb1dd9ee356c 100644
--- a/support/xunistd.h
+++ b/support/xunistd.h
@@ -45,6 +45,7 @@ long long xlseek (int fd, long long offset, int whence);
void xftruncate (int fd, long long length);
void xsymlink (const char *target, const char *linkpath);
void xchdir (const char *path);
+void xfchmod (int fd, mode_t mode);
/* Equivalent of "mkdir -p". */
void xmkdirp (const char *, mode_t);

View File

@ -0,0 +1,56 @@
commit 7b9c3260bcca73781dda6bc2ddee84869bedfb8c
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Mon Dec 14 11:42:33 2020 -0300
support: Add xchmod wrapper
Checked on x86_64-linux-gnu.
diff --git a/support/xchmod.c b/support/xchmod.c
new file mode 100644
index 0000000000000000..5e403c7cc2705aef
--- /dev/null
+++ b/support/xchmod.c
@@ -0,0 +1,30 @@
+/* chmod with error checking.
+ Copyright (C) 2020 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
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/xunistd.h>
+#include <support/check.h>
+
+#include <sys/stat.h>
+
+void
+xchmod (const char *pathname, mode_t mode)
+{
+ int r = chmod (pathname, mode);
+ if (r < 0)
+ FAIL_EXIT1 ("chmod (%s, %d): %m", pathname, mode);
+}
diff --git a/support/xunistd.h b/support/xunistd.h
index ced8cb1dd9ee356c..e92056c65efe8d6a 100644
--- a/support/xunistd.h
+++ b/support/xunistd.h
@@ -46,6 +46,7 @@ void xftruncate (int fd, long long length);
void xsymlink (const char *target, const char *linkpath);
void xchdir (const char *path);
void xfchmod (int fd, mode_t mode);
+void xchmod (const char *pathname, mode_t mode);
/* Equivalent of "mkdir -p". */
void xmkdirp (const char *, mode_t);

View File

@ -0,0 +1,73 @@
commit 4eda036f5b897fa8bc20ddd2099b5a6ed4239dc9
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Tue Mar 24 15:48:34 2020 -0300
stdlib: Move tst-system to tests-container
Fix some issues with different shell and error messages.
Checked on x86_64-linux-gnu and i686-linux-gnu.
diff --git a/stdlib/Makefile b/stdlib/Makefile
index 01194bbf7cc96851..9d0edcf6a7749b28 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -70,7 +70,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
test-canon test-canon2 tst-strtoll tst-environ \
tst-xpg-basename tst-random tst-random2 tst-bsearch \
tst-limits tst-rand48 bug-strtod tst-setcontext \
- tst-setcontext2 test-a64l tst-qsort tst-system testmb2 \
+ tst-setcontext2 test-a64l tst-qsort testmb2 \
bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \
tst-rand48-2 tst-makecontext tst-strtod5 \
tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
@@ -92,6 +92,7 @@ tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
tst-tls-atexit tst-tls-atexit-nodelete
tests-static := tst-secure-getenv
+tests-container := tst-system
ifeq ($(build-hardcoded-path-in-tests),yes)
tests += tst-empty-env
diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c
index b61bd347df7ec46a..194e09828dd5c206 100644
--- a/stdlib/tst-system.c
+++ b/stdlib/tst-system.c
@@ -88,7 +88,8 @@ do_test (void)
});
support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
- char *returnerr = xasprintf ("%s: 1: %s: not found\n",
+ char *returnerr = xasprintf ("%s: execing %s failed: "
+ "No such file or directory",
basename(_PATH_BSHELL), cmd);
TEST_COMPARE_STRING (result.err.buffer, returnerr);
free (returnerr);
@@ -106,7 +107,8 @@ do_test (void)
});
support_capture_subprocess_check (&result, "system", 0, sc_allow_stderr);
- char *returnerr = xasprintf ("%s: 1: %s: File name too long\n",
+ char *returnerr = xasprintf ("%s: execing %s failed: "
+ "File name too long",
basename(_PATH_BSHELL), cmd);
TEST_COMPARE_STRING (result.err.buffer, returnerr);
free (returnerr);
@@ -116,7 +118,7 @@ do_test (void)
struct support_capture_subprocess result;
result = support_capture_subprocess (call_system,
&(struct args) {
- "kill -USR1 $$", 0, SIGUSR1
+ "kill $$", 0, SIGTERM
});
support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
}
@@ -136,7 +138,7 @@ do_test (void)
support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
}
- TEST_COMPARE (system (":"), 0);
+ TEST_COMPARE (system (""), 0);
return 0;
}

View File

@ -0,0 +1,74 @@
commit 42dda89dcb0407f6799dbfd0b9dab1529666ad51
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date: Fri Dec 11 15:23:05 2020 -0300
posix: Fix return value of system if shell can not be executed [BZ #27053]
POSIX states that system returned code for failure to execute the shell
shall be as if the shell had terminated using _exit(127). This
behaviour was removed with 5fb7fc96350575.
Checked on x86_64-linux-gnu.
diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c
index 194e09828dd5c206..8681584f15ef3b47 100644
--- a/stdlib/tst-system.c
+++ b/stdlib/tst-system.c
@@ -26,6 +26,7 @@
#include <support/check.h>
#include <support/temp_file.h>
#include <support/support.h>
+#include <support/xunistd.h>
static char *tmpdir;
static long int namemax;
@@ -138,6 +139,22 @@ do_test (void)
support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
}
+ {
+ struct stat64 st;
+ xstat (_PATH_BSHELL, &st);
+ mode_t mode = st.st_mode;
+ xchmod (_PATH_BSHELL, mode & ~(S_IXUSR | S_IXGRP | S_IXOTH));
+
+ struct support_capture_subprocess result;
+ result = support_capture_subprocess (call_system,
+ &(struct args) {
+ "exit 1", 127, 0
+ });
+ support_capture_subprocess_check (&result, "system", 0, sc_allow_none);
+
+ xchmod (_PATH_BSHELL, st.st_mode);
+ }
+
TEST_COMPARE (system (""), 0);
return 0;
diff --git a/support/Makefile b/support/Makefile
index 4875f52495ef292d..09b41b0d57e9239a 100644
--- a/support/Makefile
+++ b/support/Makefile
@@ -86,6 +86,7 @@ libsupport-routines = \
xchroot \
xclone \
xclose \
+ xchmod \
xconnect \
xcopy_file_range \
xdlfcn \
diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c
index 7db09a05c3fbca43..047ded4badfddcab 100644
--- a/sysdeps/posix/system.c
+++ b/sysdeps/posix/system.c
@@ -171,6 +171,10 @@ do_system (const char *line)
__libc_cleanup_region_end (0);
#endif
}
+ else
+ /* POSIX states that failure to execute the shell should return
+ as if the shell had terminated using _exit(127). */
+ status = W_EXITCODE (127, 0);
DO_LOCK ();
if (SUB_REF () == 0)

View File

@ -0,0 +1,21 @@
commit 542160f0b6a7c26758c9575a8876f6624a5dd65f
Author: Girish Joshi <girish946@gmail.com>
Date: Mon Mar 2 15:19:29 2020 -0500
Fixed typo in run_command_array() in support/shell-container.c
https://sourceware.org/bugzilla/show_bug.cgi?id=23991
diff --git a/support/shell-container.c b/support/shell-container.c
index 9bd90d3f60529079..e87ac5cf1baa84e5 100644
--- a/support/shell-container.c
+++ b/support/shell-container.c
@@ -228,7 +228,7 @@ run_command_array (char **argv)
if (new_stderr != 2)
{
dup2 (new_stderr, 2);
- close (new_stdout);
+ close (new_stderr);
}
if (builtin_func != NULL)

View File

@ -0,0 +1,86 @@
commit 33e03f9cd2be4f2cd62f93fda539cc07d9c8130e
Author: Joan Bruguera <joanbrugueram@gmail.com>
Date: Mon Apr 11 19:49:56 2022 +0200
misc: Fix rare fortify crash on wchar funcs. [BZ 29030]
If `__glibc_objsize (__o) == (size_t) -1` (i.e. `__o` is unknown size), fortify
checks should pass, and `__whatever_alias` should be called.
Previously, `__glibc_objsize (__o) == (size_t) -1` was explicitly checked, but
on commit a643f60c53876b, this was moved into `__glibc_safe_or_unknown_len`.
A comment says the -1 case should work as: "The -1 check is redundant because
since it implies that __glibc_safe_len_cond is true.". But this fails when:
* `__s > 1`
* `__osz == -1` (i.e. unknown size at compile time)
* `__l` is big enough
* `__l * __s <= __osz` can be folded to a constant
(I only found this to be true for `mbsrtowcs` and other functions in wchar2.h)
In this case `__l * __s <= __osz` is false, and `__whatever_chk_warn` will be
called by `__glibc_fortify` or `__glibc_fortify_n` and crash the program.
This commit adds the explicit `__osz == -1` check again.
moc crashes on startup due to this, see: https://bugs.archlinux.org/task/74041
Minimal test case (test.c):
#include <wchar.h>
int main (void)
{
const char *hw = "HelloWorld";
mbsrtowcs (NULL, &hw, (size_t)-1, NULL);
return 0;
}
Build with:
gcc -O2 -Wp,-D_FORTIFY_SOURCE=2 test.c -o test && ./test
Output:
*** buffer overflow detected ***: terminated
Fixes: BZ #29030
Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com>
Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
diff --git a/debug/tst-fortify.c b/debug/tst-fortify.c
index 1668294e48b5c63c..701bffd1d664f289 100644
--- a/debug/tst-fortify.c
+++ b/debug/tst-fortify.c
@@ -1505,6 +1505,11 @@ do_test (void)
CHK_FAIL_END
#endif
+ /* Bug 29030 regresion check */
+ cp = "HelloWorld";
+ if (mbsrtowcs (NULL, &cp, (size_t)-1, &s) != 10)
+ FAIL ();
+
cp = "A";
if (mbstowcs (wenough, cp, 10) != 1
|| wcscmp (wenough, L"A") != 0)
diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
index a17ae0ed87e6163f..404496c7d6da4fb3 100644
--- a/misc/sys/cdefs.h
+++ b/misc/sys/cdefs.h
@@ -143,13 +143,13 @@
|| (__builtin_constant_p (__l) && (__l) > 0))
/* Length is known to be safe at compile time if the __L * __S <= __OBJSZ
- condition can be folded to a constant and if it is true. The -1 check is
- redundant because since it implies that __glibc_safe_len_cond is true. */
+ condition can be folded to a constant and if it is true, or unknown (-1) */
#define __glibc_safe_or_unknown_len(__l, __s, __osz) \
- (__glibc_unsigned_or_positive (__l) \
- && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
- __s, __osz)) \
- && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), __s, __osz))
+ ((__osz) == (__SIZE_TYPE__) -1 \
+ || (__glibc_unsigned_or_positive (__l) \
+ && __builtin_constant_p (__glibc_safe_len_cond ((__SIZE_TYPE__) (__l), \
+ (__s), (__osz))) \
+ && __glibc_safe_len_cond ((__SIZE_TYPE__) (__l), (__s), (__osz))))
/* Conversely, we know at compile time that the length is unsafe if the
__L * __S <= __OBJSZ condition can be folded to a constant and if it is

View File

@ -1,6 +1,6 @@
%define glibcsrcdir glibc-2.28 %define glibcsrcdir glibc-2.28
%define glibcversion 2.28 %define glibcversion 2.28
%define glibcrelease 197%{?dist} %define glibcrelease 199%{?dist}
# Pre-release tarballs are pulled in from git using a command that is # Pre-release tarballs are pulled in from git using a command that is
# effectively: # effectively:
# #
@ -879,6 +879,20 @@ Patch684: glibc-rh2033684-12.patch
Patch685: glibc-rh2063712.patch Patch685: glibc-rh2063712.patch
Patch686: glibc-rh2063042.patch Patch686: glibc-rh2063042.patch
Patch687: glibc-rh2071745.patch Patch687: glibc-rh2071745.patch
Patch688: glibc-rh2065588-1.patch
Patch689: glibc-rh2065588-2.patch
Patch690: glibc-rh2065588-3.patch
Patch691: glibc-rh2065588-4.patch
Patch692: glibc-rh2065588-5.patch
Patch693: glibc-rh2065588-6.patch
Patch694: glibc-rh2065588-7.patch
Patch695: glibc-rh2065588-8.patch
Patch696: glibc-rh2065588-9.patch
Patch697: glibc-rh2065588-10.patch
Patch698: glibc-rh2065588-11.patch
Patch699: glibc-rh2065588-12.patch
Patch700: glibc-rh2065588-13.patch
Patch701: glibc-rh2072329.patch
############################################################################## ##############################################################################
# Continued list of core "glibc" package information: # Continued list of core "glibc" package information:
@ -2709,6 +2723,12 @@ fi
%files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared
%changelog %changelog
* Tue Apr 26 2022 Siddhesh Poyarekar <siddhesh@redhat.com> - 2.28-199
- Fix fortify false positive with mbsrtowcs and mbsnrtowcs (#2072329).
* Fri Apr 22 2022 Carlos O'Donell <carlos@redhat.com> - 2.28-198
- Fix multi-threaded popen defect leading to segfault (#2065588)
* Tue Apr 05 2022 Arjun Shankar <arjun@redhat.com> - 2.28-197 * Tue Apr 05 2022 Arjun Shankar <arjun@redhat.com> - 2.28-197
- timezone: Fix a test that causes occasional build failure (#2071745) - timezone: Fix a test that causes occasional build failure (#2071745)