aboutsummaryrefslogtreecommitdiff
path: root/elf
diff options
context:
space:
mode:
authorAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-12-06 10:24:02 -0300
committerAdhemerval Zanella <adhemerval.zanella@linaro.org>2023-12-19 13:25:45 -0300
commitf94446c38fb3f4ad26183984c490a9590cd05282 (patch)
tree6e9ef3cea607f8bf54757a4b051ba0f79f3de6bb /elf
parent2a969b53c0b02fed7e43473a92f219d737fd217a (diff)
downloadglibc-f94446c38fb3f4ad26183984c490a9590cd05282.tar
glibc-f94446c38fb3f4ad26183984c490a9590cd05282.tar.gz
glibc-f94446c38fb3f4ad26183984c490a9590cd05282.tar.bz2
glibc-f94446c38fb3f4ad26183984c490a9590cd05282.zip
elf: Do not set invalid tunables values
The loader now warns for invalid and out-of-range tunable values. The patch also fixes the parsing of size_t maximum values, where _dl_strtoul was failing for large values close to SIZE_MAX. Checked on x86_64-linux-gnu. Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
Diffstat (limited to 'elf')
-rw-r--r--elf/dl-misc.c9
-rw-r--r--elf/dl-tunables.c35
-rw-r--r--elf/tst-tunables.c30
3 files changed, 68 insertions, 6 deletions
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index 5b84adc2f4..859d3e26f0 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -174,6 +174,9 @@ _dl_strtoul (const char *nptr, char **endptr)
return 0UL;
}
+ uint64_t cutoff = (UINT64_MAX * 2UL + 1UL) / 10;
+ uint64_t cutlim = (UINT64_MAX * 2UL + 1UL) % 10;
+
int base = 10;
max_digit = 9;
if (*nptr == '0')
@@ -182,11 +185,15 @@ _dl_strtoul (const char *nptr, char **endptr)
{
base = 16;
nptr += 2;
+ cutoff = (UINT64_MAX * 2UL + 1UL) / 16;
+ cutlim = (UINT64_MAX * 2UL + 1UL) % 16;
}
else
{
base = 8;
max_digit = 7;
+ cutoff = (UINT64_MAX * 2UL + 1UL) / 8;
+ cutlim = (UINT64_MAX * 2UL + 1UL) % 8;
}
}
@@ -207,7 +214,7 @@ _dl_strtoul (const char *nptr, char **endptr)
else
break;
- if (result >= (UINT64_MAX - digval) / base)
+ if (result > cutoff || (result == cutoff && digval > cutlim))
{
if (endptr != NULL)
*endptr = (char *) nptr;
diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
index 3d41e8e28e..092b696484 100644
--- a/elf/dl-tunables.c
+++ b/elf/dl-tunables.c
@@ -69,16 +69,27 @@ do_tunable_update_val (tunable_t *cur, const tunable_val_t *valp,
{
tunable_num_t val, min, max;
- if (cur->type.type_code == TUNABLE_TYPE_STRING)
+ switch (cur->type.type_code)
{
+ case TUNABLE_TYPE_STRING:
cur->val.strval = valp->strval;
cur->initialized = true;
return;
+ case TUNABLE_TYPE_INT_32:
+ val = (int32_t) valp->numval;
+ break;
+ case TUNABLE_TYPE_UINT_64:
+ val = (int64_t) valp->numval;
+ break;
+ case TUNABLE_TYPE_SIZE_T:
+ val = (size_t) valp->numval;
+ break;
+ default:
+ __builtin_unreachable ();
}
bool unsigned_cmp = unsigned_tunable_type (cur->type.type_code);
- val = valp->numval;
min = minp != NULL ? *minp : cur->type.min;
max = maxp != NULL ? *maxp : cur->type.max;
@@ -109,16 +120,24 @@ 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
+static bool
tunable_initialize (tunable_t *cur, const char *strval, size_t len)
{
tunable_val_t val = { 0 };
if (cur->type.type_code != TUNABLE_TYPE_STRING)
- val.numval = (tunable_num_t) _dl_strtoul (strval, NULL);
+ {
+ char *endptr = NULL;
+ uint64_t numval = _dl_strtoul (strval, &endptr);
+ if (endptr != strval + len)
+ return false;
+ val.numval = (tunable_num_t) numval;
+ }
else
val.strval = (struct tunable_str_t) { strval, len };
do_tunable_update_val (cur, &val, NULL, NULL);
+
+ return true;
}
bool
@@ -225,7 +244,13 @@ parse_tunables (const char *valstring)
}
for (int i = 0; i < ntunables; i++)
- tunable_initialize (tunables[i].t, tunables[i].value, tunables[i].len);
+ if (!tunable_initialize (tunables[i].t, tunables[i].value,
+ tunables[i].len))
+ _dl_error_printf ("WARNING: ld.so: invalid GLIBC_TUNABLES value `%.*s' "
+ "for option `%s': ignored.\n",
+ (int) tunables[i].len,
+ tunables[i].value,
+ tunables[i].t->name);
}
/* Initialize the tunables list from the environment. For now we only use the
diff --git a/elf/tst-tunables.c b/elf/tst-tunables.c
index 188345b070..d6a1e1b3ac 100644
--- a/elf/tst-tunables.c
+++ b/elf/tst-tunables.c
@@ -53,6 +53,13 @@ static const struct test_t
4096,
0,
},
+ {
+ "GLIBC_TUNABLES",
+ "glibc.malloc.mmap_threshold=-1",
+ 0,
+ SIZE_MAX,
+ 0,
+ },
/* Empty tunable are ignored. */
{
"GLIBC_TUNABLES",
@@ -224,6 +231,29 @@ static const struct test_t
0,
0,
},
+ /* Invalid numbers are ignored. */
+ {
+ "GLIBC_TUNABLES",
+ "glibc.malloc.check=abc:glibc.malloc.mmap_threshold=4096",
+ 0,
+ 4096,
+ 0,
+ },
+ {
+ "GLIBC_TUNABLES",
+ "glibc.malloc.check=2:glibc.malloc.mmap_threshold=abc",
+ 2,
+ 0,
+ 0,
+ },
+ {
+ "GLIBC_TUNABLES",
+ /* SIZE_MAX + 1 */
+ "glibc.malloc.mmap_threshold=18446744073709551616",
+ 0,
+ 0,
+ 0,
+ },
/* Also check some tunable aliases. */
{
"MALLOC_CHECK_",