aboutsummaryrefslogtreecommitdiff
path: root/elf/dl-tunables.c
diff options
context:
space:
mode:
Diffstat (limited to 'elf/dl-tunables.c')
-rw-r--r--elf/dl-tunables.c80
1 files changed, 31 insertions, 49 deletions
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 644d21d1b0..3d41e8e28e 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -36,31 +36,8 @@
#define TUNABLES_INTERNAL 1
#include "dl-tunables.h"
-#include <not-errno.h>
-
-static char *
-tunables_strdup (const char *in)
-{
- size_t i = 0;
-
- while (in[i++] != '\0');
- char *out = __minimal_malloc (i + 1);
-
- /* For most of the tunables code, we ignore user errors. However,
- this is a system error - and running out of memory at program
- startup should be reported, so we do. */
- if (out == NULL)
- _dl_fatal_printf ("failed to allocate memory to process tunables\n");
-
- while (i-- > 0)
- out[i] = in[i];
-
- return out;
-}
-
static char **
-get_next_env (char **envp, char **name, size_t *namelen, char **val,
- char ***prev_envp)
+get_next_env (char **envp, char **name, char **val, char ***prev_envp)
{
while (envp != NULL && *envp != NULL)
{
@@ -76,7 +53,6 @@ get_next_env (char **envp, char **name, size_t *namelen, char **val,
continue;
*name = envline;
- *namelen = len;
*val = &envline[len + 1];
*prev_envp = prev;
@@ -134,14 +110,14 @@ do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
/* Validate range of the input value and initialize the tunable CUR if it looks
good. */
static void
-tunable_initialize (tunable_t *cur, const char *strval)
+tunable_initialize (tunable_t *cur, const char *strval, size_t len)
{
- tunable_val_t val;
+ tunable_val_t val = { 0 };
if (cur->type.type_code != TUNABLE_TYPE_STRING)
val.numval = (tunable_num_t) _dl_strtoul (strval, NULL);
else
- val.strval = strval;
+ val.strval = (struct tunable_str_t) { strval, len };
do_tunable_update_val (cur, &val, NULL, NULL);
}
@@ -165,29 +141,29 @@ struct tunable_toset_t
{
tunable_t *t;
const char *value;
+ size_t len;
};
enum { tunables_list_size = array_length (tunable_list) };
/* Parse the tunable string VALSTRING and set TUNABLES with the found tunables
- and their respective strings. VALSTRING is a duplicated values, where
- delimiters ':' are replaced with '\0', so string tunables are null
- terminated.
+ and their respective values. The VALSTRING is parsed in place, with the
+ tunable start and size recorded in TUNABLES.
Return the number of tunables found (including 0 if the string is empty)
or -1 if for an ill-formatted definition. */
static int
-parse_tunables_string (char *valstring, struct tunable_toset_t *tunables)
+parse_tunables_string (const char *valstring, struct tunable_toset_t *tunables)
{
if (valstring == NULL || *valstring == '\0')
return 0;
- char *p = valstring;
+ const char *p = valstring;
bool done = false;
int ntunables = 0;
while (!done)
{
- char *name = p;
+ const char *name = p;
/* First, find where the name ends. */
while (*p != '=' && *p != ':' && *p != '\0')
@@ -209,7 +185,7 @@ parse_tunables_string (char *valstring, struct tunable_toset_t *tunables)
/* Skip the '='. */
p++;
- char *value = p;
+ const char *value = p;
while (*p != '=' && *p != ':' && *p != '\0')
p++;
@@ -218,8 +194,6 @@ parse_tunables_string (char *valstring, struct tunable_toset_t *tunables)
return -1;
else if (*p == '\0')
done = true;
- else
- *p++ = '\0';
/* Add the tunable if it exists. */
for (size_t i = 0; i < tunables_list_size; i++)
@@ -228,7 +202,8 @@ parse_tunables_string (char *valstring, struct tunable_toset_t *tunables)
if (tunable_is_name (cur->name, name))
{
- tunables[ntunables++] = (struct tunable_toset_t) { cur, value };
+ tunables[ntunables++] =
+ (struct tunable_toset_t) { cur, value, p - value };
break;
}
}
@@ -238,7 +213,7 @@ parse_tunables_string (char *valstring, struct tunable_toset_t *tunables)
}
static void
-parse_tunables (char *valstring)
+parse_tunables (const char *valstring)
{
struct tunable_toset_t tunables[tunables_list_size];
int ntunables = parse_tunables_string (valstring, tunables);
@@ -250,7 +225,7 @@ parse_tunables (char *valstring)
}
for (int i = 0; i < ntunables; i++)
- tunable_initialize (tunables[i].t, tunables[i].value);
+ tunable_initialize (tunables[i].t, tunables[i].value, tunables[i].len);
}
/* Initialize the tunables list from the environment. For now we only use the
@@ -261,19 +236,20 @@ __tunables_init (char **envp)
{
char *envname = NULL;
char *envval = NULL;
- size_t len = 0;
char **prev_envp = envp;
/* Ignore tunables for AT_SECURE programs. */
if (__libc_enable_secure)
return;
- while ((envp = get_next_env (envp, &envname, &len, &envval,
- &prev_envp)) != NULL)
+ while ((envp = get_next_env (envp, &envname, &envval, &prev_envp)) != NULL)
{
+ /* The environment variable is allocated on the stack by the kernel, so
+ it is safe to keep the references to the suboptions for later parsing
+ of string tunables. */
if (tunable_is_name ("GLIBC_TUNABLES", envname))
{
- parse_tunables (tunables_strdup (envval));
+ parse_tunables (envval);
continue;
}
@@ -291,7 +267,11 @@ __tunables_init (char **envp)
/* We have a match. Initialize and move on to the next line. */
if (tunable_is_name (name, envname))
{
- tunable_initialize (cur, envval);
+ size_t envvallen = 0;
+ /* The environment variable is always null-terminated. */
+ for (const char *p = envval; *p != '\0'; p++, envvallen++);
+
+ tunable_initialize (cur, envval, envvallen);
break;
}
}
@@ -305,7 +285,7 @@ __tunables_print (void)
{
const tunable_t *cur = &tunable_list[i];
if (cur->type.type_code == TUNABLE_TYPE_STRING
- && cur->val.strval == NULL)
+ && cur->val.strval.str == NULL)
_dl_printf ("%s:\n", cur->name);
else
{
@@ -331,7 +311,9 @@ __tunables_print (void)
(size_t) cur->type.max);
break;
case TUNABLE_TYPE_STRING:
- _dl_printf ("%s\n", cur->val.strval);
+ _dl_printf ("%.*s\n",
+ (int) cur->val.strval.len,
+ cur->val.strval.str);
break;
default:
__builtin_unreachable ();
@@ -364,7 +346,7 @@ __tunable_get_default (tunable_id_t id, void *valp)
}
case TUNABLE_TYPE_STRING:
{
- *((const char **)valp) = cur->def.strval;
+ *((const struct tunable_str_t **)valp) = &cur->def.strval;
break;
}
default:
@@ -399,7 +381,7 @@ __tunable_get_val (tunable_id_t id, void *valp, tunable_callback_t callback)
}
case TUNABLE_TYPE_STRING:
{
- *((const char **)valp) = cur->val.strval;
+ *((const struct tunable_str_t **) valp) = &cur->val.strval;
break;
}
default: