Remove default value for LD_PROFILE_OUTPUT
Resolves: RHEL-142193
This commit is contained in:
parent
67904a03a3
commit
6748bccde4
267
glibc-RHEL-142193-1.patch
Normal file
267
glibc-RHEL-142193-1.patch
Normal file
@ -0,0 +1,267 @@
|
||||
commit 1e1ad714ee9a663eda0e2bffad1d9f258b00a4e9
|
||||
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
Date: Mon May 6 13:18:47 2024 -0300
|
||||
|
||||
support: Add envp argument to support_capture_subprogram
|
||||
|
||||
So tests can specify a list of environment variables.
|
||||
Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
|
||||
|
||||
Conflicts:
|
||||
elf/tst-tunables-enable_secure.c
|
||||
(file does not exist downstream)
|
||||
|
||||
diff --git a/elf/tst-audit18.c b/elf/tst-audit18.c
|
||||
index 841251dd7003aa7d..cec93e269ca0b4ef 100644
|
||||
--- a/elf/tst-audit18.c
|
||||
+++ b/elf/tst-audit18.c
|
||||
@@ -79,7 +79,7 @@ do_test (int argc, char *argv[])
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod18.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit18", 0, sc_allow_stderr);
|
||||
|
||||
struct
|
||||
diff --git a/elf/tst-audit19b.c b/elf/tst-audit19b.c
|
||||
index 70bfe4eadf5ee845..88d99a416bbe93dd 100644
|
||||
--- a/elf/tst-audit19b.c
|
||||
+++ b/elf/tst-audit19b.c
|
||||
@@ -69,7 +69,7 @@ do_test (int argc, char *argv[])
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod18b.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit18b", 0, sc_allow_stderr);
|
||||
|
||||
bool find_symbind = false;
|
||||
diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c
|
||||
index 4e97be3be0c6a2e3..6aa18af948afa9c5 100644
|
||||
--- a/elf/tst-audit22.c
|
||||
+++ b/elf/tst-audit22.c
|
||||
@@ -83,7 +83,7 @@ do_test (int argc, char *argv[])
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod22.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
|
||||
|
||||
/* The respawned process should always print the vDSO address (otherwise it
|
||||
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c
|
||||
index 1b76336595fcd301..7786a74e648aeb6f 100644
|
||||
--- a/elf/tst-audit23.c
|
||||
+++ b/elf/tst-audit23.c
|
||||
@@ -87,7 +87,7 @@ do_one_test (int argc, char *argv[], bool pass_dlclose_flag)
|
||||
|
||||
setenv ("LD_AUDIT", "tst-auditmod23.so", 0);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
|
||||
|
||||
{
|
||||
diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c
|
||||
index b209ee820f2f2a02..cdd4f2ce2b54d622 100644
|
||||
--- a/elf/tst-audit25a.c
|
||||
+++ b/elf/tst-audit25a.c
|
||||
@@ -77,7 +77,7 @@ do_test (int argc, char *argv[])
|
||||
|
||||
{
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
@@ -102,7 +102,7 @@ do_test (int argc, char *argv[])
|
||||
{
|
||||
setenv ("LD_BIND_NOW", "1", 0);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c
|
||||
index 9b8665d5171b7c6b..939f4d6188368540 100644
|
||||
--- a/elf/tst-audit25b.c
|
||||
+++ b/elf/tst-audit25b.c
|
||||
@@ -76,7 +76,7 @@ do_test (int argc, char *argv[])
|
||||
|
||||
{
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
@@ -102,7 +102,7 @@ do_test (int argc, char *argv[])
|
||||
{
|
||||
setenv ("LD_BIND_NOW", "1", 0);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-audit25a", 0,
|
||||
sc_allow_stderr);
|
||||
|
||||
diff --git a/elf/tst-glibc-hwcaps-2-cache.c b/elf/tst-glibc-hwcaps-2-cache.c
|
||||
index 81ab44ff78ddbb57..af91476ccafeecff 100644
|
||||
--- a/elf/tst-glibc-hwcaps-2-cache.c
|
||||
+++ b/elf/tst-glibc-hwcaps-2-cache.c
|
||||
@@ -32,7 +32,7 @@ main (int argc, char **argv)
|
||||
/* Run ldconfig to populate the cache. */
|
||||
char *command = xasprintf ("%s/ldconfig", support_install_rootsbindir);
|
||||
struct support_capture_subprocess result =
|
||||
- support_capture_subprogram (command, &((char *) { NULL }));
|
||||
+ support_capture_subprogram (command, &((char *) { NULL }), NULL);
|
||||
support_capture_subprocess_check (&result, "ldconfig", 0, sc_allow_none);
|
||||
free (command);
|
||||
|
||||
diff --git a/elf/tst-rtld-run-static.c b/elf/tst-rtld-run-static.c
|
||||
index b2650e85ffbcdc20..f05c00eb7b76958b 100644
|
||||
--- a/elf/tst-rtld-run-static.c
|
||||
+++ b/elf/tst-rtld-run-static.c
|
||||
@@ -30,7 +30,7 @@ do_test (void)
|
||||
{
|
||||
char *argv[] = { (char *) "ld.so", ldconfig_path, (char *) "--help", NULL };
|
||||
struct support_capture_subprocess cap
|
||||
- = support_capture_subprogram (support_objdir_elf_ldso, argv);
|
||||
+ = support_capture_subprogram (support_objdir_elf_ldso, argv, NULL);
|
||||
support_capture_subprocess_check (&cap, "no --argv0", 0, sc_allow_stdout);
|
||||
puts ("info: output without --argv0:");
|
||||
puts (cap.out.buffer);
|
||||
@@ -46,7 +46,7 @@ do_test (void)
|
||||
ldconfig_path, (char *) "--help", NULL
|
||||
};
|
||||
struct support_capture_subprocess cap
|
||||
- = support_capture_subprogram (support_objdir_elf_ldso, argv);
|
||||
+ = support_capture_subprogram (support_objdir_elf_ldso, argv, NULL);
|
||||
support_capture_subprocess_check (&cap, "with --argv0", 0, sc_allow_stdout);
|
||||
puts ("info: output with --argv0:");
|
||||
puts (cap.out.buffer);
|
||||
diff --git a/elf/tst-tunables.c b/elf/tst-tunables.c
|
||||
index dff34ed748b4ae83..4884dd09f0ddc505 100644
|
||||
--- a/elf/tst-tunables.c
|
||||
+++ b/elf/tst-tunables.c
|
||||
@@ -396,7 +396,7 @@ do_test (int argc, char *argv[])
|
||||
tests[i].value);
|
||||
setenv (tests[i].name, tests[i].value, 1);
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-tunables", 0,
|
||||
sc_allow_stderr);
|
||||
support_capture_subprocess_free (&result);
|
||||
diff --git a/support/capture_subprocess.h b/support/capture_subprocess.h
|
||||
index 8cbdca3b9dfb41ba..57bb941e7d1e5c84 100644
|
||||
--- a/support/capture_subprocess.h
|
||||
+++ b/support/capture_subprocess.h
|
||||
@@ -35,11 +35,12 @@ struct support_capture_subprocess
|
||||
struct support_capture_subprocess support_capture_subprocess
|
||||
(void (*callback) (void *), void *closure);
|
||||
|
||||
-/* Issue FILE with ARGV arguments by using posix_spawn and capture standard
|
||||
- output, standard error, and the exit status. The out.buffer and err.buffer
|
||||
- are handle as support_capture_subprocess. */
|
||||
+/* Issue FILE with ARGV arguments and ENVP environments by using posix_spawn
|
||||
+ and capture standard output, standard error, and the exit status. If
|
||||
+ ENVP is NULL the current environment variable is used. The out.buffer and
|
||||
+ err.buffer are handle by support_capture_subprocess. */
|
||||
struct support_capture_subprocess support_capture_subprogram
|
||||
- (const char *file, char *const argv[]);
|
||||
+ (const char *file, char *const argv[], char *const envp[]);
|
||||
|
||||
/* Copy the running program into a setgid binary and run it with
|
||||
CHILD_ID argument. If the program exits with a non-zero status,
|
||||
diff --git a/support/subprocess.h b/support/subprocess.h
|
||||
index 8fbb895353d61965..8274a2b22bb10296 100644
|
||||
--- a/support/subprocess.h
|
||||
+++ b/support/subprocess.h
|
||||
@@ -33,10 +33,11 @@ struct support_subprocess
|
||||
struct support_subprocess support_subprocess
|
||||
(void (*callback) (void *), void *closure);
|
||||
|
||||
-/* Issue FILE with ARGV arguments by using posix_spawn and return is PID, a
|
||||
- pipe redirected to STDOUT, and a pipe redirected to STDERR. */
|
||||
+/* Issue FILE with ARGV arguments and ENVP environments by using posix_spawn
|
||||
+ and return is PID, a pipe redirected to STDOUT, and a pipe redirected to
|
||||
+ STDERR. If ENVP is NULL the current environment variable is used. */
|
||||
struct support_subprocess support_subprogram
|
||||
- (const char *file, char *const argv[]);
|
||||
+ (const char *file, char *const argv[], char *const envp[]);
|
||||
|
||||
/* Invoke program FILE with ARGV arguments by using posix_spawn and wait for it
|
||||
to complete. Return program exit status. */
|
||||
diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
|
||||
index 8dc95f8aa723b6bc..cbc695106483ab54 100644
|
||||
--- a/support/support_capture_subprocess.c
|
||||
+++ b/support/support_capture_subprocess.c
|
||||
@@ -98,13 +98,14 @@ support_capture_subprocess (void (*callback) (void *), void *closure)
|
||||
}
|
||||
|
||||
struct support_capture_subprocess
|
||||
-support_capture_subprogram (const char *file, char *const argv[])
|
||||
+support_capture_subprogram (const char *file, char *const argv[],
|
||||
+ char *const envp[])
|
||||
{
|
||||
struct support_capture_subprocess result;
|
||||
xopen_memstream (&result.out);
|
||||
xopen_memstream (&result.err);
|
||||
|
||||
- struct support_subprocess proc = support_subprogram (file, argv);
|
||||
+ struct support_subprocess proc = support_subprogram (file, argv, envp);
|
||||
|
||||
support_capture_poll (&result, &proc);
|
||||
return result;
|
||||
diff --git a/support/support_subprocess.c b/support/support_subprocess.c
|
||||
index a2fef394d42ea4f9..b692a7f8b178502d 100644
|
||||
--- a/support/support_subprocess.c
|
||||
+++ b/support/support_subprocess.c
|
||||
@@ -69,7 +69,7 @@ support_subprocess (void (*callback) (void *), void *closure)
|
||||
}
|
||||
|
||||
struct support_subprocess
|
||||
-support_subprogram (const char *file, char *const argv[])
|
||||
+support_subprogram (const char *file, char *const argv[], char *const envp[])
|
||||
{
|
||||
struct support_subprocess result = support_subprocess_init ();
|
||||
|
||||
@@ -84,7 +84,8 @@ support_subprogram (const char *file, char *const argv[])
|
||||
xposix_spawn_file_actions_addclose (&fa, result.stdout_pipe[1]);
|
||||
xposix_spawn_file_actions_addclose (&fa, result.stderr_pipe[1]);
|
||||
|
||||
- result.pid = xposix_spawn (file, &fa, NULL, argv, environ);
|
||||
+ result.pid = xposix_spawn (file, &fa, NULL, argv,
|
||||
+ envp == NULL ? environ : envp);
|
||||
|
||||
xclose (result.stdout_pipe[1]);
|
||||
xclose (result.stderr_pipe[1]);
|
||||
diff --git a/support/tst-support_capture_subprocess.c b/support/tst-support_capture_subprocess.c
|
||||
index 8145548982a935cb..756fb75d195cdf8a 100644
|
||||
--- a/support/tst-support_capture_subprocess.c
|
||||
+++ b/support/tst-support_capture_subprocess.c
|
||||
@@ -238,7 +238,7 @@ do_subprogram (const struct test *test)
|
||||
args[argc] = NULL;
|
||||
TEST_VERIFY (argc < argv_size);
|
||||
|
||||
- return support_capture_subprogram (args[0], args);
|
||||
+ return support_capture_subprogram (args[0], args, NULL);
|
||||
}
|
||||
|
||||
enum test_type
|
||||
diff --git a/sysdeps/x86/tst-hwcap-tunables.c b/sysdeps/x86/tst-hwcap-tunables.c
|
||||
index bc573c7435130dee..94307283d7cdbdc7 100644
|
||||
--- a/sysdeps/x86/tst-hwcap-tunables.c
|
||||
+++ b/sysdeps/x86/tst-hwcap-tunables.c
|
||||
@@ -133,7 +133,7 @@ do_test (int argc, char *argv[])
|
||||
setenv ("GLIBC_TUNABLES", tunable, 1);
|
||||
|
||||
struct support_capture_subprocess result
|
||||
- = support_capture_subprogram (spargv[0], spargv);
|
||||
+ = support_capture_subprogram (spargv[0], spargv, NULL);
|
||||
support_capture_subprocess_check (&result, "tst-tunables", 0,
|
||||
sc_allow_stderr);
|
||||
support_capture_subprocess_free (&result);
|
||||
171
glibc-RHEL-142193-2.patch
Normal file
171
glibc-RHEL-142193-2.patch
Normal file
@ -0,0 +1,171 @@
|
||||
commit 7b543dcdf97d07fd4346feb17916e08fe83ad0ae
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Thu Jan 15 22:29:46 2026 +0100
|
||||
|
||||
elf: Ignore LD_PROFILE if LD_PROFILE_OUTPUT is not set (bug 33797)
|
||||
|
||||
The previous default for LD_PROFILE_OUTPUT, /var/tmp, is insecure
|
||||
because it's typically a 1777 directory, and other systems could
|
||||
place malicious files there which interfere with execution.
|
||||
|
||||
Requiring the user to specify a profiling directory mitigates
|
||||
the impact of bug 33797. Clear LD_PROFILE_OUTPUT alongside
|
||||
with LD_PROFILE.
|
||||
|
||||
Rework the test not to use predictable file names.
|
||||
|
||||
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
|
||||
|
||||
Conflicts:
|
||||
elf/tst-env-setuid.c
|
||||
(Downstream is missing commit 5d23dfb289174d73b8907b86d2bef7a3ca889840)
|
||||
|
||||
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||
index cd790e37f2a323a4..8b189a87f76e7e08 100644
|
||||
--- a/elf/rtld.c
|
||||
+++ b/elf/rtld.c
|
||||
@@ -360,7 +360,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
|
||||
._dl_fpu_control = _FPU_DEFAULT,
|
||||
._dl_pagesize = EXEC_PAGESIZE,
|
||||
._dl_inhibit_cache = 0,
|
||||
- ._dl_profile_output = "/var/tmp",
|
||||
|
||||
/* Function pointers. */
|
||||
._dl_debug_printf = _dl_debug_printf,
|
||||
@@ -2735,6 +2734,15 @@ process_envvars_default (struct dl_main_state *state)
|
||||
}
|
||||
}
|
||||
|
||||
+ /* There is no fixed, safe directory to store profiling data, so
|
||||
+ activate LD_PROFILE only if LD_PROFILE_OUTPUT is set as well. */
|
||||
+ if (GLRO(dl_profile) != NULL && GLRO(dl_profile_output) == NULL)
|
||||
+ {
|
||||
+ _dl_error_printf ("\
|
||||
+warning: LD_PROFILE ignored because LD_PROFILE_OUTPUT not specified\n");
|
||||
+ GLRO(dl_profile) = NULL;
|
||||
+ }
|
||||
+
|
||||
/* If we have to run the dynamic linker in debugging mode and the
|
||||
LD_DEBUG_OUTPUT environment variable is given, we write the debug
|
||||
messages to this file. */
|
||||
diff --git a/elf/tst-env-setuid.c b/elf/tst-env-setuid.c
|
||||
index c084aa4c1a382152..ff4acd07e5e8b986 100644
|
||||
--- a/elf/tst-env-setuid.c
|
||||
+++ b/elf/tst-env-setuid.c
|
||||
@@ -40,6 +40,12 @@ static char SETGID_CHILD[] = "setgid-child";
|
||||
# define PROFILE_LIB "tst-sonamemove-runmod2.so"
|
||||
#endif
|
||||
|
||||
+/* Computed path for LD_DEBUG_OUTPUT. */
|
||||
+static char *debugoutputpath;
|
||||
+
|
||||
+/* Expected file name for erroneous LD_PROFILE output. */
|
||||
+static char *profilepath;
|
||||
+
|
||||
struct envvar_t
|
||||
{
|
||||
const char *env;
|
||||
@@ -56,13 +62,14 @@ static const struct envvar_t filtered_envvars[] =
|
||||
{ "LD_LIBRARY_PATH", FILTERED_VALUE },
|
||||
{ "LD_PRELOAD", FILTERED_VALUE },
|
||||
{ "LD_PROFILE", PROFILE_LIB },
|
||||
+ { "LD_PROFILE_OUTPUT", "/var/tmp" }, /* Not actually used. */
|
||||
{ "MALLOC_ARENA_MAX", FILTERED_VALUE },
|
||||
{ "MALLOC_PERTURB_", FILTERED_VALUE },
|
||||
{ "MALLOC_TRACE", FILTERED_VALUE },
|
||||
{ "MALLOC_TRIM_THRESHOLD_", FILTERED_VALUE },
|
||||
{ "RES_OPTIONS", FILTERED_VALUE },
|
||||
{ "LD_DEBUG", "all" },
|
||||
- { "LD_DEBUG_OUTPUT", "/tmp/some-file" },
|
||||
+ { "LD_DEBUG_OUTPUT", "overwritten" }, /* Not actually used. */
|
||||
{ "LD_WARN", FILTERED_VALUE },
|
||||
{ "LD_VERBOSE", FILTERED_VALUE },
|
||||
{ "LD_BIND_NOW", "0" },
|
||||
@@ -112,18 +119,12 @@ test_child (void)
|
||||
}
|
||||
|
||||
/* Also check if no profile file was created.
|
||||
- The parent sets LD_DEBUG_OUTPUT="/tmp/some-file"
|
||||
- which should be filtered. Then it falls back to "/var/tmp".
|
||||
Note: LD_PROFILE is not supported for static binaries. */
|
||||
- {
|
||||
- char *profilepath = xasprintf ("/var/tmp/%s.profile", PROFILE_LIB);
|
||||
- if (!access (profilepath, R_OK))
|
||||
- {
|
||||
- printf ("FAIL: LD_PROFILE file at %s was created!\n", profilepath);
|
||||
- ret = 1;
|
||||
- }
|
||||
- free (profilepath);
|
||||
- }
|
||||
+ if (!access (profilepath, R_OK))
|
||||
+ {
|
||||
+ printf ("FAIL: LD_PROFILE file at %s was created!\n", profilepath);
|
||||
+ ret = 1;
|
||||
+ }
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -136,6 +137,11 @@ do_test (int argc, char **argv)
|
||||
if (argc >= 2 && strstr (argv[1], LD_SO) != 0)
|
||||
FAIL_UNSUPPORTED ("dynamic test requires --enable-hardcoded-path-in-tests");
|
||||
|
||||
+ profilepath = xasprintf ("%s/%s.profile",
|
||||
+ support_objdir_root, PROFILE_LIB);
|
||||
+ debugoutputpath = xasprintf ("%s/tst-env-setuid-file",
|
||||
+ support_objdir_root);
|
||||
+
|
||||
/* Setgid child process. */
|
||||
if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
|
||||
{
|
||||
@@ -148,7 +154,6 @@ do_test (int argc, char **argv)
|
||||
|
||||
if (ret != 0)
|
||||
exit (1);
|
||||
- return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -162,20 +167,25 @@ do_test (int argc, char **argv)
|
||||
e++)
|
||||
setenv (e->env, e->value, 1);
|
||||
|
||||
+ /* Dynamically computed values. */
|
||||
+ setenv ("LD_DEBUG_OUTPUT", debugoutputpath, 1);
|
||||
+ setenv ("LD_PROFILE_OUTPUT", support_objdir_root, 1);
|
||||
+
|
||||
/* Ensure that the profile output does not exist from a previous run
|
||||
(e.g. if test_dir, which defaults to /tmp, is mounted nosuid.)
|
||||
Note: support_capture_subprogram_self_sgid creates the SGID binary
|
||||
in test_dir. */
|
||||
- {
|
||||
- char *profilepath = xasprintf ("/var/tmp/%s.profile", PROFILE_LIB);
|
||||
- unlink (profilepath);
|
||||
- free (profilepath);
|
||||
- }
|
||||
+ unlink (profilepath);
|
||||
|
||||
support_capture_subprogram_self_sgid (SETGID_CHILD);
|
||||
|
||||
- return 0;
|
||||
+ /* And clean up afterwards if necessary. */
|
||||
+ unlink (profilepath);
|
||||
}
|
||||
+
|
||||
+ free (profilepath);
|
||||
+ free (debugoutputpath);
|
||||
+ return 0;
|
||||
}
|
||||
|
||||
#define TEST_FUNCTION_ARGV do_test
|
||||
diff --git a/sysdeps/generic/unsecvars.h b/sysdeps/generic/unsecvars.h
|
||||
index f1724efe0f1fea7b..5ce5f090053eb09a 100644
|
||||
--- a/sysdeps/generic/unsecvars.h
|
||||
+++ b/sysdeps/generic/unsecvars.h
|
||||
@@ -17,6 +17,7 @@
|
||||
"LD_ORIGIN_PATH\0" \
|
||||
"LD_PRELOAD\0" \
|
||||
"LD_PROFILE\0" \
|
||||
+ "LD_PROFILE_OUTPUT\0" \
|
||||
"LD_SHOW_AUXV\0" \
|
||||
"LD_VERBOSE\0" \
|
||||
"LD_WARN\0" \
|
||||
28
glibc-RHEL-142193-3.patch
Normal file
28
glibc-RHEL-142193-3.patch
Normal file
@ -0,0 +1,28 @@
|
||||
commit 34d98aea6c1eaf7750a992bae55b2bca24898eab
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Jan 24 10:29:22 2026 +0100
|
||||
|
||||
support: Fix memory leaks in support_subprogram, support_subprogram_wait
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/support/support_subprocess.c b/support/support_subprocess.c
|
||||
index b692a7f8b178502d..ec0c069470a586ac 100644
|
||||
--- a/support/support_subprocess.c
|
||||
+++ b/support/support_subprocess.c
|
||||
@@ -86,6 +86,7 @@ support_subprogram (const char *file, char *const argv[], char *const envp[])
|
||||
|
||||
result.pid = xposix_spawn (file, &fa, NULL, argv,
|
||||
envp == NULL ? environ : envp);
|
||||
+ posix_spawn_file_actions_destroy (&fa);
|
||||
|
||||
xclose (result.stdout_pipe[1]);
|
||||
xclose (result.stderr_pipe[1]);
|
||||
@@ -102,6 +103,7 @@ support_subprogram_wait (const char *file, char *const argv[])
|
||||
struct support_subprocess res = support_subprocess_init ();
|
||||
|
||||
res.pid = xposix_spawn (file, &fa, NULL, argv, environ);
|
||||
+ posix_spawn_file_actions_destroy (&fa);
|
||||
|
||||
return support_process_wait (&res);
|
||||
}
|
||||
52
glibc-RHEL-142193-4.patch
Normal file
52
glibc-RHEL-142193-4.patch
Normal file
@ -0,0 +1,52 @@
|
||||
commit e8502182f09211663c1583960442eb6ff502a33e
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Jan 24 10:29:22 2026 +0100
|
||||
|
||||
support: Add support_hardcoded_paths_in_test
|
||||
|
||||
It indicates whether glibc was configured with
|
||||
--enable-hardcoded-path-in-tests.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index aee37b9c82e94499..18051532e628b887 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -250,6 +250,12 @@ CFLAGS-support_paths.c = \
|
||||
-DCOMPLOCALEDIR_PATH=\"$(complocaledir)\" \
|
||||
-DSYSCONFDIR_PATH=\"$(sysconfdir)\"
|
||||
|
||||
+ifeq ($(build-hardcoded-path-in-tests),yes)
|
||||
+CFLAGS-support_paths.c += -DHARDCODED_PATHS_IN_TEST=true
|
||||
+else
|
||||
+CFLAGS-support_paths.c += -DHARDCODED_PATHS_IN_TEST=false
|
||||
+endif
|
||||
+
|
||||
# Build with exception handling and asynchronous unwind table support.
|
||||
CFLAGS-.oS += -fexceptions -fasynchronous-unwind-tables
|
||||
|
||||
diff --git a/support/support.h b/support/support.h
|
||||
index 2717e5583add690b..df80c81e4178bc9e 100644
|
||||
--- a/support/support.h
|
||||
+++ b/support/support.h
|
||||
@@ -147,6 +147,9 @@ extern const char support_complocaledir_prefix[];
|
||||
/* Corresponds to the install's etc/ directory. */
|
||||
extern const char support_sysconfdir_prefix[];
|
||||
|
||||
+/* If true, glibc was configured with --enable-hardcoded-path-in-tests. */
|
||||
+extern const bool support_hardcoded_paths_in_test;
|
||||
+
|
||||
/* Copies the file at the path FROM to TO. If TO does not exist, it
|
||||
is created. If TO is a regular file, it is truncated before
|
||||
copying. The file mode is copied, but the permissions are not. */
|
||||
diff --git a/support/support_paths.c b/support/support_paths.c
|
||||
index 3cad09abd2244a3d..1ad605b6e2273525 100644
|
||||
--- a/support/support_paths.c
|
||||
+++ b/support/support_paths.c
|
||||
@@ -99,3 +99,5 @@ const char support_sysconfdir_prefix[] = SYSCONFDIR_PATH;
|
||||
#else
|
||||
# error please -DSYSCONFDIR_PATH=something in the Makefile
|
||||
#endif
|
||||
+
|
||||
+const bool support_hardcoded_paths_in_test = HARDCODED_PATHS_IN_TEST;
|
||||
40
glibc-RHEL-142193-5.patch
Normal file
40
glibc-RHEL-142193-5.patch
Normal file
@ -0,0 +1,40 @@
|
||||
commit 458a6a2b935f60a25a136846fe8b7a4723296dda
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Sat Jan 24 10:29:39 2026 +0100
|
||||
|
||||
support: Reinitialize containers if /etc is present
|
||||
|
||||
This prevents test failures because configuration file leftovers
|
||||
unexpectedly change glibc for future tests. Whether this
|
||||
triggers depends on test execution order.
|
||||
|
||||
Adding postclean.req files manually (before this change) appears
|
||||
too error-prone.
|
||||
|
||||
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||
|
||||
diff --git a/support/test-container.c b/support/test-container.c
|
||||
index a9c9926c21f3a21e..f2853f6a71475420 100644
|
||||
--- a/support/test-container.c
|
||||
+++ b/support/test-container.c
|
||||
@@ -134,7 +134,9 @@ int verbose = 0;
|
||||
- 'mkdirp': A minimal "mkdir -p FILE" command.
|
||||
|
||||
* mytest.root/postclean.req causes fresh rsync (with delete) after
|
||||
- test if present
|
||||
+ test if present. If /etc is present, the testroot is cleaned,
|
||||
+ too. This prevents further tests from using special
|
||||
+ configurations in /etc from previous tests.
|
||||
|
||||
* mytest.root/ldconfig.run causes ldconfig to be issued prior
|
||||
test execution (to setup the initial ld.so.cache).
|
||||
@@ -868,7 +870,8 @@ main (int argc, char **argv)
|
||||
if (strrchr (so_base, '/') != NULL)
|
||||
strrchr (so_base, '/')[1] = 0;
|
||||
|
||||
- if (file_exists (concat (command_root, "/postclean.req", NULL)))
|
||||
+ if (file_exists (concat (command_root, "/postclean.req", NULL))
|
||||
+ || file_exists (concat (command_root, "/etc", NULL)))
|
||||
do_postclean = 1;
|
||||
|
||||
if (file_exists (concat (command_root, "/ldconfig.run", NULL)))
|
||||
506
glibc-RHEL-142193-6.patch
Normal file
506
glibc-RHEL-142193-6.patch
Normal file
@ -0,0 +1,506 @@
|
||||
commit 229f65f5f322609283c7104c80c8af6434dff628
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Feb 2 21:15:48 2026 +0100
|
||||
|
||||
support: Add support_spawn_wrap and related functionality
|
||||
|
||||
It allows us to write test cases in C that run tests with
|
||||
dynamic linker wrapping.
|
||||
|
||||
The iconv test case was auto-generated. The posix_spawn usage
|
||||
is mechanical, and the interface it tests is newly added in this
|
||||
commit, so this should be acceptable.
|
||||
|
||||
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
|
||||
|
||||
diff --git a/support/Makefile b/support/Makefile
|
||||
index 18051532e628b887..f32652685e3fdc94 100644
|
||||
--- a/support/Makefile
|
||||
+++ b/support/Makefile
|
||||
@@ -90,6 +90,7 @@ libsupport-routines = \
|
||||
support_shared_allocate \
|
||||
support_small_stack_thread_attribute \
|
||||
support_socket_so_timestamp_time64 \
|
||||
+ support_spawn_wrap \
|
||||
support_stack_alloc \
|
||||
support_stat_nanoseconds \
|
||||
support_subprocess \
|
||||
@@ -256,6 +257,11 @@ else
|
||||
CFLAGS-support_paths.c += -DHARDCODED_PATHS_IN_TEST=false
|
||||
endif
|
||||
|
||||
+CFLAGS-support_spawn_wrap.c += \
|
||||
+ '-DRUN_PROGRAM_ENV=$(patsubst %, ELEMENT ("%"), $(run-program-env))' \
|
||||
+ '-DRTLD_PREFIX=$(patsubst %, ELEMENT ("%"), $(rtld-prefix))' \
|
||||
+ # CFLAGS-support_spawn_wrap.c
|
||||
+
|
||||
# Build with exception handling and asynchronous unwind table support.
|
||||
CFLAGS-.oS += -fexceptions -fasynchronous-unwind-tables
|
||||
|
||||
@@ -344,6 +350,7 @@ tests = \
|
||||
tst-support_quote_string \
|
||||
tst-support_readdir \
|
||||
tst-support_record_failure \
|
||||
+ tst-support_spawn_wrap \
|
||||
tst-test_compare \
|
||||
tst-test_compare_blob \
|
||||
tst-test_compare_string \
|
||||
diff --git a/support/subprocess.h b/support/subprocess.h
|
||||
index 8274a2b22bb10296..3438df28c23fac9e 100644
|
||||
--- a/support/subprocess.h
|
||||
+++ b/support/subprocess.h
|
||||
@@ -52,4 +52,36 @@ int support_process_wait (struct support_subprocess *proc);
|
||||
then with a SIGKILL. Return the status as for waitpid call. */
|
||||
int support_process_terminate (struct support_subprocess *proc);
|
||||
|
||||
+/* Arguments to pass to posix_spawn and related functions to run a
|
||||
+ process under the built glibc. This overrides the dynamic linker,
|
||||
+ its search path, and other search paths, such as for locales. */
|
||||
+struct support_spawn_wrapped
|
||||
+{
|
||||
+ const char *path;
|
||||
+ char *const *argv;
|
||||
+ char *const *envp;
|
||||
+};
|
||||
+
|
||||
+enum support_spawn_wrap_flags
|
||||
+ {
|
||||
+ /* Always wrap the invocation, even if test binaries are linked
|
||||
+ with overridden the default paths to point into the build tree
|
||||
+ (--enable-hardcoded-path-in-tests). Can be used to run
|
||||
+ non-test binaries. */
|
||||
+ support_spawn_wrap_force = 1 << 0,
|
||||
+ };
|
||||
+
|
||||
+/* Wrap the invocation for invoking testing. PATH is the program
|
||||
+ path. If ARGV is null, no arguments are passed. If ENVP is null,
|
||||
+ environ is used instead. The result must not be modified. It is a
|
||||
+ deep copy of the inputs. */
|
||||
+struct support_spawn_wrapped *support_spawn_wrap (const char *path,
|
||||
+ char *const argv[],
|
||||
+ char *const envp[],
|
||||
+ enum
|
||||
+ support_spawn_wrap_flags);
|
||||
+
|
||||
+/* Deallocate the result of support_spawn_wrap. */
|
||||
+void support_spawn_wrapped_free (struct support_spawn_wrapped *);
|
||||
+
|
||||
#endif
|
||||
diff --git a/support/support_spawn_wrap.c b/support/support_spawn_wrap.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..e61e12f486ca6a28
|
||||
--- /dev/null
|
||||
+++ b/support/support_spawn_wrap.c
|
||||
@@ -0,0 +1,171 @@
|
||||
+/* Wrap a subprocess invocation with an ld.so invocation.
|
||||
+ Copyright (C) 2026 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 <array_length.h>
|
||||
+#include <stdbool.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/subprocess.h>
|
||||
+#include <support/support.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#define ELEMENT(s) s,
|
||||
+static const char *const rtld_prefix[] = { RTLD_PREFIX "--argv0" };
|
||||
+static const char *const run_program_env[] = { RUN_PROGRAM_ENV };
|
||||
+#undef ELEMENT
|
||||
+
|
||||
+/* Return a newly allocated argument vector, with ld.so wrapping per
|
||||
+ rtld_prefix applied if WRAP is true. */
|
||||
+static char *const *
|
||||
+rewrite_argv (const char *path, char *const argv[], bool wrap)
|
||||
+{
|
||||
+ char *const substitute[] = { (char *) path, NULL};
|
||||
+ if (argv == NULL)
|
||||
+ argv = substitute;
|
||||
+ TEST_VERIFY (argv[0] != NULL);
|
||||
+
|
||||
+ size_t length;
|
||||
+ for (length = 0; argv[length] != 0; ++length)
|
||||
+ ;
|
||||
+ /* Potential wrapping, injected path, and null terminator. */
|
||||
+ length += array_length (rtld_prefix) + 1 + 1;
|
||||
+
|
||||
+ char **result = xcalloc (length, sizeof (result));
|
||||
+
|
||||
+ size_t inpos = 0;
|
||||
+ size_t outpos = 0;
|
||||
+ if (wrap)
|
||||
+ {
|
||||
+ for (size_t i = 0; i < array_length (rtld_prefix); ++i)
|
||||
+ {
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ result[outpos++] = xstrdup (rtld_prefix[i]);
|
||||
+ }
|
||||
+
|
||||
+ /* --argv0 argument. */
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ result[outpos++] = xstrdup (argv[0]);
|
||||
+ inpos = 1;
|
||||
+
|
||||
+ /* Path to program as used by ld.so. */
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ result[outpos++] = xstrdup (path);
|
||||
+ }
|
||||
+
|
||||
+ for (; argv[inpos] != NULL; ++inpos)
|
||||
+ {
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ result[outpos++] = xstrdup (argv[inpos]);
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ return result;
|
||||
+
|
||||
+}
|
||||
+
|
||||
+/* Return a newly allocated, rewritten environment, with the settings
|
||||
+ from run_program_env. */
|
||||
+static char *const *
|
||||
+rewrite_env (char *const envp[])
|
||||
+{
|
||||
+ if (envp == NULL)
|
||||
+ envp = environ;
|
||||
+
|
||||
+ size_t length;
|
||||
+ for (length = 0; envp[length] != 0; ++length)
|
||||
+ ;
|
||||
+ length += array_length (run_program_env) + 1;
|
||||
+
|
||||
+ /* Set to true if an element of run_program_env is copied. This is
|
||||
+ used to avoid adding it again. */
|
||||
+ bool copied[array_length (run_program_env)] = { false, };
|
||||
+
|
||||
+ char **result = xcalloc (length, sizeof (result));
|
||||
+ size_t outpos = 0;
|
||||
+ for (size_t inpos = 0; envp[inpos] != NULL; ++inpos)
|
||||
+ {
|
||||
+ const char *to_copy = envp[inpos];
|
||||
+ /* If there is no assignment operator, this environment string
|
||||
+ cannot be overridden. */
|
||||
+ const char *envp_assign = strchr (to_copy, '=');
|
||||
+ if (envp_assign != NULL)
|
||||
+ {
|
||||
+ size_t length_with_assign = envp_assign - to_copy + 1;
|
||||
+ for (size_t i = 0; i < array_length (run_program_env); ++i)
|
||||
+ {
|
||||
+ if (strncmp (to_copy, run_program_env[i], length_with_assign)
|
||||
+ == 0 && !copied[i])
|
||||
+ {
|
||||
+ to_copy = run_program_env[i];
|
||||
+ copied[i] = true;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ result[outpos++] = xstrdup (to_copy);
|
||||
+ }
|
||||
+
|
||||
+ for (size_t i = 0; i < array_length (run_program_env); ++i)
|
||||
+ {
|
||||
+ TEST_VERIFY (strchr (run_program_env[i], '=') != 0);
|
||||
+ if (!copied[i])
|
||||
+ {
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ result[outpos++] = xstrdup (run_program_env[i]);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ TEST_VERIFY (outpos < length);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+struct support_spawn_wrapped *
|
||||
+support_spawn_wrap (const char *path,
|
||||
+ char *const argv[],
|
||||
+ char *const envp[],
|
||||
+ enum support_spawn_wrap_flags flags)
|
||||
+{
|
||||
+ if (flags != 0)
|
||||
+ TEST_COMPARE (flags, support_spawn_wrap_force);
|
||||
+ bool force = flags & support_spawn_wrap_force;
|
||||
+ bool wrap = force || !support_hardcoded_paths_in_test;
|
||||
+
|
||||
+ struct support_spawn_wrapped *result = xmalloc (sizeof (*result));
|
||||
+ if (wrap)
|
||||
+ result->path = xstrdup (support_objdir_elf_ldso);
|
||||
+ else
|
||||
+ result->path = xstrdup (path);
|
||||
+ result->argv = rewrite_argv (path, argv, wrap);
|
||||
+ result->envp = rewrite_env (envp);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+void
|
||||
+support_spawn_wrapped_free (struct support_spawn_wrapped *wrapped)
|
||||
+{
|
||||
+ free ((char *) wrapped->path);
|
||||
+ for (size_t i = 0; wrapped->argv[i] != NULL; ++i)
|
||||
+ free (wrapped->argv[i]);
|
||||
+ free ((char **) wrapped->argv);
|
||||
+ for (size_t i = 0; wrapped->envp[i] != NULL; ++i)
|
||||
+ free (wrapped->envp[i]);
|
||||
+ free ((char **) wrapped->envp);
|
||||
+ free (wrapped);
|
||||
+}
|
||||
diff --git a/support/tst-support_spawn_wrap.c b/support/tst-support_spawn_wrap.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..d0bb8a419412c48d
|
||||
--- /dev/null
|
||||
+++ b/support/tst-support_spawn_wrap.c
|
||||
@@ -0,0 +1,235 @@
|
||||
+/* Tests for support_spawn_wrap.
|
||||
+ Copyright (C) 2026 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 <getopt.h>
|
||||
+#include <spawn.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/subprocess.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/xspawn.h>
|
||||
+#include <support/xunistd.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+/* Return true if running via an explicit ld.so invocation. */
|
||||
+static bool
|
||||
+running_via_ldso (void)
|
||||
+{
|
||||
+ char *self = realpath ("/proc/self/exe", NULL);
|
||||
+ if (self == NULL)
|
||||
+ FAIL_UNSUPPORTED ("/proc/self/exe not available");
|
||||
+ char *ldso = realpath (support_objdir_elf_ldso, NULL);
|
||||
+ TEST_VERIFY_EXIT (ldso != NULL);
|
||||
+ bool result = strcmp (self, ldso) == 0;
|
||||
+ free (ldso);
|
||||
+ free (self);
|
||||
+ return result;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_subprocess (int argc, char **argv)
|
||||
+{
|
||||
+ {
|
||||
+ char *argc_env = getenv ("argc");
|
||||
+ if (argc_env != NULL)
|
||||
+ {
|
||||
+ char *argc_arg = xasprintf ("%d", argc);
|
||||
+ TEST_COMPARE_STRING (argc_arg, argc_env);
|
||||
+ free (argc_arg);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (argc >= 2 && strcmp (argv[1], "alpha") == 0)
|
||||
+ {
|
||||
+ TEST_COMPARE (argc, 4);
|
||||
+ TEST_COMPARE_STRING (argv[0], "program");
|
||||
+ TEST_COMPARE_STRING (argv[2], "beta");
|
||||
+ TEST_COMPARE_STRING (argv[3], "gamma");
|
||||
+ TEST_COMPARE_STRING (argv[4], NULL);
|
||||
+ }
|
||||
+ else if (argc >= 2 && strcmp (argv[1], "check-env") == 0)
|
||||
+ printf ("%d %s\n", argc, getenv ("extra"));
|
||||
+ else if (argc >= 2 && strcmp (argv[1], "check-ld.so") == 0)
|
||||
+ TEST_VERIFY (running_via_ldso ());
|
||||
+}
|
||||
+
|
||||
+/* The "recurse" environment variable and the --recurse option
|
||||
+ indicate recursive invocation. */
|
||||
+static int flag_recurse;
|
||||
+#define CMDLINE_OPTIONS \
|
||||
+ { "recurse", no_argument, &flag_recurse, 1 }, \
|
||||
+ /* CMDLINE_OPTION */
|
||||
+
|
||||
+static void
|
||||
+prepare (int argc, char **argv)
|
||||
+{
|
||||
+ if (getenv ("recurse") != NULL || flag_recurse)
|
||||
+ {
|
||||
+ test_subprocess (argc, argv);
|
||||
+ support_record_failure_barrier ();
|
||||
+ exit (0);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#define PREPARE prepare
|
||||
+
|
||||
+/* Test wrapping of a non-test program (iconv). This uses posix_spawn
|
||||
+ directly, mainly for illustrative purposes. */
|
||||
+void
|
||||
+test_iconv (void)
|
||||
+{
|
||||
+ char *iconv_prog = xasprintf ("%s/iconv/iconv_prog", support_objdir_root);
|
||||
+ char *argv[] = { (char *) "iconv", (char *) "-f", (char *) "UTF-8",
|
||||
+ (char *) "-t", (char *) "ISO-8859-1", NULL };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (iconv_prog, argv, NULL, support_spawn_wrap_force);
|
||||
+
|
||||
+ /* Set up pipes for stdin, stdout, and stderr. */
|
||||
+ int stdin_pipe[2];
|
||||
+ xpipe (stdin_pipe);
|
||||
+ int stdout_pipe[2];
|
||||
+ xpipe (stdout_pipe);
|
||||
+ int stderr_pipe[2];
|
||||
+ xpipe (stderr_pipe);
|
||||
+
|
||||
+ posix_spawn_file_actions_t fa;
|
||||
+ posix_spawn_file_actions_init (&fa);
|
||||
+ xposix_spawn_file_actions_adddup2 (&fa, stdin_pipe[0], STDIN_FILENO);
|
||||
+ xposix_spawn_file_actions_addclose (&fa, stdin_pipe[0]);
|
||||
+ xposix_spawn_file_actions_addclose (&fa, stdin_pipe[1]);
|
||||
+ xposix_spawn_file_actions_adddup2 (&fa, stdout_pipe[1], STDOUT_FILENO);
|
||||
+ xposix_spawn_file_actions_addclose (&fa, stdout_pipe[0]);
|
||||
+ xposix_spawn_file_actions_addclose (&fa, stdout_pipe[1]);
|
||||
+ xposix_spawn_file_actions_adddup2 (&fa, stderr_pipe[1], STDERR_FILENO);
|
||||
+ xposix_spawn_file_actions_addclose (&fa, stderr_pipe[0]);
|
||||
+ xposix_spawn_file_actions_addclose (&fa, stderr_pipe[1]);
|
||||
+
|
||||
+ pid_t pid = xposix_spawn (w->path, &fa, NULL, w->argv, w->envp);
|
||||
+ posix_spawn_file_actions_destroy (&fa);
|
||||
+
|
||||
+ xclose (stdin_pipe[0]);
|
||||
+ xclose (stdout_pipe[1]);
|
||||
+ xclose (stderr_pipe[1]);
|
||||
+
|
||||
+ /* Write UTF-8 encoding of "äöü\n" to stdin. */
|
||||
+ xwrite (stdin_pipe[1], "\xc3\xa4\xc3\xb6\xc3\xbc\n", 7);
|
||||
+ xclose (stdin_pipe[1]);
|
||||
+
|
||||
+ /* Read the converted output from the pipe. */
|
||||
+ char buf[16];
|
||||
+ ssize_t ret = read (stdout_pipe[0], buf, sizeof (buf));
|
||||
+ xclose (stdout_pipe[0]);
|
||||
+
|
||||
+ /* ISO-8859-1 encoding of "äöü\n". */
|
||||
+ TEST_COMPARE_BLOB (buf, ret, "\xe4\xf6\xfc\n", 4);
|
||||
+
|
||||
+ int status;
|
||||
+ xwaitpid (pid, &status, 0);
|
||||
+ TEST_COMPARE (status, 0);
|
||||
+
|
||||
+ /* Check that nothing has been written to stderr. */
|
||||
+ ret = read (stderr_pipe[0], buf, sizeof (buf));
|
||||
+ TEST_COMPARE (ret, 0);
|
||||
+ xclose (stderr_pipe[0]);
|
||||
+
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+ free (iconv_prog);
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ char *program = xasprintf ("%s/support/tst-support_spawn_wrap",
|
||||
+ support_objdir_root);
|
||||
+
|
||||
+ {
|
||||
+ char *env[] = { (char *) "recurse=", (char *) "argc=1", NULL };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (program, NULL, env, 0);
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprogram (w->path, w->argv, w->envp);
|
||||
+ support_capture_subprocess_check (&proc, "no arguments", 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ char *argv[] = { (char *) "program", (char *) "--recurse", NULL };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (program, argv, NULL, 0);
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprogram (w->path, w->argv, w->envp);
|
||||
+ support_capture_subprocess_check (&proc, "default envvironment", 0,
|
||||
+ sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ char *argv[] = { (char *) "program", (char *) "alpha", (char *) "beta",
|
||||
+ (char *) "gamma", NULL };
|
||||
+ char *env[] = { (char *) "recurse=", (char *) "argc=4", NULL };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (program, argv, env, 0);
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprogram (w->path, w->argv, w->envp);
|
||||
+ support_capture_subprocess_check (&proc, "3 arguments", 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ char *argv[] = { (char *) "program", (char *) "check-env", NULL };
|
||||
+ char *env[] = { (char *) "recurse=", (char *) "argc=2",
|
||||
+ (char *) "extra=17", NULL };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (program, argv, env, 0);
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprogram (w->path, w->argv, w->envp);
|
||||
+ TEST_COMPARE_STRING (proc.out.buffer, "2 17\n");
|
||||
+ support_capture_subprocess_check (&proc, "check-env", 0, sc_allow_stdout);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+ }
|
||||
+
|
||||
+ test_iconv ();
|
||||
+
|
||||
+ /* This may trigger EXIT_UNSUPPORTED, so run this before the tests
|
||||
+ that rely on running_via_ldso. */
|
||||
+ TEST_COMPARE (!running_via_ldso (), support_hardcoded_paths_in_test);
|
||||
+
|
||||
+ {
|
||||
+ char *argv[] = { (char *) "program", (char *) "check-ld.so", NULL };
|
||||
+ char *env[] = { (char *) "recurse=", NULL };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (program, argv, env, support_spawn_wrap_force);
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprogram (w->path, w->argv, w->envp);
|
||||
+ support_capture_subprocess_check (&proc, "check-ld.so", 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+ }
|
||||
+
|
||||
+ free (program);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
171
glibc-RHEL-142193-7.patch
Normal file
171
glibc-RHEL-142193-7.patch
Normal file
@ -0,0 +1,171 @@
|
||||
commit 364426a59ee30ee3e528e5b5cae36b5dee045320
|
||||
Author: Florian Weimer <fweimer@redhat.com>
|
||||
Date: Mon Feb 2 21:15:48 2026 +0100
|
||||
|
||||
elf: Add test case for LD_PROFILE/LD_PROFILE_OUTPUT interaction
|
||||
|
||||
This verifies that LD_PROFILE is correctly ignored if LD_PROFILE_OUTPUT
|
||||
is not set.
|
||||
|
||||
The test was initially auto-generated, then heavily edited and re-edited
|
||||
for brevity and clarity. The test uses glibc-specific interfaces
|
||||
(including one that did not exist at all a couple of hours ago), so
|
||||
this should be unproblematic.
|
||||
|
||||
diff --git a/elf/Makefile b/elf/Makefile
|
||||
index cf54ea084489b9cf..73c426ae9c1da05c 100644
|
||||
--- a/elf/Makefile
|
||||
+++ b/elf/Makefile
|
||||
@@ -448,6 +448,7 @@ tests += \
|
||||
tst-initorder \
|
||||
tst-initorder2 \
|
||||
tst-latepthread \
|
||||
+ tst-ld_profile \
|
||||
tst-main1 \
|
||||
tst-next-ver \
|
||||
tst-nodelete-dlclose \
|
||||
diff --git a/elf/tst-ld_profile.c b/elf/tst-ld_profile.c
|
||||
new file mode 100644
|
||||
index 0000000000000000..6c392f682b950b00
|
||||
--- /dev/null
|
||||
+++ b/elf/tst-ld_profile.c
|
||||
@@ -0,0 +1,139 @@
|
||||
+/* Test LD_PROFILE/LD_PROFILE_OUTPUT interaction (bug 33797).
|
||||
+ Copyright (C) 2026 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 <gnu/lib-names.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <support/capture_subprocess.h>
|
||||
+#include <support/check.h>
|
||||
+#include <support/subprocess.h>
|
||||
+#include <support/support.h>
|
||||
+#include <support/temp_file.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+/* Expected profile file path (based on LD_PROFILE_OUTPUT and LIBC_SO). */
|
||||
+static char *profile_file_path;
|
||||
+
|
||||
+/* Path to this test program for recursive invocation. */
|
||||
+static char *program;
|
||||
+
|
||||
+/* LD_PROFILE_OUTPUT environment variable setting. */
|
||||
+static char *ld_profile_output_env;
|
||||
+
|
||||
+/* Run the test program with the specified environment array. */
|
||||
+static struct support_capture_subprocess
|
||||
+run_test_program (char *env[])
|
||||
+{
|
||||
+ /* Make sure the the potential output file does not exist. */
|
||||
+ unlink (profile_file_path);
|
||||
+
|
||||
+/* Command line arguments for recursive invocation. This turns the
|
||||
+ test program in a no-op (with LD_PROFILE output the only side effect). */
|
||||
+ static char *recurse_argv[] =
|
||||
+ {
|
||||
+ (char *) "tst-ld_profile", (char *) "recurse", NULL
|
||||
+ };
|
||||
+ struct support_spawn_wrapped *w
|
||||
+ = support_spawn_wrap (program, recurse_argv, env, 0);
|
||||
+ struct support_capture_subprocess proc
|
||||
+ = support_capture_subprogram (w->path, w->argv, w->envp);
|
||||
+ support_spawn_wrapped_free (w);
|
||||
+
|
||||
+ return proc;
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_profile_without_output (void)
|
||||
+{
|
||||
+ char *env[] = { (char *) "LD_PROFILE=" LIBC_SO, NULL };
|
||||
+ struct support_capture_subprocess proc = run_test_program (env);
|
||||
+ const char *expected_warning =
|
||||
+ "warning: LD_PROFILE ignored because LD_PROFILE_OUTPUT not specified\n";
|
||||
+ TEST_COMPARE_STRING (proc.err.buffer, expected_warning);
|
||||
+ support_capture_subprocess_check (&proc,
|
||||
+ "LD_PROFILE without LD_PROFILE_OUTPUT",
|
||||
+ 0, sc_allow_stderr);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+
|
||||
+ TEST_VERIFY (access (profile_file_path, F_OK) != 0);
|
||||
+ /* Also check the old /var/tmp path. */
|
||||
+ TEST_VERIFY (access ("/var/tmp/" LIBC_SO ".profile", F_OK) != 0);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_profile_with_output (void)
|
||||
+{
|
||||
+ char *env[] = { (char *) "LD_PROFILE=" LIBC_SO, ld_profile_output_env, NULL };
|
||||
+ struct support_capture_subprocess proc = run_test_program (env);
|
||||
+ support_capture_subprocess_check (&proc, "LD_PROFILE with LD_PROFILE_OUTPUT",
|
||||
+ 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+
|
||||
+ /* This asserts that the file was created. */
|
||||
+ TEST_COMPARE (unlink (profile_file_path), 0);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+test_output_without_profile (void)
|
||||
+{
|
||||
+ char *env[] = { ld_profile_output_env, NULL };
|
||||
+ struct support_capture_subprocess proc = run_test_program (env);
|
||||
+ support_capture_subprocess_check (&proc,
|
||||
+ "LD_PROFILE_OUTPUT without LD_PROFILE",
|
||||
+ 0, sc_allow_none);
|
||||
+ support_capture_subprocess_free (&proc);
|
||||
+
|
||||
+ TEST_VERIFY (access (profile_file_path, F_OK) != 0);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+prepare (int argc, char **argv)
|
||||
+{
|
||||
+ /* Do nothing on recursive invocation. */
|
||||
+ if (argc >= 2 && strcmp (argv[1], "recurse") == 0)
|
||||
+ exit (0);
|
||||
+}
|
||||
+
|
||||
+#define PREPARE prepare
|
||||
+
|
||||
+static int
|
||||
+do_test (void)
|
||||
+{
|
||||
+ if (access ("/var/tmp/" LIBC_SO ".profile", F_OK) == 0)
|
||||
+ FAIL_UNSUPPORTED ("/var/tmp/" LIBC_SO ".profile exists");
|
||||
+
|
||||
+ /* Temporary directory for the profile output. */
|
||||
+ char *profile_output_dir = support_create_temp_directory ("tst-ld_profile");
|
||||
+ profile_file_path = xasprintf ("%s/%s.profile", profile_output_dir, LIBC_SO);
|
||||
+ ld_profile_output_env = xasprintf ("LD_PROFILE_OUTPUT=%s",
|
||||
+ profile_output_dir);
|
||||
+ program = xasprintf ("%s/elf/tst-ld_profile", support_objdir_root);
|
||||
+
|
||||
+ test_profile_without_output ();
|
||||
+ test_profile_with_output ();
|
||||
+ test_output_without_profile ();
|
||||
+
|
||||
+ free (program);
|
||||
+ free (ld_profile_output_env);
|
||||
+ free (profile_file_path);
|
||||
+ free (profile_output_dir);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+#include <support/test-driver.c>
|
||||
Loading…
Reference in New Issue
Block a user