From: Siddhesh Poyarekar <siddhesh@sourceware.org>
To: Adhemerval Zanella <adhemerval.zanella@linaro.org>,
libc-alpha@sourceware.org
Cc: Joe Simmons-Talbott <josimmon@redhat.com>,
Yuto Maeda <maeda@cyberdefense.jp>,
Yutaro Shimizu <shimizu@cyberdefense.jp>
Subject: Re: [PATCH 1/4] elf: Only process multiple tunable once (BZ 31686)
Date: Wed, 1 May 2024 12:30:49 -0400 [thread overview]
Message-ID: <3190de63-d1ec-4d84-bf01-56b265c12f14@sourceware.org> (raw)
In-Reply-To: <20240430192739.1032549-2-adhemerval.zanella@linaro.org>
On 2024-04-30 15:25, Adhemerval Zanella wrote:
> The parse_tunables_string is a tunable entry on the 'tunable_list' list
> to be set later without checking if the entry is already present. If
> leads to a stack overflow if the tunable is set multiple times,
> for instance:
>
> GLIBC_TUNABLES=glibc.malloc.check=2:... (repeat over the number of
> total support for different tunable).
>
> Instead, use the index of the tunable list to get the expected tunable
> entry. Since now the initial list is zero-initialized, the compiler
> might emit an extra memset and this requires some minor adjustment
> on some ports.
>
> Checked on x86_64-linux-gnu and aarch64-linux-gnu.
>
> Reported-by: Yuto Maeda <maeda@cyberdefense.jp>
Please also credit Yutaro Shimizu <shimizu@cyberdefense.jp> in reporters.
> ---
> elf/dl-tunables.c | 30 ++++++-----
> elf/tst-tunables.c | 59 +++++++++++++++++++++-
> sysdeps/aarch64/multiarch/memset_generic.S | 4 ++
> sysdeps/sparc/sparc64/rtld-memset.c | 3 ++
> 4 files changed, 82 insertions(+), 14 deletions(-)
>
> diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
> index d3ccd2ecd4..1db80e0f92 100644
> --- a/elf/dl-tunables.c
> +++ b/elf/dl-tunables.c
> @@ -32,6 +32,7 @@
> #include <ldsodefs.h>
> #include <array_length.h>
> #include <dl-minimal-malloc.h>
> +#include <dl-symbol-redir-ifunc.h>
>
> #define TUNABLES_INTERNAL 1
> #include "dl-tunables.h"
> @@ -221,8 +222,7 @@ parse_tunables_string (const char *valstring, struct tunable_toset_t *tunables)
>
> if (tunable_is_name (cur->name, name))
> {
> - tunables[ntunables++] =
> - (struct tunable_toset_t) { cur, value, p - value };
> + tunables[i] = (struct tunable_toset_t) { cur, value, p - value };
Uninitialized tunables stay as NULL, tunables appearing later in the
string will persist in case of duplicates. OK.
>
> /* Ignore tunables if enable_secure is set */
> if (tunable_is_name ("glibc.rtld.enable_secure", name))
> @@ -245,23 +245,27 @@ parse_tunables_string (const char *valstring, struct tunable_toset_t *tunables)
> static void
> parse_tunables (const char *valstring)
> {
> - struct tunable_toset_t tunables[tunables_list_size];
> - int ntunables = parse_tunables_string (valstring, tunables);
> - if (ntunables == -1)
> + struct tunable_toset_t tunables[tunables_list_size] = { 0 };
zero-initialized, so tunables[i].t is NULL unless set above. OK.
> + if (parse_tunables_string (valstring, tunables) == -1)
> {
> _dl_error_printf (
> "WARNING: ld.so: invalid GLIBC_TUNABLES `%s': ignored.\n", valstring);
> return;
> }
>
> - for (int i = 0; i < ntunables; i++)
> - 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);
> + for (int i = 0; i < tunables_list_size; i++)
> + {
> + if (tunables[i].t == NULL)
> + continue;
Skip over NULLs, initializing only those that are set. OK.
> +
> + 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 095b5c81d9..ce5f62f777 100644
> --- a/elf/tst-tunables.c
> +++ b/elf/tst-tunables.c
> @@ -17,6 +17,7 @@
> <https://www.gnu.org/licenses/>. */
>
> #include <array_length.h>
> +#define TUNABLES_INTERNAL 1
> #include <dl-tunables.h>
> #include <getopt.h>
> #include <intprops.h>
> @@ -24,12 +25,13 @@
> #include <stdlib.h>
> #include <support/capture_subprocess.h>
> #include <support/check.h>
> +#include <support/support.h>
>
> static int restart;
> #define CMDLINE_OPTIONS \
> { "restart", no_argument, &restart, 1 },
>
> -static const struct test_t
> +static struct test_t
> {
> const char *name;
> const char *value;
> @@ -284,6 +286,29 @@ static const struct test_t
> 0,
> 0,
> },
> + /* Also check for repeated tunables with a count larger than the total number
> + of tunables. */
> + {
> + "GLIBC_TUNABLES",
> + NULL,
> + 2,
> + 0,
> + 0,
> + },
> + {
> + "GLIBC_TUNABLES",
> + NULL,
> + 1,
> + 0,
> + 0,
> + },
> + {
> + "GLIBC_TUNABLES",
> + NULL,
> + 0,
> + 0,
> + 0,
> + },
> };
>
> static int
> @@ -316,6 +341,7 @@ do_test (int argc, char *argv[])
>
> char nteststr[INT_BUFSIZE_BOUND (int)];
>
> +
Spurious newline.
> char *spargv[10];
> {
> int i = 0;
> @@ -327,6 +353,37 @@ do_test (int argc, char *argv[])
> spargv[i] = NULL;
> }
>
> + /* Create a tunable line with the duplicate values with a total number
> + larger than the different number of tunables. */
> + {
> + enum { tunables_list_size = array_length (tunable_list) };
> + const char *value = "";
> + for (int i = 0; i < tunables_list_size; i++)
> + value = xasprintf ("%sglibc.malloc.check=2%c",
> + value,
> + i == (tunables_list_size - 1) ? '\0' : ':');
> + tests[33].value = value;
> + }
> + /* Same as before, but the last tunable vallues is differen than the
> + rest. */
> + {
> + enum { tunables_list_size = array_length (tunable_list) };
> + const char *value = "";
> + for (int i = 0; i < tunables_list_size - 1; i++)
> + value = xasprintf ("%sglibc.malloc.check=2:", value);
> + value = xasprintf ("%sglibc.malloc.check=1", value);
> + tests[34].value = value;
> + }
> + /* Same as before, but with an invalid last entry. */
> + {
> + enum { tunables_list_size = array_length (tunable_list) };
> + const char *value = "";
> + for (int i = 0; i < tunables_list_size - 1; i++)
> + value = xasprintf ("%sglibc.malloc.check=2:", value);
> + value = xasprintf ("%sglibc.malloc.check=1=1", value);
> + tests[35].value = value;
> + }
> +
> for (int i = 0; i < array_length (tests); i++)
> {
> snprintf (nteststr, sizeof nteststr, "%d", i);
> diff --git a/sysdeps/aarch64/multiarch/memset_generic.S b/sysdeps/aarch64/multiarch/memset_generic.S
> index 81748bdbce..e125a5ed85 100644
> --- a/sysdeps/aarch64/multiarch/memset_generic.S
> +++ b/sysdeps/aarch64/multiarch/memset_generic.S
> @@ -33,3 +33,7 @@
> #endif
>
> #include <../memset.S>
> +
> +#if IS_IN (rtld)
> +strong_alias (memset, __memset_generic)
> +#endif
The extra memset you mentioned. OK.
> diff --git a/sysdeps/sparc/sparc64/rtld-memset.c b/sysdeps/sparc/sparc64/rtld-memset.c
> index 55f3835790..a19202a620 100644
> --- a/sysdeps/sparc/sparc64/rtld-memset.c
> +++ b/sysdeps/sparc/sparc64/rtld-memset.c
> @@ -1 +1,4 @@
> #include <string/memset.c>
> +#if IS_IN(rtld)
> +strong_alias (memset, __memset_ultra1)
> +#endif
Likewise.
Thanks,
Sid
next prev parent reply other threads:[~2024-05-01 16:30 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-04-30 19:25 [PATCH 0/4] More tunable fixes Adhemerval Zanella
2024-04-30 19:25 ` [PATCH 1/4] elf: Only process multiple tunable once (BZ 31686) Adhemerval Zanella
2024-05-01 12:54 ` Florian Weimer
2024-05-01 14:19 ` Adhemerval Zanella Netto
2024-05-01 16:30 ` Siddhesh Poyarekar [this message]
2024-04-30 19:25 ` [PATCH 2/4] elf: Remove glibc.rtld.enable_secure check from parse_tunables_string Adhemerval Zanella
2024-05-01 17:15 ` Siddhesh Poyarekar
2024-04-30 19:25 ` [PATCH 3/4] support: Add envp argument to support_capture_subprogram Adhemerval Zanella
2024-04-30 20:06 ` Joe Simmons-Talbott
2024-04-30 19:25 ` [PATCH 4/4] elf: Make glibc.rtld.enable_secure ignore alias environment variables Adhemerval Zanella
2024-05-01 17:40 ` Siddhesh Poyarekar
2024-05-01 18:00 ` Adhemerval Zanella Netto
2024-05-02 11:03 ` Siddhesh Poyarekar
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=3190de63-d1ec-4d84-bf01-56b265c12f14@sourceware.org \
--to=siddhesh@sourceware.org \
--cc=adhemerval.zanella@linaro.org \
--cc=josimmon@redhat.com \
--cc=libc-alpha@sourceware.org \
--cc=maeda@cyberdefense.jp \
--cc=shimizu@cyberdefense.jp \
/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).