mirror of git://sourceware.org/git/glibc.git
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>
This commit is contained in:
parent
0bbeb1fd13
commit
7b543dcdf9
6
NEWS
6
NEWS
|
|
@ -100,7 +100,11 @@ Deprecated and removed features, and other changes affecting compatibility:
|
||||||
|
|
||||||
Changes to build and runtime requirements:
|
Changes to build and runtime requirements:
|
||||||
|
|
||||||
[Add changes to build and runtime requirements here]
|
* The LD_PROFILE functionality no longer has a default directory for the
|
||||||
|
profile data it writes. Instead, developers are required to set a
|
||||||
|
directory explicitly using the LD_PROFILE_OUTPUT environment variable.
|
||||||
|
To restore the previous, insecure behavior, processes can be run with
|
||||||
|
LD_PROFILE_OUTPUT=/var/tmp.
|
||||||
|
|
||||||
Security related changes:
|
Security related changes:
|
||||||
|
|
||||||
|
|
|
||||||
10
elf/rtld.c
10
elf/rtld.c
|
|
@ -359,7 +359,6 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
|
||||||
._dl_fpu_control = _FPU_DEFAULT,
|
._dl_fpu_control = _FPU_DEFAULT,
|
||||||
._dl_pagesize = EXEC_PAGESIZE,
|
._dl_pagesize = EXEC_PAGESIZE,
|
||||||
._dl_inhibit_cache = 0,
|
._dl_inhibit_cache = 0,
|
||||||
._dl_profile_output = "/var/tmp",
|
|
||||||
|
|
||||||
/* Function pointers. */
|
/* Function pointers. */
|
||||||
._dl_debug_printf = _dl_debug_printf,
|
._dl_debug_printf = _dl_debug_printf,
|
||||||
|
|
@ -2708,6 +2707,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
|
/* If we have to run the dynamic linker in debugging mode and the
|
||||||
LD_DEBUG_OUTPUT environment variable is given, we write the debug
|
LD_DEBUG_OUTPUT environment variable is given, we write the debug
|
||||||
messages to this file. */
|
messages to this file. */
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,11 @@ static char SETGID_CHILD[] = "setgid-child";
|
||||||
# define PROFILE_LIB "tst-sonamemove-runmod2.so"
|
# define PROFILE_LIB "tst-sonamemove-runmod2.so"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define LD_DEBUG_OUTPUT "/tmp/some-file"
|
/* Computed path for LD_DEBUG_OUTPUT. */
|
||||||
|
static char *debugoutputpath;
|
||||||
|
|
||||||
|
/* Expected file name for erroneous LD_PROFILE output. */
|
||||||
|
static char *profilepath;
|
||||||
|
|
||||||
struct envvar_t
|
struct envvar_t
|
||||||
{
|
{
|
||||||
|
|
@ -57,13 +61,14 @@ static const struct envvar_t filtered_envvars[] =
|
||||||
{ "LD_LIBRARY_PATH", FILTERED_VALUE },
|
{ "LD_LIBRARY_PATH", FILTERED_VALUE },
|
||||||
{ "LD_PRELOAD", FILTERED_VALUE },
|
{ "LD_PRELOAD", FILTERED_VALUE },
|
||||||
{ "LD_PROFILE", PROFILE_LIB },
|
{ "LD_PROFILE", PROFILE_LIB },
|
||||||
|
{ "LD_PROFILE_OUTPUT", "/var/tmp" }, /* Not actually used. */
|
||||||
{ "MALLOC_ARENA_MAX", FILTERED_VALUE },
|
{ "MALLOC_ARENA_MAX", FILTERED_VALUE },
|
||||||
{ "MALLOC_PERTURB_", FILTERED_VALUE },
|
{ "MALLOC_PERTURB_", FILTERED_VALUE },
|
||||||
{ "MALLOC_TRACE", FILTERED_VALUE },
|
{ "MALLOC_TRACE", FILTERED_VALUE },
|
||||||
{ "MALLOC_TRIM_THRESHOLD_", FILTERED_VALUE },
|
{ "MALLOC_TRIM_THRESHOLD_", FILTERED_VALUE },
|
||||||
{ "RES_OPTIONS", FILTERED_VALUE },
|
{ "RES_OPTIONS", FILTERED_VALUE },
|
||||||
{ "LD_DEBUG", "all" },
|
{ "LD_DEBUG", "all" },
|
||||||
{ "LD_DEBUG_OUTPUT", LD_DEBUG_OUTPUT },
|
{ "LD_DEBUG_OUTPUT", "overwritten" }, /* Not actually used. */
|
||||||
{ "LD_WARN", FILTERED_VALUE },
|
{ "LD_WARN", FILTERED_VALUE },
|
||||||
{ "LD_VERBOSE", FILTERED_VALUE },
|
{ "LD_VERBOSE", FILTERED_VALUE },
|
||||||
{ "LD_BIND_NOW", "0" },
|
{ "LD_BIND_NOW", "0" },
|
||||||
|
|
@ -79,7 +84,7 @@ static const struct envvar_t unfiltered_envvars[] =
|
||||||
static void
|
static void
|
||||||
unlink_ld_debug_output (pid_t pid)
|
unlink_ld_debug_output (pid_t pid)
|
||||||
{
|
{
|
||||||
char *output = xasprintf ("%s.%d", LD_DEBUG_OUTPUT, pid);
|
char *output = xasprintf ("%s.%d", debugoutputpath, pid);
|
||||||
unlink (output);
|
unlink (output);
|
||||||
free (output);
|
free (output);
|
||||||
}
|
}
|
||||||
|
|
@ -121,18 +126,12 @@ test_child (void)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Also check if no profile file was created.
|
/* 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. */
|
Note: LD_PROFILE is not supported for static binaries. */
|
||||||
{
|
if (!access (profilepath, R_OK))
|
||||||
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;
|
||||||
printf ("FAIL: LD_PROFILE file at %s was created!\n", profilepath);
|
}
|
||||||
ret = 1;
|
|
||||||
}
|
|
||||||
free (profilepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
@ -145,6 +144,11 @@ do_test (int argc, char **argv)
|
||||||
if (argc >= 2 && strstr (argv[1], LD_SO) != 0)
|
if (argc >= 2 && strstr (argv[1], LD_SO) != 0)
|
||||||
FAIL_UNSUPPORTED ("dynamic test requires --enable-hardcoded-path-in-tests");
|
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. */
|
/* Setgid child process. */
|
||||||
if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
|
if (argc == 2 && strcmp (argv[1], SETGID_CHILD) == 0)
|
||||||
{
|
{
|
||||||
|
|
@ -165,7 +169,6 @@ do_test (int argc, char **argv)
|
||||||
|
|
||||||
if (ret != 0)
|
if (ret != 0)
|
||||||
exit (1);
|
exit (1);
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
@ -179,20 +182,25 @@ do_test (int argc, char **argv)
|
||||||
e++)
|
e++)
|
||||||
setenv (e->env, e->value, 1);
|
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
|
/* Ensure that the profile output does not exist from a previous run
|
||||||
(e.g. if test_dir, which defaults to /tmp, is mounted nosuid.)
|
(e.g. if test_dir, which defaults to /tmp, is mounted nosuid.)
|
||||||
Note: support_capture_subprogram_self_sgid creates the SGID binary
|
Note: support_capture_subprogram_self_sgid creates the SGID binary
|
||||||
in test_dir. */
|
in test_dir. */
|
||||||
{
|
unlink (profilepath);
|
||||||
char *profilepath = xasprintf ("/var/tmp/%s.profile", PROFILE_LIB);
|
|
||||||
unlink (profilepath);
|
|
||||||
free (profilepath);
|
|
||||||
}
|
|
||||||
|
|
||||||
support_capture_subprogram_self_sgid (SETGID_CHILD);
|
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
|
#define TEST_FUNCTION_ARGV do_test
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
"LD_ORIGIN_PATH\0" \
|
"LD_ORIGIN_PATH\0" \
|
||||||
"LD_PRELOAD\0" \
|
"LD_PRELOAD\0" \
|
||||||
"LD_PROFILE\0" \
|
"LD_PROFILE\0" \
|
||||||
|
"LD_PROFILE_OUTPUT\0" \
|
||||||
"LD_SHOW_AUXV\0" \
|
"LD_SHOW_AUXV\0" \
|
||||||
"LD_VERBOSE\0" \
|
"LD_VERBOSE\0" \
|
||||||
"LD_WARN\0" \
|
"LD_WARN\0" \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue