about summary refs log tree commit diff
path: root/elf/dl-tunables.c
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/dl-tunables.c
parent2a969b53c0b02fed7e43473a92f219d737fd217a (diff)
downloadglibc-f94446c38fb3f4ad26183984c490a9590cd05282.tar.gz
glibc-f94446c38fb3f4ad26183984c490a9590cd05282.tar.xz
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/dl-tunables.c')
-rw-r--r--elf/dl-tunables.c35
1 files changed, 30 insertions, 5 deletions
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