tunables: Avoid getenv calls and disable glibc.malloc.check by default

Builds with --enable-tunables failed on i686 because a call to getenv
got snuck into tunables, which pulled in strncmp.  This patch fixes
this build failure by making the glibc.malloc.check check even
simpler.  The previous approach was convoluted where the tunable was
disabled using an unsetenv and overwriting the tunable value with
colons.  The easier way is to simply mark the tunable as insecure by
default (i.e. won't be read for AT_SECURE programs) and then enabled
only when the /etc/suid-debug file is found.

This also ends up removing a bunch of functions that were specially
reimplemented (strlen, unsetenv) to avoid calling into string
routines.

Tested on x86_64 and i686.

	* elf/dl-tunables.c (tunables_unsetenv): Remove function.
	(min_strlen): Likewise.
	(disable_tunable): Likewise.
	(maybe_disable_malloc_check): Rename to
	maybe_enable_malloc_check.
	(maybe_enable_malloc_check): Enable glibc.malloc.check tunable
	if /etc/suid-debug file exists.
	(__tunables_init): Update caller.
	* elf/dl-tunables.list (glibc.malloc.check): Don't mark as
	secure.
This commit is contained in:
Siddhesh Poyarekar 2017-01-10 16:35:58 +05:30
parent cc25c8b4c1
commit d054a81ab3
3 changed files with 23 additions and 78 deletions

View File

@ -1,3 +1,16 @@
2016-01-10 Siddhesh Poyarekar <siddhesh@sourceware.org>
* elf/dl-tunables.c (tunables_unsetenv): Remove function.
(min_strlen): Likewise.
(disable_tunable): Likewise.
(maybe_disable_malloc_check): Rename to
maybe_enable_malloc_check.
(maybe_enable_malloc_check): Enable glibc.malloc.check tunable
if /etc/suid-debug file exists.
(__tunables_init): Update caller.
* elf/dl-tunables.list (glibc.malloc.check): Don't mark as
secure.
2016-01-10 Torvald Riegel <triegel@redhat.com>
* nptl/DESIGN-rwlock.txt: Remove.

View File

@ -100,34 +100,6 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val)
return NULL;
}
static int
tunables_unsetenv (char **ep, const char *name)
{
while (*ep != NULL)
{
size_t cnt = 0;
while ((*ep)[cnt] == name[cnt] && name[cnt] != '\0')
++cnt;
if (name[cnt] == '\0' && (*ep)[cnt] == '=')
{
/* Found it. Remove this pointer by moving later ones to
the front. */
char **dp = ep;
do
dp[0] = dp[1];
while (*dp++);
/* Continue the loop in case NAME appears again. */
}
else
++ep;
}
return 0;
}
/* A stripped down strtoul-like implementation for very early use. It does not
set errno if the result is outside bounds because it gets called before
errno may have been set up. */
@ -316,57 +288,18 @@ parse_tunables (char *tunestr)
}
#endif
static size_t
min_strlen (const char *s)
{
size_t i = 0;
while (*s++ != '\0')
i++;
return i;
}
/* Disable a tunable if it is set. */
static void
disable_tunable (tunable_id_t id, char **envp)
{
const char *env_alias = tunable_list[id].env_alias;
if (env_alias != NULL)
tunables_unsetenv (envp, tunable_list[id].env_alias);
#if TUNABLES_FRONTEND == TUNABLES_FRONTEND_valstring
char *tunable = getenv (GLIBC_TUNABLES);
const char *cmp = tunable_list[id].name;
const size_t len = min_strlen (cmp);
while (tunable && *tunable != '\0' && *tunable != ':')
{
if (is_name (tunable, cmp))
{
tunable += len;
/* Overwrite the = and the value with colons. */
while (*tunable != '\0' && *tunable != ':')
*tunable++ = ':';
break;
}
tunable++;
}
#endif
}
/* Disable the glibc.malloc.check tunable in SETUID/SETGID programs unless
the system administrator overrides it by creating the /etc/suid-debug
file. This is a special case where we want to conditionally enable/disable
a tunable even for setuid binaries. We use the special version of access()
to avoid setting ERRNO, which is a TLS variable since TLS has not yet been
set up. */
/* Enable the glibc.malloc.check tunable in SETUID/SETGID programs only when
the system administrator has created the /etc/suid-debug file. This is a
special case where we want to conditionally enable/disable a tunable even
for setuid binaries. We use the special version of access() to avoid
setting ERRNO, which is a TLS variable since TLS has not yet been set
up. */
static inline void
__always_inline
maybe_disable_malloc_check (void)
maybe_enable_malloc_check (void)
{
if (__libc_enable_secure && __access_noerrno ("/etc/suid-debug", F_OK) != 0)
disable_tunable (TUNABLE_ENUM_NAME(glibc, malloc, check), __environ);
if (__access_noerrno ("/etc/suid-debug", F_OK) == 0)
tunable_list[TUNABLE_ENUM_NAME(glibc, malloc, check)].is_secure = true;
}
/* Initialize the tunables list from the environment. For now we only use the
@ -379,7 +312,7 @@ __tunables_init (char **envp)
char *envval = NULL;
size_t len = 0;
maybe_disable_malloc_check ();
maybe_enable_malloc_check ();
while ((envp = get_next_env (envp, &envname, &len, &envval)) != NULL)
{

View File

@ -31,7 +31,6 @@ glibc {
minval: 0
maxval: 3
env_alias: MALLOC_CHECK_
is_secure: true
}
top_pad {
type: SIZE_T