public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Adhemerval Zanella <azanella@sourceware.org>
To: glibc-cvs@sourceware.org
Subject: [glibc] elf: Do not set invalid tunables values
Date: Tue, 19 Dec 2023 16:31:27 +0000 (GMT)	[thread overview]
Message-ID: <20231219163127.56A763857C5A@sourceware.org> (raw)

https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=f94446c38fb3f4ad26183984c490a9590cd05282

commit f94446c38fb3f4ad26183984c490a9590cd05282
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Dec 6 10:24:02 2023 -0300

    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>

Diff:
---
 elf/dl-misc.c      |  9 ++++++++-
 elf/dl-tunables.c  | 35 ++++++++++++++++++++++++++++++-----
 elf/tst-tunables.c | 30 ++++++++++++++++++++++++++++++
 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_",

                 reply	other threads:[~2023-12-19 16:31 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20231219163127.56A763857C5A@sourceware.org \
    --to=azanella@sourceware.org \
    --cc=glibc-cvs@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).