posix: fix system when a child cannot be created [BZ #32450]

POSIX states that "if a child process cannot be created, or if the
termination status for the command language interpreter cannot be
obtained, system() shall return -1 and set errno to indicate the error."

In the glibc implementation it could happen when posix_spawn fails,
which happens when the underlying fork, vfork, or clone call fails. They
could fail with EAGAIN and ENOMEM.

Resolves: BZ #32450
Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
Aurelien Jarno 2024-12-19 23:55:15 +01:00
parent 034cd67528
commit 6fd215d6ae
2 changed files with 28 additions and 3 deletions

View File

@ -20,6 +20,7 @@
#include <string.h>
#include <signal.h>
#include <paths.h>
#include <sys/resource.h>
#include <support/capture_subprocess.h>
#include <support/check.h>
@ -194,6 +195,26 @@ do_test (void)
xpthread_join (long_sleep_thread);
}
{
struct rlimit rlimit_orig, rlimit_new;
if (getrlimit (RLIMIT_NPROC, &rlimit_orig) != 0)
FAIL_EXIT1 ("getrlimit (RLIMIT_NPROC) failed: %m");
/* Force failure for the system call */
rlimit_new.rlim_cur = 0;
rlimit_new.rlim_max = rlimit_orig.rlim_max;
if (setrlimit (RLIMIT_NPROC, &rlimit_new) != 0)
FAIL_EXIT1 ("setrlimit (RLIMIT_NPROC) failed: %m");
TEST_COMPARE (system (""), -1);
/* Restore NPROC limit */
if (setrlimit (RLIMIT_NPROC, &rlimit_orig) != 0)
FAIL_EXIT1 ("setrlimit (RLIMIT_NPROC) failed: %m");
}
TEST_COMPARE (system (""), 0);
return 0;

View File

@ -175,6 +175,10 @@ do_system (const char *line)
__libc_cleanup_region_end (0);
#endif
}
else if (ret == EAGAIN || ret == ENOMEM)
/* POSIX states that failure to create a child process should
return -1. */
status = -1;
else
/* POSIX states that failure to execute the shell should return
as if the shell had terminated using _exit(127). */