* [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-11-15 19:01 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 02/20] elf: Add _dl_audit_objopen Adhemerval Zanella
` (18 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
For a new Lmid_t the namespace link_map list are empty, so it requires
to check if before using it. This can happen for when audit module
is used along with dlmopen.
Checked on x86_64-linux-gnu.
---
elf/Makefile | 9 ++-
elf/dl-load.c | 72 ++++++++++++------------
elf/tst-audit18.c | 129 +++++++++++++++++++++++++++++++++++++++++++
elf/tst-audit18mod.c | 23 ++++++++
elf/tst-auditmod18.c | 73 ++++++++++++++++++++++++
5 files changed, 269 insertions(+), 37 deletions(-)
create mode 100644 elf/tst-audit18.c
create mode 100644 elf/tst-audit18mod.c
create mode 100644 elf/tst-auditmod18.c
diff --git a/elf/Makefile b/elf/Makefile
index a311c3e23c..8f3e3a3602 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -229,7 +229,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-tls-ie tst-tls-ie-dlmopen argv0test \
tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \
- tst-dl-is_dso tst-ro-dynamic
+ tst-dl-is_dso tst-ro-dynamic \
+ tst-audit18 \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -370,6 +371,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \
tst-auxvalmod \
tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \
+ tst-auditmod18 \
+ tst-audit18mod \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1537,6 +1540,10 @@ $(objpfx)tst-audit16-cmp.out: tst-audit16.exp $(objpfx)tst-audit16.out
cmp $^ > $@; \
$(evaluate-test)
+$(objpfx)tst-audit18.out: $(objpfx)tst-auditmod18.so \
+ $(objpfx)tst-audit18mod.so
+tst-audit18-ARGS = -- $(host-test-program-cmd)
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 9f4fa9617d..9538bcb7dc 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1058,42 +1058,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
/* This is the ELF header. We read it in `open_verify'. */
header = (void *) fbp->buf;
- /* Signal that we are going to add new objects. */
- if (r->r_state == RT_CONSISTENT)
- {
-#ifdef SHARED
- /* Auditing checkpoint: we are going to add new objects. */
- if ((mode & __RTLD_AUDIT) == 0
- && __glibc_unlikely (GLRO(dl_naudit) > 0))
- {
- struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
- /* Do not call the functions for any auditing object. */
- if (head->l_auditing == 0)
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- afct->activity (&link_map_audit_state (head, cnt)->cookie,
- LA_ACT_ADD);
-
- afct = afct->next;
- }
- }
- }
-#endif
-
- /* Notify the debugger we have added some objects. We need to
- call _dl_debug_initialize in a static program in case dynamic
- linking has not been used before. */
- r->r_state = RT_ADD;
- _dl_debug_state ();
- LIBC_PROBE (map_start, 2, nsid, r);
- make_consistent = true;
- }
- else
- assert (r->r_state == RT_ADD);
-
/* Enter the new object in the list of loaded objects. */
l = _dl_new_object (realname, name, l_type, loader, mode, nsid);
if (__glibc_unlikely (l == NULL))
@@ -1515,6 +1479,42 @@ cannot enable executable stack as shared object requires");
/* Now that the object is fully initialized add it to the object list. */
_dl_add_to_namespace_list (l, nsid);
+ /* Signal that we are going to add new objects. */
+ if (r->r_state == RT_CONSISTENT)
+ {
+#ifdef SHARED
+ /* Auditing checkpoint: we are going to add new objects. */
+ if ((mode & __RTLD_AUDIT) == 0
+ && __glibc_unlikely (GLRO(dl_naudit) > 0))
+ {
+ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
+ /* Do not call the functions for any auditing object. */
+ if (head->l_auditing == 0)
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&link_map_audit_state (head, cnt)->cookie,
+ LA_ACT_ADD);
+
+ afct = afct->next;
+ }
+ }
+ }
+#endif
+
+ /* Notify the debugger we have added some objects. We need to
+ call _dl_debug_initialize in a static program in case dynamic
+ linking has not been used before. */
+ r->r_state = RT_ADD;
+ _dl_debug_state ();
+ LIBC_PROBE (map_start, 2, nsid, r);
+ make_consistent = true;
+ }
+ else
+ assert (r->r_state == RT_ADD);
+
#ifdef SHARED
/* Auditing checkpoint: we have a new object. */
if (__glibc_unlikely (GLRO(dl_naudit) > 0)
diff --git a/elf/tst-audit18.c b/elf/tst-audit18.c
new file mode 100644
index 0000000000..b5ed15d07f
--- /dev/null
+++ b/elf/tst-audit18.c
@@ -0,0 +1,129 @@
+/* Check DT_AUDIT with dlmopen.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <getopt.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <gnu/lib-names.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+static int
+handle_restart (void)
+{
+ {
+ void *h = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+
+ pid_t (*s)(void) = xdlsym (h, "getpid");
+ TEST_COMPARE (s (), getpid ());
+
+ xdlclose (h);
+ }
+
+ {
+ void *h = xdlmopen (LM_ID_NEWLM, "tst-audit18mod.so", RTLD_NOW);
+
+ int (*foo)(void) = xdlsym (h, "foo");
+ TEST_COMPARE (foo (), 10);
+
+ xdlclose (h);
+ }
+
+ return 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ /* We must have either:
+ - One our fource parameters left if called initially:
+ + path to ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name */
+
+ if (restart)
+ return handle_restart ();
+
+ char *spargv[9];
+ int i = 0;
+ for (; i < argc - 1; i++)
+ spargv[i] = argv[i + 1];
+ spargv[i++] = (char *) "--direct";
+ spargv[i++] = (char *) "--restart";
+ spargv[i] = NULL;
+
+ setenv ("LD_AUDIT", "tst-auditmod18.so", 0);
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit18", 0, sc_allow_stderr);
+
+ struct
+ {
+ const char *name;
+ bool found;
+ } audit_iface[] =
+ {
+ { "la_version", false },
+ { "la_objsearch", false },
+ { "la_activity", false },
+ { "la_objopen", false },
+ { "la_objclose", false },
+ { "la_preinit", false },
+#if __WORDSIZE == 32
+ { "la_symbind32", false },
+#elif __WORDSIZE == 64
+ { "la_symbind64", false },
+#endif
+ };
+
+ /* Some hooks are called more than once but the test only check if any
+ is called at least once. */
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
+ TEST_VERIFY (out != NULL);
+ char *buffer = NULL;
+ size_t buffer_length = 0;
+ while (xgetline (&buffer, &buffer_length, out))
+ {
+ for (int i = 0; i < array_length (audit_iface); i++)
+ if (strncmp (buffer, audit_iface[i].name,
+ strlen (audit_iface[i].name)) == 0)
+ audit_iface[i].found = true;
+ }
+ free (buffer);
+ xfclose (out);
+
+ for (int i = 0; i < array_length (audit_iface); i++)
+ TEST_COMPARE (audit_iface[i].found, true);
+
+ support_capture_subprocess_free (&result);
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit18mod.c b/elf/tst-audit18mod.c
new file mode 100644
index 0000000000..096a9167c9
--- /dev/null
+++ b/elf/tst-audit18mod.c
@@ -0,0 +1,23 @@
+/* Check DT_AUDIT with dlmopen.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+int
+foo (void)
+{
+ return 10;
+}
diff --git a/elf/tst-auditmod18.c b/elf/tst-auditmod18.c
new file mode 100644
index 0000000000..182992e9fd
--- /dev/null
+++ b/elf/tst-auditmod18.c
@@ -0,0 +1,73 @@
+/* Check DT_AUDIT with dlmopen.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <link.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+ fprintf (stderr, "%s\n", __func__);
+ return LAV_CURRENT;
+}
+
+char *
+la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
+{
+ fprintf (stderr, "%s\n", __func__);
+ return (char *) name;
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ fprintf (stderr, "%s\n", __func__);
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ fprintf (stderr, "%s\n", __func__);
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM;
+}
+
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+ fprintf (stderr, "%s\n", __func__);
+ return 0;
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+ fprintf (stderr, "%s\n", __func__);
+}
+
+uintptr_t
+#if __ELF_NATIVE_CLASS == 32
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+#else
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+#endif
+{
+ fprintf (stderr, "%s\n", __func__);
+ return sym->st_value;
+}
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-15 18:37 ` [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
@ 2021-11-15 19:01 ` Florian Weimer
2021-11-16 13:14 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-11-15 19:01 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> For a new Lmid_t the namespace link_map list are empty, so it requires
> to check if before using it. This can happen for when audit module
> is used along with dlmopen.
Looks like you forgot to update the commit message.
My patch linter also flags these:
+ pid_t (*s)(void) = xdlsym (h, "getpid");
+ int (*foo)(void) = xdlsym (h, "foo");
Missing space before “(void)”.
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 9f4fa9617d..9538bcb7dc 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -1515,6 +1479,42 @@ cannot enable executable stack as shared object requires");
> /* Now that the object is fully initialized add it to the object list. */
> _dl_add_to_namespace_list (l, nsid);
>
> + /* Signal that we are going to add new objects. */
> + if (r->r_state == RT_CONSISTENT)
> + {
> +#ifdef SHARED
> + /* Auditing checkpoint: we are going to add new objects. */
> + if ((mode & __RTLD_AUDIT) == 0
> + && __glibc_unlikely (GLRO(dl_naudit) > 0))
> + {
> + struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
> + /* Do not call the functions for any auditing object. */
> + if (head->l_auditing == 0)
> + {
> + struct audit_ifaces *afct = GLRO(dl_audit);
> + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
> + {
> + if (afct->activity != NULL)
> + afct->activity (&link_map_audit_state (head, cnt)->cookie,
> + LA_ACT_ADD);
> +
> + afct = afct->next;
> + }
> + }
> + }
> +#endif
Please add a comment that this happens after _dl_add_to_namespace_list,
so that the namespace is guaranteed not to be empty.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-15 19:01 ` Florian Weimer
@ 2021-11-16 13:14 ` Adhemerval Zanella
2021-11-16 13:15 ` Florian Weimer
2021-11-16 13:45 ` Andreas Schwab
0 siblings, 2 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-16 13:14 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 15/11/2021 16:01, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> For a new Lmid_t the namespace link_map list are empty, so it requires
>> to check if before using it. This can happen for when audit module
>> is used along with dlmopen.
>
> Looks like you forgot to update the commit message.
Indeed, the title is also misleading. I have changed to:
elf: Move la_activity (LA_ACT_ADD) after _dl_add_to_namespace_list() (BZ #28062)
It ensures that the the namespace is guaranteed to not be empty.
>
> My patch linter also flags these:
>
> + pid_t (*s)(void) = xdlsym (h, "getpid");
> + int (*foo)(void) = xdlsym (h, "foo");
>
> Missing space before “(void)”.
Ack.
>
>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>> index 9f4fa9617d..9538bcb7dc 100644
>> --- a/elf/dl-load.c
>> +++ b/elf/dl-load.c
>
>> @@ -1515,6 +1479,42 @@ cannot enable executable stack as shared object requires");
>> /* Now that the object is fully initialized add it to the object list. */
>> _dl_add_to_namespace_list (l, nsid);
>>
>> + /* Signal that we are going to add new objects. */
>> + if (r->r_state == RT_CONSISTENT)
>> + {
>> +#ifdef SHARED
>> + /* Auditing checkpoint: we are going to add new objects. */
>> + if ((mode & __RTLD_AUDIT) == 0
>> + && __glibc_unlikely (GLRO(dl_naudit) > 0))
>> + {
>> + struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
>> + /* Do not call the functions for any auditing object. */
>> + if (head->l_auditing == 0)
>> + {
>> + struct audit_ifaces *afct = GLRO(dl_audit);
>> + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
>> + {
>> + if (afct->activity != NULL)
>> + afct->activity (&link_map_audit_state (head, cnt)->cookie,
>> + LA_ACT_ADD);
>> +
>> + afct = afct->next;
>> + }
>> + }
>> + }
>> +#endif
>
> Please add a comment that this happens after _dl_add_to_namespace_list,
> so that the namespace is guaranteed not to be empty.
I have changed to:
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 9538bcb7dc..240b5efb45 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1483,7 +1483,9 @@ cannot enable executable stack as shared object requires");
if (r->r_state == RT_CONSISTENT)
{
#ifdef SHARED
- /* Auditing checkpoint: we are going to add new objects. */
+ /* Auditing checkpoint: we are going to add new objects. Since this
+ is called after _dl_add_to_namespace_list() the namespace is
+ guaranteed to not be empty. */
if ((mode & __RTLD_AUDIT) == 0
&& __glibc_unlikely (GLRO(dl_naudit) > 0))
{
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-16 13:14 ` Adhemerval Zanella
@ 2021-11-16 13:15 ` Florian Weimer
2021-11-16 13:45 ` Andreas Schwab
1 sibling, 0 replies; 89+ messages in thread
From: Florian Weimer @ 2021-11-16 13:15 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> On 15/11/2021 16:01, Florian Weimer wrote:
>> * Adhemerval Zanella:
>>
>>> For a new Lmid_t the namespace link_map list are empty, so it requires
>>> to check if before using it. This can happen for when audit module
>>> is used along with dlmopen.
>>
>> Looks like you forgot to update the commit message.
>
> Indeed, the title is also misleading. I have changed to:
>
> elf: Move la_activity (LA_ACT_ADD) after _dl_add_to_namespace_list() (BZ #28062)
>
> It ensures that the the namespace is guaranteed to not be empty.
Looks good with these changes.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-16 13:14 ` Adhemerval Zanella
2021-11-16 13:15 ` Florian Weimer
@ 2021-11-16 13:45 ` Andreas Schwab
2021-11-16 13:48 ` Florian Weimer
1 sibling, 1 reply; 89+ messages in thread
From: Andreas Schwab @ 2021-11-16 13:45 UTC (permalink / raw)
To: Adhemerval Zanella via Libc-alpha
Cc: Florian Weimer, Adhemerval Zanella, John Mellor-Crummey
On Nov 16 2021, Adhemerval Zanella via Libc-alpha wrote:
> + /* Auditing checkpoint: we are going to add new objects. Since this
> + is called after _dl_add_to_namespace_list() the namespace is
Not a function call here.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-16 13:45 ` Andreas Schwab
@ 2021-11-16 13:48 ` Florian Weimer
2021-11-16 14:16 ` Andreas Schwab
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-11-16 13:48 UTC (permalink / raw)
To: Andreas Schwab
Cc: Adhemerval Zanella via Libc-alpha, Adhemerval Zanella,
John Mellor-Crummey
* Andreas Schwab:
> On Nov 16 2021, Adhemerval Zanella via Libc-alpha wrote:
>
>> + /* Auditing checkpoint: we are going to add new objects. Since this
>> + is called after _dl_add_to_namespace_list() the namespace is
>
> Not a function call here.
I've stopped pointing those out in patch reviews. Is this GNU
convention really useful? If there is no other markup, it often
increases readability, particular for identifiers that are also bona
fide English words, such as read and close.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-16 13:48 ` Florian Weimer
@ 2021-11-16 14:16 ` Andreas Schwab
2021-11-18 19:58 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Andreas Schwab @ 2021-11-16 14:16 UTC (permalink / raw)
To: Florian Weimer
Cc: Adhemerval Zanella via Libc-alpha, Adhemerval Zanella,
John Mellor-Crummey
On Nov 16 2021, Florian Weimer wrote:
> * Andreas Schwab:
>
>> On Nov 16 2021, Adhemerval Zanella via Libc-alpha wrote:
>>
>>> + /* Auditing checkpoint: we are going to add new objects. Since this
>>> + is called after _dl_add_to_namespace_list() the namespace is
>>
>> Not a function call here.
>
> I've stopped pointing those out in patch reviews. Is this GNU
> convention really useful? If there is no other markup, it often
> increases readability,
You can always write "the foo function".
> particular for identifiers that are also bona fide English words, such
> as read and close.
Which only proves my point.
Andreas.
--
Andreas Schwab, schwab@linux-m68k.org
GPG Key fingerprint = 7578 EB47 D4E5 4D69 2510 2552 DF73 E780 A9DA AEC1
"And now for something completely different."
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
2021-11-16 14:16 ` Andreas Schwab
@ 2021-11-18 19:58 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-18 19:58 UTC (permalink / raw)
To: Andreas Schwab, Florian Weimer
Cc: Adhemerval Zanella via Libc-alpha, John Mellor-Crummey
On 16/11/2021 11:16, Andreas Schwab wrote:
> On Nov 16 2021, Florian Weimer wrote:
>
>> * Andreas Schwab:
>>
>>> On Nov 16 2021, Adhemerval Zanella via Libc-alpha wrote:
>>>
>>>> + /* Auditing checkpoint: we are going to add new objects. Since this
>>>> + is called after _dl_add_to_namespace_list() the namespace is
>>>
>>> Not a function call here.
>>
>> I've stopped pointing those out in patch reviews. Is this GNU
>> convention really useful? If there is no other markup, it often
>> increases readability,
>
> You can always write "the foo function".
>
>> particular for identifiers that are also bona fide English words, such
>> as read and close.
>
> Which only proves my point.
Ok, I will remove the '()' and reference to just the function name.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
2021-11-15 18:37 ` [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-10 12:40 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 03/20] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
` (17 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_objopen() audit callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Makefile | 2 +-
elf/dl-audit.c | 42 ++++++++++++++++++++++++++++++++++++++
elf/dl-load.c | 17 +--------------
elf/rtld.c | 23 ++-------------------
sysdeps/generic/ldsodefs.h | 5 +++++
5 files changed, 51 insertions(+), 38 deletions(-)
create mode 100644 elf/dl-audit.c
diff --git a/elf/Makefile b/elf/Makefile
index 8f3e3a3602..80ed31edbe 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
exception sort-maps lookup-direct \
call-libc-early-init write \
thread_gscope_wait tls_init_tp \
- debug-symbols minimal-malloc)
+ debug-symbols minimal-malloc audit)
ifeq (yes,$(use-ldconfig))
dl-routines += dl-cache
endif
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
new file mode 100644
index 0000000000..24d8557f18
--- /dev/null
+++ b/elf/dl-audit.c
@@ -0,0 +1,42 @@
+/* Audit common functions.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ldsodefs.h>
+
+#ifdef SHARED
+void
+_dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit)
+{
+ if (__glibc_likely (GLRO(dl_naudit) == 0)
+ || (check_audit && GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing))
+ return;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objopen != NULL)
+ {
+ struct auditstate *state = link_map_audit_state (l, cnt);
+ state->bindflags = afct->objopen (l, nsid, &state->cookie);
+ l->l_audit_any_plt |= state->bindflags != 0;
+ }
+
+ afct = afct->next;
+ }
+}
+#endif
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 9538bcb7dc..907ab8f5f7 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1517,22 +1517,7 @@ cannot enable executable stack as shared object requires");
#ifdef SHARED
/* Auditing checkpoint: we have a new object. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0)
- && !GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->objopen != NULL)
- {
- struct auditstate *state = link_map_audit_state (l, cnt);
- state->bindflags = afct->objopen (l, nsid, &state->cookie);
- l->l_audit_any_plt |= state->bindflags != 0;
- }
-
- afct = afct->next;
- }
- }
+ _dl_audit_objopen (l, nsid, true);
#endif
return l;
diff --git a/elf/rtld.c b/elf/rtld.c
index be2d5d8e74..647f476957 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1063,25 +1063,6 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
dlmargs.map->l_auditing = 1;
}
-/* Notify the the audit modules that the object MAP has already been
- loaded. */
-static void
-notify_audit_modules_of_loaded_object (struct link_map *map)
-{
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->objopen != NULL)
- {
- struct auditstate *state = link_map_audit_state (map, cnt);
- state->bindflags = afct->objopen (map, LM_ID_BASE, &state->cookie);
- map->l_audit_any_plt |= state->bindflags != 0;
- }
-
- afct = afct->next;
- }
-}
-
/* Load all audit modules. */
static void
load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
@@ -1100,8 +1081,8 @@ load_audit_modules (struct link_map *main_map, struct audit_list *audit_list)
program and the dynamic linker itself). */
if (GLRO(dl_naudit) > 0)
{
- notify_audit_modules_of_loaded_object (main_map);
- notify_audit_modules_of_loaded_object (&GL(dl_rtld_map));
+ _dl_audit_objopen (main_map, LM_ID_BASE, false);
+ _dl_audit_objopen (&GL(dl_rtld_map), LM_ID_BASE, false);
}
}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 1318c36dce..dec592bf53 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1391,6 +1391,11 @@ link_map_audit_state (struct link_map *l, size_t index)
return &base[index];
}
}
+
+/* Call the la_objopen() from the audit modules for the link_map L on the
+ namespace identification NSID. If CHECK_AUDIT is set it will also check
+ if main mapping of the namespace is a audit modules. */
+void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
#endif /* SHARED */
#if PTHREAD_IN_LIBC && defined SHARED
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-11-15 18:37 ` [PATCH v6 02/20] elf: Add _dl_audit_objopen Adhemerval Zanella
@ 2021-12-10 12:40 ` Florian Weimer
2021-12-10 12:48 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-10 12:40 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/Makefile b/elf/Makefile
> index 8f3e3a3602..80ed31edbe 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
> exception sort-maps lookup-direct \
> call-libc-early-init write \
> thread_gscope_wait tls_init_tp \
> - debug-symbols minimal-malloc)
> + debug-symbols minimal-malloc audit)
You can drop the #ifdef SHARED if you add this to rtld-routines.
> +/* Call the la_objopen() from the audit modules for the link_map L on the
> + namespace identification NSID. If CHECK_AUDIT is set it will also check
> + if main mapping of the namespace is a audit modules. */
> +void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
No () after function name (not sure?)
Should check_audit be named require_auditing? That would align better
with the l_auditing check, I think.
Rest looks okay.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-12-10 12:40 ` Florian Weimer
@ 2021-12-10 12:48 ` Florian Weimer
2021-12-10 13:45 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-10 12:48 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Florian Weimer:
> * Adhemerval Zanella:
>
>> diff --git a/elf/Makefile b/elf/Makefile
>> index 8f3e3a3602..80ed31edbe 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
>> exception sort-maps lookup-direct \
>> call-libc-early-init write \
>> thread_gscope_wait tls_init_tp \
>> - debug-symbols minimal-malloc)
>> + debug-symbols minimal-malloc audit)
>
> You can drop the #ifdef SHARED if you add this to rtld-routines.
>
>> +/* Call the la_objopen() from the audit modules for the link_map L on the
>> + namespace identification NSID. If CHECK_AUDIT is set it will also check
>> + if main mapping of the namespace is a audit modules. */
>> +void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
>
> No () after function name (not sure?)
>
> Should check_audit be named require_auditing? That would align better
> with the l_auditing check, I think.
Hmm. require_auditing is also not quite right. What about
skip_auditing?
And the comment should say which namespace (there's nsid and l->l_ns).
Maybe the check should be moved into the caller because
notify_audit_modules_of_loaded_object does not need it?
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-12-10 12:48 ` Florian Weimer
@ 2021-12-10 13:45 ` Adhemerval Zanella
2021-12-10 14:11 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-10 13:45 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 10/12/2021 09:48, Florian Weimer wrote:
> * Florian Weimer:
>
>> * Adhemerval Zanella:
>>
>>> diff --git a/elf/Makefile b/elf/Makefile
>>> index 8f3e3a3602..80ed31edbe 100644
>>> --- a/elf/Makefile
>>> +++ b/elf/Makefile
>>> @@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
>>> exception sort-maps lookup-direct \
>>> call-libc-early-init write \
>>> thread_gscope_wait tls_init_tp \
>>> - debug-symbols minimal-malloc)
>>> + debug-symbols minimal-malloc audit)
>>
>> You can drop the #ifdef SHARED if you add this to rtld-routines.
Ack, I will change it.
>>
>>> +/* Call the la_objopen() from the audit modules for the link_map L on the
>>> + namespace identification NSID. If CHECK_AUDIT is set it will also check
>>> + if main mapping of the namespace is a audit modules. */
>>> +void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
>>
>> No () after function name (not sure?)
Ok, I will remove all the () on function descriptions.
>>
>> Should check_audit be named require_auditing? That would align better
>> with the l_auditing check, I think.
>
> Hmm. require_auditing is also not quite right. What about
> skip_auditing?
>
> And the comment should say which namespace (there's nsid and l->l_ns).
>
> Maybe the check should be moved into the caller because
> notify_audit_modules_of_loaded_object does not need it?
Yeah, this make more sense.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-12-10 13:45 ` Adhemerval Zanella
@ 2021-12-10 14:11 ` Adhemerval Zanella
2021-12-10 14:15 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-10 14:11 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 10/12/2021 10:45, Adhemerval Zanella wrote:
>
>
> On 10/12/2021 09:48, Florian Weimer wrote:
>> * Florian Weimer:
>>
>>> * Adhemerval Zanella:
>>>
>>>> diff --git a/elf/Makefile b/elf/Makefile
>>>> index 8f3e3a3602..80ed31edbe 100644
>>>> --- a/elf/Makefile
>>>> +++ b/elf/Makefile
>>>> @@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
>>>> exception sort-maps lookup-direct \
>>>> call-libc-early-init write \
>>>> thread_gscope_wait tls_init_tp \
>>>> - debug-symbols minimal-malloc)
>>>> + debug-symbols minimal-malloc audit)
>>>
>>> You can drop the #ifdef SHARED if you add this to rtld-routines.
>
> Ack, I will change it.
I recalled why I addon dl-routines: _dl_audit_pltexit is currently required
for static build as well. I can refactor it, but I think it simpler to
added the SHARED instead.
>
>>>
>>>> +/* Call the la_objopen() from the audit modules for the link_map L on the
>>>> + namespace identification NSID. If CHECK_AUDIT is set it will also check
>>>> + if main mapping of the namespace is a audit modules. */
>>>> +void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
>>>
>>> No () after function name (not sure?)
>
> Ok, I will remove all the () on function descriptions.
>
>>>
>>> Should check_audit be named require_auditing? That would align better
>>> with the l_auditing check, I think.
>>
>> Hmm. require_auditing is also not quite right. What about
>> skip_auditing?
>>
>> And the comment should say which namespace (there's nsid and l->l_ns).
>>
>> Maybe the check should be moved into the caller because
>> notify_audit_modules_of_loaded_object does not need it?
>
> Yeah, this make more sense.
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-12-10 14:11 ` Adhemerval Zanella
@ 2021-12-10 14:15 ` Florian Weimer
2021-12-10 14:41 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-10 14:15 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> On 10/12/2021 10:45, Adhemerval Zanella wrote:
>>
>>
>> On 10/12/2021 09:48, Florian Weimer wrote:
>>> * Florian Weimer:
>>>
>>>> * Adhemerval Zanella:
>>>>
>>>>> diff --git a/elf/Makefile b/elf/Makefile
>>>>> index 8f3e3a3602..80ed31edbe 100644
>>>>> --- a/elf/Makefile
>>>>> +++ b/elf/Makefile
>>>>> @@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
>>>>> exception sort-maps lookup-direct \
>>>>> call-libc-early-init write \
>>>>> thread_gscope_wait tls_init_tp \
>>>>> - debug-symbols minimal-malloc)
>>>>> + debug-symbols minimal-malloc audit)
>>>>
>>>> You can drop the #ifdef SHARED if you add this to rtld-routines.
>>
>> Ack, I will change it.
>
> I recalled why I addon dl-routines: _dl_audit_pltexit is currently required
> for static build as well. I can refactor it, but I think it simpler to
> added the SHARED instead.
I think the usual way is to add stubs to elf/dl-support.c, with a
comment why this is needed (different trampolines glued together in the
build system). This obviously can't be called for static executables.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 02/20] elf: Add _dl_audit_objopen
2021-12-10 14:15 ` Florian Weimer
@ 2021-12-10 14:41 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-10 14:41 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 10/12/2021 11:15, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> On 10/12/2021 10:45, Adhemerval Zanella wrote:
>>>
>>>
>>> On 10/12/2021 09:48, Florian Weimer wrote:
>>>> * Florian Weimer:
>>>>
>>>>> * Adhemerval Zanella:
>>>>>
>>>>>> diff --git a/elf/Makefile b/elf/Makefile
>>>>>> index 8f3e3a3602..80ed31edbe 100644
>>>>>> --- a/elf/Makefile
>>>>>> +++ b/elf/Makefile
>>>>>> @@ -36,7 +36,7 @@ dl-routines = $(addprefix dl-,load lookup object reloc deps \
>>>>>> exception sort-maps lookup-direct \
>>>>>> call-libc-early-init write \
>>>>>> thread_gscope_wait tls_init_tp \
>>>>>> - debug-symbols minimal-malloc)
>>>>>> + debug-symbols minimal-malloc audit)
>>>>>
>>>>> You can drop the #ifdef SHARED if you add this to rtld-routines.
>>>
>>> Ack, I will change it.
>>
>> I recalled why I addon dl-routines: _dl_audit_pltexit is currently required
>> for static build as well. I can refactor it, but I think it simpler to
>> added the SHARED instead.
>
> I think the usual way is to add stubs to elf/dl-support.c, with a
> comment why this is needed (different trampolines glued together in the
> build system). This obviously can't be called for static executables.
Ack.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 03/20] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
2021-11-15 18:37 ` [PATCH v6 01/20] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
2021-11-15 18:37 ` [PATCH v6 02/20] elf: Add _dl_audit_objopen Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-10 13:54 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 04/20] elf: Add _dl_audit_objsearch Adhemerval Zanella
` (16 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_activity() audit
callback.
Also for a new Lmid_t the namespace link_map list are empty, so it
requires to check if before using it. This can happen for when audit
module is used along with dlmopen.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/dl-audit.c | 23 ++++++++++++++++
elf/dl-close.c | 54 +++++++-------------------------------
elf/dl-load.c | 20 +-------------
elf/dl-open.c | 20 +-------------
elf/rtld.c | 31 ++--------------------
sysdeps/generic/ldsodefs.h | 7 +++++
6 files changed, 43 insertions(+), 112 deletions(-)
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index 24d8557f18..5fbc76a36c 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -19,6 +19,29 @@
#include <ldsodefs.h>
#ifdef SHARED
+void
+_dl_audit_activity_map (struct link_map *l, int action)
+{
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->activity != NULL)
+ afct->activity (&link_map_audit_state (l, cnt)->cookie, action);
+ afct = afct->next;
+ }
+}
+
+void
+_dl_audit_activity_nsid (Lmid_t nsid, int action)
+{
+ struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
+ if (__glibc_likely (GLRO(dl_naudit) == 0)
+ || head == NULL || head->l_auditing)
+ return;
+
+ _dl_audit_activity_map (head, action);
+}
+
void
_dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit)
{
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 4f5cfcc1c3..79dbb41094 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -472,25 +472,7 @@ _dl_close_worker (struct link_map *map, bool force)
#ifdef SHARED
/* Auditing checkpoint: we will start deleting objects. */
- if (__glibc_unlikely (do_audit))
- {
- struct link_map *head = ns->_ns_loaded;
- struct audit_ifaces *afct = GLRO(dl_audit);
- /* Do not call the functions for any auditing object. */
- if (head->l_auditing == 0)
- {
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- {
- struct auditstate *state = link_map_audit_state (head, cnt);
- afct->activity (&state->cookie, LA_ACT_DELETE);
- }
-
- afct = afct->next;
- }
- }
- }
+ _dl_audit_activity_nsid (nsid, LA_ACT_DELETE);
#endif
/* Notify the debugger we are about to remove some loaded objects. */
@@ -785,32 +767,14 @@ _dl_close_worker (struct link_map *map, bool force)
__rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
#ifdef SHARED
- /* Auditing checkpoint: we have deleted all objects. */
- if (__glibc_unlikely (do_audit))
- {
- struct link_map *head = ns->_ns_loaded;
- /* If head is NULL, the namespace has become empty, and the
- audit interface does not give us a way to signal
- LA_ACT_CONSISTENT for it because the first loaded module is
- used to identify the namespace.
-
- Furthermore, do not notify auditors of the cleanup of a
- failed audit module loading attempt. */
- if (head != NULL && head->l_auditing == 0)
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- {
- struct auditstate *state = link_map_audit_state (head, cnt);
- afct->activity (&state->cookie, LA_ACT_CONSISTENT);
- }
-
- afct = afct->next;
- }
- }
- }
+ /* Auditing checkpoint: we have deleted all objects. If head is NULL, the
+ namespace has become empty, and the audit interface does not give us a
+ way to signal LA_ACT_CONSISTENT for it because the first loaded module
+ is used to identify the namespace.
+
+ Furthermore, do not notify auditors of the cleanup of a failed audit
+ module loading attempt. */
+ _dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT);
#endif
if (__builtin_expect (ns->_ns_loaded == NULL, 0)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 907ab8f5f7..848d3e08eb 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1483,25 +1483,7 @@ cannot enable executable stack as shared object requires");
if (r->r_state == RT_CONSISTENT)
{
#ifdef SHARED
- /* Auditing checkpoint: we are going to add new objects. */
- if ((mode & __RTLD_AUDIT) == 0
- && __glibc_unlikely (GLRO(dl_naudit) > 0))
- {
- struct link_map *head = GL(dl_ns)[nsid]._ns_loaded;
- /* Do not call the functions for any auditing object. */
- if (head->l_auditing == 0)
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- afct->activity (&link_map_audit_state (head, cnt)->cookie,
- LA_ACT_ADD);
-
- afct = afct->next;
- }
- }
- }
+ _dl_audit_activity_nsid (nsid, LA_ACT_ADD);
#endif
/* Notify the debugger we have added some objects. We need to
diff --git a/elf/dl-open.c b/elf/dl-open.c
index 6ea5dd2457..e2f2e713e7 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -611,25 +611,7 @@ dl_open_worker_begin (void *a)
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0))
- {
- struct link_map *head = GL(dl_ns)[new->l_ns]._ns_loaded;
- /* Do not call the functions for any auditing object. */
- if (head->l_auditing == 0)
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- {
- struct auditstate *state = link_map_audit_state (head, cnt);
- afct->activity (&state->cookie, LA_ACT_CONSISTENT);
- }
-
- afct = afct->next;
- }
- }
- }
+ _dl_audit_activity_nsid (new->l_ns, LA_ACT_CONSISTENT);
#endif
/* Notify the debugger all new objects are now ready to go. */
diff --git a/elf/rtld.c b/elf/rtld.c
index 647f476957..dc20643ee9 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1759,18 +1759,7 @@ dl_main (const ElfW(Phdr) *phdr,
/* Auditing checkpoint: we are ready to signal that the initial map
is being constructed. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0))
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- afct->activity (&link_map_audit_state (main_map, cnt)->cookie,
- LA_ACT_ADD);
-
- afct = afct->next;
- }
- }
+ _dl_audit_activity_map (main_map, LA_ACT_ADD);
/* We have two ways to specify objects to preload: via environment
variable and via the file /etc/ld.so.preload. The latter can also
@@ -2451,23 +2440,7 @@ dl_main (const ElfW(Phdr) *phdr,
#ifdef SHARED
/* Auditing checkpoint: we have added all objects. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0))
- {
- struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
- /* Do not call the functions for any auditing object. */
- if (head->l_auditing == 0)
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->activity != NULL)
- afct->activity (&link_map_audit_state (head, cnt)->cookie,
- LA_ACT_CONSISTENT);
-
- afct = afct->next;
- }
- }
- }
+ _dl_audit_activity_nsid (LM_ID_BASE, LA_ACT_CONSISTENT);
#endif
/* Notify the debugger all new objects are now ready to go. We must re-get
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index dec592bf53..ea481cbe84 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1392,6 +1392,13 @@ link_map_audit_state (struct link_map *l, size_t index)
}
}
+/* Call the la_activity() from the audit modules from the link map L
+ and issues the ACTION argument. */
+void _dl_audit_activity_map (struct link_map *l, int action)
+ attribute_hidden;
+/* Call the la_activity() from the audit modules from the link map
+ from the namespace NSSID and issues the ACTION argument. */
+void _dl_audit_activity_nsid (Lmid_t nsid, int action);
/* Call the la_objopen() from the audit modules for the link_map L on the
namespace identification NSID. If CHECK_AUDIT is set it will also check
if main mapping of the namespace is a audit modules. */
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 03/20] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid
2021-11-15 18:37 ` [PATCH v6 03/20] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
@ 2021-12-10 13:54 ` Florian Weimer
2021-12-10 14:58 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-10 13:54 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-close.c b/elf/dl-close.c
> index 4f5cfcc1c3..79dbb41094 100644
> --- a/elf/dl-close.c
> +++ b/elf/dl-close.c
> + /* Auditing checkpoint: we have deleted all objects. If head is NULL, the
> + namespace has become empty, and the audit interface does not give us a
> + way to signal LA_ACT_CONSISTENT for it because the first loaded module
> + is used to identify the namespace.
> +
> + Furthermore, do not notify auditors of the cleanup of a failed audit
> + module loading attempt. */
> + _dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT);
> #endif
The comment is not really well-placed here. I think it belongs to the
head == NULL check in _dl_audit_activity_nsid.
>
> if (__builtin_expect (ns->_ns_loaded == NULL, 0)
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 907ab8f5f7..848d3e08eb 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -1483,25 +1483,7 @@ cannot enable executable stack as shared object requires");
> if (r->r_state == RT_CONSISTENT)
> {
> #ifdef SHARED
> - /* Auditing checkpoint: we are going to add new objects. */
> - if ((mode & __RTLD_AUDIT) == 0
> - && __glibc_unlikely (GLRO(dl_naudit) > 0))
The mode & __RTLD_AUDIT check is not included in
_dl_audit_activity_nsid.
> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
> index dec592bf53..ea481cbe84 100644
> --- a/sysdeps/generic/ldsodefs.h
> +++ b/sysdeps/generic/ldsodefs.h
> @@ -1392,6 +1392,13 @@ link_map_audit_state (struct link_map *l, size_t index)
> }
> }
>
> +/* Call the la_activity() from the audit modules from the link map L
> + and issues the ACTION argument. */
> +void _dl_audit_activity_map (struct link_map *l, int action)
> + attribute_hidden;
> +/* Call the la_activity() from the audit modules from the link map
> + from the namespace NSSID and issues the ACTION argument. */
> +void _dl_audit_activity_nsid (Lmid_t nsid, int action);
(), typo: NS[S]ID. Maybe we should have a general comment here that
these notifications are skipped for auditing namespaces?
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 03/20] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid
2021-12-10 13:54 ` Florian Weimer
@ 2021-12-10 14:58 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-10 14:58 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 10/12/2021 10:54, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-close.c b/elf/dl-close.c
>> index 4f5cfcc1c3..79dbb41094 100644
>> --- a/elf/dl-close.c
>> +++ b/elf/dl-close.c
>
>> + /* Auditing checkpoint: we have deleted all objects. If head is NULL, the
>> + namespace has become empty, and the audit interface does not give us a
>> + way to signal LA_ACT_CONSISTENT for it because the first loaded module
>> + is used to identify the namespace.
>> +
>> + Furthermore, do not notify auditors of the cleanup of a failed audit
>> + module loading attempt. */
>> + _dl_audit_activity_nsid (nsid, LA_ACT_CONSISTENT);
>> #endif
>
> The comment is not really well-placed here. I think it belongs to the
> head == NULL check in _dl_audit_activity_nsid.
>
Ack.
>>
>> if (__builtin_expect (ns->_ns_loaded == NULL, 0)
>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>> index 907ab8f5f7..848d3e08eb 100644
>> --- a/elf/dl-load.c
>> +++ b/elf/dl-load.c
>> @@ -1483,25 +1483,7 @@ cannot enable executable stack as shared object requires");
>> if (r->r_state == RT_CONSISTENT)
>> {
>> #ifdef SHARED
>> - /* Auditing checkpoint: we are going to add new objects. */
>> - if ((mode & __RTLD_AUDIT) == 0
>> - && __glibc_unlikely (GLRO(dl_naudit) > 0))
>
> The mode & __RTLD_AUDIT check is not included in
> _dl_audit_activity_nsid.
Ack, I have reinstated it on _dl_map_object_from_fd.
>
>> diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
>> index dec592bf53..ea481cbe84 100644
>> --- a/sysdeps/generic/ldsodefs.h
>> +++ b/sysdeps/generic/ldsodefs.h
>> @@ -1392,6 +1392,13 @@ link_map_audit_state (struct link_map *l, size_t index)
>> }
>> }
>>
>> +/* Call the la_activity() from the audit modules from the link map L
>> + and issues the ACTION argument. */
>> +void _dl_audit_activity_map (struct link_map *l, int action)
>> + attribute_hidden;
>> +/* Call the la_activity() from the audit modules from the link map
>> + from the namespace NSSID and issues the ACTION argument. */
>> +void _dl_audit_activity_nsid (Lmid_t nsid, int action);
>
> (), typo: NS[S]ID. Maybe we should have a general comment here that
> these notifications are skipped for auditing namespaces?
Ack. Yeah I think mention auditing namespaces is worth here.
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 04/20] elf: Add _dl_audit_objsearch
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (2 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 03/20] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-17 12:21 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 05/20] elf: Add _dl_audit_objclose Adhemerval Zanella
` (15 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_objsearch() audit
callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/dl-audit.c | 37 +++++++++++++++++++++++
elf/dl-load.c | 61 ++++----------------------------------
sysdeps/generic/ldsodefs.h | 2 ++
3 files changed, 44 insertions(+), 56 deletions(-)
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index 5fbc76a36c..de85ef1ddd 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -42,6 +42,43 @@ _dl_audit_activity_nsid (Lmid_t nsid, int action)
_dl_audit_activity_map (head, action);
}
+bool
+_dl_audit_objsearch (const char **name, const char **origname,
+ struct link_map *l, unsigned int code)
+{
+ if (__glibc_likely (GLRO(dl_naudit) == 0)
+ || l == NULL || l->l_auditing
+ || code == 0)
+ return true;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objsearch != NULL)
+ {
+ const char *before = *name;
+ struct auditstate *state = link_map_audit_state (l, cnt);
+ *name = afct->objsearch (*name, &state->cookie, code);
+ if (*name == NULL)
+ return false;
+
+ if (origname != NULL && before != *name
+ && strcmp (before, *name) != 0)
+ {
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+ _dl_debug_printf ("audit changed filename %s -> %s\n",
+ before, *name);
+
+ if (*origname == NULL)
+ *origname = before;
+ }
+ }
+ afct = afct->next;
+ }
+
+ return true;
+}
+
void
_dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit)
{
diff --git a/elf/dl-load.c b/elf/dl-load.c
index 848d3e08eb..e28893b779 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1595,33 +1595,8 @@ open_verify (const char *name, int fd,
#ifdef SHARED
/* Give the auditing libraries a chance. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0) && whatcode != 0
- && loader->l_auditing == 0)
- {
- const char *original_name = name;
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->objsearch != NULL)
- {
- struct auditstate *state = link_map_audit_state (loader, cnt);
- name = afct->objsearch (name, &state->cookie, whatcode);
- if (name == NULL)
- /* Ignore the path. */
- return -1;
- }
-
- afct = afct->next;
- }
-
- if (fd != -1 && name != original_name && strcmp (name, original_name))
- {
- /* An audit library changed what we're supposed to open,
- so FD no longer matches it. */
- __close_nocancel (fd);
- fd = -1;
- }
- }
+ if (!_dl_audit_objsearch (&name, NULL, loader, whatcode))
+ return -1;
#endif
if (fd == -1)
@@ -2059,36 +2034,10 @@ _dl_map_object (struct link_map *loader, const char *name,
#ifdef SHARED
/* Give the auditing libraries a chance to change the name before we
try anything. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0)
- && (loader == NULL || loader->l_auditing == 0))
+ if (!_dl_audit_objsearch (&name, &origname, loader, LA_SER_ORIG))
{
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->objsearch != NULL)
- {
- const char *before = name;
- struct auditstate *state = link_map_audit_state (loader, cnt);
- name = afct->objsearch (name, &state->cookie, LA_SER_ORIG);
- if (name == NULL)
- {
- /* Do not try anything further. */
- fd = -1;
- goto no_file;
- }
- if (before != name && strcmp (before, name) != 0)
- {
- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
- _dl_debug_printf ("audit changed filename %s -> %s\n",
- before, name);
-
- if (origname == NULL)
- origname = before;
- }
- }
-
- afct = afct->next;
- }
+ fd = -1;
+ goto no_file;
}
#endif
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index ea481cbe84..b1c76361d2 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1392,6 +1392,8 @@ link_map_audit_state (struct link_map *l, size_t index)
}
}
+bool _dl_audit_objsearch (const char **name, const char **origname,
+ struct link_map *l, unsigned int code);
/* Call the la_activity() from the audit modules from the link map L
and issues the ACTION argument. */
void _dl_audit_activity_map (struct link_map *l, int action)
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 04/20] elf: Add _dl_audit_objsearch
2021-11-15 18:37 ` [PATCH v6 04/20] elf: Add _dl_audit_objsearch Adhemerval Zanella
@ 2021-12-17 12:21 ` Florian Weimer
2021-12-17 16:09 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 12:21 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
> index 5fbc76a36c..de85ef1ddd 100644
> --- a/elf/dl-audit.c
> +++ b/elf/dl-audit.c
> @@ -42,6 +42,43 @@ _dl_audit_activity_nsid (Lmid_t nsid, int action)
> _dl_audit_activity_map (head, action);
> }
>
> +bool
> +_dl_audit_objsearch (const char **name, const char **origname,
> + struct link_map *l, unsigned int code)
> +{
> + if (__glibc_likely (GLRO(dl_naudit) == 0)
> + || l == NULL || l->l_auditing
> + || code == 0)
> + return true;
> +
> + struct audit_ifaces *afct = GLRO(dl_audit);
> + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
> + {
> + if (afct->objsearch != NULL)
> + {
> + const char *before = *name;
> + struct auditstate *state = link_map_audit_state (l, cnt);
> + *name = afct->objsearch (*name, &state->cookie, code);
> + if (*name == NULL)
> + return false;
> +
> + if (origname != NULL && before != *name
> + && strcmp (before, *name) != 0)
> + {
> + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
> + _dl_debug_printf ("audit changed filename %s -> %s\n",
> + before, *name);
> +
> + if (*origname == NULL)
> + *origname = before;
> + }
> + }
> + afct = afct->next;
> + }
> +
> + return true;
> +}
Sorry, I find the interface rather confusing. *name is an in-out
parameter, and *origname is an out parameter. This is not really clear
from their names.
I looked at the rest of elf/dl-load.c, and origname appears to be solely
used as an optimization, to avoid having to call add_name_to_object
twice. (add_name_to_object already filters out duplicate names.)
I think this interface should work:
const char *_dl_audit_objsearch (const char *name, struct link_map *l,
unsigned int code);
Callers need to check for NULL return values and stop loading the
object. Otherwise they have to register both names with
add_name_to_object.
What do you think?
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 04/20] elf: Add _dl_audit_objsearch
2021-12-17 12:21 ` Florian Weimer
@ 2021-12-17 16:09 ` Adhemerval Zanella
2021-12-17 16:12 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-17 16:09 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 17/12/2021 09:21, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
>> index 5fbc76a36c..de85ef1ddd 100644
>> --- a/elf/dl-audit.c
>> +++ b/elf/dl-audit.c
>> @@ -42,6 +42,43 @@ _dl_audit_activity_nsid (Lmid_t nsid, int action)
>> _dl_audit_activity_map (head, action);
>> }
>>
>> +bool
>> +_dl_audit_objsearch (const char **name, const char **origname,
>> + struct link_map *l, unsigned int code)
>> +{
>> + if (__glibc_likely (GLRO(dl_naudit) == 0)
>> + || l == NULL || l->l_auditing
>> + || code == 0)
>> + return true;
>> +
>> + struct audit_ifaces *afct = GLRO(dl_audit);
>> + for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
>> + {
>> + if (afct->objsearch != NULL)
>> + {
>> + const char *before = *name;
>> + struct auditstate *state = link_map_audit_state (l, cnt);
>> + *name = afct->objsearch (*name, &state->cookie, code);
>> + if (*name == NULL)
>> + return false;
>> +
>> + if (origname != NULL && before != *name
>> + && strcmp (before, *name) != 0)
>> + {
>> + if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
>> + _dl_debug_printf ("audit changed filename %s -> %s\n",
>> + before, *name);
>> +
>> + if (*origname == NULL)
>> + *origname = before;
>> + }
>> + }
>> + afct = afct->next;
>> + }
>> +
>> + return true;
>> +}
>
> Sorry, I find the interface rather confusing. *name is an in-out
> parameter, and *origname is an out parameter. This is not really clear
> from their names.
>
> I looked at the rest of elf/dl-load.c, and origname appears to be solely
> used as an optimization, to avoid having to call add_name_to_object
> twice. (add_name_to_object already filters out duplicate names.)
>
> I think this interface should work:
>
> const char *_dl_audit_objsearch (const char *name, struct link_map *l,
> unsigned int code);
>
> Callers need to check for NULL return values and stop loading the
> object. Otherwise they have to register both names with
> add_name_to_object.
>
> What do you think?
To replace the second command and keep the 'origname' update we will
need to pass it as an out argument (or return as a tuple from
_dl_audit_objsearch).
Also, by just returning a 'const char *' there is no indication that
audit modules are really handled, so we need to check on both sites
if there are really enabled (which should be ok).
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
[...]
}
What about:
const char *_dl_audit_objsearch (const char *name, const char **origname,
struct link_map *l, unsigned int code);
Where 'origname' is updated if non NULL?
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 04/20] elf: Add _dl_audit_objsearch
2021-12-17 16:09 ` Adhemerval Zanella
@ 2021-12-17 16:12 ` Florian Weimer
2021-12-17 16:33 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 16:12 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> To replace the second command and keep the 'origname' update we will
> need to pass it as an out argument (or return as a tuple from
> _dl_audit_objsearch).
Why is that? Isn't it going to be to the name variable in the caller?
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 04/20] elf: Add _dl_audit_objsearch
2021-12-17 16:12 ` Florian Weimer
@ 2021-12-17 16:33 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-17 16:33 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 17/12/2021 13:12, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> To replace the second command and keep the 'origname' update we will
>> need to pass it as an out argument (or return as a tuple from
>> _dl_audit_objsearch).
>
> Why is that? Isn't it going to be to the name variable in the caller?
>
> Thanks,
> Florian
>
Checking again it seems we can update it before, I will updated the patch.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 05/20] elf: Add _dl_audit_objclose
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (3 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 04/20] elf: Add _dl_audit_objsearch Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-17 16:29 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 06/20] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Adhemerval Zanella
` (14 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_objclose() audit
callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/dl-audit.c | 21 +++++++++++++++++++++
elf/dl-close.c | 20 +-------------------
elf/dl-fini.c | 16 +---------------
sysdeps/generic/ldsodefs.h | 1 +
4 files changed, 24 insertions(+), 34 deletions(-)
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index de85ef1ddd..ef34ff761c 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -99,4 +99,25 @@ _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit)
afct = afct->next;
}
}
+
+void
+_dl_audit_objclose (struct link_map *l, Lmid_t nsid)
+{
+ if (__glibc_likely (GLRO(dl_naudit) == 0)
+ || GL(dl_ns)[l->l_ns]._ns_loaded->l_auditing)
+ return;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->objclose != NULL)
+ {
+ struct auditstate *state= link_map_audit_state (l, cnt);
+ /* Return value is ignored. */
+ afct->objclose (&state->cookie);
+ }
+
+ afct = afct->next;
+ }
+}
#endif
diff --git a/elf/dl-close.c b/elf/dl-close.c
index 79dbb41094..df4e948498 100644
--- a/elf/dl-close.c
+++ b/elf/dl-close.c
@@ -260,9 +260,6 @@ _dl_close_worker (struct link_map *map, bool force)
_dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true);
/* Call all termination functions at once. */
-#ifdef SHARED
- bool do_audit = GLRO(dl_naudit) > 0 && !ns->_ns_loaded->l_auditing;
-#endif
bool unload_any = false;
bool scope_mem_left = false;
unsigned int unload_global = 0;
@@ -296,22 +293,7 @@ _dl_close_worker (struct link_map *map, bool force)
#ifdef SHARED
/* Auditing checkpoint: we remove an object. */
- if (__glibc_unlikely (do_audit))
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->objclose != NULL)
- {
- struct auditstate *state
- = link_map_audit_state (imap, cnt);
- /* Return value is ignored. */
- (void) afct->objclose (&state->cookie);
- }
-
- afct = afct->next;
- }
- }
+ _dl_audit_objclose (imap, nsid);
#endif
/* This object must not be used anymore. */
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index c683884c35..1720cfaeb8 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -146,21 +146,7 @@ _dl_fini (void)
#ifdef SHARED
/* Auditing checkpoint: another object closed. */
- if (!do_audit && __builtin_expect (GLRO(dl_naudit) > 0, 0))
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->objclose != NULL)
- {
- struct auditstate *state
- = link_map_audit_state (l, cnt);
- /* Return value is ignored. */
- (void) afct->objclose (&state->cookie);
- }
- afct = afct->next;
- }
- }
+ _dl_audit_objclose (l, ns);
#endif
}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index b1c76361d2..82dbc66d79 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1405,6 +1405,7 @@ void _dl_audit_activity_nsid (Lmid_t nsid, int action);
namespace identification NSID. If CHECK_AUDIT is set it will also check
if main mapping of the namespace is a audit modules. */
void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
+void _dl_audit_objclose (struct link_map *l, Lmid_t nsid);
#endif /* SHARED */
#if PTHREAD_IN_LIBC && defined SHARED
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 05/20] elf: Add _dl_audit_objclose
2021-11-15 18:37 ` [PATCH v6 05/20] elf: Add _dl_audit_objclose Adhemerval Zanella
@ 2021-12-17 16:29 ` Florian Weimer
2021-12-17 16:39 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 16:29 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
> index de85ef1ddd..ef34ff761c 100644
> --- a/elf/dl-audit.c
> +++ b/elf/dl-audit.c
> @@ -99,4 +99,25 @@ _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit)
> afct = afct->next;
> }
> }
> +
> +void
> +_dl_audit_objclose (struct link_map *l, Lmid_t nsid)
The nsid argument is unused, l->l_ns is used instead. Rest looks good.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 05/20] elf: Add _dl_audit_objclose
2021-12-17 16:29 ` Florian Weimer
@ 2021-12-17 16:39 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-17 16:39 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 17/12/2021 13:29, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
>> index de85ef1ddd..ef34ff761c 100644
>> --- a/elf/dl-audit.c
>> +++ b/elf/dl-audit.c
>> @@ -99,4 +99,25 @@ _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit)
>> afct = afct->next;
>> }
>> }
>> +
>> +void
>> +_dl_audit_objclose (struct link_map *l, Lmid_t nsid)
>
> The nsid argument is unused, l->l_ns is used instead. Rest looks good.
Ack.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 06/20] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (4 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 05/20] elf: Add _dl_audit_objclose Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-17 16:50 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 07/20] elf: Add _dl_audit_preinit Adhemerval Zanella
` (13 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_symbind{32,64}() audit
callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Versions | 1 +
elf/dl-audit.c | 122 +++++++++++++++++++++++++++++++++++++
elf/dl-sym-post.h | 47 +-------------
sysdeps/generic/ldsodefs.h | 6 ++
4 files changed, 130 insertions(+), 46 deletions(-)
diff --git a/elf/Versions b/elf/Versions
index 775aab62af..25e91339b5 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -55,6 +55,7 @@ ld {
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info;
_dl_deallocate_tls; _dl_make_stack_executable;
_dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf;
+ _dl_audit_symbind_alt;
_rtld_global; _rtld_global_ro;
# Only here for gdb while a better method is developed.
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index ef34ff761c..8e4c65fdaf 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -16,6 +16,7 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <assert.h>
#include <ldsodefs.h>
#ifdef SHARED
@@ -120,4 +121,125 @@ _dl_audit_objclose (struct link_map *l, Lmid_t nsid)
afct = afct->next;
}
}
+
+void
+_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
+ lookup_t result)
+{
+ if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0)
+ return;
+
+ const char *strtab = (const char *) D_PTR (result, l_info[DT_STRTAB]);
+ /* Compute index of the symbol entry in the symbol table of the DSO with
+ the definition. */
+ unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result, l_info[DT_SYMTAB]));
+
+ unsigned int altvalue = 0;
+ /* Synthesize a symbol record where the st_value field is the result. */
+ ElfW(Sym) sym = *ref;
+ sym.st_value = (ElfW(Addr)) *value;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ struct auditstate *match_audit = link_map_audit_state (l, cnt);
+ struct auditstate *result_audit = link_map_audit_state (result, cnt);
+ if (afct->symbind != NULL
+ && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
+ || ((result_audit->bindflags & LA_FLG_BINDTO)
+ != 0)))
+ {
+ unsigned int flags = altvalue | LA_SYMB_DLSYM;
+ uintptr_t new_value = afct->symbind (&sym, ndx,
+ &match_audit->cookie,
+ &result_audit->cookie,
+ &flags, strtab + ref->st_name);
+ if (new_value != (uintptr_t) sym.st_value)
+ {
+ altvalue = LA_SYMB_ALTVALUE;
+ sym.st_value = new_value;
+ }
+
+ afct = afct->next;
+ }
+
+ *value = (void *) sym.st_value;
+ }
+}
+rtld_hidden_def (_dl_audit_symbind_alt)
+
+void
+_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
+ const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
+ lookup_t result)
+{
+ reloc_result->bound = result;
+ /* Compute index of the symbol entry in the symbol table of the DSO with the
+ definition. */
+ reloc_result->boundndx = (defsym - (ElfW(Sym) *) D_PTR (result,
+ l_info[DT_SYMTAB]));
+
+ if ((l->l_audit_any_plt | result->l_audit_any_plt) == 0)
+ {
+ /* Set all bits since this symbol binding is not interesting. */
+ reloc_result->enterexit = (1u << DL_NNS) - 1;
+ return;
+ }
+
+ /* Synthesize a symbol record where the st_value field is the result. */
+ ElfW(Sym) sym = *defsym;
+ sym.st_value = DL_FIXUP_VALUE_ADDR (*value);
+
+ /* Keep track whether there is any interest in tracing the call in the lower
+ two bits. */
+ assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
+ assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
+ reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
+
+ const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]);
+
+ unsigned int flags = 0;
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ /* XXX Check whether both DSOs must request action or only one */
+ struct auditstate *l_state = link_map_audit_state (l, cnt);
+ struct auditstate *result_state = link_map_audit_state (result, cnt);
+ if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
+ && (result_state->bindflags & LA_FLG_BINDTO) != 0)
+ {
+ if (afct->symbind != NULL)
+ {
+ uintptr_t new_value = afct->symbind (&sym,
+ reloc_result->boundndx,
+ &l_state->cookie,
+ &result_state->cookie,
+ &flags,
+ strtab2 + defsym->st_name);
+ if (new_value != (uintptr_t) sym.st_value)
+ {
+ flags |= LA_SYMB_ALTVALUE;
+ sym.st_value = new_value;
+ }
+ }
+
+ /* Remember the results for every audit library and store a summary
+ in the first two bits. */
+ reloc_result->enterexit &= flags & (LA_SYMB_NOPLTENTER
+ | LA_SYMB_NOPLTEXIT);
+ reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER
+ | LA_SYMB_NOPLTEXIT))
+ << ((cnt + 1) * 2));
+ }
+ else
+ /* If the bind flags say this auditor is not interested, set the bits
+ manually. */
+ reloc_result->enterexit |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
+ << ((cnt + 1) * 2));
+ afct = afct->next;
+ }
+
+ reloc_result->flags = flags;
+ *value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+}
#endif
diff --git a/elf/dl-sym-post.h b/elf/dl-sym-post.h
index d68c2d2b1c..a11095d3e8 100644
--- a/elf/dl-sym-post.h
+++ b/elf/dl-sym-post.h
@@ -52,54 +52,9 @@ _dl_sym_post (lookup_t result, const ElfW(Sym) *ref, void *value,
tell us whether further auditing is wanted. */
if (__glibc_unlikely (GLRO(dl_naudit) > 0))
{
- const char *strtab = (const char *) D_PTR (result,
- l_info[DT_STRTAB]);
- /* Compute index of the symbol entry in the symbol table of
- the DSO with the definition. */
- unsigned int ndx = (ref - (ElfW(Sym) *) D_PTR (result,
- l_info[DT_SYMTAB]));
-
if (match == NULL)
match = _dl_sym_find_caller_link_map (caller);
-
- if ((match->l_audit_any_plt | result->l_audit_any_plt) != 0)
- {
- unsigned int altvalue = 0;
- struct audit_ifaces *afct = GLRO(dl_audit);
- /* Synthesize a symbol record where the st_value field is
- the result. */
- ElfW(Sym) sym = *ref;
- sym.st_value = (ElfW(Addr)) value;
-
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- struct auditstate *match_audit
- = link_map_audit_state (match, cnt);
- struct auditstate *result_audit
- = link_map_audit_state (result, cnt);
- if (afct->symbind != NULL
- && ((match_audit->bindflags & LA_FLG_BINDFROM) != 0
- || ((result_audit->bindflags & LA_FLG_BINDTO)
- != 0)))
- {
- unsigned int flags = altvalue | LA_SYMB_DLSYM;
- uintptr_t new_value
- = afct->symbind (&sym, ndx,
- &match_audit->cookie,
- &result_audit->cookie,
- &flags, strtab + ref->st_name);
- if (new_value != (uintptr_t) sym.st_value)
- {
- altvalue = LA_SYMB_ALTVALUE;
- sym.st_value = new_value;
- }
- }
-
- afct = afct->next;
- }
-
- value = (void *) sym.st_value;
- }
+ _dl_audit_symbind_alt (match, ref, &value, result);
}
#endif
return value;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 82dbc66d79..dccd43b39d 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1406,6 +1406,12 @@ void _dl_audit_activity_nsid (Lmid_t nsid, int action);
if main mapping of the namespace is a audit modules. */
void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
void _dl_audit_objclose (struct link_map *l, Lmid_t nsid);
+void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
+ const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
+ lookup_t result);
+void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,
+ void **value, lookup_t result);
+rtld_hidden_proto (_dl_audit_symbind_alt)
#endif /* SHARED */
#if PTHREAD_IN_LIBC && defined SHARED
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 06/20] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind
2021-11-15 18:37 ` [PATCH v6 06/20] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Adhemerval Zanella
@ 2021-12-17 16:50 ` Florian Weimer
2021-12-17 18:46 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 16:50 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
> index ef34ff761c..8e4c65fdaf 100644
> --- a/elf/dl-audit.c
> +++ b/elf/dl-audit.c
> @@ -16,6 +16,7 @@
> +void
> +_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
> + lookup_t result)
> +_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
> + const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
> + lookup_t result)
> +{
The call to _dl_audit_symbind is added in patch 10 of the series (“elf:
Avoid unnecessary slowdown from profiling with audit (BZ#15533)”).
But I would expected this patch here to replace the copy in
elf/dl-runtime.c.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 06/20] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind
2021-12-17 16:50 ` Florian Weimer
@ 2021-12-17 18:46 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-17 18:46 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 17/12/2021 13:50, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
>> index ef34ff761c..8e4c65fdaf 100644
>> --- a/elf/dl-audit.c
>> +++ b/elf/dl-audit.c
>> @@ -16,6 +16,7 @@
>
>> +void
>> +_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
>> + lookup_t result)
>
>> +_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
>> + const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
>> + lookup_t result)
>> +{
>
> The call to _dl_audit_symbind is added in patch 10 of the series (“elf:
> Avoid unnecessary slowdown from profiling with audit (BZ#15533)”).
>
> But I would expected this patch here to replace the copy in
> elf/dl-runtime.c.
It does make sense, ack.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 07/20] elf: Add _dl_audit_preinit
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (5 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 06/20] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-17 17:13 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 08/20] elf: Add _dl_audit_pltenter Adhemerval Zanella
` (12 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_preinit() audit
callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
csu/libc-start.c | 23 +++--------------------
elf/Versions | 2 +-
elf/dl-audit.c | 15 +++++++++++++++
sysdeps/generic/ldsodefs.h | 1 +
4 files changed, 20 insertions(+), 21 deletions(-)
diff --git a/csu/libc-start.c b/csu/libc-start.c
index 0350b006fd..d01e57ea59 100644
--- a/csu/libc-start.c
+++ b/csu/libc-start.c
@@ -377,32 +377,15 @@ LIBC_START_MAIN (int (*main) (int, char **, char ** MAIN_AUXVEC_DECL),
/* This is a current program. Use the dynamic segment to find
constructors. */
call_init (argc, argv, __environ);
-#else /* !SHARED */
- call_init (argc, argv, __environ);
-#endif /* SHARED */
-#ifdef SHARED
/* Auditing checkpoint: we have a new object. */
- if (__glibc_unlikely (GLRO(dl_naudit) > 0))
- {
- struct audit_ifaces *afct = GLRO(dl_audit);
- struct link_map *head = GL(dl_ns)[LM_ID_BASE]._ns_loaded;
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->preinit != NULL)
- afct->preinit (&link_map_audit_state (head, cnt)->cookie);
-
- afct = afct->next;
- }
- }
-#endif
+ _dl_audit_preinit (GL(dl_ns)[LM_ID_BASE]._ns_loaded);
-#ifdef SHARED
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_IMPCALLS))
GLRO(dl_debug_printf) ("\ntransferring control: %s\n\n", argv[0]);
-#endif
+#else /* !SHARED */
+ call_init (argc, argv, __environ);
-#ifndef SHARED
_dl_debug_initialize (0, LM_ID_BASE);
#endif
diff --git a/elf/Versions b/elf/Versions
index 25e91339b5..bfe1aec293 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -55,7 +55,7 @@ ld {
_dl_argv; _dl_find_dso_for_object; _dl_get_tls_static_info;
_dl_deallocate_tls; _dl_make_stack_executable;
_dl_rtld_di_serinfo; _dl_starting_up; _dl_fatal_printf;
- _dl_audit_symbind_alt;
+ _dl_audit_symbind_alt; _dl_audit_preinit;
_rtld_global; _rtld_global_ro;
# Only here for gdb while a better method is developed.
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index 8e4c65fdaf..a968cbde16 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -122,6 +122,21 @@ _dl_audit_objclose (struct link_map *l, Lmid_t nsid)
}
}
+void
+_dl_audit_preinit (struct link_map *l)
+{
+ if (__glibc_likely (GLRO(dl_naudit) < 0))
+ return;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->preinit != NULL)
+ afct->preinit (&link_map_audit_state (l, cnt)->cookie);
+ afct = afct->next;
+ }
+}
+
void
_dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
lookup_t result)
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index dccd43b39d..b7ed59bf51 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1406,6 +1406,7 @@ void _dl_audit_activity_nsid (Lmid_t nsid, int action);
if main mapping of the namespace is a audit modules. */
void _dl_audit_objopen (struct link_map *l, Lmid_t nsid, bool check_audit);
void _dl_audit_objclose (struct link_map *l, Lmid_t nsid);
+void _dl_audit_preinit (struct link_map *l);
void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
lookup_t result);
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 07/20] elf: Add _dl_audit_preinit
2021-11-15 18:37 ` [PATCH v6 07/20] elf: Add _dl_audit_preinit Adhemerval Zanella
@ 2021-12-17 17:13 ` Florian Weimer
2021-12-17 18:54 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 17:13 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
> index 8e4c65fdaf..a968cbde16 100644
> --- a/elf/dl-audit.c
> +++ b/elf/dl-audit.c
> @@ -122,6 +122,21 @@ _dl_audit_objclose (struct link_map *l, Lmid_t nsid)
> }
> }
>
> +void
> +_dl_audit_preinit (struct link_map *l)
> +{
> + if (__glibc_likely (GLRO(dl_naudit) < 0))
> + return;
Typo, should be == 0, I think.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 07/20] elf: Add _dl_audit_preinit
2021-12-17 17:13 ` Florian Weimer
@ 2021-12-17 18:54 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-17 18:54 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 17/12/2021 14:13, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
>> index 8e4c65fdaf..a968cbde16 100644
>> --- a/elf/dl-audit.c
>> +++ b/elf/dl-audit.c
>> @@ -122,6 +122,21 @@ _dl_audit_objclose (struct link_map *l, Lmid_t nsid)
>> }
>> }
>>
>> +void
>> +_dl_audit_preinit (struct link_map *l)
>> +{
>> + if (__glibc_likely (GLRO(dl_naudit) < 0))
>> + return;
>
> Typo, should be == 0, I think.
Ack.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 08/20] elf: Add _dl_audit_pltenter
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (6 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 07/20] elf: Add _dl_audit_preinit Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-17 17:21 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 09/20] elf: Add _dl_audit_pltexit Adhemerval Zanella
` (11 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_pltenter() audit
callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/dl-audit.c | 77 ++++++++++++++++++++++++++++++++++++++
elf/dl-runtime.c | 73 +-----------------------------------
sysdeps/generic/ldsodefs.h | 3 ++
3 files changed, 81 insertions(+), 72 deletions(-)
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index a968cbde16..7d410bc128 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -17,7 +17,9 @@
<https://www.gnu.org/licenses/>. */
#include <assert.h>
+#include <link.h>
#include <ldsodefs.h>
+#include <dl-machine.h>
#ifdef SHARED
void
@@ -257,4 +259,79 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
reloc_result->flags = flags;
*value = DL_FIXUP_ADDR_VALUE (sym.st_value);
}
+
+void
+_dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
+ DL_FIXUP_VALUE_TYPE *value, void *regs, long int *framesize)
+{
+ /* Don't do anything if no auditor wants to intercept this call. */
+ if (GLRO(dl_naudit) == 0
+ || (reloc_result->enterexit & LA_SYMB_NOPLTENTER))
+ return;
+
+ /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
+ initialized earlier in this function or in another thread. */
+ assert (DL_FIXUP_VALUE_CODE_ADDR (*value) != 0);
+ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
+ l_info[DT_SYMTAB])
+ + reloc_result->boundndx);
+
+ /* Set up the sym parameter. */
+ ElfW(Sym) sym = *defsym;
+ sym.st_value = DL_FIXUP_VALUE_ADDR (*value);
+
+ /* Get the symbol name. */
+ const char *strtab = (const void *) D_PTR (reloc_result->bound,
+ l_info[DT_STRTAB]);
+ const char *symname = strtab + sym.st_name;
+
+ /* Keep track of overwritten addresses. */
+ unsigned int flags = reloc_result->flags;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->ARCH_LA_PLTENTER != NULL
+ && (reloc_result->enterexit
+ & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
+ {
+ long int new_framesize = -1;
+ struct auditstate *l_state = link_map_audit_state (l, cnt);
+ struct auditstate *bound_state
+ = link_map_audit_state (reloc_result->bound, cnt);
+ uintptr_t new_value
+ = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
+ &l_state->cookie, &bound_state->cookie,
+ regs, &flags, symname, &new_framesize);
+ if (new_value != (uintptr_t) sym.st_value)
+ {
+ flags |= LA_SYMB_ALTVALUE;
+ sym.st_value = new_value;
+ }
+
+ /* Remember the results for every audit library and store a summary
+ in the first two bits. */
+ reloc_result->enterexit |= ((flags & (LA_SYMB_NOPLTENTER
+ | LA_SYMB_NOPLTEXIT))
+ << (2 * (cnt + 1)));
+
+ if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
+ << (2 * (cnt + 1))))
+ == 0 && new_framesize != -1 && *framesize != -2)
+ {
+ /* If this is the first call providing information, use it. */
+ if (*framesize == -1)
+ *framesize = new_framesize;
+ /* If two pltenter calls provide conflicting information, use
+ the larger value. */
+ else if (new_framesize != *framesize)
+ *framesize = MAX (new_framesize, *framesize);
+ }
+ }
+
+ afct = afct->next;
+ }
+
+ *value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+}
#endif
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 61c260ddb8..1db5e211db 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -397,78 +397,7 @@ _dl_profile_fixup (
#ifdef SHARED
/* Auditing checkpoint: report the PLT entering and allow the
auditors to change the value. */
- if (GLRO(dl_naudit) > 0
- /* Don't do anything if no auditor wants to intercept this call. */
- && (reloc_result->enterexit & LA_SYMB_NOPLTENTER) == 0)
- {
- /* Sanity check: DL_FIXUP_VALUE_CODE_ADDR (value) should have been
- initialized earlier in this function or in another thread. */
- assert (DL_FIXUP_VALUE_CODE_ADDR (value) != 0);
- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
- l_info[DT_SYMTAB])
- + reloc_result->boundndx);
-
- /* Set up the sym parameter. */
- ElfW(Sym) sym = *defsym;
- sym.st_value = DL_FIXUP_VALUE_ADDR (value);
-
- /* Get the symbol name. */
- const char *strtab = (const void *) D_PTR (reloc_result->bound,
- l_info[DT_STRTAB]);
- const char *symname = strtab + sym.st_name;
-
- /* Keep track of overwritten addresses. */
- unsigned int flags = reloc_result->flags;
-
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->ARCH_LA_PLTENTER != NULL
- && (reloc_result->enterexit
- & (LA_SYMB_NOPLTENTER << (2 * (cnt + 1)))) == 0)
- {
- long int new_framesize = -1;
- struct auditstate *l_state = link_map_audit_state (l, cnt);
- struct auditstate *bound_state
- = link_map_audit_state (reloc_result->bound, cnt);
- uintptr_t new_value
- = afct->ARCH_LA_PLTENTER (&sym, reloc_result->boundndx,
- &l_state->cookie,
- &bound_state->cookie,
- regs, &flags, symname,
- &new_framesize);
- if (new_value != (uintptr_t) sym.st_value)
- {
- flags |= LA_SYMB_ALTVALUE;
- sym.st_value = new_value;
- }
-
- /* Remember the results for every audit library and
- store a summary in the first two bits. */
- reloc_result->enterexit
- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
- << (2 * (cnt + 1)));
-
- if ((reloc_result->enterexit & (LA_SYMB_NOPLTEXIT
- << (2 * (cnt + 1))))
- == 0 && new_framesize != -1 && framesize != -2)
- {
- /* If this is the first call providing information,
- use it. */
- if (framesize == -1)
- framesize = new_framesize;
- /* If two pltenter calls provide conflicting information,
- use the larger value. */
- else if (new_framesize != framesize)
- framesize = MAX (new_framesize, framesize);
- }
- }
-
- afct = afct->next;
- }
-
- value = DL_FIXUP_ADDR_VALUE (sym.st_value);
- }
+ _dl_audit_pltenter (l, reloc_result, &value, regs, &framesize);
#endif
/* Store the frame size information. */
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index b7ed59bf51..abff37ab86 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1413,6 +1413,9 @@ void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,
void **value, lookup_t result);
rtld_hidden_proto (_dl_audit_symbind_alt)
+void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
+ DL_FIXUP_VALUE_TYPE *value, void *regs,
+ long int *framesize);
#endif /* SHARED */
#if PTHREAD_IN_LIBC && defined SHARED
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 08/20] elf: Add _dl_audit_pltenter
2021-11-15 18:37 ` [PATCH v6 08/20] elf: Add _dl_audit_pltenter Adhemerval Zanella
@ 2021-12-17 17:21 ` Florian Weimer
0 siblings, 0 replies; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 17:21 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> It consolidates the code required to call la_pltenter() audit
> callback.
>
> Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
> ---
> elf/dl-audit.c | 77 ++++++++++++++++++++++++++++++++++++++
> elf/dl-runtime.c | 73 +-----------------------------------
> sysdeps/generic/ldsodefs.h | 3 ++
> 3 files changed, 81 insertions(+), 72 deletions(-)
This one looks okay to me.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 09/20] elf: Add _dl_audit_pltexit
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (7 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 08/20] elf: Add _dl_audit_pltenter Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-17 17:43 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 10/20] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
` (10 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
It consolidates the code required to call la_pltexit() audit
callback.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/dl-audit.c | 56 ++++++++++++++++++++
elf/dl-runtime.c | 62 ++---------------------
sysdeps/aarch64/dl-trampoline.S | 2 +-
sysdeps/alpha/dl-trampoline.S | 8 +--
sysdeps/arm/dl-trampoline.S | 2 +-
sysdeps/generic/dl-fixup-attribute.h | 24 +++++++++
sysdeps/generic/ldsodefs.h | 5 ++
sysdeps/hppa/dl-runtime.c | 2 +-
sysdeps/hppa/dl-trampoline.S | 6 +--
sysdeps/i386/dl-fixup-attribute.h | 30 +++++++++++
sysdeps/i386/dl-machine.h | 23 ---------
sysdeps/i386/dl-trampoline.S | 2 +-
sysdeps/ia64/dl-trampoline.S | 16 +++---
sysdeps/m68k/dl-trampoline.S | 2 +-
sysdeps/powerpc/powerpc64/dl-trampoline.S | 4 +-
sysdeps/s390/s390-32/dl-trampoline.h | 4 +-
sysdeps/s390/s390-64/dl-trampoline.h | 2 +-
sysdeps/sh/dl-trampoline.S | 4 +-
sysdeps/sparc/sparc32/dl-trampoline.S | 2 +-
sysdeps/sparc/sparc64/dl-trampoline.S | 2 +-
sysdeps/x86_64/dl-runtime.h | 2 +-
sysdeps/x86_64/dl-trampoline.h | 6 +--
22 files changed, 151 insertions(+), 115 deletions(-)
create mode 100644 sysdeps/generic/dl-fixup-attribute.h
create mode 100644 sysdeps/i386/dl-fixup-attribute.h
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index 7d410bc128..c3569cb357 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -20,6 +20,8 @@
#include <link.h>
#include <ldsodefs.h>
#include <dl-machine.h>
+#include <dl-runtime.h>
+#include <dl-fixup-attribute.h>
#ifdef SHARED
void
@@ -335,3 +337,57 @@ _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
*value = DL_FIXUP_ADDR_VALUE (sym.st_value);
}
#endif
+
+#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
+ || ELF_MACHINE_NO_REL
+# define PLTREL ElfW(Rela)
+#else
+# define PLTREL ElfW(Rel)
+#endif
+
+void
+DL_ARCH_FIXUP_ATTRIBUTE
+_dl_audit_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
+ const void *inregs, void *outregs)
+{
+#ifdef SHARED
+ const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
+
+ /* This is the address in the array where we store the result of previous
+ relocations. */
+ // XXX Maybe the bound information must be stored on the stack since
+ // XXX with bind_not a new value could have been stored in the meantime.
+ struct reloc_result *reloc_result =
+ &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
+ ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
+ l_info[DT_SYMTAB])
+ + reloc_result->boundndx);
+
+ /* Set up the sym parameter. */
+ ElfW(Sym) sym = *defsym;
+ sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
+
+ /* Get the symbol name. */
+ const char *strtab = (const void *) D_PTR (reloc_result->bound,
+ l_info[DT_STRTAB]);
+ const char *symname = strtab + sym.st_name;
+
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ if (afct->ARCH_LA_PLTEXIT != NULL
+ && (reloc_result->enterexit
+ & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
+ {
+ struct auditstate *l_state = link_map_audit_state (l, cnt);
+ struct auditstate *bound_state
+ = link_map_audit_state (reloc_result->bound, cnt);
+ afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
+ &l_state->cookie, &bound_state->cookie,
+ inregs, outregs, symname);
+ }
+
+ afct = afct->next;
+ }
+#endif
+}
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 1db5e211db..03da689503 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -16,8 +16,6 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
-#define IN_DL_RUNTIME 1 /* This can be tested in dl-machine.h. */
-
#include <alloca.h>
#include <assert.h>
#include <stdlib.h>
@@ -38,12 +36,6 @@
# define PLTREL ElfW(Rel)
#endif
-/* The fixup functions might have need special attributes. If none
- are provided define the macro as empty. */
-#ifndef ARCH_FIXUP_ATTRIBUTE
-# define ARCH_FIXUP_ATTRIBUTE
-#endif
-
/* This function is called through a special trampoline from the PLT the
first time each PLT entry is called. We must perform the relocation
specified in the PLT of the given shared object, and return the resolved
@@ -52,7 +44,7 @@
function. */
DL_FIXUP_VALUE_TYPE
-attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE
_dl_fixup (
# ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
@@ -148,7 +140,8 @@ _dl_fixup (
#ifndef PROF
DL_FIXUP_VALUE_TYPE
-__attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+__attribute ((noinline))
+DL_ARCH_FIXUP_ATTRIBUTE
_dl_profile_fixup (
#ifdef ELF_MACHINE_RUNTIME_FIXUP_ARGS
ELF_MACHINE_RUNTIME_FIXUP_ARGS,
@@ -409,52 +402,3 @@ _dl_profile_fixup (
}
#endif /* PROF */
-
-
-#include <stdio.h>
-void
-ARCH_FIXUP_ATTRIBUTE
-_dl_call_pltexit (struct link_map *l, ElfW(Word) reloc_arg,
- const void *inregs, void *outregs)
-{
-#ifdef SHARED
- const uintptr_t pltgot = (uintptr_t) D_PTR (l, l_info[DT_PLTGOT]);
-
- /* This is the address in the array where we store the result of previous
- relocations. */
- // XXX Maybe the bound information must be stored on the stack since
- // XXX with bind_not a new value could have been stored in the meantime.
- struct reloc_result *reloc_result =
- &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
- ElfW(Sym) *defsym = ((ElfW(Sym) *) D_PTR (reloc_result->bound,
- l_info[DT_SYMTAB])
- + reloc_result->boundndx);
-
- /* Set up the sym parameter. */
- ElfW(Sym) sym = *defsym;
- sym.st_value = DL_FIXUP_VALUE_ADDR (reloc_result->addr);
-
- /* Get the symbol name. */
- const char *strtab = (const void *) D_PTR (reloc_result->bound,
- l_info[DT_STRTAB]);
- const char *symname = strtab + sym.st_name;
-
- struct audit_ifaces *afct = GLRO(dl_audit);
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- if (afct->ARCH_LA_PLTEXIT != NULL
- && (reloc_result->enterexit
- & (LA_SYMB_NOPLTEXIT >> (2 * cnt))) == 0)
- {
- struct auditstate *l_state = link_map_audit_state (l, cnt);
- struct auditstate *bound_state
- = link_map_audit_state (reloc_result->bound, cnt);
- afct->ARCH_LA_PLTEXIT (&sym, reloc_result->boundndx,
- &l_state->cookie, &bound_state->cookie,
- inregs, outregs, symname);
- }
-
- afct = afct->next;
- }
-#endif
-}
diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S
index a7e9267c1c..9b352b1d0f 100644
--- a/sysdeps/aarch64/dl-trampoline.S
+++ b/sysdeps/aarch64/dl-trampoline.S
@@ -293,7 +293,7 @@ _dl_runtime_profile:
ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
add x2, x29, #OFFSET_RG
add x3, x29, #OFFSET_RV
- bl _dl_call_pltexit
+ bl _dl_audit_pltexit
ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
diff --git a/sysdeps/alpha/dl-trampoline.S b/sysdeps/alpha/dl-trampoline.S
index 9dfce5b083..55380d48ad 100644
--- a/sysdeps/alpha/dl-trampoline.S
+++ b/sysdeps/alpha/dl-trampoline.S
@@ -187,7 +187,7 @@ _dl_runtime_profile_new:
jsr $26, ($27), 0
ldgp $29, 0($26)
- /* Set up for call to _dl_call_pltexit. */
+ /* Set up for call to _dl_audit_pltexit. */
ldq $16, 16*8($15)
ldq $17, 17*8($15)
stq $0, 16*8($15)
@@ -196,7 +196,7 @@ _dl_runtime_profile_new:
lda $19, 16*8($15)
stt $f0, 18*8($15)
stt $f1, 19*8($15)
- bsr $26, _dl_call_pltexit !samegp
+ bsr $26, _dl_audit_pltexit !samegp
mov $15, $30
cfi_def_cfa_register (30)
@@ -518,7 +518,7 @@ _dl_runtime_profile_old:
jsr $26, ($27), 0
ldgp $29, 0($26)
- /* Set up for call to _dl_call_pltexit. */
+ /* Set up for call to _dl_audit_pltexit. */
ldq $16, 48*8($15)
ldq $17, 49*8($15)
stq $0, 46*8($15)
@@ -527,7 +527,7 @@ _dl_runtime_profile_old:
lda $19, 46*8($15)
stt $f0, 48*8($15)
stt $f1, 49*8($15)
- bsr $26, _dl_call_pltexit !samegp
+ bsr $26, _dl_audit_pltexit !samegp
mov $15, $30
cfi_def_cfa_register (30)
diff --git a/sysdeps/arm/dl-trampoline.S b/sysdeps/arm/dl-trampoline.S
index 70105308ca..a2d322706d 100644
--- a/sysdeps/arm/dl-trampoline.S
+++ b/sysdeps/arm/dl-trampoline.S
@@ -194,7 +194,7 @@ _dl_runtime_profile:
ldmia ip, {r0,r1}
add r2, r7, #72
add r3, r7, #0
- bl _dl_call_pltexit
+ bl _dl_audit_pltexit
@ Return to caller.
ldmia r7, {r0-r3}
diff --git a/sysdeps/generic/dl-fixup-attribute.h b/sysdeps/generic/dl-fixup-attribute.h
new file mode 100644
index 0000000000..aa92169b70
--- /dev/null
+++ b/sysdeps/generic/dl-fixup-attribute.h
@@ -0,0 +1,24 @@
+/* ABI specifics for lazy resolution functions.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_FIXUP_ATTRIBUTE_H
+#define _DL_FIXUP_ATTRIBUTE_H
+
+#define DL_ARCH_FIXUP_ATTRIBUTE
+
+#endif
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index abff37ab86..d419a62dbd 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -35,6 +35,7 @@
#include <link.h>
#include <dl-lookupcfg.h>
#include <dl-sysdep.h>
+#include <dl-fixup-attribute.h>
#include <libc-lock.h>
#include <hp-timing.h>
#include <tls.h>
@@ -1416,6 +1417,10 @@ rtld_hidden_proto (_dl_audit_symbind_alt)
void _dl_audit_pltenter (struct link_map *l, struct reloc_result *reloc_result,
DL_FIXUP_VALUE_TYPE *value, void *regs,
long int *framesize);
+void DL_ARCH_FIXUP_ATTRIBUTE _dl_audit_pltexit (struct link_map *l,
+ ElfW(Word) reloc_arg,
+ const void *inregs,
+ void *outregs);
#endif /* SHARED */
#if PTHREAD_IN_LIBC && defined SHARED
diff --git a/sysdeps/hppa/dl-runtime.c b/sysdeps/hppa/dl-runtime.c
index e7fbb7417d..b60a6b5390 100644
--- a/sysdeps/hppa/dl-runtime.c
+++ b/sysdeps/hppa/dl-runtime.c
@@ -26,7 +26,7 @@
_dl_fixup with the relocation offset. */
ElfW(Word)
-attribute_hidden __attribute ((noinline)) ARCH_FIXUP_ATTRIBUTE
+attribute_hidden __attribute ((noinline)) DL_ARCH_FIXUP_ATTRIBUTE
_dl_fix_reloc_arg (struct fdesc *fptr, struct link_map *l)
{
Elf32_Addr l_addr, iplt, jmprel, end_jmprel, r_type;
diff --git a/sysdeps/hppa/dl-trampoline.S b/sysdeps/hppa/dl-trampoline.S
index cb18ea7eab..c54879bae0 100644
--- a/sysdeps/hppa/dl-trampoline.S
+++ b/sysdeps/hppa/dl-trampoline.S
@@ -300,7 +300,7 @@ L(cont):
ldw -4(%sp),%r1
copy %r1, %sp
- /* Arguments to _dl_call_pltexit */
+ /* Arguments to _dl_audit_pltexit */
ldw -116(%sp), %r26 /* (1) got[1] == struct link_map */
ldw -120(%sp), %r25 /* (2) reloc offsets */
ldo -56(%sp), %r24 /* (3) *La_hppa_regs */
@@ -312,8 +312,8 @@ L(cont):
ldo -128(%sp), %r1
fstd %fr4,0(%r1)
- /* Call _dl_call_pltexit */
- bl _dl_call_pltexit,%rp
+ /* Call _dl_audit_pltexit */
+ bl _dl_audit_pltexit,%rp
nop
/* Restore *La_hppa_retval */
diff --git a/sysdeps/i386/dl-fixup-attribute.h b/sysdeps/i386/dl-fixup-attribute.h
new file mode 100644
index 0000000000..c10e9936f4
--- /dev/null
+++ b/sysdeps/i386/dl-fixup-attribute.h
@@ -0,0 +1,30 @@
+/* ABI specifics for lazy resolution functions. i386 version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _DL_FIXUP_ATTRIBUTE_H
+#define _DL_FIXUP_ATTRIBUTE_H
+
+/* We cannot use this scheme for profiling because the _mcount call destroys
+ the passed register information. */
+#ifndef PROF
+# define DL_ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused))
+#else
+# define DL_ARCH_FIXUP_ATTRIBUTE
+#endif
+
+#endif
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 169bed50ff..2f0dbc27a9 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -115,29 +115,6 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
return lazy;
}
-#ifdef IN_DL_RUNTIME
-
-# ifndef PROF
-/* We add a declaration of this function here so that in dl-runtime.c
- the ELF_MACHINE_RUNTIME_TRAMPOLINE macro really can pass the parameters
- in registers.
-
- We cannot use this scheme for profiling because the _mcount call
- destroys the passed register information. */
-#define ARCH_FIXUP_ATTRIBUTE __attribute__ ((regparm (3), stdcall, unused))
-
-extern ElfW(Addr) _dl_fixup (struct link_map *l,
- ElfW(Word) reloc_offset)
- ARCH_FIXUP_ATTRIBUTE;
-extern ElfW(Addr) _dl_profile_fixup (struct link_map *l,
- ElfW(Word) reloc_offset,
- ElfW(Addr) retaddr, void *regs,
- long int *framesizep)
- ARCH_FIXUP_ATTRIBUTE;
-# endif
-
-#endif
-
/* Mask identifying addresses reserved for the user program,
where the dynamic linker should not map anything. */
#define ELF_MACHINE_USER_ADDRESS_MASK 0xf0000000UL
diff --git a/sysdeps/i386/dl-trampoline.S b/sysdeps/i386/dl-trampoline.S
index 5669ab18f5..1e555de32e 100644
--- a/sysdeps/i386/dl-trampoline.S
+++ b/sysdeps/i386/dl-trampoline.S
@@ -252,7 +252,7 @@ _dl_runtime_profile:
movl (LRV_SIZE + 4 + LR_SIZE)(%esp), %eax
# PLT1
movl (LRV_SIZE + 4 + LR_SIZE + 4)(%esp), %edx
- call _dl_call_pltexit
+ call _dl_audit_pltexit
movl LRV_EAX_OFFSET(%esp), %eax
movl LRV_EDX_OFFSET(%esp), %edx
fldt LRV_ST1_OFFSET(%esp)
diff --git a/sysdeps/ia64/dl-trampoline.S b/sysdeps/ia64/dl-trampoline.S
index 3053405a3a..11e86932c7 100644
--- a/sysdeps/ia64/dl-trampoline.S
+++ b/sysdeps/ia64/dl-trampoline.S
@@ -133,7 +133,7 @@ END(_dl_runtime_resolve)
/* The fourth argument to _dl_profile_fixup and the third one to
- _dl_call_pltexit are a pointer to La_ia64_regs:
+ _dl_audit_pltexit are a pointer to La_ia64_regs:
8byte r8
8byte r9
@@ -159,7 +159,7 @@ END(_dl_runtime_resolve)
8byte sp
The fifth argument to _dl_profile_fixup is a pointer to long int.
- The fourth argument to _dl_call_pltexit is a pointer to
+ The fourth argument to _dl_audit_pltexit is a pointer to
La_ia64_retval:
8byte r8
@@ -261,7 +261,7 @@ ENTRY(_dl_runtime_profile)
}
{ .mii
mov r18 = ar.unat /* save it in La_ia64_regs */
- mov loc7 = out3 /* save it for _dl_call_pltexit */
+ mov loc7 = out3 /* save it for _dl_audit_pltexit */
mov loc5 = r11 /* preserve language specific register */
}
{ .mmi
@@ -272,7 +272,7 @@ ENTRY(_dl_runtime_profile)
}
{ .mii
mov ar.unat = r17 /* restore it for function call */
- mov loc8 = r16 /* save it for _dl_call_pltexit */
+ mov loc8 = r16 /* save it for _dl_audit_pltexit */
nop.i 0x0
}
{ .mmi
@@ -291,7 +291,7 @@ ENTRY(_dl_runtime_profile)
{ .mmi
stf.spill [r2] = f14, 32
stf.spill [r3] = f15, 24
- mov loc9 = out1 /* save it for _dl_call_pltexit */
+ mov loc9 = out1 /* save it for _dl_audit_pltexit */
;;
}
{ .mmb
@@ -426,7 +426,7 @@ ENTRY(_dl_runtime_profile)
br.call.sptk.many b0 = b6
}
{ .mii
- /* Prepare stack for _dl_call_pltexit. Loc10 has the original
+ /* Prepare stack for _dl_audit_pltexit. Loc10 has the original
stack pointer. */
adds r12 = -PLTEXIT_FRAME_SIZE, loc10
adds r2 = -(PLTEXIT_FRAME_SIZE - 16), loc10
@@ -461,14 +461,14 @@ ENTRY(_dl_runtime_profile)
{ .mmi
stf.spill [r2] = f12, 32
stf.spill [r3] = f13, 32
- /* We need to restore gp for _dl_call_pltexit. */
+ /* We need to restore gp for _dl_audit_pltexit. */
mov gp = loc11
;;
}
{ .mmb
stf.spill [r2] = f14
stf.spill [r3] = f15
- br.call.sptk.many b0 = _dl_call_pltexit
+ br.call.sptk.many b0 = _dl_audit_pltexit
}
{ .mmi
/* Load all the non-floating and floating return values. Skip
diff --git a/sysdeps/m68k/dl-trampoline.S b/sysdeps/m68k/dl-trampoline.S
index a51a5f7f57..72bde664c3 100644
--- a/sysdeps/m68k/dl-trampoline.S
+++ b/sysdeps/m68k/dl-trampoline.S
@@ -202,7 +202,7 @@ _dl_runtime_profile:
cfi_adjust_cfa_offset (4)
move.l (32+FPSPACE)(%sp), -(%sp)
cfi_adjust_cfa_offset (4)
- jbsr _dl_call_pltexit
+ jbsr _dl_audit_pltexit
lea 16(%sp), %sp
cfi_adjust_cfa_offset (-16)
move.l (%sp)+, %d0
diff --git a/sysdeps/powerpc/powerpc64/dl-trampoline.S b/sysdeps/powerpc/powerpc64/dl-trampoline.S
index 61bd8571fc..97f0105ce7 100644
--- a/sysdeps/powerpc/powerpc64/dl-trampoline.S
+++ b/sysdeps/powerpc/powerpc64/dl-trampoline.S
@@ -197,7 +197,7 @@ END(_dl_runtime_resolve)
#ifndef PROF
ENTRY (_dl_profile_resolve, 4)
/* Spill r30, r31 to preserve the link_map* and reloc_addr, in case we
- need to call _dl_call_pltexit. */
+ need to call _dl_audit_pltexit. */
std r31,-8(r1)
std r30,-16(r1)
/* We need to save the registers used to pass parameters, ie. r3 thru
@@ -452,7 +452,7 @@ L(restoreFXR2):
L(callpltexit):
addi r5,r1,INT_PARMS
addi r6,r1,INT_RTN
- bl JUMPTARGET(_dl_call_pltexit)
+ bl JUMPTARGET(_dl_audit_pltexit)
#ifndef SHARED
nop
#endif
diff --git a/sysdeps/s390/s390-32/dl-trampoline.h b/sysdeps/s390/s390-32/dl-trampoline.h
index c224a2b928..9e4cd1055f 100644
--- a/sysdeps/s390/s390-32/dl-trampoline.h
+++ b/sysdeps/s390/s390-32/dl-trampoline.h
@@ -282,7 +282,7 @@ _dl_runtime_profile:
basr %r1,0
5: l %r14,7f-5b(%r1)
la %r5,CFA_OFF+RETVAL_OFF(%r12) # struct La_s390_32_retval *
- bas %r14,0(%r14,%r1) # call _dl_call_pltexit
+ bas %r14,0(%r14,%r1) # call _dl_audit_pltexit
lr %r15,%r12 # remove stack frame
# undef FRAME_SIZE
@@ -301,7 +301,7 @@ _dl_runtime_profile:
br %r14
6: .long _dl_profile_fixup - 0b
-7: .long _dl_call_pltexit - 5b
+7: .long _dl_audit_pltexit - 5b
cfi_endproc
.size _dl_runtime_profile, .-_dl_runtime_profile
# undef SIZEOF_STRUCT_LA_S390_32_REGS
diff --git a/sysdeps/s390/s390-64/dl-trampoline.h b/sysdeps/s390/s390-64/dl-trampoline.h
index ae741a3bad..6e5bad4045 100644
--- a/sysdeps/s390/s390-64/dl-trampoline.h
+++ b/sysdeps/s390/s390-64/dl-trampoline.h
@@ -284,7 +284,7 @@ _dl_runtime_profile:
lmg %r2,%r4,CFA_OFF+PLT1_OFF(%r12) # r2, r3: args saved by PLT
# r4: struct La_s390_64_regs *
la %r5,CFA_OFF+RETVAL_OFF(%r12) # struct La_s390_64_retval *
- brasl %r14,_dl_call_pltexit
+ brasl %r14,_dl_audit_pltexit
lgr %r15,%r12 # remove stack frame
# undef FRAME_SIZE
diff --git a/sysdeps/sh/dl-trampoline.S b/sysdeps/sh/dl-trampoline.S
index 824ac84ba1..f9038cd10e 100644
--- a/sysdeps/sh/dl-trampoline.S
+++ b/sysdeps/sh/dl-trampoline.S
@@ -423,8 +423,8 @@ _dl_runtime_profile:
.align 2
#ifdef SHARED
7: .long _GLOBAL_OFFSET_TABLE_
-8: .long _dl_call_pltexit@GOTOFF
+8: .long _dl_audit_pltexit@GOTOFF
#else
-8: .long _dl_call_pltexit
+8: .long _dl_audit_pltexit
#endif
.size _dl_runtime_profile, .-_dl_runtime_profile
diff --git a/sysdeps/sparc/sparc32/dl-trampoline.S b/sysdeps/sparc/sparc32/dl-trampoline.S
index 426f90c99a..2f64809731 100644
--- a/sysdeps/sparc/sparc32/dl-trampoline.S
+++ b/sysdeps/sparc/sparc32/dl-trampoline.S
@@ -127,7 +127,7 @@ _dl_profile_invoke:
mov %l5, %o0
mov %l6, %o1
add %sp, (11 * 8), %o2
- call _dl_call_pltexit
+ call _dl_audit_pltexit
add %sp, ( 9 * 8), %o3
ldd [%sp + ( 9 * 8)], %i0
diff --git a/sysdeps/sparc/sparc64/dl-trampoline.S b/sysdeps/sparc/sparc64/dl-trampoline.S
index 8d59fa6720..86605e37ac 100644
--- a/sysdeps/sparc/sparc64/dl-trampoline.S
+++ b/sysdeps/sparc/sparc64/dl-trampoline.S
@@ -196,7 +196,7 @@ _dl_profile_invoke:
mov %l5, %o0
mov %l6, %o1
add %sp, STACK_BIAS + (24 * 8), %o2
- call _dl_call_pltexit
+ call _dl_audit_pltexit
add %sp, STACK_BIAS + (16 * 8), %o3
ldx [%sp + STACK_BIAS + (16 * 8)], %i0
diff --git a/sysdeps/x86_64/dl-runtime.h b/sysdeps/x86_64/dl-runtime.h
index 9c8d3977ee..19ba33ef30 100644
--- a/sysdeps/x86_64/dl-runtime.h
+++ b/sysdeps/x86_64/dl-runtime.h
@@ -18,7 +18,7 @@
02111-1307 USA. */
/* The ABI calls for the PLT stubs to pass the index of the relocation
- and not its offset. In _dl_profile_fixup and _dl_call_pltexit we
+ and not its offset. In _dl_profile_fixup and _dl_audit_pltexit we
also use the index. Therefore it is wasteful to compute the offset
in the trampoline just to reverse the operation immediately
afterwards. */
diff --git a/sysdeps/x86_64/dl-trampoline.h b/sysdeps/x86_64/dl-trampoline.h
index dfbfefbd4a..812f67f23d 100644
--- a/sysdeps/x86_64/dl-trampoline.h
+++ b/sysdeps/x86_64/dl-trampoline.h
@@ -357,7 +357,7 @@ _dl_runtime_profile:
jns 3f
/* There's nothing in the frame size, so there
- will be no call to the _dl_call_pltexit. */
+ will be no call to the _dl_audit_pltexit. */
/* Get back registers content. */
movq LR_RCX_OFFSET(%rsp), %rcx
@@ -403,7 +403,7 @@ _dl_runtime_profile:
mov 24(%rbx), %RSP_LP # Drop the copied stack content
/* Now we have to prepare the La_x86_64_retval structure for the
- _dl_call_pltexit. The La_x86_64_regs is being pointed by rsp now,
+ _dl_audit_pltexit. The La_x86_64_regs is being pointed by rsp now,
so we just need to allocate the sizeof(La_x86_64_retval) space on
the stack, since the alignment has already been taken care of. */
# ifdef RESTORE_AVX
@@ -448,7 +448,7 @@ _dl_runtime_profile:
movq 24(%rbx), %rdx # La_x86_64_regs argument to %rdx.
movq 40(%rbx), %rsi # Copy args pushed by PLT in register.
movq 32(%rbx), %rdi # %rdi: link_map, %rsi: reloc_index
- call _dl_call_pltexit
+ call _dl_audit_pltexit
/* Restore return registers. */
movq LRV_RAX_OFFSET(%rsp), %rax
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 09/20] elf: Add _dl_audit_pltexit
2021-11-15 18:37 ` [PATCH v6 09/20] elf: Add _dl_audit_pltexit Adhemerval Zanella
@ 2021-12-17 17:43 ` Florian Weimer
2021-12-17 19:02 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-17 17:43 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> +#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
> + || ELF_MACHINE_NO_REL
> +# define PLTREL ElfW(Rela)
> +#else
> +# define PLTREL ElfW(Rel)
> +#endif
Can you move this definition into some shared header, so that
elf/dl-runtime.c and elf/dl-audit.c can use a single definition?
I have looked at the actual _dl_audit_pltexit function introduction, and
it looks okay. But I'd review this again as part of a repost, actually
applying the patch.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 09/20] elf: Add _dl_audit_pltexit
2021-12-17 17:43 ` Florian Weimer
@ 2021-12-17 19:02 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-17 19:02 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 17/12/2021 14:43, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> +#if (!ELF_MACHINE_NO_RELA && !defined ELF_MACHINE_PLT_REL) \
>> + || ELF_MACHINE_NO_REL
>> +# define PLTREL ElfW(Rela)
>> +#else
>> +# define PLTREL ElfW(Rel)
>> +#endif
>
> Can you move this definition into some shared header, so that
> elf/dl-runtime.c and elf/dl-audit.c can use a single definition?
>
> I have looked at the actual _dl_audit_pltexit function introduction, and
> it looks okay. But I'd review this again as part of a repost, actually
> applying the patch.
I recall why I haven't done it: it is mainly because it requires the
dl-machine.h definition and this header is kinda tricky to include.
I will check if we can move to a common header.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 10/20] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (8 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 09/20] elf: Add _dl_audit_pltexit Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-18 18:45 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 11/20] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
` (9 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer
Cc: John Mellor-Crummey, Ben Woodard, Alexander Monakov
The rtld-audit interfaces introduces a slowdown due to enabling profiling
instrumentation (as if LD_AUDIT implied LD_PROFILE). However, instrumenting
is only necessary if one of audit libraries provides PLT callbacks (
la_pltenter or la_pltexit symbols). Otherwise, the slowdown can be avoided.
The following patch adjusts the logic that enables profiling to iterate
over all audit modules and check if any of those provides a PLT hook.
To keep la_symbind() to work even without PLT callbacks, _dl_fixup now
calls the audit callback if the modules implements it.
Co-authored-by: Alexander Monakov <amonakov@ispras.ru>
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
NEWS | 4 ++
elf/Makefile | 12 +++++
elf/dl-reloc.c | 20 +++++++-
elf/dl-runtime.c | 110 ++++++++++++------------------------------
elf/rtld.c | 8 +--
elf/tst-audit19a.c | 39 +++++++++++++++
elf/tst-audit19b.c | 94 ++++++++++++++++++++++++++++++++++++
elf/tst-audit19bmod.c | 23 +++++++++
elf/tst-auditmod19a.c | 23 +++++++++
elf/tst-auditmod19b.c | 46 ++++++++++++++++++
include/link.h | 2 +
11 files changed, 294 insertions(+), 87 deletions(-)
create mode 100644 elf/tst-audit19a.c
create mode 100644 elf/tst-audit19b.c
create mode 100644 elf/tst-audit19bmod.c
create mode 100644 elf/tst-auditmod19a.c
create mode 100644 elf/tst-auditmod19b.c
diff --git a/NEWS b/NEWS
index f10971b180..427cd2a27d 100644
--- a/NEWS
+++ b/NEWS
@@ -184,6 +184,10 @@ Major new features:
than or equal to a given integer. This function is a GNU extension,
although Solaris also provides a similar function.
+* The audit libraries will avoid unnecessary slowdown if it is not required
+ PLT tracking (by not implementing the la_pltenter() or la_pltexit()
+ callbacks).
+
Deprecated and removed features, and other changes affecting compatibility:
* The function pthread_mutex_consistent_np has been deprecated; programs
diff --git a/elf/Makefile b/elf/Makefile
index 80ed31edbe..d2a71f73f1 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -231,6 +231,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \
tst-dl-is_dso tst-ro-dynamic \
tst-audit18 \
+ tst-audit19a \
+ tst-audit19b \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -373,6 +375,9 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \
tst-auditmod18 \
tst-audit18mod \
+ tst-auditmod19a \
+ tst-auditmod19b \
+ tst-audit19bmod \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1544,6 +1549,13 @@ $(objpfx)tst-audit18.out: $(objpfx)tst-auditmod18.so \
$(objpfx)tst-audit18mod.so
tst-audit18-ARGS = -- $(host-test-program-cmd)
+$(objpfx)tst-audit19a.out: $(objpfx)tst-auditmod19a.so
+tst-audit19a-ENV = LD_AUDIT=$(objpfx)tst-auditmod19a.so
+
+$(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so
+$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so
+tst-audit19b-ARGS = -- $(host-test-program-cmd)
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 0d5b727c64..64a96c36e8 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -205,12 +205,28 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
#ifdef SHARED
+ bool consider_symbind = false;
/* If we are auditing, install the same handlers we need for profiling. */
if ((reloc_mode & __RTLD_AUDIT) == 0)
- consider_profiling |= GLRO(dl_audit) != NULL;
+ {
+ struct audit_ifaces *afct = GLRO(dl_audit);
+ for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
+ {
+ /* Profiling is needed only if PLT hooks are provided. */
+ if (afct->ARCH_LA_PLTENTER != NULL
+ || afct->ARCH_LA_PLTEXIT != NULL)
+ consider_profiling = 1;
+ if (afct->symbind != NULL)
+ consider_symbind = true;
+
+ afct = afct->next;
+ }
+ }
#elif defined PROF
/* Never use dynamic linker profiling for gprof profiling code. */
# define consider_profiling 0
+#else
+# define consider_symbind 0
#endif
if (l->l_relocated)
@@ -272,7 +288,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
#ifndef PROF
- if (__glibc_unlikely (consider_profiling)
+ if (consider_profiling | consider_symbind
&& l->l_info[DT_PLTRELSZ] != NULL)
{
/* Allocate the array which will contain the already found
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 03da689503..9a38eea7cc 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -131,6 +131,37 @@ _dl_fixup (
&& __builtin_expect (ELFW(ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0))
value = elf_ifunc_invoke (DL_FIXUP_VALUE_ADDR (value));
+#ifdef SHARED
+ /* Auditing checkpoint: we have a new binding. Provide the auditing
+ libraries the possibility to change the value and tell us whether further
+ auditing is wanted.
+ The l_reloc_result is only allocated if there is an audit module which
+ provides a la_symbind(). */
+ if (l->l_reloc_result != NULL)
+ {
+ /* This is the address in the array where we store the result of previous
+ relocations. */
+ struct reloc_result *reloc_result
+ = &l->l_reloc_result[reloc_index (pltgot, reloc_arg, sizeof (PLTREL))];
+ unsigned int init = atomic_load_acquire (&reloc_result->init);
+ if (init == 0)
+ {
+ _dl_audit_symbind (l, reloc_result, sym, &value, result);
+
+ /* Store the result for later runs. */
+ if (__glibc_likely (! GLRO(dl_bind_not)))
+ {
+ reloc_result->addr = value;
+ /* Guarantee all previous writes complete before init is
+ updated. See CONCURRENCY NOTES below. */
+ atomic_store_release (&reloc_result->init, 1);
+ }
+ }
+ else
+ value = reloc_result->addr;
+ }
+#endif
+
/* Finally, fix up the plt itself. */
if (__glibc_unlikely (GLRO(dl_bind_not)))
return value;
@@ -290,84 +321,7 @@ _dl_profile_fixup (
auditing libraries the possibility to change the value and
tell us whether further auditing is wanted. */
if (defsym != NULL && GLRO(dl_naudit) > 0)
- {
- reloc_result->bound = result;
- /* Compute index of the symbol entry in the symbol table of
- the DSO with the definition. */
- reloc_result->boundndx = (defsym
- - (ElfW(Sym) *) D_PTR (result,
- l_info[DT_SYMTAB]));
-
- /* Determine whether any of the two participating DSOs is
- interested in auditing. */
- if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
- {
- unsigned int flags = 0;
- struct audit_ifaces *afct = GLRO(dl_audit);
- /* Synthesize a symbol record where the st_value field is
- the result. */
- ElfW(Sym) sym = *defsym;
- sym.st_value = DL_FIXUP_VALUE_ADDR (value);
-
- /* Keep track whether there is any interest in tracing
- the call in the lower two bits. */
- assert (DL_NNS * 2 <= sizeof (reloc_result->flags) * 8);
- assert ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) == 3);
- reloc_result->enterexit = LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT;
-
- const char *strtab2 = (const void *) D_PTR (result,
- l_info[DT_STRTAB]);
-
- for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
- {
- /* XXX Check whether both DSOs must request action or
- only one */
- struct auditstate *l_state = link_map_audit_state (l, cnt);
- struct auditstate *result_state
- = link_map_audit_state (result, cnt);
- if ((l_state->bindflags & LA_FLG_BINDFROM) != 0
- && (result_state->bindflags & LA_FLG_BINDTO) != 0)
- {
- if (afct->symbind != NULL)
- {
- uintptr_t new_value
- = afct->symbind (&sym, reloc_result->boundndx,
- &l_state->cookie,
- &result_state->cookie,
- &flags,
- strtab2 + defsym->st_name);
- if (new_value != (uintptr_t) sym.st_value)
- {
- flags |= LA_SYMB_ALTVALUE;
- sym.st_value = new_value;
- }
- }
-
- /* Remember the results for every audit library and
- store a summary in the first two bits. */
- reloc_result->enterexit
- &= flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT);
- reloc_result->enterexit
- |= ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT))
- << ((cnt + 1) * 2));
- }
- else
- /* If the bind flags say this auditor is not interested,
- set the bits manually. */
- reloc_result->enterexit
- |= ((LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)
- << ((cnt + 1) * 2));
-
- afct = afct->next;
- }
-
- reloc_result->flags = flags;
- value = DL_FIXUP_ADDR_VALUE (sym.st_value);
- }
- else
- /* Set all bits since this symbol binding is not interesting. */
- reloc_result->enterexit = (1u << DL_NNS) - 1;
- }
+ _dl_audit_symbind (l, reloc_result, defsym, &value, result);
#endif
/* Store the result for later runs. */
diff --git a/elf/rtld.c b/elf/rtld.c
index dc20643ee9..73a852ad42 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1015,13 +1015,7 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
"la_objsearch\0"
"la_objopen\0"
"la_preinit\0"
-#if __ELF_NATIVE_CLASS == 32
- "la_symbind32\0"
-#elif __ELF_NATIVE_CLASS == 64
- "la_symbind64\0"
-#else
-# error "__ELF_NATIVE_CLASS must be defined"
-#endif
+ LA_SYMBIND "\0"
#define STRING(s) __STRING (s)
"la_" STRING (ARCH_LA_PLTENTER) "\0"
"la_" STRING (ARCH_LA_PLTEXIT) "\0"
diff --git a/elf/tst-audit19a.c b/elf/tst-audit19a.c
new file mode 100644
index 0000000000..36b781f9be
--- /dev/null
+++ b/elf/tst-audit19a.c
@@ -0,0 +1,39 @@
+/* Check if DT_AUDIT a module without la_plt{enter,exit} symbols does not incur
+ in profiling (BZ#15533).
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <stdio.h>
+
+/* We interpose the profile resolver and if it is called it means profiling is
+ enabled. */
+void
+_dl_runtime_profile (ElfW(Word) addr)
+{
+ volatile int *p = NULL;
+ *p = 0;
+}
+
+static int
+do_test (void)
+{
+ printf ("...");
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit19b.c b/elf/tst-audit19b.c
new file mode 100644
index 0000000000..300197ca2e
--- /dev/null
+++ b/elf/tst-audit19b.c
@@ -0,0 +1,94 @@
+/* Check if DT_AUDIT a module with la_plt{enter,exit} call la_symbind()
+ for lazy resolution.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <getopt.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+int tst_audit18bmod1_func (void);
+
+static int
+handle_restart (void)
+{
+ TEST_COMPARE (tst_audit18bmod1_func (), 10);
+ return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+ size_t lenpre = strlen (pre);
+ size_t lenstr = strlen (str);
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ /* We must have either:
+ - One our fource parameters left if called initially:
+ + path to ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name */
+
+ if (restart)
+ return handle_restart ();
+
+ char *spargv[9];
+ int i = 0;
+ for (; i < argc - 1; i++)
+ spargv[i] = argv[i + 1];
+ spargv[i++] = (char *) "--direct";
+ spargv[i++] = (char *) "--restart";
+ spargv[i] = NULL;
+
+ setenv ("LD_AUDIT", "tst-auditmod18b.so", 0);
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit18b", 0, sc_allow_stderr);
+
+ bool find_symbind = false;
+
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
+ TEST_VERIFY (out != NULL);
+ char *buffer = NULL;
+ size_t buffer_length = 0;
+ while (xgetline (&buffer, &buffer_length, out))
+ if (startswith (buffer, "la_symbind: tst_audit18bmod1_func") == 0)
+ find_symbind = true;
+
+ TEST_COMPARE (find_symbind, true);
+
+ free (buffer);
+ xfclose (out);
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit19bmod.c b/elf/tst-audit19bmod.c
new file mode 100644
index 0000000000..9ffdcd8f3f
--- /dev/null
+++ b/elf/tst-audit19bmod.c
@@ -0,0 +1,23 @@
+/* Extra module for tst-audit18b.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+int
+tst_audit18bmod1_func (void)
+{
+ return 10;
+}
diff --git a/elf/tst-auditmod19a.c b/elf/tst-auditmod19a.c
new file mode 100644
index 0000000000..2296382a1c
--- /dev/null
+++ b/elf/tst-auditmod19a.c
@@ -0,0 +1,23 @@
+/* Audit module for tst-audit18a.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+unsigned int
+la_version (unsigned int version)
+{
+ return version;
+}
diff --git a/elf/tst-auditmod19b.c b/elf/tst-auditmod19b.c
new file mode 100644
index 0000000000..52bb88c7d7
--- /dev/null
+++ b/elf/tst-auditmod19b.c
@@ -0,0 +1,46 @@
+/* Audit module for tst-audit18b.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <string.h>
+#include <stdio.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+ return version;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ return LA_FLG_BINDTO | LA_FLG_BINDFROM;
+}
+
+uintptr_t
+#if __ELF_NATIVE_CLASS == 32
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+#else
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, unsigned int *flags, const char *symname)
+#endif
+{
+ fprintf (stderr, "la_symbind: %s\n", symname);
+ return sym->st_value;
+}
diff --git a/include/link.h b/include/link.h
index c1c382ccfa..6a9f788d2b 100644
--- a/include/link.h
+++ b/include/link.h
@@ -367,8 +367,10 @@ extern struct r_debug_extended _r_debug_extended attribute_hidden;
#if __ELF_NATIVE_CLASS == 32
# define symbind symbind32
+# define LA_SYMBIND "la_symbind32"
#elif __ELF_NATIVE_CLASS == 64
# define symbind symbind64
+# define LA_SYMBIND "la_symbind64"
#else
# error "__ELF_NATIVE_CLASS must be defined"
#endif
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 10/20] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
2021-11-15 18:37 ` [PATCH v6 10/20] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
@ 2021-12-18 18:45 ` Florian Weimer
2021-12-20 12:10 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-18 18:45 UTC (permalink / raw)
To: Adhemerval Zanella
Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Alexander Monakov
* Adhemerval Zanella:
> The rtld-audit interfaces introduces a slowdown due to enabling profiling
> instrumentation (as if LD_AUDIT implied LD_PROFILE). However, instrumenting
> is only necessary if one of audit libraries provides PLT callbacks (
> la_pltenter or la_pltexit symbols). Otherwise, the slowdown can be avoided.
Awkward linebreak after (.
> To keep la_symbind() to work even without PLT callbacks, _dl_fixup now
> +* The audit libraries will avoid unnecessary slowdown if it is not required
> + PLT tracking (by not implementing the la_pltenter() or la_pltexit()
> + callbacks).
I think we don't use the () markers? (Although I said before I wouldn't
point this out anymore.)
> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
> index 0d5b727c64..64a96c36e8 100644
> --- a/elf/dl-reloc.c
> +++ b/elf/dl-reloc.c
> @@ -205,12 +205,28 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
> int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
> #ifndef PROF
> - if (__glibc_unlikely (consider_profiling)
> + if (consider_profiling | consider_symbind
> && l->l_info[DT_PLTRELSZ] != NULL)
> {
> /* Allocate the array which will contain the already found
Please add parentheses around the | expression (which should perhaps
use || too).
> diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
> index 03da689503..9a38eea7cc 100644
> --- a/elf/dl-runtime.c
> +++ b/elf/dl-runtime.c
> @@ -131,6 +131,37 @@ _dl_fixup (
> - /* Determine whether any of the two participating DSOs is
> - interested in auditing. */
> - if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
> - {
> - unsigned int flags = 0;
> - struct audit_ifaces *afct = GLRO(dl_audit);
> - /* Synthesize a symbol record where the st_value field is
> - the result. */
> - ElfW(Sym) sym = *defsym;
> - sym.st_value = DL_FIXUP_VALUE_ADDR (value);
All this was copied over in patch 06/20 of the series to dl-audit.c.
> diff --git a/elf/tst-audit19a.c b/elf/tst-audit19a.c
> new file mode 100644
> index 0000000000..36b781f9be
> --- /dev/null
> +++ b/elf/tst-audit19a.c
> +#include <link.h>
> +#include <stdio.h>
> +
> +/* We interpose the profile resolver and if it is called it means profiling is
> + enabled. */
> +void
> +_dl_runtime_profile (ElfW(Word) addr)
I don't think this works. _dl_runtime_profile is not an exported
symbol, so it can't be interposed.
Maybe you can check for an allocated l_reloc_result instead. If it's
not there, profiling isn't possible. It's not entirely equivalent, but
it provides at least some testing.
> diff --git a/elf/tst-auditmod19a.c b/elf/tst-auditmod19a.c
> new file mode 100644
> index 0000000000..2296382a1c
> --- /dev/null
> +++ b/elf/tst-auditmod19a.c
> @@ -0,0 +1,23 @@
> +unsigned int
> +la_version (unsigned int version)
> +{
> + return version;
> +}
This should use LAV_CURRENT.
> diff --git a/elf/tst-auditmod19b.c b/elf/tst-auditmod19b.c
> new file mode 100644
> index 0000000000..52bb88c7d7
> --- /dev/null
> +++ b/elf/tst-auditmod19b.c
> +unsigned int
> +la_version (unsigned int version)
> +{
> + return version;
> +}
Likweise.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 10/20] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
2021-12-18 18:45 ` Florian Weimer
@ 2021-12-20 12:10 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 12:10 UTC (permalink / raw)
To: Florian Weimer
Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Alexander Monakov
On 18/12/2021 15:45, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> The rtld-audit interfaces introduces a slowdown due to enabling profiling
>> instrumentation (as if LD_AUDIT implied LD_PROFILE). However, instrumenting
>> is only necessary if one of audit libraries provides PLT callbacks (
>> la_pltenter or la_pltexit symbols). Otherwise, the slowdown can be avoided.
>
> Awkward linebreak after (.
Ack.
>
>> To keep la_symbind() to work even without PLT callbacks, _dl_fixup now
>
>> +* The audit libraries will avoid unnecessary slowdown if it is not required
>> + PLT tracking (by not implementing the la_pltenter() or la_pltexit()
>> + callbacks).
>
> I think we don't use the () markers? (Although I said before I wouldn't
> point this out anymore.)
I though I have removed all of them, I will fix this as well.
>
>> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
>> index 0d5b727c64..64a96c36e8 100644
>> --- a/elf/dl-reloc.c
>> +++ b/elf/dl-reloc.c
>> @@ -205,12 +205,28 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>> int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
>
>> #ifndef PROF
>> - if (__glibc_unlikely (consider_profiling)
>> + if (consider_profiling | consider_symbind
>> && l->l_info[DT_PLTRELSZ] != NULL)
>> {
>> /* Allocate the array which will contain the already found
>
> Please add parentheses around the | expression (which should perhaps
> use || too).
>
Ack.
>> diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
>> index 03da689503..9a38eea7cc 100644
>> --- a/elf/dl-runtime.c
>> +++ b/elf/dl-runtime.c
>> @@ -131,6 +131,37 @@ _dl_fixup (
>
>> - /* Determine whether any of the two participating DSOs is
>> - interested in auditing. */
>> - if ((l->l_audit_any_plt | result->l_audit_any_plt) != 0)
>> - {
>> - unsigned int flags = 0;
>> - struct audit_ifaces *afct = GLRO(dl_audit);
>> - /* Synthesize a symbol record where the st_value field is
>> - the result. */
>> - ElfW(Sym) sym = *defsym;
>> - sym.st_value = DL_FIXUP_VALUE_ADDR (value);
>
> All this was copied over in patch 06/20 of the series to dl-audit.c.
Ack, I have moved this to the 06/20 patch.
>
>> diff --git a/elf/tst-audit19a.c b/elf/tst-audit19a.c
>> new file mode 100644
>> index 0000000000..36b781f9be
>> --- /dev/null
>> +++ b/elf/tst-audit19a.c
>
>> +#include <link.h>
>> +#include <stdio.h>
>> +
>> +/* We interpose the profile resolver and if it is called it means profiling is
>> + enabled. */
>> +void
>> +_dl_runtime_profile (ElfW(Word) addr)
>
> I don't think this works. _dl_runtime_profile is not an exported
> symbol, so it can't be interposed.
>
> Maybe you can check for an allocated l_reloc_result instead. If it's
> not there, profiling isn't possible. It's not entirely equivalent, but
> it provides at least some testing.
Indeed, I am not sure why I haven't see it that removing the segfault
does not make the test fail. I have added a l_reloc_result check
instead.
>
>> diff --git a/elf/tst-auditmod19a.c b/elf/tst-auditmod19a.c
>> new file mode 100644
>> index 0000000000..2296382a1c
>> --- /dev/null
>> +++ b/elf/tst-auditmod19a.c
>> @@ -0,0 +1,23 @@
>
>> +unsigned int
>> +la_version (unsigned int version)
>> +{
>> + return version;
>> +}
>
> This should use LAV_CURRENT.
>
Ack.
>
>> diff --git a/elf/tst-auditmod19b.c b/elf/tst-auditmod19b.c
>> new file mode 100644
>> index 0000000000..52bb88c7d7
>> --- /dev/null
>> +++ b/elf/tst-auditmod19b.c
>
>> +unsigned int
>> +la_version (unsigned int version)
>> +{
>> + return version;
>> +}
>
> Likweise.
Ack.
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 11/20] elf: Add audit tests for modules with TLSDESC
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (9 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 10/20] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-18 18:53 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 12/20] elf: Do not fail for failed dlmopen on audit modules (BZ #28061) Adhemerval Zanella
` (8 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Makefile | 14 +++++++
elf/tst-audit-tlsdesc-audit.c | 25 +++++++++++++
elf/tst-audit-tlsdesc-dlopen.c | 67 ++++++++++++++++++++++++++++++++++
elf/tst-audit-tlsdesc.c | 60 ++++++++++++++++++++++++++++++
elf/tst-auditmod-tlsdesc1.c | 41 +++++++++++++++++++++
elf/tst-auditmod-tlsdesc2.c | 33 +++++++++++++++++
6 files changed, 240 insertions(+)
create mode 100644 elf/tst-audit-tlsdesc-audit.c
create mode 100644 elf/tst-audit-tlsdesc-dlopen.c
create mode 100644 elf/tst-audit-tlsdesc.c
create mode 100644 elf/tst-auditmod-tlsdesc1.c
create mode 100644 elf/tst-auditmod-tlsdesc2.c
diff --git a/elf/Makefile b/elf/Makefile
index d2a71f73f1..19ec680144 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -390,6 +390,20 @@ modules-names += tst-gnu2-tls1mod
$(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
tst-gnu2-tls1mod.so-no-z-defs = yes
CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
+
+tests += tst-audit-tlsdesc tst-audit-tlsdesc-dlopen
+modules-names += tst-auditmod-tlsdesc1 tst-auditmod-tlsdesc2 tst-audit-tlsdesc-audit
+$(objpfx)tst-audit-tlsdesc: $(objpfx)tst-auditmod-tlsdesc1.so \
+ $(objpfx)tst-auditmod-tlsdesc2.so \
+ $(shared-thread-library)
+CFLAGS-tst-auditmod-tlsdesc1.c += -mtls-dialect=gnu2
+CFLAGS-tst-auditmod-tlsdesc2.c += -mtls-dialect=gnu2
+$(objpfx)tst-audit-tlsdesc-dlopen: $(shared-thread-library)
+$(objpfx)tst-audit-tlsdesc-dlopen.out: $(objpfx)tst-auditmod-tlsdesc1.so \
+ $(objpfx)tst-auditmod-tlsdesc2.so
+$(objpfx)tst-auditmod-tlsdesc1.so: $(objpfx)tst-auditmod-tlsdesc2.so
+tst-audit-tlsdesc-ENV = LD_AUDIT=$(objpfx)tst-audit-tlsdesc-audit.so
+tst-audit-tlsdesc-dlopen-ENV = LD_AUDIT=$(objpfx)tst-audit-tlsdesc-audit.so
endif
ifeq (yes,$(have-protected-data))
modules-names += tst-protected1moda tst-protected1modb
diff --git a/elf/tst-audit-tlsdesc-audit.c b/elf/tst-audit-tlsdesc-audit.c
new file mode 100644
index 0000000000..e4b835d1f1
--- /dev/null
+++ b/elf/tst-audit-tlsdesc-audit.c
@@ -0,0 +1,25 @@
+/* DT_AUDIT with modules with TLSDESC.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
diff --git a/elf/tst-audit-tlsdesc-dlopen.c b/elf/tst-audit-tlsdesc-dlopen.c
new file mode 100644
index 0000000000..e4d631fc94
--- /dev/null
+++ b/elf/tst-audit-tlsdesc-dlopen.c
@@ -0,0 +1,67 @@
+/* DT_AUDIT with modules with TLSDESC.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xthread.h>
+#include <support/xdlfcn.h>
+
+static void *
+thr_func (void *mod)
+{
+ int* (*get_global1)(void) = xdlsym (mod, "get_global1");
+ int* (*get_global2)(void) = xdlsym (mod, "get_global2");
+ void (*set_global2)(int) = xdlsym (mod, "set_global2");
+ int* (*get_local1)(void) = xdlsym (mod, "get_local1");
+ int* (*get_local2)(void) = xdlsym (mod, "get_local2");
+
+ int *global1 = get_global1 ();
+ TEST_COMPARE (*global1, 0);
+ ++*global1;
+
+ int *global2 = get_global2 ();
+ TEST_COMPARE (*global2, 0);
+ ++*global2;
+ TEST_COMPARE (*global2, 1);
+
+ set_global2 (10);
+ TEST_COMPARE (*global2, 10);
+
+ int *local1 = get_local1 ();
+ TEST_COMPARE (*local1, 0);
+ ++*local1;
+
+ int *local2 = get_local2 ();
+ TEST_COMPARE (*local2, 0);
+ ++*local2;
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ void *mod = xdlopen ("tst-auditmod-tlsdesc1.so", RTLD_LAZY);
+
+ pthread_t thr = xpthread_create (NULL, thr_func, mod);
+ void *r = xpthread_join (thr);
+ TEST_VERIFY (r == NULL);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit-tlsdesc.c b/elf/tst-audit-tlsdesc.c
new file mode 100644
index 0000000000..3c8be81c95
--- /dev/null
+++ b/elf/tst-audit-tlsdesc.c
@@ -0,0 +1,60 @@
+/* DT_AUDIT with modules with TLSDESC.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/xthread.h>
+
+extern __thread int global1;
+extern __thread int global2;
+void *get_local1 (void);
+void set_global2 (int v);
+void *get_local2 (void);
+
+static void *
+thr_func (void *clousure)
+{
+ TEST_COMPARE (global1, 0);
+ ++global1;
+ TEST_COMPARE (global2, 0);
+ ++global2;
+ TEST_COMPARE (global2, 1);
+
+ set_global2 (10);
+ TEST_COMPARE (global2, 10);
+
+ int *local1 = get_local1 ();
+ TEST_COMPARE (*local1, 0);
+ ++*local1;
+
+ int *local2 = get_local2 ();
+ TEST_COMPARE (*local2, 0);
+ ++*local2;
+
+ return 0;
+}
+
+static int
+do_test (void)
+{
+ pthread_t thr = xpthread_create (NULL, thr_func, NULL);
+ void *r = xpthread_join (thr);
+ TEST_VERIFY (r == NULL);
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-auditmod-tlsdesc1.c b/elf/tst-auditmod-tlsdesc1.c
new file mode 100644
index 0000000000..61c7dd99a2
--- /dev/null
+++ b/elf/tst-auditmod-tlsdesc1.c
@@ -0,0 +1,41 @@
+/* DT_AUDIT with modules with TLSDESC.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+__thread int global1;
+
+int *
+get_global1 (void)
+{
+ return &global1;
+}
+
+static __thread int local1;
+
+void *
+get_local1 (void)
+{
+ return &local1;
+}
+
+extern __thread int global2;
+
+void
+set_global2 (int v)
+{
+ global2 = v;
+}
diff --git a/elf/tst-auditmod-tlsdesc2.c b/elf/tst-auditmod-tlsdesc2.c
new file mode 100644
index 0000000000..28aef635f6
--- /dev/null
+++ b/elf/tst-auditmod-tlsdesc2.c
@@ -0,0 +1,33 @@
+/* DT_AUDIT with modules with TLSDESC.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+__thread int global2;
+
+int *
+get_global2 (void)
+{
+ return &global2;
+}
+
+static __thread int local2;
+
+void *
+get_local2 (void)
+{
+ return &local2;
+}
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 11/20] elf: Add audit tests for modules with TLSDESC
2021-11-15 18:37 ` [PATCH v6 11/20] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
@ 2021-12-18 18:53 ` Florian Weimer
2021-12-20 12:23 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-18 18:53 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
The test module naming is a bit confusing. tst-auditmod-tlsdesc1.so and
tst-auditmod-tlsdesc2.so are not actually audit modules, but
tst-audit-tlsdesc-audit.so is.
Otherwise the tests look okay. Not sure why I expected something with
*audit modules* that use TLSDESC.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 11/20] elf: Add audit tests for modules with TLSDESC
2021-12-18 18:53 ` Florian Weimer
@ 2021-12-20 12:23 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 12:23 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 18/12/2021 15:53, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
>
> The test module naming is a bit confusing. tst-auditmod-tlsdesc1.so and
> tst-auditmod-tlsdesc2.so are not actually audit modules, but
> tst-audit-tlsdesc-audit.so is.
I have changed tst-auditmod-tlsdesc1 to tst-audit-tlsdesc-mod1, tst-auditmod-tlsdesc2
to tst-audit-tlsdesc-mod2, and tst-audit-tlsdesc-audit to tst-auditmod-tlsdesc. It
should in par with the rest to audit names scheme.
>
> Otherwise the tests look okay. Not sure why I expected something with
> *audit modules* that use TLSDESC.
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 12/20] elf: Do not fail for failed dlmopen on audit modules (BZ #28061)
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (10 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 11/20] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-18 18:59 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 13/20] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
` (7 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
The dl_main() sets the LM_ID_BASE to RT_ADD just before starting to
add load new shared objects. The state is set to R_CONSISTENT just
after all objects are loaded.
However if a audit modules tries to dlmopen() an inexistent module,
the _dl_open() will assert that the namespace is in an inconsistent
state.
This is different than dlopen(), since first it will not use
LM_ID_BASE and second _dl_map_object_from_fd() is the sole responsible
to set and reset the r_state value.
So the assert() on _dl_open() can not really be seen if the state is
consistent, since _dt_main() resets it. This patch removes the assert.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Makefile | 5 ++++
elf/dl-open.c | 2 --
elf/tst-audit20.c | 25 +++++++++++++++++++
elf/tst-auditmod20.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 87 insertions(+), 2 deletions(-)
create mode 100644 elf/tst-audit20.c
create mode 100644 elf/tst-auditmod20.c
diff --git a/elf/Makefile b/elf/Makefile
index 19ec680144..4636a2743a 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -233,6 +233,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit18 \
tst-audit19a \
tst-audit19b \
+ tst-audit20 \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -378,6 +379,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod19a \
tst-auditmod19b \
tst-audit19bmod \
+ tst-auditmod20 \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1570,6 +1572,9 @@ $(objpfx)tst-audit19b.out: $(objpfx)tst-auditmod19b.so
$(objpfx)tst-audit19b: $(objpfx)tst-audit19bmod.so
tst-audit19b-ARGS = -- $(host-test-program-cmd)
+$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so
+tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-open.c b/elf/dl-open.c
index e2f2e713e7..4f4d72e325 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -914,8 +914,6 @@ no more namespaces available for dlmopen()"));
the flag here. */
}
- assert (_dl_debug_update (args.nsid)->r_state == RT_CONSISTENT);
-
/* Release the lock. */
__rtld_lock_unlock_recursive (GL(dl_load_lock));
diff --git a/elf/tst-audit20.c b/elf/tst-audit20.c
new file mode 100644
index 0000000000..6f39ccee86
--- /dev/null
+++ b/elf/tst-audit20.c
@@ -0,0 +1,25 @@
+/* Check dlopen failure on audit modules.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+static int
+do_test (void)
+{
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-auditmod20.c b/elf/tst-auditmod20.c
new file mode 100644
index 0000000000..c57e50ee4e
--- /dev/null
+++ b/elf/tst-auditmod20.c
@@ -0,0 +1,57 @@
+/* Check dlopen failure on audit modules.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <dlfcn.h>
+#include <link.h>
+#include <stdlib.h>
+
+unsigned int
+la_version (unsigned int v)
+{
+ return LAV_CURRENT;
+}
+
+static void
+check (void)
+{
+ {
+ void *mod = dlopen ("nonexistent.so", RTLD_NOW);
+ if (mod != NULL)
+ abort ();
+ }
+
+ {
+ void *mod = dlmopen (LM_ID_BASE, "nonexistent.so", RTLD_NOW);
+ if (mod != NULL)
+ abort ();
+ }
+}
+
+void
+la_activity (uintptr_t *cookie, unsigned int flag)
+{
+ if (flag != LA_ACT_CONSISTENT)
+ return;
+ check ();
+}
+
+void
+la_preinit (uintptr_t *cookie)
+{
+ check ();
+}
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 12/20] elf: Do not fail for failed dlmopen on audit modules (BZ #28061)
2021-11-15 18:37 ` [PATCH v6 12/20] elf: Do not fail for failed dlmopen on audit modules (BZ #28061) Adhemerval Zanella
@ 2021-12-18 18:59 ` Florian Weimer
2021-12-20 12:24 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-18 18:59 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> The dl_main() sets the LM_ID_BASE to RT_ADD just before starting to
> add load new shared objects. The state is set to R_CONSISTENT just
> after all objects are loaded.
>
> However if a audit modules tries to dlmopen() an inexistent module,
> the _dl_open() will assert that the namespace is in an inconsistent
> state.
>
> This is different than dlopen(), since first it will not use
> LM_ID_BASE and second _dl_map_object_from_fd() is the sole responsible
> to set and reset the r_state value.
>
> So the assert() on _dl_open() can not really be seen if the state is
> consistent, since _dt_main() resets it. This patch removes the assert.
See previous comments about ().
> diff --git a/elf/dl-open.c b/elf/dl-open.c
> index e2f2e713e7..4f4d72e325 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -914,8 +914,6 @@ no more namespaces available for dlmopen()"));
> the flag here. */
> }
>
> - assert (_dl_debug_update (args.nsid)->r_state == RT_CONSISTENT);
> -
_dl_debug_update has already been called for its side effect above, so
deleting the line is fine.
Reviewed-by: Florian Weimer <fweimer@redhat.com>
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 12/20] elf: Do not fail for failed dlmopen on audit modules (BZ #28061)
2021-12-18 18:59 ` Florian Weimer
@ 2021-12-20 12:24 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 12:24 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 18/12/2021 15:59, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> The dl_main() sets the LM_ID_BASE to RT_ADD just before starting to
>> add load new shared objects. The state is set to R_CONSISTENT just
>> after all objects are loaded.
>>
>> However if a audit modules tries to dlmopen() an inexistent module,
>> the _dl_open() will assert that the namespace is in an inconsistent
>> state.
>>
>> This is different than dlopen(), since first it will not use
>> LM_ID_BASE and second _dl_map_object_from_fd() is the sole responsible
>> to set and reset the r_state value.
>>
>> So the assert() on _dl_open() can not really be seen if the state is
>> consistent, since _dt_main() resets it. This patch removes the assert.
>
> See previous comments about ().
Ack, I removed all '()'.
>
>> diff --git a/elf/dl-open.c b/elf/dl-open.c
>> index e2f2e713e7..4f4d72e325 100644
>> --- a/elf/dl-open.c
>> +++ b/elf/dl-open.c
>> @@ -914,8 +914,6 @@ no more namespaces available for dlmopen()"));
>> the flag here. */
>> }
>>
>> - assert (_dl_debug_update (args.nsid)->r_state == RT_CONSISTENT);
>> -
>
>
> _dl_debug_update has already been called for its side effect above, so
> deleting the line is fine.
>
> Reviewed-by: Florian Weimer <fweimer@redhat.com>
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 13/20] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (11 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 12/20] elf: Do not fail for failed dlmopen on audit modules (BZ #28061) Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-18 18:01 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
` (6 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
For ldaudit modules or dependencies with initial-exec TLS, we can not
set the initial TLS image on default loader initialization because it
would already be set by the ldaudit setup. However, subsequent thread
creation would need to follow the default behaviour.
This patch fixes by making_dl_new_object() sets a new link_map flag
'l_dont_set_tls_static' only for __RTLD_AUDIT modules. The flag is
later reset on _dl_allocate_tls_init().
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Makefile | 8 +++++
elf/dl-object.c | 3 ++
elf/dl-tls.c | 16 ++++++---
elf/rtld.c | 2 ++
elf/tst-audit21.c | 42 +++++++++++++++++++++++
elf/tst-auditmod21a.c | 80 +++++++++++++++++++++++++++++++++++++++++++
elf/tst-auditmod21b.c | 22 ++++++++++++
include/link.h | 2 ++
8 files changed, 171 insertions(+), 4 deletions(-)
create mode 100644 elf/tst-audit21.c
create mode 100644 elf/tst-auditmod21a.c
create mode 100644 elf/tst-auditmod21b.c
diff --git a/elf/Makefile b/elf/Makefile
index 4636a2743a..587df12b3d 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -234,6 +234,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit19a \
tst-audit19b \
tst-audit20 \
+ tst-audit21 \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -380,6 +381,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod19b \
tst-audit19bmod \
tst-auditmod20 \
+ tst-auditmod21a \
+ tst-auditmod21b \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1575,6 +1578,11 @@ tst-audit19b-ARGS = -- $(host-test-program-cmd)
$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so
tst-audit20-ENV = LD_AUDIT=$(objpfx)tst-auditmod20.so
+$(objpfx)tst-audit21: $(shared-thread-library)
+$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so
+$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so
+tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-object.c b/elf/dl-object.c
index 1875599eb2..eb2158a84b 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -175,6 +175,9 @@ _dl_new_object (char *realname, const char *libname, int type,
new->l_local_scope[0] = &new->l_searchlist;
+ if (mode & __RTLD_AUDIT)
+ new->l_dont_set_tls_static = 1;
+
/* Determine the origin. If allocating the link map for the main
executable, the realname is not known and "". In this case, the
origin needs to be determined by other means. However, in case
diff --git a/elf/dl-tls.c b/elf/dl-tls.c
index 9260d2d696..512ed9a9dc 100644
--- a/elf/dl-tls.c
+++ b/elf/dl-tls.c
@@ -593,10 +593,18 @@ _dl_allocate_tls_init (void *result)
some platforms use in static programs requires it. */
dtv[map->l_tls_modid].pointer.val = dest;
- /* Copy the initialization image and clear the BSS part. */
- memset (__mempcpy (dest, map->l_tls_initimage,
- map->l_tls_initimage_size), '\0',
- map->l_tls_blocksize - map->l_tls_initimage_size);
+ /* Copy the initialization image and clear the BSS part. For
+ ldaudit modules or depedencies with initial-exec TLS, we can not
+ set the initial TLS image on default loader initialization
+ because it would already be set by the ldaudit setup. However,
+ subsequent thread creation would need to follow the default
+ behaviour. */
+ if (__glibc_unlikely (!map->l_dont_set_tls_static))
+ memset (__mempcpy (dest, map->l_tls_initimage,
+ map->l_tls_initimage_size), '\0',
+ map->l_tls_blocksize - map->l_tls_initimage_size);
+ else
+ map->l_dont_set_tls_static = 0;
}
total += cnt;
diff --git a/elf/rtld.c b/elf/rtld.c
index 73a852ad42..faba319e5c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1055,6 +1055,8 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
/* Mark the DSO as being used for auditing. */
dlmargs.map->l_auditing = 1;
+ /* Mark the DSO to not clear the TLS bss in tls initialization. */
+ dlmargs.map->l_dont_set_tls_static = 1;
}
/* Load all audit modules. */
diff --git a/elf/tst-audit21.c b/elf/tst-audit21.c
new file mode 100644
index 0000000000..307cb6fc3b
--- /dev/null
+++ b/elf/tst-audit21.c
@@ -0,0 +1,42 @@
+/* Check DT_AUDIT with static TLS.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ctype.h>
+#include <support/xthread.h>
+#include <support/check.h>
+
+static volatile __thread int out __attribute__ ((tls_model ("initial-exec")));
+
+static void *
+tf (void *arg)
+{
+ TEST_COMPARE (out, 0);
+ out = isspace (' ');
+ return NULL;
+}
+
+int main (int argc, char *argv[])
+{
+ TEST_COMPARE (out, 0);
+ out = isspace (' ');
+
+ pthread_t t = xpthread_create (NULL, tf, NULL);
+ xpthread_join (t);
+
+ return 0;
+}
diff --git a/elf/tst-auditmod21a.c b/elf/tst-auditmod21a.c
new file mode 100644
index 0000000000..a0584f36e6
--- /dev/null
+++ b/elf/tst-auditmod21a.c
@@ -0,0 +1,80 @@
+/* Check DT_AUDIT with static TLS.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <link.h>
+
+#define tls_ie __attribute__ ((tls_model ("initial-exec")))
+
+__thread int tls_var0 tls_ie;
+__thread int tls_var1 tls_ie = 0x10;
+
+/* Defined tst-auditmod21b.so */
+extern __thread int tls_var2;
+extern __thread int tls_var3;
+
+static volatile int out;
+
+static void
+call_libc (void)
+{
+ /* isspace() access the initial-exec glibc TLS variables, which are
+ setup in glibc initialization. */
+ out = isspace (' ');
+}
+
+unsigned int
+la_version (unsigned int v)
+{
+ tls_var0 = 0x1;
+ if (tls_var1 != 0x10)
+ abort ();
+ tls_var1 = 0x20;
+
+ tls_var2 = 0x2;
+ if (tls_var3 != 0x20)
+ abort ();
+ tls_var3 = 0x40;
+
+ call_libc ();
+
+ return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie)
+{
+ call_libc ();
+ *cookie = (uintptr_t) map;
+ return 0;
+}
+
+void
+la_activity (uintptr_t* cookie, unsigned int flag)
+{
+ if (tls_var0 != 0x1 || tls_var1 != 0x20)
+ abort ();
+ call_libc ();
+}
+
+void
+la_preinit (uintptr_t* cookie)
+{
+ call_libc ();
+}
diff --git a/elf/tst-auditmod21b.c b/elf/tst-auditmod21b.c
new file mode 100644
index 0000000000..550f858b1d
--- /dev/null
+++ b/elf/tst-auditmod21b.c
@@ -0,0 +1,22 @@
+/* Check DT_AUDIT with static TLS.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define tls_ie __attribute__ ((tls_model ("initial-exec")))
+
+__thread int tls_var2 tls_ie;
+__thread int tls_var3 tls_ie = 0x20;
diff --git a/include/link.h b/include/link.h
index 6a9f788d2b..ba4c588873 100644
--- a/include/link.h
+++ b/include/link.h
@@ -195,6 +195,8 @@ struct link_map
unsigned int l_need_tls_init:1; /* Nonzero if GL(dl_init_static_tls)
should be called on this link map
when relocation finishes. */
+ unsigned int l_dont_set_tls_static:1; /* Non zero if static TLS setup should
+ not be initialized. */
unsigned int l_auditing:1; /* Nonzero if the DSO is used in auditing. */
unsigned int l_audit_any_plt:1; /* Nonzero if at least one audit module
is interested in the PLT interception.*/
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 13/20] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
2021-11-15 18:37 ` [PATCH v6 13/20] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
@ 2021-12-18 18:01 ` Florian Weimer
2021-12-20 13:25 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-18 18:01 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-object.c b/elf/dl-object.c
> index 1875599eb2..eb2158a84b 100644
> --- a/elf/dl-object.c
> +++ b/elf/dl-object.c
> @@ -175,6 +175,9 @@ _dl_new_object (char *realname, const char *libname, int type,
>
> new->l_local_scope[0] = &new->l_searchlist;
>
> + if (mode & __RTLD_AUDIT)
> + new->l_dont_set_tls_static = 1;
> +
> /* Determine the origin. If allocating the link map for the main
> executable, the realname is not known and "". In this case, the
> origin needs to be determined by other means. However, in case
Is this sufficient? What happens if an auditor calls dlopen? I don't
see anything that causes that dlopen call to use __RTLD_AUDIT, so
I suspect the change in initialization logic needs to be changed for
audit namespaces, not just each audit module contained in them.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 13/20] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
2021-12-18 18:01 ` Florian Weimer
@ 2021-12-20 13:25 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 13:25 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 18/12/2021 15:01, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-object.c b/elf/dl-object.c
>> index 1875599eb2..eb2158a84b 100644
>> --- a/elf/dl-object.c
>> +++ b/elf/dl-object.c
>> @@ -175,6 +175,9 @@ _dl_new_object (char *realname, const char *libname, int type,
>>
>> new->l_local_scope[0] = &new->l_searchlist;
>>
>> + if (mode & __RTLD_AUDIT)
>> + new->l_dont_set_tls_static = 1;
>> +
>> /* Determine the origin. If allocating the link map for the main
>> executable, the realname is not known and "". In this case, the
>> origin needs to be determined by other means. However, in case
>
> Is this sufficient? What happens if an auditor calls dlopen? I don't
> see anything that causes that dlopen call to use __RTLD_AUDIT, so
>
> I suspect the change in initialization logic needs to be changed for
> audit namespaces, not just each audit module contained in them.
Good point, maybe just check if nsid != LM_ID_BASE and also not
initialize for dlmopen.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (12 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 13/20] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-18 20:00 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
` (5 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
The vDSO is is listed in the link_map chain, but is never the subject of
an la_objopen call. A new internal flag __RTLD_VDSO is added that
acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate'
extra space for the 'struct link_map'.
The return value from the callback() is currently ignored, since there
is no PLT call involved by glibc when using the vDSO, neither the vDSO
are exported directly.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Makefile | 5 ++
elf/dl-object.c | 17 +++---
elf/rtld.c | 7 +++
elf/setup-vdso.h | 2 +-
elf/tst-audit22.c | 124 +++++++++++++++++++++++++++++++++++++++++++
elf/tst-auditmod22.c | 51 ++++++++++++++++++
include/dlfcn.h | 1 +
7 files changed, 199 insertions(+), 8 deletions(-)
create mode 100644 elf/tst-audit22.c
create mode 100644 elf/tst-auditmod22.c
diff --git a/elf/Makefile b/elf/Makefile
index 587df12b3d..35e45d969e 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -235,6 +235,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit19b \
tst-audit20 \
tst-audit21 \
+ tst-audit22 \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -383,6 +384,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod20 \
tst-auditmod21a \
tst-auditmod21b \
+ tst-auditmod22 \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1583,6 +1585,9 @@ $(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so
$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so
tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so
+$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so
+tst-audit22-ARGS = -- $(host-test-program-cmd)
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-object.c b/elf/dl-object.c
index eb2158a84b..6f26da4310 100644
--- a/elf/dl-object.c
+++ b/elf/dl-object.c
@@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type,
{
#ifdef SHARED
unsigned int naudit;
- if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
+ if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0))
{
- assert (type == lt_executable);
- assert (nsid == LM_ID_BASE);
+ if (mode & __RTLD_OPENEXEC)
+ {
+ assert (type == lt_executable);
+ assert (nsid == LM_ID_BASE);
- /* Ignore the specified libname for the main executable. It is
- only known with an explicit loader invocation. */
- libname = "";
+ /* Ignore the specified libname for the main executable. It is
+ only known with an explicit loader invocation. */
+ libname = "";
+ }
- /* We create the map for the executable before we know whether
+ /* We create the map for the executable and vDSO before we know whether
we have auditing libraries and if yes, how many. Assume the
worst. */
naudit = DL_NNS;
diff --git a/elf/rtld.c b/elf/rtld.c
index faba319e5c..55b4eb91f2 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1879,6 +1879,13 @@ dl_main (const ElfW(Phdr) *phdr,
assert (i == npreloads);
}
+#ifdef NEED_DL_SYSINFO_DSO
+ /* Now that the audit modules are opened, call la_objopen() for the
+ vDSO. */
+ if (GLRO(dl_sysinfo_map) != NULL)
+ _dl_audit_objopen (GLRO(dl_sysinfo_map), LM_ID_BASE, true);
+#endif
+
/* Load all the libraries specified by DT_NEEDED entries. If LD_PRELOAD
specified some libraries to load, these are inserted before the actual
dependencies in the executable's searchlist for symbol resolution. */
diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
index 3f20578046..2b013d974a 100644
--- a/elf/setup-vdso.h
+++ b/elf/setup-vdso.h
@@ -30,7 +30,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
We just want our data structures to describe it as if we had just
mapped and relocated it normally. */
struct link_map *l = _dl_new_object ((char *) "", "", lt_library, NULL,
- 0, LM_ID_BASE);
+ __RTLD_VDSO, LM_ID_BASE);
if (__glibc_likely (l != NULL))
{
l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c
new file mode 100644
index 0000000000..f136f25a32
--- /dev/null
+++ b/elf/tst-audit22.c
@@ -0,0 +1,124 @@
+/* Check DTAUDIT and vDSO interaction.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+static uintptr_t vdso_addr;
+
+static int
+handle_restart (void)
+{
+ fprintf (stderr, "vdso: %p\n", (void*) vdso_addr);
+ return 0;
+}
+
+static uintptr_t
+parse_address (const char *str)
+{
+ void *r;
+ TEST_COMPARE (sscanf (str, "%p\n", &r), 1);
+ return (uintptr_t) r;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+ size_t lenpre = strlen (pre);
+ size_t lenstr = strlen (str);
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ vdso_addr = getauxval (AT_SYSINFO_EHDR);
+ if (vdso_addr == 0)
+ FAIL_UNSUPPORTED ("getauxval (AT_SYSINFO_EHDR) returned 0");
+
+ /* We must have either:
+ - One our fource parameters left if called initially:
+ + path to ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name */
+ if (restart)
+ return handle_restart ();
+
+ char *spargv[9];
+ int i = 0;
+ for (; i < argc - 1; i++)
+ spargv[i] = argv[i + 1];
+ spargv[i++] = (char *) "--direct";
+ spargv[i++] = (char *) "--restart";
+ spargv[i] = NULL;
+
+ setenv ("LD_AUDIT", "tst-auditmod22.so", 0);
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
+
+ /* The respawned process should always print the vDSO address (otherwise it
+ will fails as unsupported). However, on some architectures the audit
+ module might see the vDSO with l_addr being 0, meaning a fixed mapping
+ (linux-gate.so). In this case we don't its value against AT_SYSINFO_EHDR
+ one. */
+ uintptr_t vdso_process = 0;
+ bool vdso_audit_found = false;
+ uintptr_t vdso_audit = 0;
+
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
+ TEST_VERIFY (out != NULL);
+ char *buffer = NULL;
+ size_t buffer_length = 0;
+ while (xgetline (&buffer, &buffer_length, out))
+ {
+ if (startswith (buffer, "vdso: "))
+ vdso_process = parse_address (buffer + strlen ("vdso "));
+ else if (startswith (buffer, "vdso found: "))
+ {
+ vdso_audit = parse_address (buffer + strlen ("vdso found: "));
+ vdso_audit_found = true;
+ }
+ }
+
+ TEST_COMPARE (vdso_audit_found, true);
+ if (vdso_audit != 0)
+ TEST_COMPARE (vdso_process, vdso_audit);
+
+ free (buffer);
+ xfclose (out);
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c
new file mode 100644
index 0000000000..8e05ce8cbb
--- /dev/null
+++ b/elf/tst-auditmod22.c
@@ -0,0 +1,51 @@
+/* Check DTAUDIT and vDSO interaction.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <string.h>
+#include <stdio.h>
+#include <sys/auxv.h>
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+ size_t lenpre = strlen (pre);
+ size_t lenstr = strlen (str);
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ /* The linux-gate.so is placed at a fixed address, thus l_addr being 0,
+ and it might be the value reported as the AT_SYSINFO_EHDR. */
+ if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so"))
+ fprintf (stderr, "vdso found: %p\n", NULL);
+ else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
+ fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
+
+ return 0;
+}
diff --git a/include/dlfcn.h b/include/dlfcn.h
index a4c283728f..66bcf2dff9 100644
--- a/include/dlfcn.h
+++ b/include/dlfcn.h
@@ -12,6 +12,7 @@
#define __RTLD_AUDIT 0x08000000
#define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
#define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */
+#define __RTLD_VDSO 0x01000000
#define __LM_ID_CALLER -2
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO
2021-11-15 18:37 ` [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
@ 2021-12-18 20:00 ` Florian Weimer
2021-12-20 12:50 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-18 20:00 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> The vDSO is is listed in the link_map chain, but is never the subject of
> an la_objopen call. A new internal flag __RTLD_VDSO is added that
> acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate'
> extra space for the 'struct link_map'.
>
> The return value from the callback() is currently ignored, since there
> is no PLT call involved by glibc when using the vDSO, neither the vDSO
> are exported directly.
The usual comment about (). 8-)
> diff --git a/elf/dl-object.c b/elf/dl-object.c
> index eb2158a84b..6f26da4310 100644
> --- a/elf/dl-object.c
> +++ b/elf/dl-object.c
> @@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type,
> {
> #ifdef SHARED
> unsigned int naudit;
> - if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
> + if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0))
> {
> - assert (type == lt_executable);
> - assert (nsid == LM_ID_BASE);
> + if (mode & __RTLD_OPENEXEC)
> + {
> + assert (type == lt_executable);
> + assert (nsid == LM_ID_BASE);
>
> - /* Ignore the specified libname for the main executable. It is
> - only known with an explicit loader invocation. */
> - libname = "";
> + /* Ignore the specified libname for the main executable. It is
> + only known with an explicit loader invocation. */
> + libname = "";
> + }
>
> - /* We create the map for the executable before we know whether
> + /* We create the map for the executable and vDSO before we know whether
> we have auditing libraries and if yes, how many. Assume the
> worst. */
> naudit = DL_NNS;
Okay, we call _dl_new_object early for the vDSO, too, so the comment is
appropriate.
> diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c
> new file mode 100644
> index 0000000000..f136f25a32
> --- /dev/null
> +++ b/elf/tst-audit22.c
> + /* The respawned process should always print the vDSO address (otherwise it
> + will fails as unsupported). However, on some architectures the audit
> + module might see the vDSO with l_addr being 0, meaning a fixed mapping
> + (linux-gate.so). In this case we don't its value against AT_SYSINFO_EHDR
> + one. */
“we don't [check] its value”
> + uintptr_t vdso_process = 0;
> + bool vdso_audit_found = false;
> + uintptr_t vdso_audit = 0;
> +
> + FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
> + TEST_VERIFY (out != NULL);
> + char *buffer = NULL;
> + size_t buffer_length = 0;
> + while (xgetline (&buffer, &buffer_length, out))
> + {
> + if (startswith (buffer, "vdso: "))
> + vdso_process = parse_address (buffer + strlen ("vdso "));
"vdso: " (with colon), but sscanf already skips the leading space.
> +#define TEST_FUNCTION_ARGV do_test
> +#include <support/test-driver.c>
> diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c
> new file mode 100644
> index 0000000000..8e05ce8cbb
> +static inline bool
> +startswith (const char *str, const char *pre)
> +{
> + size_t lenpre = strlen (pre);
> + size_t lenstr = strlen (str);
> + return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
> +}
lenstr >= lenpre && memcmp (pre, str, lenpre) == 0
> +
> +unsigned int
> +la_version (unsigned int version)
> +{
> + return LAV_CURRENT;
> +}
> +
> +unsigned int
> +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
> +{
> + /* The linux-gate.so is placed at a fixed address, thus l_addr being 0,
> + and it might be the value reported as the AT_SYSINFO_EHDR. */
> + if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so"))
> + fprintf (stderr, "vdso found: %p\n", NULL);
> + else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
> + fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
> +
> + return 0;
> +}
Would it be possible to look at the program headers to get the minimum
mapped address for the linux-gate.so object?
> diff --git a/include/dlfcn.h b/include/dlfcn.h
> index a4c283728f..66bcf2dff9 100644
> --- a/include/dlfcn.h
> +++ b/include/dlfcn.h
> @@ -12,6 +12,7 @@
> #define __RTLD_AUDIT 0x08000000
> #define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
> #define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */
> +#define __RTLD_VDSO 0x01000000
>
> #define __LM_ID_CALLER -2
The __RTLD_VDSO definition is unique, okay. But maybe add a comment,
like “Tell _dl_new_object the object is system-loaded.”
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO
2021-12-18 20:00 ` Florian Weimer
@ 2021-12-20 12:50 ` Adhemerval Zanella
2021-12-20 13:18 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 12:50 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 18/12/2021 17:00, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> The vDSO is is listed in the link_map chain, but is never the subject of
>> an la_objopen call. A new internal flag __RTLD_VDSO is added that
>> acts as __RTLD_OPENEXEC to allocate the required 'struct auditstate'
>> extra space for the 'struct link_map'.
>>
>> The return value from the callback() is currently ignored, since there
>> is no PLT call involved by glibc when using the vDSO, neither the vDSO
>> are exported directly.
>
> The usual comment about (). 8-)
Ack.
>
>> diff --git a/elf/dl-object.c b/elf/dl-object.c
>> index eb2158a84b..6f26da4310 100644
>> --- a/elf/dl-object.c
>> +++ b/elf/dl-object.c
>> @@ -59,16 +59,19 @@ _dl_new_object (char *realname, const char *libname, int type,
>> {
>> #ifdef SHARED
>> unsigned int naudit;
>> - if (__glibc_unlikely ((mode & __RTLD_OPENEXEC) != 0))
>> + if (__glibc_unlikely ((mode & (__RTLD_OPENEXEC | __RTLD_VDSO)) != 0))
>> {
>> - assert (type == lt_executable);
>> - assert (nsid == LM_ID_BASE);
>> + if (mode & __RTLD_OPENEXEC)
>> + {
>> + assert (type == lt_executable);
>> + assert (nsid == LM_ID_BASE);
>>
>> - /* Ignore the specified libname for the main executable. It is
>> - only known with an explicit loader invocation. */
>> - libname = "";
>> + /* Ignore the specified libname for the main executable. It is
>> + only known with an explicit loader invocation. */
>> + libname = "";
>> + }
>>
>> - /* We create the map for the executable before we know whether
>> + /* We create the map for the executable and vDSO before we know whether
>> we have auditing libraries and if yes, how many. Assume the
>> worst. */
>> naudit = DL_NNS;
>
> Okay, we call _dl_new_object early for the vDSO, too, so the comment is
> appropriate.
>
>> diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c
>> new file mode 100644
>> index 0000000000..f136f25a32
>> --- /dev/null
>> +++ b/elf/tst-audit22.c
>
>> + /* The respawned process should always print the vDSO address (otherwise it
>> + will fails as unsupported). However, on some architectures the audit
>> + module might see the vDSO with l_addr being 0, meaning a fixed mapping
>> + (linux-gate.so). In this case we don't its value against AT_SYSINFO_EHDR
>> + one. */
>
> “we don't [check] its value”
Ack.
>
>> + uintptr_t vdso_process = 0;
>> + bool vdso_audit_found = false;
>> + uintptr_t vdso_audit = 0;
>> +
>> + FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
>> + TEST_VERIFY (out != NULL);
>> + char *buffer = NULL;
>> + size_t buffer_length = 0;
>> + while (xgetline (&buffer, &buffer_length, out))
>> + {
>> + if (startswith (buffer, "vdso: "))
>> + vdso_process = parse_address (buffer + strlen ("vdso "));
>
> "vdso: " (with colon), but sscanf already skips the leading space.
Ack.
>
>> +#define TEST_FUNCTION_ARGV do_test
>> +#include <support/test-driver.c>
>> diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c
>> new file mode 100644
>> index 0000000000..8e05ce8cbb
>
>> +static inline bool
>> +startswith (const char *str, const char *pre)
>> +{
>> + size_t lenpre = strlen (pre);
>> + size_t lenstr = strlen (str);
>> + return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
>> +}
>
> lenstr >= lenpre && memcmp (pre, str, lenpre) == 0
Ack.
>
>> +
>> +unsigned int
>> +la_version (unsigned int version)
>> +{
>> + return LAV_CURRENT;
>> +}
>> +
>> +unsigned int
>> +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
>> +{
>> + /* The linux-gate.so is placed at a fixed address, thus l_addr being 0,
>> + and it might be the value reported as the AT_SYSINFO_EHDR. */
>> + if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so"))
>> + fprintf (stderr, "vdso found: %p\n", NULL);
>> + else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
>> + fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
>> +
>> + return 0;
>> +}
>
> Would it be possible to look at the program headers to get the minimum
> mapped address for the linux-gate.so object?
It should be possible, but I only saw it on a ia64 machine (which I don't
have access anymore) and reading the kernel source linux-gate.so is
provided also for x86, sh, and sparc 32-bits kernels. I am not sure
if it worth the trouble.
>
>> diff --git a/include/dlfcn.h b/include/dlfcn.h
>> index a4c283728f..66bcf2dff9 100644
>> --- a/include/dlfcn.h
>> +++ b/include/dlfcn.h
>> @@ -12,6 +12,7 @@
>> #define __RTLD_AUDIT 0x08000000
>> #define __RTLD_SECURE 0x04000000 /* Apply additional security checks. */
>> #define __RTLD_NOIFUNC 0x02000000 /* Suppress calling ifunc functions. */
>> +#define __RTLD_VDSO 0x01000000
>>
>> #define __LM_ID_CALLER -2
>
> The __RTLD_VDSO definition is unique, okay. But maybe add a comment,
> like “Tell _dl_new_object the object is system-loaded.”
Ack.
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO
2021-12-20 12:50 ` Adhemerval Zanella
@ 2021-12-20 13:18 ` Florian Weimer
0 siblings, 0 replies; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 13:18 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
>>> +unsigned int
>>> +la_version (unsigned int version)
>>> +{
>>> + return LAV_CURRENT;
>>> +}
>>> +
>>> +unsigned int
>>> +la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
>>> +{
>>> + /* The linux-gate.so is placed at a fixed address, thus l_addr being 0,
>>> + and it might be the value reported as the AT_SYSINFO_EHDR. */
>>> + if (map->l_addr == 0 && startswith (map->l_name, "linux-gate.so"))
>>> + fprintf (stderr, "vdso found: %p\n", NULL);
>>> + else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
>>> + fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
>>> +
>>> + return 0;
>>> +}
>>
>> Would it be possible to look at the program headers to get the minimum
>> mapped address for the linux-gate.so object?
>
> It should be possible, but I only saw it on a ia64 machine (which I don't
> have access anymore) and reading the kernel source linux-gate.so is
> provided also for x86, sh, and sparc 32-bits kernels. I am not sure
> if it worth the trouble.
Fair enough, keep the current version then.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (13 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 14/20] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-18 20:08 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 16/20] elf: Add main application on main_map l_name Adhemerval Zanella
` (4 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
The DSO constructor should not be ignored if the main executable
has the SONAME set to a dependency. It fixes the case where
(using the scripts/dso-ordering-test.py definition):
{}->a->b->c;soname({})=c
Where the constructors should return
c>b>a>{}<a<b<c
Checked on x86_64-linux-gnu.
---
elf/dl-load.c | 11 +++++++++--
elf/dso-sort-tests-1.def | 5 ++++-
2 files changed, 13 insertions(+), 3 deletions(-)
diff --git a/elf/dl-load.c b/elf/dl-load.c
index e28893b779..6bf1eabfe5 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1993,13 +1993,20 @@ _dl_map_object (struct link_map *loader, const char *name,
assert (nsid >= 0);
assert (nsid < GL(dl_nns));
+ /* Special case: trying to map itself. An empty name correspond to
+ a NULL or "" argument for dlopen(), and it returns the head object
+ of the namespace. */
+ if (name[0] == '\0')
+ return GL(dl_ns)[nsid]._ns_loaded;
+
/* Look for this name among those already loaded. */
for (l = GL(dl_ns)[nsid]._ns_loaded; l; l = l->l_next)
{
/* If the requested name matches the soname of a loaded object,
use that object. Elide this check for names that have not
- yet been opened. */
- if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0))
+ yet been opened or the executable itself. */
+ if (__glibc_unlikely ((l->l_faked | l->l_removed) != 0
+ || l->l_type == lt_executable))
continue;
if (!_dl_name_match_p (name, l))
{
diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def
index 5f7f18ef27..2228910c0d 100644
--- a/elf/dso-sort-tests-1.def
+++ b/elf/dso-sort-tests-1.def
@@ -50,7 +50,10 @@ output: e>d>c>b>a>{}<a<b<c<d<e
# Test if init/fini ordering behavior is proper, despite main program with
# an soname that may cause confusion
tst-dso-ordering10: {}->a->b->c;soname({})=c
-output: b>a>{}<a<b
+output: c>b>a>{}<a<b<c
+# Same as before, but setting the soname as a direct dependency.
+tst-dso-ordering11: {}->a->b->c;soname({})=a
+output: c>b>a>{}<a<b<c
# Complex example from Bugzilla #15311, under-linked and with circular
# relocation(dynamic) dependencies. While this is technically unspecified, the
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency
2021-11-15 18:37 ` [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
@ 2021-12-18 20:08 ` Florian Weimer
2021-12-20 16:49 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-18 20:08 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> The DSO constructor should not be ignored if the main executable
> has the SONAME set to a dependency. It fixes the case where
> (using the scripts/dso-ordering-test.py definition):
>
> {}->a->b->c;soname({})=c
>
> Where the constructors should return
>
> c>b>a>{}<a<b<c
I'm a bit unclear what is this trying to fix.
It reminds me of this change:
commit 9ffa50b26b0cb5d3043adf6d3d0b1ea735acc147
Author: Florian Weimer <fweimer@redhat.com>
Date: Fri Dec 11 17:30:03 2020 +0100
elf: Include libc.so.6 as main program in dependency sort (bug 20972)
_dl_map_object_deps always sorts the initially loaded object first
during dependency sorting. This means it is relocated last in
dl_open_worker. This results in crashes in IFUNC resolvers without
lazy bindings if libraries are preloaded that refer to IFUNCs in
libc.so.6: the resolvers are called when libc.so.6 has not been
relocated yet, so references to _rtld_global_ro etc. crash.
The fix is to check against the libc.so.6 link map recorded by the
__libc_early_init framework, and let it participate in the dependency
sort.
This fixes bug 20972.
Reviewed-by: Carlos O'Donell <carlos@redhat.com>
Is it a more general/correct version of this commit?
But if the main program has a soname, wouldn't we stop loading it as a
dependency, too? So that the expected ouptut turns into:
b>a>{}<a<b
because the separate c is not actually loaded.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency
2021-12-18 20:08 ` Florian Weimer
@ 2021-12-20 16:49 ` Adhemerval Zanella
2021-12-20 16:52 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 16:49 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 18/12/2021 17:08, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> The DSO constructor should not be ignored if the main executable
>> has the SONAME set to a dependency. It fixes the case where
>> (using the scripts/dso-ordering-test.py definition):
>>
>> {}->a->b->c;soname({})=c
>>
>> Where the constructors should return
>>
>> c>b>a>{}<a<b<c
>
> I'm a bit unclear what is this trying to fix.
The issue is tst-dso-ordering11 sets its SONAME as one of its NEEDED objects:
$ readelf -d t
st-dso-ordering11 | grep 'SONAME\|NEEDED'
0x0000000000000001 (NEEDED) Shared library: [[...]/tst-dso-ordering11-dir/tst-dso-ordering11-a.so]
0x0000000000000001 (NEEDED) Shared library: [libc.so.6]
0x000000000000000e (SONAME) Library soname: [[...]/tst-dso-ordering11-dir/tst-dso-ordering11-a.so]
And then the tst-dso-ordering11-a.so constructor is skipped.
>
> It reminds me of this change:
>
> commit 9ffa50b26b0cb5d3043adf6d3d0b1ea735acc147
> Author: Florian Weimer <fweimer@redhat.com>
> Date: Fri Dec 11 17:30:03 2020 +0100
>
> elf: Include libc.so.6 as main program in dependency sort (bug 20972)
>
> _dl_map_object_deps always sorts the initially loaded object first
> during dependency sorting. This means it is relocated last in
> dl_open_worker. This results in crashes in IFUNC resolvers without
> lazy bindings if libraries are preloaded that refer to IFUNCs in
> libc.so.6: the resolvers are called when libc.so.6 has not been
> relocated yet, so references to _rtld_global_ro etc. crash.
>
> The fix is to check against the libc.so.6 link map recorded by the
> __libc_early_init framework, and let it participate in the dependency
> sort.
>
> This fixes bug 20972.
>
> Reviewed-by: Carlos O'Donell <carlos@redhat.com>
>
> Is it a more general/correct version of this commit?
I think it is unrelated.
>
> But if the main program has a soname, wouldn't we stop loading it as a
> dependency, too? So that the expected ouptut turns into:
>
> b>a>{}<a<b
>
> because the separate c is not actually loaded.
Right, so if the idea is indeed to not load an dependency that matches the
binary SONAME current behavior is indeed what is expected. Not sure if
this the expected behavior, if so I will drop this patch.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency
2021-12-20 16:49 ` Adhemerval Zanella
@ 2021-12-20 16:52 ` Florian Weimer
2021-12-20 16:55 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 16:52 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
>> But if the main program has a soname, wouldn't we stop loading it as a
>> dependency, too? So that the expected ouptut turns into:
>>
>> b>a>{}<a<b
>>
>> because the separate c is not actually loaded.
>
> Right, so if the idea is indeed to not load an dependency that matches the
> binary SONAME current behavior is indeed what is expected. Not sure if
> this the expected behavior, if so I will drop this patch.
Is it the current behavior?
I can see some value in preserving that, e.g. for scripting language
interpreters which historically avoided DSOs for the core interpreter,
preferring position-dependent code for it (but still offering a DSO for
embedding). They may even set DT_SONAME on the main program; I haven't
checked.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency
2021-12-20 16:52 ` Florian Weimer
@ 2021-12-20 16:55 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 16:55 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 20/12/2021 13:52, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>>> But if the main program has a soname, wouldn't we stop loading it as a
>>> dependency, too? So that the expected ouptut turns into:
>>>
>>> b>a>{}<a<b
>>>
>>> because the separate c is not actually loaded.
>>
>> Right, so if the idea is indeed to not load an dependency that matches the
>> binary SONAME current behavior is indeed what is expected. Not sure if
>> this the expected behavior, if so I will drop this patch.
>
> Is it the current behavior?
Yes.
>
> I can see some value in preserving that, e.g. for scripting language
> interpreters which historically avoided DSOs for the core interpreter,
> preferring position-dependent code for it (but still offering a DSO for
> embedding). They may even set DT_SONAME on the main program; I haven't
> checked.
Right, this does make sense (although accomplished in a kinda hackish
way).
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 16/20] elf: Add main application on main_map l_name
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (14 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 15/20] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-20 13:32 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 17/20] elf: Add la_activity during application exit Adhemerval Zanella
` (3 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
For the la_objopen() the path listed in link_map->l_name for the main
application binary is empty, even though dladdr() is able to recover the
correct path.
By setting the expected application name on l_name, it allows to
simplify the code to handle the special case and make the API that
return such information (la_objopen(), dladdr() and dlinfo() to have
similar semantic.
Checked on x86_64-linux-gnu.
---
dlfcn/Makefile | 4 ++-
dlfcn/tst-dladdr-self.c | 55 +++++++++++++++++++++++++++++++++++++++++
elf/dl-addr.c | 5 ----
elf/dl-dst.h | 2 +-
elf/dl-init.c | 3 +--
elf/dl-misc.c | 1 +
elf/rtld.c | 6 +----
elf/tst-audit22.c | 4 +++
elf/tst-auditmod22.c | 8 ++++++
gmon/gmon.c | 10 ++++----
10 files changed, 79 insertions(+), 19 deletions(-)
create mode 100644 dlfcn/tst-dladdr-self.c
diff --git a/dlfcn/Makefile b/dlfcn/Makefile
index 6bbfbb8344..bceb2b2885 100644
--- a/dlfcn/Makefile
+++ b/dlfcn/Makefile
@@ -51,7 +51,7 @@ endif
ifeq (yes,$(build-shared))
tests = glrefmain failtest tst-dladdr default errmsg1 tstcxaatexit \
bug-dlopen1 bug-dlsym1 tst-dlinfo bug-atexit1 bug-atexit2 \
- bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen
+ bug-atexit3 tstatexit bug-dl-leaf tst-rec-dlopen tst-dladdr-self
endif
modules-names = glreflib1 glreflib2 glreflib3 failtestmod defaultmod1 \
defaultmod2 errmsg1mod modatexit modcxaatexit \
@@ -143,3 +143,5 @@ $(objpfx)bug-dl-leaf.out: $(objpfx)bug-dl-leaf-lib-cb.so
$(objpfx)bug-dl-leaf-lib-cb.so: $(objpfx)bug-dl-leaf-lib.so
$(objpfx)tst-rec-dlopen.out: $(objpfx)moddummy1.so $(objpfx)moddummy2.so
+
+LDFLAGS-tst-dladdr-self = -rdynamic
diff --git a/dlfcn/tst-dladdr-self.c b/dlfcn/tst-dladdr-self.c
new file mode 100644
index 0000000000..0eddaf1cd7
--- /dev/null
+++ b/dlfcn/tst-dladdr-self.c
@@ -0,0 +1,55 @@
+/* Check dladdr with the reference to own exectuable.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+void
+test_symbol (void)
+{
+}
+
+static int
+do_test (void)
+{
+ void *handle = xdlopen (NULL, RTLD_NOW);
+ int (*sym)(void) = xdlsym (handle, "test_symbol");
+
+ Dl_info info = { 0 };
+ {
+ int r = dladdr (sym, &info);
+ TEST_VERIFY_EXIT (r != 0);
+ }
+
+ {
+ const char *p = strrchr (info.dli_fname, '/');
+ const char *dli_name = p == NULL ? info.dli_fname : p + 1;
+
+ TEST_COMPARE_STRING (dli_name, "tst-dladdr-self");
+ }
+
+ TEST_COMPARE_STRING (info.dli_sname, "test_symbol");
+ TEST_COMPARE ((uintptr_t) info.dli_saddr, (uintptr_t) test_symbol);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/dl-addr.c b/elf/dl-addr.c
index 3226880d48..c2c93c63ad 100644
--- a/elf/dl-addr.c
+++ b/elf/dl-addr.c
@@ -30,11 +30,6 @@ determine_info (const ElfW(Addr) addr, struct link_map *match, Dl_info *info,
info->dli_fname = match->l_name;
info->dli_fbase = (void *) match->l_map_start;
- /* If this is the main program the information is incomplete. */
- if (__builtin_expect (match->l_name[0], 'a') == '\0'
- && match->l_type == lt_executable)
- info->dli_fname = _dl_argv[0];
-
const ElfW(Sym) *symtab
= (const ElfW(Sym) *) D_PTR (match, l_info[DT_SYMTAB]);
const char *strtab = (const char *) D_PTR (match, l_info[DT_STRTAB]);
diff --git a/elf/dl-dst.h b/elf/dl-dst.h
index 34bbaf65dc..a1e9af5a06 100644
--- a/elf/dl-dst.h
+++ b/elf/dl-dst.h
@@ -44,7 +44,7 @@
auditing, in ld.so. */ \
if ((l)->l_origin == NULL) \
{ \
- assert ((l)->l_name[0] == '\0' || IS_RTLD (l)); \
+ assert ((l)->l_type == lt_executable || IS_RTLD (l)); \
(l)->l_origin = _dl_get_origin (); \
dst_len = ((l)->l_origin && (l)->l_origin != (char *) -1 \
? strlen ((l)->l_origin) : 0); \
diff --git a/elf/dl-init.c b/elf/dl-init.c
index f924d26642..9fa8403290 100644
--- a/elf/dl-init.c
+++ b/elf/dl-init.c
@@ -39,8 +39,7 @@ call_init (struct link_map *l, int argc, char **argv, char **env)
l->l_init_called = 1;
/* Check for object which constructors we do not run here. */
- if (__builtin_expect (l->l_name[0], 'a') == '\0'
- && l->l_type == lt_executable)
+ if (l->l_type == lt_executable)
return;
/* Print a debug message if wanted. */
diff --git a/elf/dl-misc.c b/elf/dl-misc.c
index b256d792c6..b62bbcb8b4 100644
--- a/elf/dl-misc.c
+++ b/elf/dl-misc.c
@@ -338,6 +338,7 @@ rtld_hidden_def (_dl_fatal_printf)
int
_dl_name_match_p (const char *name, const struct link_map *map)
{
+ /* Filter out the main executable. */
if (strcmp (name, map->l_name) == 0)
return 1;
diff --git a/elf/rtld.c b/elf/rtld.c
index 55b4eb91f2..29a37f51d3 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1361,11 +1361,6 @@ dl_main (const ElfW(Phdr) *phdr,
phdr = main_map->l_phdr;
phnum = main_map->l_phnum;
- /* We overwrite here a pointer to a malloc()ed string. But since
- the malloc() implementation used at this point is the dummy
- implementations which has no real free() function it does not
- makes sense to free the old string first. */
- main_map->l_name = (char *) "";
*user_entry = main_map->l_entry;
/* Set bit indicating this is the main program map. */
@@ -1431,6 +1426,7 @@ dl_main (const ElfW(Phdr) *phdr,
information for the program. */
}
+ main_map->l_name = _dl_argv[0];
main_map->l_map_end = 0;
main_map->l_text_end = 0;
/* Perhaps the executable has no PT_LOAD header entries at all. */
diff --git a/elf/tst-audit22.c b/elf/tst-audit22.c
index f136f25a32..f5e16c69fe 100644
--- a/elf/tst-audit22.c
+++ b/elf/tst-audit22.c
@@ -94,6 +94,7 @@ do_test (int argc, char *argv[])
uintptr_t vdso_process = 0;
bool vdso_audit_found = false;
uintptr_t vdso_audit = 0;
+ bool mainapp_found = false;
FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
TEST_VERIFY (out != NULL);
@@ -108,11 +109,14 @@ do_test (int argc, char *argv[])
vdso_audit = parse_address (buffer + strlen ("vdso found: "));
vdso_audit_found = true;
}
+ else if (startswith (buffer, "mainapp found"))
+ mainapp_found = true;
}
TEST_COMPARE (vdso_audit_found, true);
if (vdso_audit != 0)
TEST_COMPARE (vdso_process, vdso_audit);
+ TEST_COMPARE (mainapp_found, true);
free (buffer);
xfclose (out);
diff --git a/elf/tst-auditmod22.c b/elf/tst-auditmod22.c
index 8e05ce8cbb..687789ab34 100644
--- a/elf/tst-auditmod22.c
+++ b/elf/tst-auditmod22.c
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <string.h>
#include <stdio.h>
+#include <string.h>
#include <sys/auxv.h>
static inline bool
@@ -47,5 +48,12 @@ la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
else if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
fprintf (stderr, "vdso found: %p\n", (void*) map->l_addr);
+ {
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ if (strcmp (l_name, "tst-audit22") == 0)
+ fprintf (stderr, "mainapp found\n");
+ }
+
return 0;
}
diff --git a/gmon/gmon.c b/gmon/gmon.c
index dee64803ad..cb8327b8e4 100644
--- a/gmon/gmon.c
+++ b/gmon/gmon.c
@@ -48,16 +48,16 @@
#ifdef PIC
# include <link.h>
+# include <ldsodefs.h>
static int
callback (struct dl_phdr_info *info, size_t size, void *data)
{
- if (info->dlpi_name[0] == '\0')
+ if (info->dlpi_name == _dl_argv[0])
{
- /* The link map for the executable is created by calling
- _dl_new_object with "" as filename. dl_iterate_phdr
- calls the callback function with filename from the
- link map as dlpi_name. */
+ /* The link map l_name for the executable is set to the _dl_argv[0]
+ after argument processing. dl_iterate_phdr() calls the callback
+ function with filename from the link map as dlpi_name. */
u_long *load_address = data;
*load_address = (u_long) info->dlpi_addr;
return 1;
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 16/20] elf: Add main application on main_map l_name
2021-11-15 18:37 ` [PATCH v6 16/20] elf: Add main application on main_map l_name Adhemerval Zanella
@ 2021-12-20 13:32 ` Florian Weimer
2021-12-20 18:04 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 13:32 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> For the la_objopen() the path listed in link_map->l_name for the main
> application binary is empty, even though dladdr() is able to recover the
> correct path.
>
> By setting the expected application name on l_name, it allows to
> simplify the code to handle the special case and make the API that
> return such information (la_objopen(), dladdr() and dlinfo() to have
> similar semantic.
I would like to recommend skipping this patch for now, as discussed. At
least "" is unambiguous, a real-looking path won't be because in some
cases, we just can't provide an accurate path.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 16/20] elf: Add main application on main_map l_name
2021-12-20 13:32 ` Florian Weimer
@ 2021-12-20 18:04 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 18:04 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 20/12/2021 10:32, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> For the la_objopen() the path listed in link_map->l_name for the main
>> application binary is empty, even though dladdr() is able to recover the
>> correct path.
>>
>> By setting the expected application name on l_name, it allows to
>> simplify the code to handle the special case and make the API that
>> return such information (la_objopen(), dladdr() and dlinfo() to have
>> similar semantic.
>
> I would like to recommend skipping this patch for now, as discussed. At
> least "" is unambiguous, a real-looking path won't be because in some
> cases, we just can't provide an accurate path.
>
Fair enough. I also changed to take in consideration the previous comments:
main_map->l_name = __glibc_unlikely (__libc_enable_secure)
? (char *) "/proc/self/exe"
: rtld_is_main ? _dl_argv[0] : GLRO(dl_execfn);
But I can discuss in another patch submission.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 17/20] elf: Add la_activity during application exit
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (15 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 16/20] elf: Add main application on main_map l_name Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-20 13:34 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
` (2 subsequent siblings)
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
la_activity() is not called during application exit, even though
la_objclose is.
Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
elf/Makefile | 7 ++
elf/dl-fini.c | 9 +++
elf/tst-audit23.c | 173 +++++++++++++++++++++++++++++++++++++++++++
elf/tst-audit23mod.c | 23 ++++++
elf/tst-auditmod23.c | 68 +++++++++++++++++
5 files changed, 280 insertions(+)
create mode 100644 elf/tst-audit23.c
create mode 100644 elf/tst-audit23mod.c
create mode 100644 elf/tst-auditmod23.c
diff --git a/elf/Makefile b/elf/Makefile
index 35e45d969e..ee4daae0fc 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -236,6 +236,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit20 \
tst-audit21 \
tst-audit22 \
+ tst-audit23 \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -385,6 +386,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod21a \
tst-auditmod21b \
tst-auditmod22 \
+ tst-auditmod23 \
+ tst-audit23mod \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1588,6 +1591,10 @@ tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so
$(objpfx)tst-audit22.out: $(objpfx)tst-auditmod22.so
tst-audit22-ARGS = -- $(host-test-program-cmd)
+$(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \
+ $(objpfx)tst-audit23mod.so
+tst-audit23-ARGS = -- $(host-test-program-cmd)
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-fini.c b/elf/dl-fini.c
index 1720cfaeb8..7c5f2f0e40 100644
--- a/elf/dl-fini.c
+++ b/elf/dl-fini.c
@@ -64,6 +64,10 @@ _dl_fini (void)
__rtld_lock_unlock_recursive (GL(dl_load_lock));
else
{
+#ifdef SHARED
+ /* Auditing checkpoint: we will start deleting objects. */
+ _dl_audit_activity_nsid (ns, LA_ACT_DELETE);
+#endif
/* Now we can allocate an array to hold all the pointers and
copy the pointers in. */
struct link_map *maps[nloaded];
@@ -153,6 +157,11 @@ _dl_fini (void)
/* Correct the previous increment. */
--l->l_direct_opencount;
}
+
+#ifdef SHARED
+ /* Auditing checkpoint: we will start deleting objects. */
+ _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT);
+#endif
}
}
diff --git a/elf/tst-audit23.c b/elf/tst-audit23.c
new file mode 100644
index 0000000000..c0070b3b00
--- /dev/null
+++ b/elf/tst-audit23.c
@@ -0,0 +1,173 @@
+/* Check DT_AUDIT la_objopen and la_objclose for all objects.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <gnu/lib-names.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/xdlfcn.h>
+#include <support/support.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+static int
+handle_restart (void)
+{
+ xdlopen ("tst-audit23mod.so", RTLD_NOW);
+ xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
+
+ return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+ size_t lenpre = strlen (pre);
+ size_t lenstr = strlen (str);
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static inline bool
+is_name_vdso (const char *str)
+{
+ return startswith (str, "linux-gate")
+ || startswith (str, "linux-vdso");
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ /* We must have either:
+ - One our fource parameters left if called initially:
+ + path to ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name */
+ if (restart)
+ return handle_restart ();
+
+ char *spargv[9];
+ int i = 0;
+ for (; i < argc - 1; i++)
+ spargv[i] = argv[i + 1];
+ spargv[i++] = (char *) "--direct";
+ spargv[i++] = (char *) "--restart";
+ spargv[i] = NULL;
+
+ setenv ("LD_AUDIT", "tst-auditmod23.so", 0);
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit22", 0, sc_allow_stderr);
+
+
+ /* We expect la_objopen/la_objclose for the objects:
+ 1. executable
+ 2. loader
+ 3. libc.so
+ 4. tst-audit23mod.so
+ 5. libc.so (LM_ID_NEWLM).
+ 6. vdso (optional and ignored). */
+ enum { max_objs = 6 };
+ struct la_obj_t
+ {
+ char *lname;
+ uintptr_t laddr;
+ Lmid_t lmid;
+ bool closed;
+ } objs[max_objs] = { [0 ... max_objs-1] = { .closed = false } };
+ size_t nobjs = 0;
+
+ FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
+ TEST_VERIFY (out != NULL);
+ char *buffer = NULL;
+ size_t buffer_length = 0;
+ while (xgetline (&buffer, &buffer_length, out))
+ {
+ enum { LA_OBJOPEN, LA_OBJCLOSE} mode;
+ ptrdiff_t offset;
+ if (startswith (buffer, "la_objopen: "))
+ {
+ offset = strlen ("la_objopen: ");
+ mode = LA_OBJOPEN;
+ }
+ else if (startswith (buffer, "la_objclose: "))
+ {
+ offset = strlen ("la_objclose: ");
+ mode = LA_OBJCLOSE;
+ }
+ else
+ continue;
+
+ char *lname;
+ uintptr_t laddr;
+ Lmid_t lmid;
+ int r = sscanf (buffer + offset, "%ms %"SCNxPTR" %ld", &lname, &laddr,
+ &lmid);
+ TEST_COMPARE (r, 3);
+
+ if (mode == LA_OBJOPEN)
+ {
+ /* la_objclose is not triggered by vDSO because glibc does not
+ unload it. */
+ if (is_name_vdso (lname))
+ continue;
+ if (nobjs == max_objs)
+ FAIL_EXIT1 ("non expected la_objopen: %s %"PRIxPTR" %ld",
+ lname, laddr, lmid);
+ objs[nobjs].lname = lname;
+ objs[nobjs].laddr = laddr;
+ objs[nobjs].lmid = lmid;
+ objs[nobjs].closed = false;
+ nobjs++;
+ }
+ else if (mode == LA_OBJCLOSE)
+ {
+ for (size_t i = 0; i < nobjs; i++)
+ {
+ if (strcmp (lname, objs[i].lname) == 0 && lmid == objs[i].lmid)
+ {
+ TEST_COMPARE (objs[i].closed, false);
+ objs[i].closed = true;
+ break;
+ }
+ }
+ }
+ }
+
+ for (size_t i = 0; i < nobjs; i++)
+ {
+ TEST_COMPARE (objs[i].closed, true);
+ free (objs[i].lname);
+ }
+
+ free (buffer);
+ xfclose (out);
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit23mod.c b/elf/tst-audit23mod.c
new file mode 100644
index 0000000000..4ca66cf772
--- /dev/null
+++ b/elf/tst-audit23mod.c
@@ -0,0 +1,23 @@
+/* Extra modules for tst-audit23
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+int
+foo (void)
+{
+ return 0;
+}
diff --git a/elf/tst-auditmod23.c b/elf/tst-auditmod23.c
new file mode 100644
index 0000000000..869afd372f
--- /dev/null
+++ b/elf/tst-auditmod23.c
@@ -0,0 +1,68 @@
+/* Audit modules loaded by tst-audit23.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/auxv.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
+
+struct map_desc_t
+{
+ char *lname;
+ uintptr_t laddr;
+ Lmid_t lmid;
+};
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ fprintf (stderr, "%s: %s %"PRIxPTR" %ld\n", __func__,
+ map->l_name, map->l_addr, lmid);
+
+ struct map_desc_t *map_desc = malloc (sizeof (struct map_desc_t));
+ if (map_desc == NULL)
+ abort ();
+
+ map_desc->lname = strdup (map->l_name);
+ map_desc->laddr = map->l_addr;
+ map_desc->lmid = lmid;
+
+ *cookie = (uintptr_t) map_desc;
+
+ return 0;
+}
+
+unsigned int
+la_objclose (uintptr_t *cookie)
+{
+ struct map_desc_t *map_desc = (struct map_desc_t *) *cookie;
+ fprintf (stderr, "%s: %s %"PRIxPTR" %ld\n", __func__,
+ map_desc->lname, map_desc->laddr, map_desc->lmid);
+ free (map_desc->lname);
+ free (map_desc);
+
+ return 0;
+}
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 17/20] elf: Add la_activity during application exit
2021-11-15 18:37 ` [PATCH v6 17/20] elf: Add la_activity during application exit Adhemerval Zanella
@ 2021-12-20 13:34 ` Florian Weimer
2021-12-20 19:46 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 13:34 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/dl-fini.c b/elf/dl-fini.c
> index 1720cfaeb8..7c5f2f0e40 100644
> --- a/elf/dl-fini.c
> +++ b/elf/dl-fini.c
> @@ -64,6 +64,10 @@ _dl_fini (void)
> __rtld_lock_unlock_recursive (GL(dl_load_lock));
> else
> {
> +#ifdef SHARED
> + /* Auditing checkpoint: we will start deleting objects. */
> + _dl_audit_activity_nsid (ns, LA_ACT_DELETE);
> +#endif
> /* Now we can allocate an array to hold all the pointers and
> copy the pointers in. */
> struct link_map *maps[nloaded];
> @@ -153,6 +157,11 @@ _dl_fini (void)
> /* Correct the previous increment. */
> --l->l_direct_opencount;
> }
> +
> +#ifdef SHARED
> + /* Auditing checkpoint: we will start deleting objects. */
> + _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT);
> +#endif
> }
> }
This looks okay in principle. I don't know if we want to merge my
_dl_fine rework first, though, in which case this change has to be
redone from scratch against the new version.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 17/20] elf: Add la_activity during application exit
2021-12-20 13:34 ` Florian Weimer
@ 2021-12-20 19:46 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 19:46 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 20/12/2021 10:34, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/dl-fini.c b/elf/dl-fini.c
>> index 1720cfaeb8..7c5f2f0e40 100644
>> --- a/elf/dl-fini.c
>> +++ b/elf/dl-fini.c
>> @@ -64,6 +64,10 @@ _dl_fini (void)
>> __rtld_lock_unlock_recursive (GL(dl_load_lock));
>> else
>> {
>> +#ifdef SHARED
>> + /* Auditing checkpoint: we will start deleting objects. */
>> + _dl_audit_activity_nsid (ns, LA_ACT_DELETE);
>> +#endif
>> /* Now we can allocate an array to hold all the pointers and
>> copy the pointers in. */
>> struct link_map *maps[nloaded];
>> @@ -153,6 +157,11 @@ _dl_fini (void)
>> /* Correct the previous increment. */
>> --l->l_direct_opencount;
>> }
>> +
>> +#ifdef SHARED
>> + /* Auditing checkpoint: we will start deleting objects. */
>> + _dl_audit_activity_nsid (ns, LA_ACT_CONSISTENT);
>> +#endif
>> }
>> }
>
> This looks okay in principle. I don't know if we want to merge my
> _dl_fine rework first, though, in which case this change has to be
> redone from scratch against the new version.
I will send as-is based on current master, if your rework got it first
I will rebase it.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734)
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (16 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 17/20] elf: Add la_activity during application exit Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-20 19:18 ` Florian Weimer
2021-11-15 18:37 ` [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
2021-11-15 18:37 ` [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
The audit callback is not called for binaries built with -Wl,-z,now or
when LD_BIND_NOW=1 is used. The PLT tracking callbacks are still not
issue for such case, since this will would change the expected program
semantic (where no PTL is expected) and also yield performance
implications (such as for BZ#15533).
To handle powerpc64 ELFv1 function descriptor, _dl_audit_symbind()
requires to know whether bind-now is used so the symbol value is
updated to function text segment instead of the OPD (for lazy binding
this is done by PPC64_LOAD_FUNCPTR on _dl_runtime_resolve).
Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
powerpc64-linux-gnu.
---
elf/Makefile | 86 ++++++++++++++++++++++
elf/dl-audit.c | 19 ++---
elf/dl-reloc.c | 8 +--
elf/dl-runtime.c | 4 +-
elf/do-rel.h | 65 +++++++++++++----
elf/tst-audit24a.c | 36 ++++++++++
elf/tst-audit24amod1.c | 31 ++++++++
elf/tst-audit24amod2.c | 25 +++++++
elf/tst-audit24b.c | 37 ++++++++++
elf/tst-audit24bmod1.c | 31 ++++++++
elf/tst-audit24bmod2.c | 23 ++++++
elf/tst-audit24c.c | 2 +
elf/tst-audit24d.c | 36 ++++++++++
elf/tst-audit24dmod1.c | 33 +++++++++
elf/tst-audit24dmod2.c | 28 ++++++++
elf/tst-audit24dmod3.c | 31 ++++++++
elf/tst-audit24dmod4.c | 25 +++++++
elf/tst-audit25a.c | 127 ++++++++++++++++++++++++++++++++
elf/tst-audit25b.c | 128 +++++++++++++++++++++++++++++++++
elf/tst-audit25mod1.c | 30 ++++++++
elf/tst-audit25mod2.c | 30 ++++++++
elf/tst-audit25mod3.c | 22 ++++++
elf/tst-audit25mod4.c | 22 ++++++
elf/tst-auditmod24.h | 29 ++++++++
elf/tst-auditmod24a.c | 113 +++++++++++++++++++++++++++++
elf/tst-auditmod24b.c | 103 ++++++++++++++++++++++++++
elf/tst-auditmod24c.c | 3 +
elf/tst-auditmod24d.c | 119 ++++++++++++++++++++++++++++++
elf/tst-auditmod25.c | 78 ++++++++++++++++++++
sysdeps/generic/dl-lookupcfg.h | 3 +
sysdeps/generic/ldsodefs.h | 2 +-
sysdeps/hppa/dl-lookupcfg.h | 3 +
sysdeps/ia64/dl-lookupcfg.h | 3 +
sysdeps/powerpc/dl-lookupcfg.h | 39 ++++++++++
34 files changed, 1344 insertions(+), 30 deletions(-)
create mode 100644 elf/tst-audit24a.c
create mode 100644 elf/tst-audit24amod1.c
create mode 100644 elf/tst-audit24amod2.c
create mode 100644 elf/tst-audit24b.c
create mode 100644 elf/tst-audit24bmod1.c
create mode 100644 elf/tst-audit24bmod2.c
create mode 100644 elf/tst-audit24c.c
create mode 100644 elf/tst-audit24d.c
create mode 100644 elf/tst-audit24dmod1.c
create mode 100644 elf/tst-audit24dmod2.c
create mode 100644 elf/tst-audit24dmod3.c
create mode 100644 elf/tst-audit24dmod4.c
create mode 100644 elf/tst-audit25a.c
create mode 100644 elf/tst-audit25b.c
create mode 100644 elf/tst-audit25mod1.c
create mode 100644 elf/tst-audit25mod2.c
create mode 100644 elf/tst-audit25mod3.c
create mode 100644 elf/tst-audit25mod4.c
create mode 100644 elf/tst-auditmod24.h
create mode 100644 elf/tst-auditmod24a.c
create mode 100644 elf/tst-auditmod24b.c
create mode 100644 elf/tst-auditmod24c.c
create mode 100644 elf/tst-auditmod24d.c
create mode 100644 elf/tst-auditmod25.c
create mode 100644 sysdeps/powerpc/dl-lookupcfg.h
diff --git a/elf/Makefile b/elf/Makefile
index ee4daae0fc..acce163078 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -237,6 +237,12 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
tst-audit21 \
tst-audit22 \
tst-audit23 \
+ tst-audit24a \
+ tst-audit24b \
+ tst-audit24c \
+ tst-audit24d \
+ tst-audit25a \
+ tst-audit25b \
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
@@ -388,6 +394,23 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
tst-auditmod22 \
tst-auditmod23 \
tst-audit23mod \
+ tst-auditmod24a \
+ tst-audit24amod1 \
+ tst-audit24amod2 \
+ tst-auditmod24b \
+ tst-audit24bmod1 \
+ tst-audit24bmod2 \
+ tst-auditmod24c \
+ tst-auditmod24d \
+ tst-audit24dmod1 \
+ tst-audit24dmod2 \
+ tst-audit24dmod3 \
+ tst-audit24dmod4 \
+ tst-auditmod25 \
+ tst-audit25mod1 \
+ tst-audit25mod2 \
+ tst-audit25mod3 \
+ tst-audit25mod4 \
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
@@ -1595,6 +1618,69 @@ $(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \
$(objpfx)tst-audit23mod.so
tst-audit23-ARGS = -- $(host-test-program-cmd)
+$(objpfx)tst-audit24a.out: $(objpfx)tst-auditmod24a.so
+$(objpfx)tst-audit24a: $(objpfx)tst-audit24amod1.so \
+ $(objpfx)tst-audit24amod2.so
+tst-audit24a-ENV = LD_AUDIT=$(objpfx)tst-auditmod24a.so
+LDFLAGS-tst-audit24a = -Wl,-z,now
+
+$(objpfx)tst-audit24b.out: $(objpfx)tst-auditmod24b.so
+$(objpfx)tst-audit24b: $(objpfx)tst-audit24bmod1.so \
+ $(objpfx)tst-audit24bmod2.so
+$(objpfx)tst-audit24bmod1: $(objpfx)tst-audit24bmod2.so
+# The test check if a library without .gnu.version correctly calls the
+# audit callbacks. So it uses an explicit link rule to avoid linking
+# against libc.so.
+$(objpfx)tst-audit24bmod1.so: $(objpfx)tst-audit24bmod1.os
+ $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod1.os \
+ -Wl,-z,now
+ $(call after-link,$@.new)
+ mv -f $@.new $@
+CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod1)
+$(objpfx)tst-audit24bmod2.so: $(objpfx)tst-audit24bmod2.os
+ $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod2.os
+ $(call after-link,$@.new)
+ mv -f $@.new $@
+CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod2)
+tst-audit24b-ENV = LD_AUDIT=$(objpfx)tst-auditmod24b.so
+LDFLAGS-tst-audit24b = -Wl,-z,now
+
+# Same as tst-audit24a, but tests LD_BIND_NOW
+$(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so
+$(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \
+ $(objpfx)tst-audit24amod2.so
+tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so
+LDFLAGS-tst-audit24b = -Wl,-z,lazy
+
+$(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so
+$(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \
+ $(objpfx)tst-audit24dmod2.so
+$(objpfx)tst-audit24dmod1.so: $(objpfx)tst-audit24dmod3.so
+LDFLAGS-tst-audit24dmod1.so = -Wl,-z,now
+$(objpfx)tst-audit24dmod2.so: $(objpfx)tst-audit24dmod4.so
+LDFLAGS-tst-audit24dmod2.so = -Wl,-z,lazy
+tst-audit24d-ENV = LD_AUDIT=$(objpfx)tst-auditmod24d.so
+LDFLAGS-tst-audit24d = -Wl,-z,lazy
+
+$(objpfx)tst-audit25a.out: $(objpfx)tst-auditmod25.so
+$(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \
+ $(objpfx)tst-audit25mod2.so \
+ $(objpfx)tst-audit25mod3.so \
+ $(objpfx)tst-audit25mod4.so
+$(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so
+LDFLAGS-tst-audit25mod1.so = -Wl,-z,now
+$(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so
+LDFLAGS-tst-audit25mod2.so = -Wl,-z,lazy
+tst-audit25a-ARGS = -- $(host-test-program-cmd)
+
+$(objpfx)tst-audit25b.out: $(objpfx)tst-auditmod25.so
+$(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \
+ $(objpfx)tst-audit25mod2.so \
+ $(objpfx)tst-audit25mod3.so \
+ $(objpfx)tst-audit25mod4.so
+LDFLAGS-tst-audit25b = -Wl,-z,now
+tst-audit25b-ARGS = -- $(host-test-program-cmd)
+
# tst-sonamemove links against an older implementation of the library.
LDFLAGS-tst-sonamemove-linkmod1.so = \
-Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index c3569cb357..f080591596 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -190,7 +190,7 @@ rtld_hidden_def (_dl_audit_symbind_alt)
void
_dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
- lookup_t result)
+ lookup_t result, bool bindnow)
{
reloc_result->bound = result;
/* Compute index of the symbol entry in the symbol table of the DSO with the
@@ -219,6 +219,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
unsigned int flags = 0;
struct audit_ifaces *afct = GLRO(dl_audit);
+ uintptr_t new_value = (uintptr_t) sym.st_value;
for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
{
/* XXX Check whether both DSOs must request action or only one */
@@ -229,16 +230,16 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
{
if (afct->symbind != NULL)
{
- uintptr_t new_value = afct->symbind (&sym,
- reloc_result->boundndx,
- &l_state->cookie,
- &result_state->cookie,
- &flags,
- strtab2 + defsym->st_name);
+ flags |= bindnow ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT : 0;
+ new_value = afct->symbind (&sym, reloc_result->boundndx,
+ &l_state->cookie,
+ &result_state->cookie, &flags,
+ strtab2 + defsym->st_name);
if (new_value != (uintptr_t) sym.st_value)
{
flags |= LA_SYMB_ALTVALUE;
- sym.st_value = new_value;
+ sym.st_value = bindnow
+ ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value;
}
}
@@ -259,7 +260,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
}
reloc_result->flags = flags;
- *value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+ DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
}
void
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 64a96c36e8..345809e3e2 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -234,9 +234,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
/* If DT_BIND_NOW is set relocate all references in this object. We
do not do this if we are profiling, of course. */
- // XXX Correct for auditing?
- if (!consider_profiling
- && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
+ if (!consider_profiling && l->l_info[DT_BIND_NOW] != NULL)
lazy = 0;
if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
@@ -285,8 +283,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
{
/* Do the actual relocation of the object's GOT and other data. */
- ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
-
#ifndef PROF
if (consider_profiling | consider_symbind
&& l->l_info[DT_PLTRELSZ] != NULL)
@@ -309,6 +305,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
}
}
#endif
+
+ ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
}
/* Mark the object so we know this work has been done. */
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 9a38eea7cc..66945b57f8 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -146,7 +146,7 @@ _dl_fixup (
unsigned int init = atomic_load_acquire (&reloc_result->init);
if (init == 0)
{
- _dl_audit_symbind (l, reloc_result, sym, &value, result);
+ _dl_audit_symbind (l, reloc_result, sym, &value, result, false);
/* Store the result for later runs. */
if (__glibc_likely (! GLRO(dl_bind_not)))
@@ -321,7 +321,7 @@ _dl_profile_fixup (
auditing libraries the possibility to change the value and
tell us whether further auditing is wanted. */
if (defsym != NULL && GLRO(dl_naudit) > 0)
- _dl_audit_symbind (l, reloc_result, defsym, &value, result);
+ _dl_audit_symbind (l, reloc_result, defsym, &value, result, false);
#endif
/* Store the result for later runs. */
diff --git a/elf/do-rel.h b/elf/do-rel.h
index f441b74919..c3368f09ab 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -16,6 +16,8 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <ldsodefs.h>
+
/* This file may be included twice, to define both
`elf_dynamic_do_rel' and `elf_dynamic_do_rela'. */
@@ -121,8 +123,15 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
const ElfW(Half) *const version =
(const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
+#if defined SHARED && !defined RTLD_BOOTSTRAP
+ size_t ri = 0;
+#endif
for (; r < end; ++r)
{
+ ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
+ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
+ void *const r_addr_arg = (void *) (l_addr + r->r_offset);
+ const struct r_found_version *rversion = &map->l_versions[ndx];
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
{
@@ -133,10 +142,20 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
}
#endif
- ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
- elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)],
- &map->l_versions[ndx],
- (void *) (l_addr + r->r_offset), skip_ifunc);
+ elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
+ skip_ifunc);
+#if defined SHARED && !defined RTLD_BOOTSTRAP
+ if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
+ && map->l_reloc_result != NULL)
+ {
+ struct link_map *sym_map
+ = RESOLVE_MAP (map, scope, &sym, rversion,
+ ELF_MACHINE_JMP_SLOT);
+ if (sym != NULL)
+ _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+ r_addr_arg, sym_map, true);
+ }
+#endif
}
#if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
@@ -157,18 +176,38 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
#ifndef RTLD_BOOTSTRAP
else
{
+# if defined SHARED && !defined RTLD_BOOTSTRAP
+ size_t ri = 0;
+# endif
for (; r < end; ++r)
+ {
+ const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
+ void *const r_addr_arg = (void *) (l_addr + r->r_offset);
# ifdef ELF_MACHINE_IRELATIVE
- if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
- {
- if (r2 == NULL)
- r2 = r;
- end2 = r;
- }
- else
+ if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
+ {
+ if (r2 == NULL)
+ r2 = r;
+ end2 = r;
+ continue;
+ }
# endif
- elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
- (void *) (l_addr + r->r_offset), skip_ifunc);
+ elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
+ skip_ifunc);
+# if defined SHARED && !defined RTLD_BOOTSTRAP
+ if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
+ && map->l_reloc_result != NULL)
+ {
+ struct link_map *sym_map
+ = RESOLVE_MAP (map, scope, &sym,
+ (struct r_found_version *) NULL,
+ ELF_MACHINE_JMP_SLOT);
+ if (sym != NULL)
+ _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+ r_addr_arg, sym_map, true);
+ }
+# endif
+ }
# ifdef ELF_MACHINE_IRELATIVE
if (r2 != NULL)
diff --git a/elf/tst-audit24a.c b/elf/tst-audit24a.c
new file mode 100644
index 0000000000..24160f4685
--- /dev/null
+++ b/elf/tst-audit24a.c
@@ -0,0 +1,36 @@
+/* DL_AUDIT test for la_symbind() and bind-now.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+
+int tst_audit24amod1_func1 (void);
+int tst_audit24amod1_func2 (void);
+int tst_audit24amod2_func1 (void);
+
+int
+do_test (void)
+{
+ TEST_COMPARE (tst_audit24amod1_func1 (), 1);
+ TEST_COMPARE (tst_audit24amod1_func2 (), 2);
+ TEST_COMPARE (tst_audit24amod2_func1 (), 10);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit24amod1.c b/elf/tst-audit24amod1.c
new file mode 100644
index 0000000000..43d3831677
--- /dev/null
+++ b/elf/tst-audit24amod1.c
@@ -0,0 +1,31 @@
+/* Modules used by tst-audit24a.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24amod1_func1 (void)
+{
+ abort ();
+}
+
+int
+tst_audit24amod1_func2 (void)
+{
+ return 2;
+}
diff --git a/elf/tst-audit24amod2.c b/elf/tst-audit24amod2.c
new file mode 100644
index 0000000000..c995827855
--- /dev/null
+++ b/elf/tst-audit24amod2.c
@@ -0,0 +1,25 @@
+/* Modules used by tst-audit24a.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24amod2_func1 (void)
+{
+ abort ();
+}
diff --git a/elf/tst-audit24b.c b/elf/tst-audit24b.c
new file mode 100644
index 0000000000..44643d64ef
--- /dev/null
+++ b/elf/tst-audit24b.c
@@ -0,0 +1,37 @@
+/* DL_AUDIT test for la_symbind() and bind-now.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+/* This is similar to tst-audit24a, with the difference this modules
+ does not have the .gnu.version section header. */
+
+#include <support/check.h>
+#include <support/support.h>
+
+int tst_audit24bmod1_func1 (void);
+int tst_audit24bmod1_func2 (void);
+
+int
+do_test (void)
+{
+ TEST_COMPARE (tst_audit24bmod1_func1 (), 1);
+ TEST_COMPARE (tst_audit24bmod1_func2 (), 2);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit24bmod1.c b/elf/tst-audit24bmod1.c
new file mode 100644
index 0000000000..91c6fa0251
--- /dev/null
+++ b/elf/tst-audit24bmod1.c
@@ -0,0 +1,31 @@
+/* Modules used by tst-audit24c.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+int tst_audit24bmod2_func1 (void);
+
+int
+tst_audit24bmod1_func1 (void)
+{
+ return -1;
+}
+
+int
+tst_audit24bmod1_func2 (void)
+{
+ return tst_audit24bmod2_func1 ();
+}
diff --git a/elf/tst-audit24bmod2.c b/elf/tst-audit24bmod2.c
new file mode 100644
index 0000000000..3baf9e8bd4
--- /dev/null
+++ b/elf/tst-audit24bmod2.c
@@ -0,0 +1,23 @@
+/* Modules used by tst-audit24b.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+int
+tst_audit24bmod2_func1 (void)
+{
+ return -1;
+}
diff --git a/elf/tst-audit24c.c b/elf/tst-audit24c.c
new file mode 100644
index 0000000000..46ed328756
--- /dev/null
+++ b/elf/tst-audit24c.c
@@ -0,0 +1,2 @@
+/* It tests LD_BIND_NOW=1 instead of linking with -Wl,-z,now */
+#include "tst-audit24a.c"
diff --git a/elf/tst-audit24d.c b/elf/tst-audit24d.c
new file mode 100644
index 0000000000..79b580331a
--- /dev/null
+++ b/elf/tst-audit24d.c
@@ -0,0 +1,36 @@
+/* DL_AUDIT test for la_symbind() and bind-now.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <support/check.h>
+#include <support/support.h>
+
+int tst_audit24dmod1_func1 (void);
+int tst_audit24dmod1_func2 (void);
+int tst_audit24dmod2_func1 (void);
+
+int
+do_test (void)
+{
+ TEST_COMPARE (tst_audit24dmod1_func1 (), 1);
+ TEST_COMPARE (tst_audit24dmod1_func2 (), 32);
+ TEST_COMPARE (tst_audit24dmod2_func1 (), 10);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit24dmod1.c b/elf/tst-audit24dmod1.c
new file mode 100644
index 0000000000..792da3b581
--- /dev/null
+++ b/elf/tst-audit24dmod1.c
@@ -0,0 +1,33 @@
+/* Modules used by tst-audit24d.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+int tst_audit24dmod3_func1 (void);
+
+_Noreturn int
+tst_audit24dmod1_func1 (void)
+{
+ abort ();
+}
+
+int
+tst_audit24dmod1_func2 (void)
+{
+ return 2 + tst_audit24dmod3_func1 ();;
+}
diff --git a/elf/tst-audit24dmod2.c b/elf/tst-audit24dmod2.c
new file mode 100644
index 0000000000..8c76257885
--- /dev/null
+++ b/elf/tst-audit24dmod2.c
@@ -0,0 +1,28 @@
+/* Module for tst-audit24d.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+int tst_audit24dmod4_func1 (void);
+
+_Noreturn int
+tst_audit24dmod2_func1 (void)
+{
+ tst_audit24dmod4_func1 ();
+ abort ();
+}
diff --git a/elf/tst-audit24dmod3.c b/elf/tst-audit24dmod3.c
new file mode 100644
index 0000000000..367c776eb5
--- /dev/null
+++ b/elf/tst-audit24dmod3.c
@@ -0,0 +1,31 @@
+/* Module for tst-audit24d.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24dmod3_func1 (void)
+{
+ abort ();
+}
+
+int
+tst_audit24dmod3_func2 (void)
+{
+ return 4;
+}
diff --git a/elf/tst-audit24dmod4.c b/elf/tst-audit24dmod4.c
new file mode 100644
index 0000000000..c994c7cf03
--- /dev/null
+++ b/elf/tst-audit24dmod4.c
@@ -0,0 +1,25 @@
+/* Module for tst-audit24d.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24dmod4_func1 (void)
+{
+ abort ();
+}
diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c
new file mode 100644
index 0000000000..e3e7200f85
--- /dev/null
+++ b/elf/tst-audit25a.c
@@ -0,0 +1,127 @@
+/* Check DT_AUDIT and LA_SYMB_NOW.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+void tst_audit25mod1_func1 (void);
+void tst_audit25mod1_func2 (void);
+void tst_audit25mod2_func1 (void);
+void tst_audit25mod2_func2 (void);
+
+static int
+handle_restart (void)
+{
+ tst_audit25mod1_func1 ();
+ tst_audit25mod1_func2 ();
+ tst_audit25mod2_func1 ();
+ tst_audit25mod2_func2 ();
+
+ return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+ size_t lenpre = strlen (pre);
+ size_t lenstr = strlen (str);
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ /* We must have either:
+ - One our fource parameters left if called initially:
+ + path to ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name */
+
+ if (restart)
+ return handle_restart ();
+
+ setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
+
+ char *spargv[9];
+ int i = 0;
+ for (; i < argc - 1; i++)
+ spargv[i] = argv[i + 1];
+ spargv[i++] = (char *) "--direct";
+ spargv[i++] = (char *) "--restart";
+ spargv[i] = NULL;
+
+ {
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit25a", 0,
+ sc_allow_stderr);
+
+ /* tst-audit25a is build with -Wl,-z,lazy and tst-audit25mod1 with
+ -Wl,-z,now; so only tst_audit25mod3_func1 should be expected to
+ have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */
+ TEST_COMPARE_STRING (result.err.buffer,
+ "la_symbind: tst_audit25mod3_func1 1\n"
+ "la_symbind: tst_audit25mod1_func1 0\n"
+ "la_symbind: tst_audit25mod1_func2 0\n"
+ "la_symbind: tst_audit25mod2_func1 0\n"
+ "la_symbind: tst_audit25mod4_func1 0\n"
+ "la_symbind: tst_audit25mod2_func2 0\n");
+
+ support_capture_subprocess_free (&result);
+ }
+
+ {
+ setenv ("LD_BIND_NOW", "1", 0);
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit25a", 0,
+ sc_allow_stderr);
+
+ /* With LD_BIND_NOW all symbols are expected to have
+ LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution
+ order is done in breadth-first order. */
+ TEST_COMPARE_STRING (result.err.buffer,
+ "la_symbind: tst_audit25mod4_func1 1\n"
+ "la_symbind: tst_audit25mod3_func1 1\n"
+ "la_symbind: tst_audit25mod1_func1 1\n"
+ "la_symbind: tst_audit25mod2_func1 1\n"
+ "la_symbind: tst_audit25mod1_func2 1\n"
+ "la_symbind: tst_audit25mod2_func2 1\n");
+
+ support_capture_subprocess_free (&result);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c
new file mode 100644
index 0000000000..d497b82d56
--- /dev/null
+++ b/elf/tst-audit25b.c
@@ -0,0 +1,128 @@
+/* Check DT_AUDIT and LA_SYMB_NOW.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+ { "restart", no_argument, &restart, 1 },
+
+void tst_audit25mod1_func1 (void);
+void tst_audit25mod1_func2 (void);
+void tst_audit25mod2_func1 (void);
+void tst_audit25mod2_func2 (void);
+
+static int
+handle_restart (void)
+{
+ tst_audit25mod1_func1 ();
+ tst_audit25mod1_func2 ();
+ tst_audit25mod2_func1 ();
+ tst_audit25mod2_func2 ();
+
+ return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+ size_t lenpre = strlen (pre);
+ size_t lenstr = strlen (str);
+ return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+ /* We must have either:
+ - One our fource parameters left if called initially:
+ + path to ld.so optional
+ + "--library-path" optional
+ + the library path optional
+ + the application name */
+
+ if (restart)
+ return handle_restart ();
+
+ setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
+
+ char *spargv[9];
+ int i = 0;
+ for (; i < argc - 1; i++)
+ spargv[i] = argv[i + 1];
+ spargv[i++] = (char *) "--direct";
+ spargv[i++] = (char *) "--restart";
+ spargv[i] = NULL;
+
+ {
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit25a", 0,
+ sc_allow_stderr);
+
+ /* tst-audit25a and tst-audit25mod1 are built with -Wl,-z,now, but
+ tst-audit25mod2 is built with -Wl,z,lazy. So only
+ tst_audit25mod4_func1 (called by tst_audit25mod2_func1) should not
+ have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. */
+ TEST_COMPARE_STRING (result.err.buffer,
+ "la_symbind: tst_audit25mod3_func1 1\n"
+ "la_symbind: tst_audit25mod1_func1 1\n"
+ "la_symbind: tst_audit25mod2_func1 1\n"
+ "la_symbind: tst_audit25mod1_func2 1\n"
+ "la_symbind: tst_audit25mod2_func2 1\n"
+ "la_symbind: tst_audit25mod4_func1 0\n");
+
+ support_capture_subprocess_free (&result);
+ }
+
+ {
+ setenv ("LD_BIND_NOW", "1", 0);
+ struct support_capture_subprocess result
+ = support_capture_subprogram (spargv[0], spargv);
+ support_capture_subprocess_check (&result, "tst-audit25a", 0,
+ sc_allow_stderr);
+
+ /* With LD_BIND_NOW all symbols are expected to have
+ LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT. Also the resolution
+ order is done in breadth-first order. */
+ TEST_COMPARE_STRING (result.err.buffer,
+ "la_symbind: tst_audit25mod4_func1 1\n"
+ "la_symbind: tst_audit25mod3_func1 1\n"
+ "la_symbind: tst_audit25mod1_func1 1\n"
+ "la_symbind: tst_audit25mod2_func1 1\n"
+ "la_symbind: tst_audit25mod1_func2 1\n"
+ "la_symbind: tst_audit25mod2_func2 1\n");
+
+ support_capture_subprocess_free (&result);
+ }
+
+ return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit25mod1.c b/elf/tst-audit25mod1.c
new file mode 100644
index 0000000000..9aa39ed325
--- /dev/null
+++ b/elf/tst-audit25mod1.c
@@ -0,0 +1,30 @@
+/* Modules used by tst-audit25.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+void tst_audit25mod3_func1 (void);
+
+void
+tst_audit25mod1_func1 (void)
+{
+ tst_audit25mod3_func1 ();
+}
+
+void
+tst_audit25mod1_func2 (void)
+{
+}
diff --git a/elf/tst-audit25mod2.c b/elf/tst-audit25mod2.c
new file mode 100644
index 0000000000..6d8e225fcc
--- /dev/null
+++ b/elf/tst-audit25mod2.c
@@ -0,0 +1,30 @@
+/* Modules used by tst-audit25.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+void tst_audit25mod4_func1 (void);
+
+void
+tst_audit25mod2_func1 (void)
+{
+ tst_audit25mod4_func1 ();
+}
+
+void
+tst_audit25mod2_func2 (void)
+{
+}
diff --git a/elf/tst-audit25mod3.c b/elf/tst-audit25mod3.c
new file mode 100644
index 0000000000..c0d5977fd8
--- /dev/null
+++ b/elf/tst-audit25mod3.c
@@ -0,0 +1,22 @@
+/* Modules used by tst-audit25.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+void
+tst_audit25mod3_func1 (void)
+{
+}
diff --git a/elf/tst-audit25mod4.c b/elf/tst-audit25mod4.c
new file mode 100644
index 0000000000..689ee5138f
--- /dev/null
+++ b/elf/tst-audit25mod4.c
@@ -0,0 +1,22 @@
+/* Modules used by tst-audit25.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+void
+tst_audit25mod4_func1 (void)
+{
+}
diff --git a/elf/tst-auditmod24.h b/elf/tst-auditmod24.h
new file mode 100644
index 0000000000..621fd50364
--- /dev/null
+++ b/elf/tst-auditmod24.h
@@ -0,0 +1,29 @@
+/* Auxiliary functions for tst-audit24x.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TST_AUDITMOD24_H
+#define _TST_AUDITMOD24_H
+
+static void
+check_symbind_flags (unsigned int flags)
+{
+ if ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 0)
+ abort ();
+}
+
+#endif
diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c
new file mode 100644
index 0000000000..09d89269df
--- /dev/null
+++ b/elf/tst-auditmod24a.c
@@ -0,0 +1,113 @@
+/* Audit modules for tst-audit24a.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tst-auditmod24.h>
+
+#define AUDIT24_COOKIE 0x1
+#define AUDIT24MOD1_COOKIE 0x2
+#define AUDIT24MOD2_COOKIE 0x3
+
+#ifndef TEST_NAME
+# define TEST_NAME "tst-audit24a"
+#endif
+#ifndef TEST_MOD
+# define TEST_MOD TEST_NAME
+#endif
+#ifndef TEST_FUNC
+# define TEST_FUNC "tst_audit24a"
+#endif
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
+ ck = AUDIT24MOD1_COOKIE;
+ else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
+ ck = AUDIT24MOD2_COOKIE;
+ else if (strcmp (l_name, TEST_NAME) == 0)
+ ck = AUDIT24_COOKIE;
+
+ *cookie = ck;
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+static int
+tst_func1 (void)
+{
+ return 1;
+}
+
+static int
+tst_func2 (void)
+{
+ return 10;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#endif
+{
+ if (*refcook == AUDIT24_COOKIE)
+ {
+ if (*defcook == AUDIT24MOD1_COOKIE)
+ {
+ /* Check if bind-now symbols are advertised to not call the PLT
+ hooks. */
+ check_symbind_flags (*flags);
+
+ if (strcmp (symname, TEST_FUNC "mod1_func1") == 0)
+ return (uintptr_t) tst_func1;
+ else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0)
+ return sym->st_value;
+ abort ();
+ }
+ if (*defcook == AUDIT24MOD2_COOKIE
+ && (strcmp (symname, TEST_FUNC "mod2_func1") == 0))
+ {
+ check_symbind_flags (*flags);
+
+ return (uintptr_t) tst_func2;
+ }
+
+ /* malloc functions. */
+ return sym->st_value;
+ }
+
+ abort ();
+}
diff --git a/elf/tst-auditmod24b.c b/elf/tst-auditmod24b.c
new file mode 100644
index 0000000000..dd3771ae5b
--- /dev/null
+++ b/elf/tst-auditmod24b.c
@@ -0,0 +1,103 @@
+/* Audit modules for tst-audit24b.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tst-auditmod24.h>
+
+#define TEST_NAME "tst-audit24b"
+#define TEST_FUNC "tst_audit24b"
+
+#define AUDIT24_COOKIE 0x1
+#define AUDIT24MOD1_COOKIE 0x2
+#define AUDIT24MOD2_COOKIE 0x3
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strcmp (l_name, TEST_NAME "mod1.so") == 0)
+ ck = AUDIT24MOD1_COOKIE;
+ else if (strcmp (l_name, TEST_NAME "mod2.so") == 0)
+ ck = AUDIT24MOD2_COOKIE;
+ else if (strcmp (l_name, TEST_NAME) == 0)
+ ck = AUDIT24_COOKIE;
+
+ *cookie = ck;
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+static int
+tst_func1 (void)
+{
+ return 1;
+}
+
+static int
+tst_func2 (void)
+{
+ return 2;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#endif
+{
+ if (*refcook == AUDIT24_COOKIE)
+ {
+ if (*defcook == AUDIT24MOD1_COOKIE)
+ {
+ if (strcmp (symname, TEST_FUNC "mod1_func1") == 0)
+ return (uintptr_t) tst_func1;
+ else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0)
+ return sym->st_value;
+ abort ();
+ }
+ /* malloc functions. */
+ return sym->st_value;
+ }
+ else if (*refcook == AUDIT24MOD1_COOKIE)
+ {
+ if (*defcook == AUDIT24MOD2_COOKIE
+ && (strcmp (symname, TEST_FUNC "mod2_func1") == 0))
+ {
+ check_symbind_flags (*flags);
+ return (uintptr_t) tst_func2;
+ }
+ }
+
+ abort ();
+}
diff --git a/elf/tst-auditmod24c.c b/elf/tst-auditmod24c.c
new file mode 100644
index 0000000000..67e62c9d33
--- /dev/null
+++ b/elf/tst-auditmod24c.c
@@ -0,0 +1,3 @@
+#define TEST_NAME "tst-audit24c"
+#define TEST_MOD "tst-audit24a"
+#include "tst-auditmod24a.c"
diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c
new file mode 100644
index 0000000000..67e958f926
--- /dev/null
+++ b/elf/tst-auditmod24d.c
@@ -0,0 +1,119 @@
+/* Audit module for tst-audit24d.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tst-auditmod24.h>
+
+#define AUDIT24_COOKIE 0x0
+#define AUDIT24MOD1_COOKIE 0x1
+#define AUDIT24MOD2_COOKIE 0x2
+#define AUDIT24MOD3_COOKIE 0x3
+#define AUDIT24MOD4_COOKIE 0x4
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strcmp (l_name, "tst-audit24dmod1.so") == 0)
+ ck = AUDIT24MOD1_COOKIE;
+ else if (strcmp (l_name, "tst-audit24dmod2.so") == 0)
+ ck = AUDIT24MOD2_COOKIE;
+ else if (strcmp (l_name, "tst-audit24dmod3.so") == 0)
+ ck = AUDIT24MOD3_COOKIE;
+ else if (strcmp (l_name, "tst-audit24dmod.so") == 0)
+ ck = AUDIT24MOD4_COOKIE;
+ else if (strcmp (l_name, "tst-audit24d") == 0)
+ ck = AUDIT24_COOKIE;
+
+ *cookie = ck;
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+static int
+tst_audit24dmod1_func1 (void)
+{
+ return 1;
+}
+
+static int
+tst_audit24dmod2_func1 (void)
+{
+ return 10;
+}
+
+static int
+tst_audit24dmod3_func1 (void)
+{
+ return 30;
+}
+
+#include <stdio.h>
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#endif
+{
+ if (*refcook == AUDIT24_COOKIE)
+ {
+ if (*defcook == AUDIT24MOD1_COOKIE)
+ {
+ if (strcmp (symname, "tst_audit24dmod1_func1") == 0)
+ return (uintptr_t) tst_audit24dmod1_func1;
+ else if (strcmp (symname, "tst_audit24dmod1_func2") == 0)
+ return sym->st_value;
+ abort ();
+ }
+ if (*defcook == AUDIT24MOD2_COOKIE
+ && (strcmp (symname, "tst_audit24dmod2_func1") == 0))
+ return (uintptr_t) tst_audit24dmod2_func1;
+
+ /* malloc functions. */
+ return sym->st_value;
+ }
+ else if (*refcook == AUDIT24MOD1_COOKIE)
+ {
+ if (*defcook == AUDIT24MOD3_COOKIE
+ && strcmp (symname, "tst_audit24dmod3_func1") == 0)
+ {
+ check_symbind_flags (*flags);
+
+ return (uintptr_t) tst_audit24dmod3_func1;
+ }
+ }
+
+ abort ();
+}
diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c
new file mode 100644
index 0000000000..bfdeadace5
--- /dev/null
+++ b/elf/tst-auditmod25.c
@@ -0,0 +1,78 @@
+/* Audit modules for tst-audit25a.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define AUDIT25_COOKIE 0x1
+#define AUDIT25MOD1_COOKIE 0x2
+#define AUDIT25MOD2_COOKIE 0x3
+#define AUDIT25MOD3_COOKIE 0x2
+#define AUDIT25MOD4_COOKIE 0x3
+
+#define TEST_NAME "tst-audit25"
+#define TEST_MOD "tst-audit25"
+#define TEST_FUNC "tst_audit25"
+
+unsigned int
+la_version (unsigned int version)
+{
+ return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
+ ck = AUDIT25MOD1_COOKIE;
+ else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
+ ck = AUDIT25MOD2_COOKIE;
+ else if (strcmp (l_name, TEST_MOD "mod3.so") == 0)
+ ck = AUDIT25MOD3_COOKIE;
+ else if (strcmp (l_name, TEST_MOD "mod4.so") == 0)
+ ck = AUDIT25MOD4_COOKIE;
+ else if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
+ ck = AUDIT25_COOKIE;
+
+ *cookie = ck;
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+ uintptr_t *refcook, uintptr_t *defcook,
+ unsigned int *flags, const char *symname)
+#endif
+{
+ if (*refcook != -1 && *defcook != -1)
+ fprintf (stderr, "la_symbind: %s %u\n", symname,
+ *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0);
+ return sym->st_value;
+}
diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h
index c038c31ce6..a15fd32771 100644
--- a/sysdeps/generic/dl-lookupcfg.h
+++ b/sysdeps/generic/dl-lookupcfg.h
@@ -26,3 +26,6 @@
#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
#define DL_FIXUP_VALUE_ADDR(value) (value)
#define DL_FIXUP_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+ (*value) = st_value;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index d419a62dbd..a73859d16e 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1410,7 +1410,7 @@ void _dl_audit_objclose (struct link_map *l, Lmid_t nsid);
void _dl_audit_preinit (struct link_map *l);
void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
- lookup_t result);
+ lookup_t result, bool bindnow);
void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,
void **value, lookup_t result);
rtld_hidden_proto (_dl_audit_symbind_alt)
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h
index a9a927f26c..f376965600 100644
--- a/sysdeps/hppa/dl-lookupcfg.h
+++ b/sysdeps/hppa/dl-lookupcfg.h
@@ -80,3 +80,6 @@ void attribute_hidden _dl_unmap (struct link_map *map);
#define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip)
#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+ (*value) = *(struct fdesc *) (st_value)
diff --git a/sysdeps/ia64/dl-lookupcfg.h b/sysdeps/ia64/dl-lookupcfg.h
index 58ca32424b..2b8b2fa5db 100644
--- a/sysdeps/ia64/dl-lookupcfg.h
+++ b/sysdeps/ia64/dl-lookupcfg.h
@@ -74,3 +74,6 @@ extern void attribute_hidden _dl_unmap (struct link_map *map);
#define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
#define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+ (*value) = *(struct fdesc *) (st_value)
diff --git a/sysdeps/powerpc/dl-lookupcfg.h b/sysdeps/powerpc/dl-lookupcfg.h
new file mode 100644
index 0000000000..43fc94a7f6
--- /dev/null
+++ b/sysdeps/powerpc/dl-lookupcfg.h
@@ -0,0 +1,39 @@
+/* Configuration of lookup functions. PowerPC version.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#define DL_FIXUP_VALUE_TYPE ElfW(Addr)
+#define DL_FIXUP_MAKE_VALUE(map, addr) (addr)
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
+#define DL_FIXUP_VALUE_ADDR(value) (value)
+#define DL_FIXUP_ADDR_VALUE(addr) (addr)
+#if __WORDSIZE == 64 && _CALL_ELF == 1
+/* We need to correctly set the audit modules value for bind-now. */
+# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) \
+ (((Elf64_FuncDesc *)(addr))->fd_func)
+# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+ ({ \
+ Elf64_FuncDesc *opd = (Elf64_FuncDesc *) (value); \
+ opd->fd_func = (st_value); \
+ if ((new_value) != (uintptr_t) (st_value)) \
+ opd->fd_toc = ((Elf64_FuncDesc *)(new_value))->fd_toc; \
+ })
+#else
+# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+ (*value) = st_value;
+#endif
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734)
2021-11-15 18:37 ` [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
@ 2021-12-20 19:18 ` Florian Weimer
2021-12-20 20:43 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 19:18 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
I believe this change needs to update elf/sotruss-lib.c:
uintptr_t
la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook,
uintptr_t *defcook, unsigned int *flags, const char *symname)
{
if (!do_exit)
*flags = LA_SYMB_NOPLTEXIT;
return sym->st_value;
}
* Adhemerval Zanella:
> diff --git a/elf/Makefile b/elf/Makefile
> index ee4daae0fc..acce163078 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> +# The test check if a library without .gnu.version correctly calls the
> +# audit callbacks. So it uses an explicit link rule to avoid linking
> +# against libc.so.
> +$(objpfx)tst-audit24bmod1.so: $(objpfx)tst-audit24bmod1.os
> + $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod1.os \
> + -Wl,-z,now
> + $(call after-link,$@.new)
> + mv -f $@.new $@
I think you may have to update modules-names-nobuild as well.
> # tst-sonamemove links against an older implementation of the library.
> LDFLAGS-tst-sonamemove-linkmod1.so = \
> -Wl,--version-script=tst-sonamemove-linkmod1.map \
> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
> index c3569cb357..f080591596 100644
> --- a/elf/dl-audit.c
> +++ b/elf/dl-audit.c
> @@ -190,7 +190,7 @@ rtld_hidden_def (_dl_audit_symbind_alt)
> void
> _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
> const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
> - lookup_t result)
> + lookup_t result, bool bindnow)
> {
Should “bindow“ be called “for_jmp_slot”?
> @@ -229,16 +230,16 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
> {
> if (afct->symbind != NULL)
> {
> - uintptr_t new_value = afct->symbind (&sym,
> - reloc_result->boundndx,
> - &l_state->cookie,
> - &result_state->cookie,
> - &flags,
> - strtab2 + defsym->st_name);
> + flags |= bindnow ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT : 0;
> + new_value = afct->symbind (&sym, reloc_result->boundndx,
> + &l_state->cookie,
> + &result_state->cookie, &flags,
> + strtab2 + defsym->st_name);
> if (new_value != (uintptr_t) sym.st_value)
> {
> flags |= LA_SYMB_ALTVALUE;
> - sym.st_value = new_value;
> + sym.st_value = bindnow
> + ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value;
> }
> }
We could error out if the audit callback clears the LA_SYMB_NOPLT* flags
we've set (after fixing sotruss).
And then we'll have to make this change conditional on the la_version
return value, I think.
> --- a/elf/dl-reloc.c
> +++ b/elf/dl-reloc.c
> @@ -234,9 +234,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>
> /* If DT_BIND_NOW is set relocate all references in this object. We
> do not do this if we are profiling, of course. */
> - // XXX Correct for auditing?
> - if (!consider_profiling
> - && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
> + if (!consider_profiling && l->l_info[DT_BIND_NOW] != NULL)
> lazy = 0;
>
> if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
> @@ -285,8 +283,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
> {
> /* Do the actual relocation of the object's GOT and other data. */
>
> - ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
> -
> #ifndef PROF
> if (consider_profiling | consider_symbind
> && l->l_info[DT_PLTRELSZ] != NULL)
> @@ -309,6 +305,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
> }
> }
> #endif
> +
> + ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
> }
I don't understand why this is needed. Can we indeed use the profiling
trampoline with a BIND_NOW binding? If not, then we shouldn't need the
allocation of l_reloc_result, either. We should patch in the changed
symbol variable directly, not going through l_reloc_result.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734)
2021-12-20 19:18 ` Florian Weimer
@ 2021-12-20 20:43 ` Adhemerval Zanella
2021-12-20 21:04 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 20:43 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 20/12/2021 16:18, Florian Weimer wrote:
> I believe this change needs to update elf/sotruss-lib.c:
>
> uintptr_t
> la_symbind (Elf_Sym *sym, unsigned int ndx, uintptr_t *refcook,
> uintptr_t *defcook, unsigned int *flags, const char *symname)
> {
> if (!do_exit)
> *flags = LA_SYMB_NOPLTEXIT;
>
> return sym->st_value;
> }
>
> * Adhemerval Zanella:
>
>> diff --git a/elf/Makefile b/elf/Makefile
>> index ee4daae0fc..acce163078 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>
>> +# The test check if a library without .gnu.version correctly calls the
>> +# audit callbacks. So it uses an explicit link rule to avoid linking
>> +# against libc.so.
>> +$(objpfx)tst-audit24bmod1.so: $(objpfx)tst-audit24bmod1.os
>> + $(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod1.os \
>> + -Wl,-z,now
>> + $(call after-link,$@.new)
>> + mv -f $@.new $@
>
> I think you may have to update modules-names-nobuild as well.
Ack.
>
>> # tst-sonamemove links against an older implementation of the library.
>> LDFLAGS-tst-sonamemove-linkmod1.so = \
>> -Wl,--version-script=tst-sonamemove-linkmod1.map \
>> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
>> index c3569cb357..f080591596 100644
>> --- a/elf/dl-audit.c
>> +++ b/elf/dl-audit.c
>> @@ -190,7 +190,7 @@ rtld_hidden_def (_dl_audit_symbind_alt)
>> void
>> _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
>> const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
>> - lookup_t result)
>> + lookup_t result, bool bindnow)
>> {
>
> Should “bindow“ be called “for_jmp_slot”?
Ok, it does make sense if the idea would be extend not only for functions
calls.
>
>> @@ -229,16 +230,16 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
>> {
>> if (afct->symbind != NULL)
>> {
>> - uintptr_t new_value = afct->symbind (&sym,
>> - reloc_result->boundndx,
>> - &l_state->cookie,
>> - &result_state->cookie,
>> - &flags,
>> - strtab2 + defsym->st_name);
>> + flags |= bindnow ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT : 0;
>> + new_value = afct->symbind (&sym, reloc_result->boundndx,
>> + &l_state->cookie,
>> + &result_state->cookie, &flags,
>> + strtab2 + defsym->st_name);
>> if (new_value != (uintptr_t) sym.st_value)
>> {
>> flags |= LA_SYMB_ALTVALUE;
>> - sym.st_value = new_value;
>> + sym.st_value = bindnow
>> + ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value;
>> }
>> }
>
> We could error out if the audit callback clears the LA_SYMB_NOPLT* flags
> we've set (after fixing sotruss).
I don't oppose bumping LAV_CURRENT, it is large change than I envisioned
in this change but it makes sense.
>
> And then we'll have to make this change conditional on the la_version
> return value, I think.
My understanding from previous discussion is we don't want to support mixed
lav versions, so bumping the minimal version should be suffice. It would
required older modules to be rebuild against a newer glibc, but I think
it should be ok.
>
>> --- a/elf/dl-reloc.c
>> +++ b/elf/dl-reloc.c
>> @@ -234,9 +234,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>>
>> /* If DT_BIND_NOW is set relocate all references in this object. We
>> do not do this if we are profiling, of course. */
>> - // XXX Correct for auditing?
>> - if (!consider_profiling
>> - && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
>> + if (!consider_profiling && l->l_info[DT_BIND_NOW] != NULL)
>> lazy = 0;
>>
>> if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
>> @@ -285,8 +283,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>> {
>> /* Do the actual relocation of the object's GOT and other data. */
>>
>> - ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
>> -
>> #ifndef PROF
>> if (consider_profiling | consider_symbind
>> && l->l_info[DT_PLTRELSZ] != NULL)
>> @@ -309,6 +305,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>> }
>> }
>> #endif
>> +
>> + ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
>> }
>
> I don't understand why this is needed. Can we indeed use the profiling
> trampoline with a BIND_NOW binding? If not, then we shouldn't need the
> allocation of l_reloc_result, either. We should patch in the changed
> symbol variable directly, not going through l_reloc_result.
I does not indeed, I just did it to avoid adjusting _dl_audit_symbind. But
I agree that not requiring allocate l_reloc_results for bind-now is a better
strategy. I will fix it.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734)
2021-12-20 20:43 ` Adhemerval Zanella
@ 2021-12-20 21:04 ` Florian Weimer
2021-12-20 21:09 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 21:04 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
>> And then we'll have to make this change conditional on the la_version
>> return value, I think.
>
> My understanding from previous discussion is we don't want to support mixed
> lav versions, so bumping the minimal version should be suffice. It would
> required older modules to be rebuild against a newer glibc, but I think
> it should be ok.
I'm concerned that this change might trip older audit modules, breaking
them until their sources are adjusted to cope with additional symbind
callbacks. See the sotruss code I cited, it really does not expect
BIND_NOW symbind.
>> I don't understand why this is needed. Can we indeed use the profiling
>> trampoline with a BIND_NOW binding? If not, then we shouldn't need the
>> allocation of l_reloc_result, either. We should patch in the changed
>> symbol variable directly, not going through l_reloc_result.
>
> I does not indeed, I just did it to avoid adjusting _dl_audit_symbind. But
> I agree that not requiring allocate l_reloc_results for bind-now is a better
> strategy. I will fix it.
Thanks.
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734)
2021-12-20 21:04 ` Florian Weimer
@ 2021-12-20 21:09 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-20 21:09 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 20/12/2021 18:04, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>>> And then we'll have to make this change conditional on the la_version
>>> return value, I think.
>>
>> My understanding from previous discussion is we don't want to support mixed
>> lav versions, so bumping the minimal version should be suffice. It would
>> required older modules to be rebuild against a newer glibc, but I think
>> it should be ok.
>
> I'm concerned that this change might trip older audit modules, breaking
> them until their sources are adjusted to cope with additional symbind
> callbacks. See the sotruss code I cited, it really does not expect
> BIND_NOW symbind.
My impression on previous discussions is due the restricted users we do not
add to add the complexity of lav versioning and the backward support.
>
>>> I don't understand why this is needed. Can we indeed use the profiling
>>> trampoline with a BIND_NOW binding? If not, then we shouldn't need the
>>> allocation of l_reloc_result, either. We should patch in the changed
>>> symbol variable directly, not going through l_reloc_result.
>>
>> I does not indeed, I just did it to avoid adjusting _dl_audit_symbind. But
>> I agree that not requiring allocate l_reloc_results for bind-now is a better
>> strategy. I will fix it.
>
> Thanks.
>
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (17 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 18/20] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-20 21:32 ` Florian Weimer
` (2 more replies)
2021-11-15 18:37 ` [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
19 siblings, 3 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
From: Ben Woodard <woodard@redhat.com>
The dynamic linker's auditing has some issues aarch64. with two distinct
problems:
1. _dl_runtime_resolve was not preserving x8 the indirect result
location register.
2. The NEON Q registers pushed onto the stack by _dl_runtime_resolve()
were twice the size of D registers extracted from the stack frame by
_dl_runtime_profile().
To fix it the rtld-auditor interfaces is changed for aarch64:
* LAV_CURRENT is bumped to v2 and loader will fail to load audit
modules that return a version different than the one supported.
* The La_aarch64_regs structure was expanded to include x8 and the
full sized NEON V registers that are required to be preserved by the
ABI.
* dl_runtime_profile needed to extract registers saved by
_dl_runtime_resolve and put them into the new correctly sized
La_aarch64_regs structure.
* The return value structure La_aarch64_retval also did not have the
correctly sized NEON V registers.
Similar to x86, a new La_aarch64_vector type to represent the NEON
register is added on the La_aarch64_regs (so each type can be accessed
easier).
Checked on aarch64-linux-gnu.
Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
---
elf/rtld.c | 4 +-
sysdeps/aarch64/Makefile | 20 +++
sysdeps/aarch64/bits/link.h | 24 ++--
sysdeps/aarch64/bits/link_lavcurrent.h | 25 ++++
sysdeps/aarch64/dl-link.sym | 4 +-
sysdeps/aarch64/dl-trampoline.S | 93 ++++++++-----
sysdeps/aarch64/tst-audit26.c | 37 ++++++
sysdeps/aarch64/tst-audit26mod.c | 33 +++++
sysdeps/aarch64/tst-audit26mod.h | 50 +++++++
sysdeps/aarch64/tst-audit27.c | 64 +++++++++
sysdeps/aarch64/tst-audit27mod.c | 95 ++++++++++++++
sysdeps/aarch64/tst-audit27mod.h | 67 ++++++++++
sysdeps/aarch64/tst-auditmod26.c | 98 ++++++++++++++
sysdeps/aarch64/tst-auditmod27.c | 175 +++++++++++++++++++++++++
14 files changed, 741 insertions(+), 48 deletions(-)
create mode 100644 sysdeps/aarch64/bits/link_lavcurrent.h
create mode 100644 sysdeps/aarch64/tst-audit26.c
create mode 100644 sysdeps/aarch64/tst-audit26mod.c
create mode 100644 sysdeps/aarch64/tst-audit26mod.h
create mode 100644 sysdeps/aarch64/tst-audit27.c
create mode 100644 sysdeps/aarch64/tst-audit27mod.c
create mode 100644 sysdeps/aarch64/tst-audit27mod.h
create mode 100644 sysdeps/aarch64/tst-auditmod26.c
create mode 100644 sysdeps/aarch64/tst-auditmod27.c
diff --git a/elf/rtld.c b/elf/rtld.c
index 29a37f51d3..1a13ae6314 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -990,10 +990,10 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
return;
}
- if (lav > LAV_CURRENT)
+ if (lav != LAV_CURRENT)
{
_dl_debug_printf ("\
-ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
+ERROR: audit interface '%s' requires version %d (current supported version %d); ignored.\n",
name, lav, LAV_CURRENT);
unload_audit_module (dlmargs.map, original_tls_idx);
return;
diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index 7c66fb97aa..7183895d04 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -10,6 +10,26 @@ endif
ifeq ($(subdir),elf)
sysdep-dl-routines += dl-bti
+
+tests += tst-audit26 \
+ tst-audit27
+
+modules-names += \
+ tst-audit26mod \
+ tst-auditmod26 \
+ tst-audit27mod \
+ tst-auditmod27
+
+$(objpfx)tst-audit26: $(objpfx)tst-audit26mod.so \
+ $(objpfx)tst-auditmod26.so
+LDFLAGS-tst-audit26 += -Wl,-z,lazy
+tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so
+
+$(objpfx)tst-audit27: $(objpfx)tst-audit27mod.so \
+ $(objpfx)tst-auditmod27.so
+$(objpfx)tst-audit27mod.so: $(libsupport)
+LDFLAGS-tst-audit27 += -Wl,-z,lazy
+tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so
endif
ifeq ($(subdir),elf)
diff --git a/sysdeps/aarch64/bits/link.h b/sysdeps/aarch64/bits/link.h
index 774bbe5f45..2af90ca6be 100644
--- a/sysdeps/aarch64/bits/link.h
+++ b/sysdeps/aarch64/bits/link.h
@@ -20,23 +20,29 @@
# error "Never include <bits/link.h> directly; use <link.h> instead."
#endif
+typedef union
+{
+ float s;
+ double d;
+ long double q;
+} La_aarch64_vector;
+
/* Registers for entry into PLT on AArch64. */
typedef struct La_aarch64_regs
{
- uint64_t lr_xreg[8];
- uint64_t lr_dreg[8];
- uint64_t lr_sp;
- uint64_t lr_lr;
+ uint64_t lr_xreg[9];
+ La_aarch64_vector lr_vreg[8];
+ uint64_t lr_sp;
+ uint64_t lr_lr;
} La_aarch64_regs;
/* Return values for calls from PLT on AArch64. */
typedef struct La_aarch64_retval
{
- /* Up to two integer registers can be used for a return value. */
- uint64_t lrv_xreg[2];
- /* Up to four D registers can be used for a return value. */
- uint64_t lrv_dreg[4];
-
+ /* Up to eight integer registers can be used for a return value. */
+ uint64_t lrv_xreg[8];
+ /* Up to eight V registers can be used for a return value. */
+ La_aarch64_vector lrv_vreg[8];
} La_aarch64_retval;
__BEGIN_DECLS
diff --git a/sysdeps/aarch64/bits/link_lavcurrent.h b/sysdeps/aarch64/bits/link_lavcurrent.h
new file mode 100644
index 0000000000..c48835d12b
--- /dev/null
+++ b/sysdeps/aarch64/bits/link_lavcurrent.h
@@ -0,0 +1,25 @@
+/* Data structure for communication from the run-time dynamic linker for
+ loaded ELF shared objects. LAV_CURRENT definition.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _LINK_H
+# error "Never include <bits/link_lavcurrent.h> directly; use <link.h> instead."
+#endif
+
+/* Version numbers for la_version handshake interface. */
+#define LAV_CURRENT 2
diff --git a/sysdeps/aarch64/dl-link.sym b/sysdeps/aarch64/dl-link.sym
index d67d28b40c..70d153a1d5 100644
--- a/sysdeps/aarch64/dl-link.sym
+++ b/sysdeps/aarch64/dl-link.sym
@@ -7,9 +7,9 @@ DL_SIZEOF_RG sizeof(struct La_aarch64_regs)
DL_SIZEOF_RV sizeof(struct La_aarch64_retval)
DL_OFFSET_RG_X0 offsetof(struct La_aarch64_regs, lr_xreg)
-DL_OFFSET_RG_D0 offsetof(struct La_aarch64_regs, lr_dreg)
+DL_OFFSET_RG_V0 offsetof(struct La_aarch64_regs, lr_vreg)
DL_OFFSET_RG_SP offsetof(struct La_aarch64_regs, lr_sp)
DL_OFFSET_RG_LR offsetof(struct La_aarch64_regs, lr_lr)
DL_OFFSET_RV_X0 offsetof(struct La_aarch64_retval, lrv_xreg)
-DL_OFFSET_RV_D0 offsetof(struct La_aarch64_retval, lrv_dreg)
+DL_OFFSET_RV_V0 offsetof(struct La_aarch64_retval, lrv_vreg)
diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S
index 9b352b1d0f..0d540651d4 100644
--- a/sysdeps/aarch64/dl-trampoline.S
+++ b/sysdeps/aarch64/dl-trampoline.S
@@ -45,7 +45,8 @@ _dl_runtime_resolve:
cfi_rel_offset (lr, 8)
- /* Save arguments. */
+ /* Note: Saving x9 is not required by the ABI but the assember requires
+ the immediate values of operand 3 to be a multiple of 16 */
stp x8, x9, [sp, #-(80+8*16)]!
cfi_adjust_cfa_offset (80+8*16)
cfi_rel_offset (x8, 0)
@@ -142,13 +143,17 @@ _dl_runtime_profile:
Stack frame layout:
[sp, #...] lr
[sp, #...] &PLTGOT[n]
- [sp, #96] La_aarch64_regs
- [sp, #48] La_aarch64_retval
- [sp, #40] frame size return from pltenter
- [sp, #32] dl_profile_call saved x1
- [sp, #24] dl_profile_call saved x0
- [sp, #16] t1
- [sp, #0] x29, lr <- x29
+ -----------------------
+ [sp, #384] La_aarch64_regs::lr_xreg (x0-x8)
+ [sp, #256] La_aarch64_regs::lr_vreg (q0-q7)
+ [sp, #240] La_aarch64_regs::sp and La_aarch64_regs::lr
+ [sp, #176] La_aarch64_retval::lrv_xreg (x0-x7)
+ [sp, # 48] La_aarch64_retval::lrv_vreg (q0-q7)
+ [sp, # 40] frame size return from pltenter
+ [sp, # 32] dl_profile_call saved x1
+ [sp, # 24] dl_profile_call saved x0
+ [sp, # 16] t1
+ [sp, # 0] x29, lr <- x29
*/
# define OFFSET_T1 16
@@ -183,19 +188,22 @@ _dl_runtime_profile:
stp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
cfi_rel_offset (x6, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
cfi_rel_offset (x7, OFFSET_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
-
- stp d0, d1, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
- cfi_rel_offset (d0, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0)
- cfi_rel_offset (d1, OFFSET_RG + DL_OFFSET_RG_D0 + 16*0 + 8)
- stp d2, d3, [X29, #OFFSET_RG+ DL_OFFSET_RG_D0 + 16*1]
- cfi_rel_offset (d2, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 0)
- cfi_rel_offset (d3, OFFSET_RG + DL_OFFSET_RG_D0 + 16*1 + 8)
- stp d4, d5, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
- cfi_rel_offset (d4, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 0)
- cfi_rel_offset (d5, OFFSET_RG + DL_OFFSET_RG_D0 + 16*2 + 8)
- stp d6, d7, [X29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
- cfi_rel_offset (d6, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 0)
- cfi_rel_offset (d7, OFFSET_RG + DL_OFFSET_RG_D0 + 16*3 + 8)
+ str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4 + 0]
+ cfi_rel_offset (x8, OFFSET_RG + DL_OFFSET_RG_X0 + 16*4 + 0)
+ /* Note 8 bytes of padding is in the stack frame for alignment */
+
+ stp q0, q1, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0]
+ cfi_rel_offset (q0, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0)
+ cfi_rel_offset (q1, OFFSET_RG + DL_OFFSET_RG_V0 + 32*0 + 16)
+ stp q2, q3, [X29, #OFFSET_RG+ DL_OFFSET_RG_V0 + 32*1]
+ cfi_rel_offset (q2, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 0)
+ cfi_rel_offset (q3, OFFSET_RG + DL_OFFSET_RG_V0 + 32*1 + 16)
+ stp q4, q5, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2]
+ cfi_rel_offset (q4, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 0)
+ cfi_rel_offset (q5, OFFSET_RG + DL_OFFSET_RG_V0 + 32*2 + 16)
+ stp q6, q7, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3]
+ cfi_rel_offset (q6, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 0)
+ cfi_rel_offset (q7, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 16)
add x0, x29, #SF_SIZE + 16
ldr x1, [x29, #OFFSET_LR]
@@ -234,10 +242,11 @@ _dl_runtime_profile:
ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
- ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
- ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
- ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
- ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
+ ldr x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4]
+ ldp q0, q1, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0]
+ ldp q2, q3, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1]
+ ldp q4, q5, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2]
+ ldp q6, q7, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3]
cfi_def_cfa_register (sp)
ldp x29, x30, [x29, #0]
@@ -280,14 +289,21 @@ _dl_runtime_profile:
ldp x2, x3, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*1]
ldp x4, x5, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*2]
ldp x6, x7, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*3]
- ldp d0, d1, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*0]
- ldp d2, d3, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*1]
- ldp d4, d5, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*2]
- ldp d6, d7, [x29, #OFFSET_RG + DL_OFFSET_RG_D0 + 16*3]
+ ldr x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4]
+ ldp q0, q1, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*0]
+ ldp q2, q3, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*1]
+ ldp q4, q5, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*2]
+ ldp q6, q7, [x29, #OFFSET_RG + DL_OFFSET_RG_V0 + 32*3]
blr ip0
- stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
- stp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
- stp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
+ stp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*0]
+ stp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1]
+ stp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2]
+ stp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3]
+ str x8, [x29, #OFFSET_RG + DL_OFFSET_RG_X0 + 16*4]
+ stp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0]
+ stp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1]
+ stp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2]
+ stp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3]
/* Setup call to pltexit */
ldp x0, x1, [x29, #OFFSET_SAVED_CALL_X0]
@@ -295,9 +311,16 @@ _dl_runtime_profile:
add x3, x29, #OFFSET_RV
bl _dl_audit_pltexit
- ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0]
- ldp d0, d1, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*0]
- ldp d2, d3, [x29, #OFFSET_RV + DL_OFFSET_RV_D0 + 16*1]
+ ldp x0, x1, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*0]
+ ldp x2, x3, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*1]
+ ldp x4, x5, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*2]
+ ldp x6, x7, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*3]
+ ldr x8, [x29, #OFFSET_RV + DL_OFFSET_RV_X0 + 16*4]
+ ldp q0, q1, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*0]
+ ldp q2, q3, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*1]
+ ldp q4, q5, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*2]
+ ldp q6, q7, [x29, #OFFSET_RV + DL_OFFSET_RV_V0 + 32*3]
+
/* LR from within La_aarch64_reg */
ldr lr, [x29, #OFFSET_RG + DL_OFFSET_RG_LR]
cfi_restore(lr)
diff --git a/sysdeps/aarch64/tst-audit26.c b/sysdeps/aarch64/tst-audit26.c
new file mode 100644
index 0000000000..44d2479e08
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit26.c
@@ -0,0 +1,37 @@
+/* Check DT_AUDIT for aarch64 ABI specifics.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <string.h>
+#include <support/check.h>
+#include "tst-audit26mod.h"
+
+int
+do_test (void)
+{
+ /* Returning a large struct uses 'x8' as indirect result location. */
+ struct large_struct r = tst_audit26_func (ARG1, ARG2, ARG3);
+
+ struct large_struct e = set_large_struct (ARG1, ARG2, ARG3);
+
+ TEST_COMPARE_BLOB (r.a, sizeof (r.a), e.a, sizeof (e.a));
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/aarch64/tst-audit26mod.c b/sysdeps/aarch64/tst-audit26mod.c
new file mode 100644
index 0000000000..f8d9270898
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit26mod.c
@@ -0,0 +1,33 @@
+/* Check DT_AUDIT for aarch64 ABI specifics.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <stdlib.h>
+#include "tst-audit26mod.h"
+
+struct large_struct
+tst_audit26_func (char a, short b, long int c)
+{
+ if (a != ARG1)
+ abort ();
+ if (b != ARG2)
+ abort ();
+ if (c != ARG3)
+ abort ();
+
+ return set_large_struct (a, b, c);
+}
diff --git a/sysdeps/aarch64/tst-audit26mod.h b/sysdeps/aarch64/tst-audit26mod.h
new file mode 100644
index 0000000000..dd9ddcdada
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit26mod.h
@@ -0,0 +1,50 @@
+/* Check DT_AUDIT for aarch64 specific ABI.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TST_AUDIT27MOD_H
+#define _TST_AUDIT27MOD_H 1
+
+#include <array_length.h>
+
+struct large_struct
+{
+ char a[16];
+ short b[8];
+ long int c[4];
+};
+
+static inline struct large_struct
+set_large_struct (char a, short b, long int c)
+{
+ struct large_struct r;
+ for (int i = 0; i < array_length (r.a); i++)
+ r.a[i] = a;
+ for (int i = 0; i < array_length (r.b); i++)
+ r.b[i] = b;
+ for (int i = 0; i < array_length (r.c); i++)
+ r.c[i] = c;
+ return r;
+}
+
+#define ARG1 0x12
+#define ARG2 0x1234
+#define ARG3 0x12345678
+
+struct large_struct tst_audit26_func (char a, short b, long int c);
+
+#endif
diff --git a/sysdeps/aarch64/tst-audit27.c b/sysdeps/aarch64/tst-audit27.c
new file mode 100644
index 0000000000..e19b58bc3b
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit27.c
@@ -0,0 +1,64 @@
+/* Check DT_AUDIT for aarch64 ABI specifics.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <string.h>
+#include <support/check.h>
+#include "tst-audit27mod.h"
+
+int
+do_test (void)
+{
+ {
+ float r = tst_audit27_func_float (FUNC_FLOAT_ARG0, FUNC_FLOAT_ARG1,
+ FUNC_FLOAT_ARG2, FUNC_FLOAT_ARG3,
+ FUNC_FLOAT_ARG4, FUNC_FLOAT_ARG5,
+ FUNC_FLOAT_ARG6, FUNC_FLOAT_ARG7);
+ if (r != FUNC_FLOAT_RET)
+ FAIL_EXIT1 ("tst_audit27_func_float() returned %a, expected %a",
+ r, FUNC_FLOAT_RET);
+ }
+
+ {
+ double r = tst_audit27_func_double (FUNC_DOUBLE_ARG0, FUNC_DOUBLE_ARG1,
+ FUNC_DOUBLE_ARG2, FUNC_DOUBLE_ARG3,
+ FUNC_DOUBLE_ARG4, FUNC_DOUBLE_ARG5,
+ FUNC_DOUBLE_ARG6, FUNC_DOUBLE_ARG7);
+ if (r != FUNC_DOUBLE_RET)
+ FAIL_EXIT1 ("tst_audit27_func_double() returned %la, expected %la",
+ r, FUNC_DOUBLE_RET);
+ }
+
+ {
+ long double r = tst_audit27_func_ldouble (FUNC_LDOUBLE_ARG0,
+ FUNC_LDOUBLE_ARG1,
+ FUNC_LDOUBLE_ARG2,
+ FUNC_LDOUBLE_ARG3,
+ FUNC_LDOUBLE_ARG4,
+ FUNC_LDOUBLE_ARG5,
+ FUNC_LDOUBLE_ARG6,
+ FUNC_LDOUBLE_ARG7);
+ if (r != FUNC_LDOUBLE_RET)
+ FAIL_EXIT1 ("tst_audit27_func_ldouble() returned %La, expected %La",
+ r, FUNC_LDOUBLE_RET);
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/aarch64/tst-audit27mod.c b/sysdeps/aarch64/tst-audit27mod.c
new file mode 100644
index 0000000000..a8e8b28523
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit27mod.c
@@ -0,0 +1,95 @@
+/* Check DT_AUDIT for aarch64 ABI specifics.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include "tst-audit27mod.h"
+
+float
+tst_audit27_func_float (float a0, float a1, float a2, float a3, float a4,
+ float a5, float a6, float a7)
+{
+ if (a0 != FUNC_FLOAT_ARG0)
+ FAIL_EXIT1 ("a0: %a != %a", a0, FUNC_FLOAT_ARG0);
+ if (a1 != FUNC_FLOAT_ARG1)
+ FAIL_EXIT1 ("a1: %a != %a", a1, FUNC_FLOAT_ARG1);
+ if (a2 != FUNC_FLOAT_ARG2)
+ FAIL_EXIT1 ("a2: %a != %a", a2, FUNC_FLOAT_ARG2);
+ if (a3 != FUNC_FLOAT_ARG3)
+ FAIL_EXIT1 ("a3: %a != %a", a3, FUNC_FLOAT_ARG3);
+ if (a4 != FUNC_FLOAT_ARG4)
+ FAIL_EXIT1 ("a4: %a != %a", a4, FUNC_FLOAT_ARG4);
+ if (a5 != FUNC_FLOAT_ARG5)
+ FAIL_EXIT1 ("a5: %a != %a", a5, FUNC_FLOAT_ARG5);
+ if (a6 != FUNC_FLOAT_ARG6)
+ FAIL_EXIT1 ("a6: %a != %a", a6, FUNC_FLOAT_ARG6);
+ if (a7 != FUNC_FLOAT_ARG7)
+ FAIL_EXIT1 ("a7: %a != %a", a7, FUNC_FLOAT_ARG7);
+
+ return FUNC_FLOAT_RET;
+}
+
+double
+tst_audit27_func_double (double a0, double a1, double a2, double a3, double a4,
+ double a5, double a6, double a7)
+{
+ if (a0 != FUNC_DOUBLE_ARG0)
+ FAIL_EXIT1 ("a0: %la != %la", a0, FUNC_DOUBLE_ARG0);
+ if (a1 != FUNC_DOUBLE_ARG1)
+ FAIL_EXIT1 ("a1: %la != %la", a1, FUNC_DOUBLE_ARG1);
+ if (a2 != FUNC_DOUBLE_ARG2)
+ FAIL_EXIT1 ("a2: %la != %la", a2, FUNC_DOUBLE_ARG2);
+ if (a3 != FUNC_DOUBLE_ARG3)
+ FAIL_EXIT1 ("a3: %la != %la", a3, FUNC_DOUBLE_ARG3);
+ if (a4 != FUNC_DOUBLE_ARG4)
+ FAIL_EXIT1 ("a4: %la != %la", a4, FUNC_DOUBLE_ARG4);
+ if (a5 != FUNC_DOUBLE_ARG5)
+ FAIL_EXIT1 ("a5: %la != %la", a5, FUNC_DOUBLE_ARG5);
+ if (a6 != FUNC_DOUBLE_ARG6)
+ FAIL_EXIT1 ("a6: %la != %la", a6, FUNC_DOUBLE_ARG6);
+ if (a7 != FUNC_DOUBLE_ARG7)
+ FAIL_EXIT1 ("a7: %la != %la", a7, FUNC_DOUBLE_ARG7);
+
+ return FUNC_DOUBLE_RET;
+}
+
+long double
+tst_audit27_func_ldouble (long double a0, long double a1, long double a2,
+ long double a3, long double a4, long double a5,
+ long double a6, long double a7)
+{
+ if (a0 != FUNC_LDOUBLE_ARG0)
+ FAIL_EXIT1 ("a0: %La != %La", a0, FUNC_LDOUBLE_ARG0);
+ if (a1 != FUNC_LDOUBLE_ARG1)
+ FAIL_EXIT1 ("a1: %La != %La", a1, FUNC_LDOUBLE_ARG1);
+ if (a2 != FUNC_LDOUBLE_ARG2)
+ FAIL_EXIT1 ("a2: %La != %La", a2, FUNC_LDOUBLE_ARG2);
+ if (a3 != FUNC_LDOUBLE_ARG3)
+ FAIL_EXIT1 ("a3: %La != %La", a3, FUNC_LDOUBLE_ARG3);
+ if (a4 != FUNC_LDOUBLE_ARG4)
+ FAIL_EXIT1 ("a4: %La != %La", a4, FUNC_LDOUBLE_ARG4);
+ if (a5 != FUNC_LDOUBLE_ARG5)
+ FAIL_EXIT1 ("a5: %La != %La", a5, FUNC_LDOUBLE_ARG5);
+ if (a6 != FUNC_LDOUBLE_ARG6)
+ FAIL_EXIT1 ("a6: %La != %La", a6, FUNC_LDOUBLE_ARG6);
+ if (a7 != FUNC_LDOUBLE_ARG7)
+ FAIL_EXIT1 ("a7: %La != %La", a7, FUNC_LDOUBLE_ARG7);
+
+ return FUNC_LDOUBLE_RET;
+}
diff --git a/sysdeps/aarch64/tst-audit27mod.h b/sysdeps/aarch64/tst-audit27mod.h
new file mode 100644
index 0000000000..cbd44c4bdf
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit27mod.h
@@ -0,0 +1,67 @@
+/* Check DT_AUDIT for aarch64 specific ABI.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TST_AUDIT27MOD_H
+#define _TST_AUDIT27MOD_H 1
+
+#include <float.h>
+
+#define FUNC_FLOAT_ARG0 FLT_MIN
+#define FUNC_FLOAT_ARG1 FLT_MAX
+#define FUNC_FLOAT_ARG2 FLT_EPSILON
+#define FUNC_FLOAT_ARG3 FLT_TRUE_MIN
+#define FUNC_FLOAT_ARG4 0.0f
+#define FUNC_FLOAT_ARG5 1.0f
+#define FUNC_FLOAT_ARG6 2.0f
+#define FUNC_FLOAT_ARG7 3.0f
+#define FUNC_FLOAT_RET 4.0f
+
+float
+tst_audit27_func_float (float a0, float a1, float a2, float a3, float a4,
+ float a5, float a6, float a7);
+
+#define FUNC_DOUBLE_ARG0 DBL_MIN
+#define FUNC_DOUBLE_ARG1 DBL_MAX
+#define FUNC_DOUBLE_ARG2 DBL_EPSILON
+#define FUNC_DOUBLE_ARG3 DBL_TRUE_MIN
+#define FUNC_DOUBLE_ARG4 0.0
+#define FUNC_DOUBLE_ARG5 1.0
+#define FUNC_DOUBLE_ARG6 2.0
+#define FUNC_DOUBLE_ARG7 3.0
+#define FUNC_DOUBLE_RET 0x1.fffffe0000001p+127
+
+double
+tst_audit27_func_double (double a0, double a1, double a2, double a3, double a4,
+ double a5, double a6, double a7);
+
+#define FUNC_LDOUBLE_ARG0 DBL_MAX + 1.0L
+#define FUNC_LDOUBLE_ARG1 DBL_MAX + 2.0L
+#define FUNC_LDOUBLE_ARG2 DBL_MAX + 3.0L
+#define FUNC_LDOUBLE_ARG3 DBL_MAX + 4.0L
+#define FUNC_LDOUBLE_ARG4 DBL_MAX + 5.0L
+#define FUNC_LDOUBLE_ARG5 DBL_MAX + 6.0L
+#define FUNC_LDOUBLE_ARG6 DBL_MAX + 7.0L
+#define FUNC_LDOUBLE_ARG7 DBL_MAX + 8.0L
+#define FUNC_LDOUBLE_RET 0x1.fffffffffffff000000000000001p+1023L
+
+long double
+tst_audit27_func_ldouble (long double a0, long double a1, long double a2,
+ long double a3, long double a4, long double a5,
+ long double a6, long double a7);
+
+#endif
diff --git a/sysdeps/aarch64/tst-auditmod26.c b/sysdeps/aarch64/tst-auditmod26.c
new file mode 100644
index 0000000000..028f638446
--- /dev/null
+++ b/sysdeps/aarch64/tst-auditmod26.c
@@ -0,0 +1,98 @@
+/* Check DT_AUDIT for aarch64 specific ABI.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <link.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "tst-audit26mod.h"
+
+#define TEST_NAME "tst-audit26"
+
+#define AUDIT26_COOKIE 0
+
+unsigned int
+la_version (unsigned int v)
+{
+ return v;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
+ ck = AUDIT26_COOKIE;
+ *cookie = ck;
+ printf ("objopen: %ld, %s [cookie=%ld]\n", lmid, l_name, ck);
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+ElfW(Addr)
+la_aarch64_gnu_pltenter (ElfW(Sym) *sym __attribute__ ((unused)),
+ unsigned int ndx __attribute__ ((unused)),
+ uintptr_t *refcook, uintptr_t *defcook,
+ La_aarch64_regs *regs, unsigned int *flags,
+ const char *symname, long int *framesizep)
+{
+ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ if (strcmp (symname, "tst_audit26_func") == 0)
+ {
+ assert (regs->lr_xreg[0] == ARG1);
+ assert (regs->lr_xreg[1] == ARG2);
+ assert (regs->lr_xreg[2] == ARG3);
+ }
+ else
+ abort ();
+
+ /* Clobber 'x8'. */
+ asm volatile ("mov x8, -1" : : : "x8");
+
+ *framesizep = 1024;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_aarch64_regs *inregs,
+ struct La_aarch64_retval *outregs, const char *symname)
+{
+ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n",
+ symname, (long int) sym->st_value, ndx);
+
+ if (strcmp (symname, "tst_audit26_func") == 0)
+ {
+ assert (inregs->lr_xreg[0] == ARG1);
+ assert (inregs->lr_xreg[1] == ARG2);
+ assert (inregs->lr_xreg[2] == ARG3);
+ }
+ else
+ abort ();
+
+ /* Clobber 'x8'. */
+ asm volatile ("mov x8, -1" : : : "x8");
+
+ return 0;
+}
diff --git a/sysdeps/aarch64/tst-auditmod27.c b/sysdeps/aarch64/tst-auditmod27.c
new file mode 100644
index 0000000000..b1dbff8330
--- /dev/null
+++ b/sysdeps/aarch64/tst-auditmod27.c
@@ -0,0 +1,175 @@
+/* Check DT_AUDIT for aarch64 specific ABI.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <assert.h>
+#include <link.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "tst-audit27mod.h"
+
+#define TEST_NAME "tst-audit27"
+
+#define AUDIT27_COOKIE 0
+
+unsigned int
+la_version (unsigned int v)
+{
+ return v;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
+ ck = AUDIT27_COOKIE;
+ *cookie = ck;
+ printf ("objopen: %ld, %s [%ld]\n", lmid, l_name, ck);
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+ElfW(Addr)
+la_aarch64_gnu_pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, La_aarch64_regs *regs,
+ unsigned int *flags, const char *symname,
+ long int *framesizep)
+{
+ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+
+ if (strcmp (symname, "tst_audit27_func_float") == 0)
+ {
+ assert (regs->lr_vreg[0].s == FUNC_FLOAT_ARG0);
+ assert (regs->lr_vreg[1].s == FUNC_FLOAT_ARG1);
+ assert (regs->lr_vreg[2].s == FUNC_FLOAT_ARG2);
+ assert (regs->lr_vreg[3].s == FUNC_FLOAT_ARG3);
+ assert (regs->lr_vreg[4].s == FUNC_FLOAT_ARG4);
+ assert (regs->lr_vreg[5].s == FUNC_FLOAT_ARG5);
+ assert (regs->lr_vreg[6].s == FUNC_FLOAT_ARG6);
+ assert (regs->lr_vreg[7].s == FUNC_FLOAT_ARG7);
+ }
+ else if (strcmp (symname, "tst_audit27_func_double") == 0)
+ {
+ assert (regs->lr_vreg[0].d == FUNC_DOUBLE_ARG0);
+ assert (regs->lr_vreg[1].d == FUNC_DOUBLE_ARG1);
+ assert (regs->lr_vreg[2].d == FUNC_DOUBLE_ARG2);
+ assert (regs->lr_vreg[3].d == FUNC_DOUBLE_ARG3);
+ assert (regs->lr_vreg[4].d == FUNC_DOUBLE_ARG4);
+ assert (regs->lr_vreg[5].d == FUNC_DOUBLE_ARG5);
+ assert (regs->lr_vreg[6].d == FUNC_DOUBLE_ARG6);
+ assert (regs->lr_vreg[7].d == FUNC_DOUBLE_ARG7);
+ }
+ else if (strcmp (symname, "tst_audit27_func_ldouble") == 0)
+ {
+ assert (regs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0);
+ assert (regs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1);
+ assert (regs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2);
+ assert (regs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3);
+ assert (regs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4);
+ assert (regs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5);
+ assert (regs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6);
+ assert (regs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7);
+ }
+ else
+ abort ();
+
+ /* Clobber the q registers on exit. */
+ uint8_t v = 0xff;
+ asm volatile ("dup v0.8b, %w0" : : "r" (v) : "v0");
+ asm volatile ("dup v1.8b, %w0" : : "r" (v) : "v1");
+ asm volatile ("dup v2.8b, %w0" : : "r" (v) : "v2");
+ asm volatile ("dup v3.8b, %w0" : : "r" (v) : "v3");
+ asm volatile ("dup v4.8b, %w0" : : "r" (v) : "v4");
+ asm volatile ("dup v5.8b, %w0" : : "r" (v) : "v5");
+ asm volatile ("dup v6.8b, %w0" : : "r" (v) : "v6");
+ asm volatile ("dup v7.8b, %w0" : : "r" (v) : "v7");
+
+ *framesizep = 1024;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_aarch64_regs *inregs,
+ struct La_aarch64_retval *outregs,
+ const char *symname)
+{
+ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n",
+ symname, (long int) sym->st_value, ndx);
+
+ if (strcmp (symname, "tst_audit27_func_float") == 0)
+ {
+ assert (inregs->lr_vreg[0].s == FUNC_FLOAT_ARG0);
+ assert (inregs->lr_vreg[1].s == FUNC_FLOAT_ARG1);
+ assert (inregs->lr_vreg[2].s == FUNC_FLOAT_ARG2);
+ assert (inregs->lr_vreg[3].s == FUNC_FLOAT_ARG3);
+ assert (inregs->lr_vreg[4].s == FUNC_FLOAT_ARG4);
+ assert (inregs->lr_vreg[5].s == FUNC_FLOAT_ARG5);
+ assert (inregs->lr_vreg[6].s == FUNC_FLOAT_ARG6);
+ assert (inregs->lr_vreg[7].s == FUNC_FLOAT_ARG7);
+
+ assert (outregs->lrv_vreg[0].s == FUNC_FLOAT_RET);
+ }
+ else if (strcmp (symname, "tst_audit27_func_double") == 0)
+ {
+ assert (inregs->lr_vreg[0].d == FUNC_DOUBLE_ARG0);
+ assert (inregs->lr_vreg[1].d == FUNC_DOUBLE_ARG1);
+ assert (inregs->lr_vreg[2].d == FUNC_DOUBLE_ARG2);
+ assert (inregs->lr_vreg[3].d == FUNC_DOUBLE_ARG3);
+ assert (inregs->lr_vreg[4].d == FUNC_DOUBLE_ARG4);
+ assert (inregs->lr_vreg[5].d == FUNC_DOUBLE_ARG5);
+ assert (inregs->lr_vreg[6].d == FUNC_DOUBLE_ARG6);
+ assert (inregs->lr_vreg[7].d == FUNC_DOUBLE_ARG7);
+
+ assert (outregs->lrv_vreg[0].d == FUNC_DOUBLE_RET);
+ }
+ else if (strcmp (symname, "tst_audit27_func_ldouble") == 0)
+ {
+ assert (inregs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0);
+ assert (inregs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1);
+ assert (inregs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2);
+ assert (inregs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3);
+ assert (inregs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4);
+ assert (inregs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5);
+ assert (inregs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6);
+ assert (inregs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7);
+
+ assert (outregs->lrv_vreg[0].q == FUNC_LDOUBLE_RET);
+ }
+ else
+ abort ();
+
+ /* Clobber the q registers on exit. */
+ uint8_t v = 0xff;
+ asm volatile ("dup v0.8b, %w0" : : "r" (v) : "v0");
+ asm volatile ("dup v1.8b, %w0" : : "r" (v) : "v1");
+ asm volatile ("dup v2.8b, %w0" : : "r" (v) : "v2");
+ asm volatile ("dup v3.8b, %w0" : : "r" (v) : "v3");
+ asm volatile ("dup v4.8b, %w0" : : "r" (v) : "v4");
+ asm volatile ("dup v5.8b, %w0" : : "r" (v) : "v5");
+ asm volatile ("dup v6.8b, %w0" : : "r" (v) : "v6");
+ asm volatile ("dup v7.8b, %w0" : : "r" (v) : "v7");
+
+ return 0;
+}
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-11-15 18:37 ` [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
@ 2021-12-20 21:32 ` Florian Weimer
2021-12-21 14:33 ` Adhemerval Zanella
2021-12-20 21:34 ` Florian Weimer
2021-12-21 17:47 ` Szabolcs Nagy
2 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 21:32 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/elf/rtld.c b/elf/rtld.c
> index 29a37f51d3..1a13ae6314 100644
> --- a/elf/rtld.c
> +++ b/elf/rtld.c
> @@ -990,10 +990,10 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
> return;
> }
>
> - if (lav > LAV_CURRENT)
> + if (lav != LAV_CURRENT)
> {
> _dl_debug_printf ("\
> -ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
> +ERROR: audit interface '%s' requires version %d (current supported version %d); ignored.\n",
> name, lav, LAV_CURRENT);
> unload_audit_module (dlmargs.map, original_tls_idx);
> return;
Sorry, this is not what I had in mind. I'd like to increase LAV_CURRENT
and pretend that the old and new versions have the same behavior, at
least as far as aarch64 is concerned. We need not write the
compatibility code for the old <link.h> at this time, only if there
actual users out there that demand it.
(However, for the symbind change, I think we should look at the audit
module version. It is also much easier to implement both behaviors
there, I hope.)
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-20 21:32 ` Florian Weimer
@ 2021-12-21 14:33 ` Adhemerval Zanella
2021-12-21 14:44 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 14:33 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 20/12/2021 18:32, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> diff --git a/elf/rtld.c b/elf/rtld.c
>> index 29a37f51d3..1a13ae6314 100644
>> --- a/elf/rtld.c
>> +++ b/elf/rtld.c
>> @@ -990,10 +990,10 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
>> return;
>> }
>>
>> - if (lav > LAV_CURRENT)
>> + if (lav != LAV_CURRENT)
>> {
>> _dl_debug_printf ("\
>> -ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
>> +ERROR: audit interface '%s' requires version %d (current supported version %d); ignored.\n",
>> name, lav, LAV_CURRENT);
>> unload_audit_module (dlmargs.map, original_tls_idx);
>> return;
>
> Sorry, this is not what I had in mind. I'd like to increase LAV_CURRENT
> and pretend that the old and new versions have the same behavior, at
> least as far as aarch64 is concerned. We need not write the
> compatibility code for the old <link.h> at this time, only if there
> actual users out there that demand it.
Do you mean to only check if lav >= LAV_CURRENT and allow old audit modules
as well?
At least for aarch64 old audit modules are error-prone and potentially adds
more subtle issues since they do not save/restore some return register that
I don't see any real gain to keep supporting them.
>
> (However, for the symbind change, I think we should look at the audit
> module version. It is also much easier to implement both behaviors
> there, I hope.)
For symbind it does make sense, although I am very convinced that users
will really care about it.
>
> Thanks,
> Florian
>
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 14:33 ` Adhemerval Zanella
@ 2021-12-21 14:44 ` Florian Weimer
2021-12-21 14:48 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-21 14:44 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> On 20/12/2021 18:32, Florian Weimer wrote:
>> * Adhemerval Zanella:
>>
>>> diff --git a/elf/rtld.c b/elf/rtld.c
>>> index 29a37f51d3..1a13ae6314 100644
>>> --- a/elf/rtld.c
>>> +++ b/elf/rtld.c
>>> @@ -990,10 +990,10 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
>>> return;
>>> }
>>>
>>> - if (lav > LAV_CURRENT)
>>> + if (lav != LAV_CURRENT)
>>> {
>>> _dl_debug_printf ("\
>>> -ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
>>> +ERROR: audit interface '%s' requires version %d (current supported version %d); ignored.\n",
>>> name, lav, LAV_CURRENT);
>>> unload_audit_module (dlmargs.map, original_tls_idx);
>>> return;
>>
>> Sorry, this is not what I had in mind. I'd like to increase LAV_CURRENT
>> and pretend that the old and new versions have the same behavior, at
>> least as far as aarch64 is concerned. We need not write the
>> compatibility code for the old <link.h> at this time, only if there
>> actual users out there that demand it.
>
> Do you mean to only check if lav >= LAV_CURRENT and allow old audit modules
> as well?
Yes.
> At least for aarch64 old audit modules are error-prone and potentially adds
> more subtle issues since they do not save/restore some return register that
> I don't see any real gain to keep supporting them.
I disagree. la_objsearch alone is a significant use case, and I don't
see why it wouldn't work today. It does not need any
architecture-specific code whatsoever.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 14:44 ` Florian Weimer
@ 2021-12-21 14:48 ` Adhemerval Zanella
2021-12-21 14:54 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 14:48 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 21/12/2021 11:44, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> On 20/12/2021 18:32, Florian Weimer wrote:
>>> * Adhemerval Zanella:
>>>
>>>> diff --git a/elf/rtld.c b/elf/rtld.c
>>>> index 29a37f51d3..1a13ae6314 100644
>>>> --- a/elf/rtld.c
>>>> +++ b/elf/rtld.c
>>>> @@ -990,10 +990,10 @@ file=%s [%lu]; audit interface function la_version returned zero; ignored.\n",
>>>> return;
>>>> }
>>>>
>>>> - if (lav > LAV_CURRENT)
>>>> + if (lav != LAV_CURRENT)
>>>> {
>>>> _dl_debug_printf ("\
>>>> -ERROR: audit interface '%s' requires version %d (maximum supported version %d); ignored.\n",
>>>> +ERROR: audit interface '%s' requires version %d (current supported version %d); ignored.\n",
>>>> name, lav, LAV_CURRENT);
>>>> unload_audit_module (dlmargs.map, original_tls_idx);
>>>> return;
>>>
>>> Sorry, this is not what I had in mind. I'd like to increase LAV_CURRENT
>>> and pretend that the old and new versions have the same behavior, at
>>> least as far as aarch64 is concerned. We need not write the
>>> compatibility code for the old <link.h> at this time, only if there
>>> actual users out there that demand it.
>>
>> Do you mean to only check if lav >= LAV_CURRENT and allow old audit modules
>> as well?
>
> Yes.
>
>> At least for aarch64 old audit modules are error-prone and potentially adds
>> more subtle issues since they do not save/restore some return register that
>> I don't see any real gain to keep supporting them.
>
> I disagree. la_objsearch alone is a significant use case, and I don't
> see why it wouldn't work today. It does not need any
> architecture-specific code whatsoever.
My main problem is provide a API which undocumented and missing support
where if users tries to replicate what other architecture does it will
shoot in the foot. I think this is just a broken API and we should
avoid it.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 14:48 ` Adhemerval Zanella
@ 2021-12-21 14:54 ` Florian Weimer
2021-12-21 17:03 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-21 14:54 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
>>> At least for aarch64 old audit modules are error-prone and potentially adds
>>> more subtle issues since they do not save/restore some return register that
>>> I don't see any real gain to keep supporting them.
>>
>> I disagree. la_objsearch alone is a significant use case, and I don't
>> see why it wouldn't work today. It does not need any
>> architecture-specific code whatsoever.
>
> My main problem is provide a API which undocumented and missing support
> where if users tries to replicate what other architecture does it will
> shoot in the foot. I think this is just a broken API and we should
> avoid it.
Sorry, which API?
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 14:54 ` Florian Weimer
@ 2021-12-21 17:03 ` Adhemerval Zanella
2021-12-21 17:22 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 17:03 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 21/12/2021 11:54, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>>>> At least for aarch64 old audit modules are error-prone and potentially adds
>>>> more subtle issues since they do not save/restore some return register that
>>>> I don't see any real gain to keep supporting them.
>>>
>>> I disagree. la_objsearch alone is a significant use case, and I don't
>>> see why it wouldn't work today. It does not need any
>>> architecture-specific code whatsoever.
>>
>> My main problem is provide a API which undocumented and missing support
>> where if users tries to replicate what other architecture does it will
>> shoot in the foot. I think this is just a broken API and we should
>> avoid it.
>
> Sorry, which API?
THe audit modules one, making la_objsearch work when the rest of the possible
callbacks functions might trigger undefined behavior (as per BZ#26643) does
not seems to me as as good way forward. It has not bitten us before because
the user case is quite limited.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 17:03 ` Adhemerval Zanella
@ 2021-12-21 17:22 ` Florian Weimer
2021-12-21 17:38 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-21 17:22 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> On 21/12/2021 11:54, Florian Weimer wrote:
>> * Adhemerval Zanella:
>>
>>>>> At least for aarch64 old audit modules are error-prone and potentially adds
>>>>> more subtle issues since they do not save/restore some return register that
>>>>> I don't see any real gain to keep supporting them.
>>>>
>>>> I disagree. la_objsearch alone is a significant use case, and I don't
>>>> see why it wouldn't work today. It does not need any
>>>> architecture-specific code whatsoever.
>>>
>>> My main problem is provide a API which undocumented and missing support
>>> where if users tries to replicate what other architecture does it will
>>> shoot in the foot. I think this is just a broken API and we should
>>> avoid it.
>>
>> Sorry, which API?
>
> THe audit modules one, making la_objsearch work when the rest of the possible
> callbacks functions might trigger undefined behavior (as per BZ#26643) does
> not seems to me as as good way forward. It has not bitten us before because
> the user case is quite limited.
Red Hat has at least one customer that only uses la_objsearch and not
la_symbind (but they don't use aarch64, so they aren't impacted by this
bug either way).
However, you are changing generic code, so what you are proposing
rejects all old audit modules on all architectures. This is really not
the way to do this.
Let me summarize my recommendation:
. Change LAV_CURRENT to 2.
. Treat la_version return values 1 and 2 the same for now (so > as
before in the check, not !=).
. *If* a user shows up whose aarch64 audit modules were broken by the
fix for bug 26643, support two ABIs for the PLT enter/exit hooks.
. Consider issuing more la_symbind callbacks for LAV_CURRENT == 2
only (BIND_NOW functions and basically all symbols).
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 17:22 ` Florian Weimer
@ 2021-12-21 17:38 ` Adhemerval Zanella
2021-12-21 18:11 ` Florian Weimer
0 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 17:38 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 21/12/2021 14:22, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> On 21/12/2021 11:54, Florian Weimer wrote:
>>> * Adhemerval Zanella:
>>>
>>>>>> At least for aarch64 old audit modules are error-prone and potentially adds
>>>>>> more subtle issues since they do not save/restore some return register that
>>>>>> I don't see any real gain to keep supporting them.
>>>>>
>>>>> I disagree. la_objsearch alone is a significant use case, and I don't
>>>>> see why it wouldn't work today. It does not need any
>>>>> architecture-specific code whatsoever.
>>>>
>>>> My main problem is provide a API which undocumented and missing support
>>>> where if users tries to replicate what other architecture does it will
>>>> shoot in the foot. I think this is just a broken API and we should
>>>> avoid it.
>>>
>>> Sorry, which API?
>>
>> THe audit modules one, making la_objsearch work when the rest of the possible
>> callbacks functions might trigger undefined behavior (as per BZ#26643) does
>> not seems to me as as good way forward. It has not bitten us before because
>> the user case is quite limited.
>
> Red Hat has at least one customer that only uses la_objsearch and not
> la_symbind (but they don't use aarch64, so they aren't impacted by this
> bug either way).
>
> However, you are changing generic code, so what you are proposing
> rejects all old audit modules on all architectures. This is really not
> the way to do this.
Yes, I agree that changing the generic code was kind unnecessary on most
architectures.
>
> Let me summarize my recommendation:
>
> . Change LAV_CURRENT to 2.
>
> . Treat la_version return values 1 and 2 the same for now (so > as
> before in the check, not !=).
And that is what I am doing now.
>
> . *If* a user shows up whose aarch64 audit modules were broken by the
> fix for bug 26643, support two ABIs for the PLT enter/exit hooks.
And that is what I really dislike and I want to avoid, I see absolute
no gain about supporting an interface for aarch64 (or any other port,
the issue is only aarch64 is currently showing) that has subtle and
broken API.
For aarch64 I still think it better to just avoid loading old audit
modules.
>
> . Consider issuing more la_symbind callbacks for LAV_CURRENT == 2
> only (BIND_NOW functions and basically all symbols).
>
What about newer audit module version that request PLT trace? Currently
my plan is to stop execution with an error, instead of just ignoring it.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 17:38 ` Adhemerval Zanella
@ 2021-12-21 18:11 ` Florian Weimer
2021-12-21 18:19 ` Adhemerval Zanella
0 siblings, 1 reply; 89+ messages in thread
From: Florian Weimer @ 2021-12-21 18:11 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
>> . *If* a user shows up whose aarch64 audit modules were broken by the
>> fix for bug 26643, support two ABIs for the PLT enter/exit hooks.
>
> And that is what I really dislike and I want to avoid, I see absolute
> no gain about supporting an interface for aarch64 (or any other port,
> the issue is only aarch64 is currently showing) that has subtle and
> broken API.
I agree! I just want to have an escape hatch in case we have to support
them. That's why I recommend changing LAV_CURRENT.
> For aarch64 I still think it better to just avoid loading old audit
> modules.
In the end, it is your port, but I strongly advise against this.
>> . Consider issuing more la_symbind callbacks for LAV_CURRENT == 2
>> only (BIND_NOW functions and basically all symbols).
>>
> What about newer audit module version that request PLT trace? Currently
> my plan is to stop execution with an error, instead of just ignoring it.
You mean la_version returns 2, a jump slot is available, and the
la_symbind function requests callbacks? I don't see why we'd have to
reject that.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 18:11 ` Florian Weimer
@ 2021-12-21 18:19 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 18:19 UTC (permalink / raw)
To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 21/12/2021 15:11, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>>> . *If* a user shows up whose aarch64 audit modules were broken by the
>>> fix for bug 26643, support two ABIs for the PLT enter/exit hooks.
>>
>> And that is what I really dislike and I want to avoid, I see absolute
>> no gain about supporting an interface for aarch64 (or any other port,
>> the issue is only aarch64 is currently showing) that has subtle and
>> broken API.
>
> I agree! I just want to have an escape hatch in case we have to support
> them. That's why I recommend changing LAV_CURRENT.>
>> For aarch64 I still think it better to just avoid loading old audit
>> modules.
>
> In the end, it is your port, but I strongly advise against this.
The problem with aarch64 currently is it is subtle broken even when
PLT tracking is not enabled, since _dl_runtime_profile does not
save/restore x8. The reproducer from BZ#26643 at least trigger a
SEGFAULT, but since is essentially undefined behavior this is hard to
reason to keep supporting the older version.
Also, it would require more effort by providing two different
_dl_runtime_profile.
>
>>> . Consider issuing more la_symbind callbacks for LAV_CURRENT == 2
>>> only (BIND_NOW functions and basically all symbols).
>>>
>> What about newer audit module version that request PLT trace? Currently
>> my plan is to stop execution with an error, instead of just ignoring it.
>
> You mean la_version returns 2, a jump slot is available, and the
> la_symbind function requests callbacks? I don't see why we'd have to
> reject that.
Alright, I think I can live it with.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-11-15 18:37 ` [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
2021-12-20 21:32 ` Florian Weimer
@ 2021-12-20 21:34 ` Florian Weimer
2021-12-21 17:47 ` Szabolcs Nagy
2 siblings, 0 replies; 89+ messages in thread
From: Florian Weimer @ 2021-12-20 21:34 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> diff --git a/sysdeps/aarch64/bits/link.h b/sysdeps/aarch64/bits/link.h
> index 774bbe5f45..2af90ca6be 100644
> --- a/sysdeps/aarch64/bits/link.h
> +++ b/sysdeps/aarch64/bits/link.h
> @@ -20,23 +20,29 @@
> # error "Never include <bits/link.h> directly; use <link.h> instead."
> #endif
>
> +typedef union
> +{
> + float s;
> + double d;
> + long double q;
> +} La_aarch64_vector;
> +
> /* Registers for entry into PLT on AArch64. */
> typedef struct La_aarch64_regs
> {
> - uint64_t lr_xreg[8];
> - uint64_t lr_dreg[8];
> - uint64_t lr_sp;
> - uint64_t lr_lr;
> + uint64_t lr_xreg[9];
> + La_aarch64_vector lr_vreg[8];
> + uint64_t lr_sp;
> + uint64_t lr_lr;
> } La_aarch64_regs;
Ultimately this is up to the aarch64 maintainers to review, but I wonder
if it would make sense to extend support to non-standard calling
conventions by preserving more GPRs and vector registers.
(There is also talk of a C++-specific calling convention that uses the
carry flag as part of the function return …)
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-11-15 18:37 ` [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
2021-12-20 21:32 ` Florian Weimer
2021-12-20 21:34 ` Florian Weimer
@ 2021-12-21 17:47 ` Szabolcs Nagy
2021-12-21 17:49 ` Adhemerval Zanella
2 siblings, 1 reply; 89+ messages in thread
From: Szabolcs Nagy @ 2021-12-21 17:47 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, Florian Weimer, John Mellor-Crummey
The 11/15/2021 15:37, Adhemerval Zanella via Libc-alpha wrote:
> --- a/sysdeps/aarch64/bits/link.h
> +++ b/sysdeps/aarch64/bits/link.h
> @@ -20,23 +20,29 @@
> # error "Never include <bits/link.h> directly; use <link.h> instead."
> #endif
>
> +typedef union
> +{
> + float s;
> + double d;
> + long double q;
> +} La_aarch64_vector;
> +
> /* Registers for entry into PLT on AArch64. */
> typedef struct La_aarch64_regs
> {
> - uint64_t lr_xreg[8];
> - uint64_t lr_dreg[8];
> - uint64_t lr_sp;
> - uint64_t lr_lr;
> + uint64_t lr_xreg[9];
> + La_aarch64_vector lr_vreg[8];
> + uint64_t lr_sp;
> + uint64_t lr_lr;
> } La_aarch64_regs;
>
> /* Return values for calls from PLT on AArch64. */
> typedef struct La_aarch64_retval
> {
> - /* Up to two integer registers can be used for a return value. */
> - uint64_t lrv_xreg[2];
> - /* Up to four D registers can be used for a return value. */
> - uint64_t lrv_dreg[4];
> -
> + /* Up to eight integer registers can be used for a return value. */
> + uint64_t lrv_xreg[8];
> + /* Up to eight V registers can be used for a return value. */
> + La_aarch64_vector lrv_vreg[8];
> } La_aarch64_retval;
> __BEGIN_DECLS
i think for variant_pcs we will only need a
void *extension;
or similar member at the end of both structs.
(we can make it point to a dump of all registers
in some format for variant_pcs PLT hooks)
if this can avoid a second bump of LAV_CURRENT
when we add variant_pcs support then it may be
useful to have. (if this turns out to be not
enough then we don't lose much, but it also
means users have to check extension==0 for now
and avoid interpreting or touching the registers
otherwise. not sure if this is better or bump,
depends on how many users need to keep updating
their auditor libs on our bumps.)
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
2021-12-21 17:47 ` Szabolcs Nagy
@ 2021-12-21 17:49 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 17:49 UTC (permalink / raw)
To: Szabolcs Nagy; +Cc: libc-alpha, Florian Weimer, John Mellor-Crummey
On 21/12/2021 14:47, Szabolcs Nagy wrote:
> The 11/15/2021 15:37, Adhemerval Zanella via Libc-alpha wrote:
>> --- a/sysdeps/aarch64/bits/link.h
>> +++ b/sysdeps/aarch64/bits/link.h
>> @@ -20,23 +20,29 @@
>> # error "Never include <bits/link.h> directly; use <link.h> instead."
>> #endif
>>
>> +typedef union
>> +{
>> + float s;
>> + double d;
>> + long double q;
>> +} La_aarch64_vector;
>> +
>> /* Registers for entry into PLT on AArch64. */
>> typedef struct La_aarch64_regs
>> {
>> - uint64_t lr_xreg[8];
>> - uint64_t lr_dreg[8];
>> - uint64_t lr_sp;
>> - uint64_t lr_lr;
>> + uint64_t lr_xreg[9];
>> + La_aarch64_vector lr_vreg[8];
>> + uint64_t lr_sp;
>> + uint64_t lr_lr;
>> } La_aarch64_regs;
>>
>> /* Return values for calls from PLT on AArch64. */
>> typedef struct La_aarch64_retval
>> {
>> - /* Up to two integer registers can be used for a return value. */
>> - uint64_t lrv_xreg[2];
>> - /* Up to four D registers can be used for a return value. */
>> - uint64_t lrv_dreg[4];
>> -
>> + /* Up to eight integer registers can be used for a return value. */
>> + uint64_t lrv_xreg[8];
>> + /* Up to eight V registers can be used for a return value. */
>> + La_aarch64_vector lrv_vreg[8];
>> } La_aarch64_retval;
>> __BEGIN_DECLS
>
>
> i think for variant_pcs we will only need a
>
> void *extension;
>
> or similar member at the end of both structs.
>
> (we can make it point to a dump of all registers
> in some format for variant_pcs PLT hooks)
>
> if this can avoid a second bump of LAV_CURRENT
> when we add variant_pcs support then it may be
> useful to have. (if this turns out to be not
> enough then we don't lose much, but it also
> means users have to check extension==0 for now
> and avoid interpreting or touching the registers
> otherwise. not sure if this is better or bump,
> depends on how many users need to keep updating
> their auditor libs on our bumps.)
That's my idea as well, I really don't want to bump LAV_CURRENT for
aarch64 on 2.36.
^ permalink raw reply [flat|nested] 89+ messages in thread
* [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit
2021-11-15 18:37 [PATCH v6 00/20] Multiple rtld-audit fixes Adhemerval Zanella
` (18 preceding siblings ...)
2021-11-15 18:37 ` [PATCH v6 19/20] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
@ 2021-11-15 18:37 ` Adhemerval Zanella
2021-12-21 14:27 ` Florian Weimer
19 siblings, 1 reply; 89+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 18:37 UTC (permalink / raw)
To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard
To implement lazy binding is enabled when profiling or auditing used,
even when STO_AARCH64_VARIANT_PCS is set. Also, to not incur in
performance penalties on architecture without SVE, the PLT entrypoint
is set to a newer one, _dl_runtime_profile_sve, which is used iff
'hwcap' has HWCAP_SVE bit set.
This should be a fair assumption since SVE has a defined set of
registers for argument passing and return values. A new ABI with either
different argument passing or different registers would require a
different PLT entry, but I assume this would require another symbol flag
anyway (or at least a different ELF mark to indicate so).
The profile '_dl_runtime_profile_sve' entrypoint assumes the largest SVE
register size possible (2048 bits) and thus it requires a quite large
stack (8976 bytes). I think it would be possible make the stack
requirement dynamic depending of the vector length, but it would make
the PLT audit function way more complex.
It extends the La_aarch64_vector with a long double pointer to a stack
alloced buffer to hold the SVE Z register, along with a pointer to hold
the P registers on La_aarch64_regs.
It means the if 'lr_sve' is 0 in either La_aarch64_regs or
La_aarch64_retval the La_aarch64_vector contains the floating-pointer
registers that can be accessed directly (non SVE hardware). Otherwise,
'La_aarch64_vector.z' points to a memory area that holds up to 'lr_sve'
bytes for the Z registers, which can be loaded with svld1 intrinsic for
instance (as tst-audit28.c does). The P register follows the same
logic, with each La_aarch64_regs.lr_sve_pregs pointing to an area of
memory 'lr_sve/8' in size.
So, to access the FP register as float you can use:
static inline float regs_vec_to_float (const La_aarch64_regs *regs,
int idx)
{
float r;
if (regs->lr_sve == 0)
r = regs->lr_vreg[idx].s;
else
memcpy (&r, ®s->lr_vreg[idx].z[0], sizeof (r));
return r;
}
This patch is not complete yet: the tst-audit28 does not check if
compiler supports SVE (we would need a configure check to disable for
such case), I need to add a proper comment for the
_dl_runtime_profile_sve stack layout, the test need to check for the P
register state clobbering.
I also haven't check the performance penalties with this approach, and
maybe the way I am saving/restoring the SVE register might be optimized.
In any case, I checked on a SVE machine and at least the testcase work
as expected without any regressions. I also did a sniff test on a non
SVE machine.
Checked on aarch64-linux-gnu with SVE support.
---
elf/do-rel.h | 6 +-
elf/dynamic-link.h | 26 ++-
sysdeps/aarch64/Makefile | 16 +-
sysdeps/aarch64/bits/link.h | 4 +
sysdeps/aarch64/dl-link.sym | 3 +
sysdeps/aarch64/dl-machine.h | 14 +-
sysdeps/aarch64/dl-trampoline.S | 299 ++++++++++++++++++++++++-
sysdeps/aarch64/tst-audit28.c | 44 ++++
sysdeps/aarch64/tst-audit28mod.c | 48 ++++
sysdeps/aarch64/tst-audit28mod.h | 74 ++++++
sysdeps/aarch64/tst-auditmod27.c | 187 +++++++++++-----
sysdeps/aarch64/tst-auditmod28.c | 193 ++++++++++++++++
sysdeps/alpha/dl-machine.h | 2 +-
sysdeps/arc/dl-machine.h | 2 +-
sysdeps/arm/dl-machine.h | 2 +-
sysdeps/csky/dl-machine.h | 2 +-
sysdeps/hppa/dl-machine.h | 2 +-
sysdeps/i386/dl-machine.h | 2 +-
sysdeps/ia64/dl-machine.h | 2 +-
sysdeps/m68k/dl-machine.h | 2 +-
sysdeps/microblaze/dl-machine.h | 2 +-
sysdeps/mips/dl-machine.h | 2 +-
sysdeps/nios2/dl-machine.h | 2 +-
sysdeps/powerpc/powerpc32/dl-machine.h | 2 +-
sysdeps/powerpc/powerpc64/dl-machine.h | 2 +-
sysdeps/riscv/dl-machine.h | 2 +-
sysdeps/s390/s390-32/dl-machine.h | 2 +-
sysdeps/s390/s390-64/dl-machine.h | 2 +-
sysdeps/sh/dl-machine.h | 2 +-
sysdeps/sparc/sparc32/dl-machine.h | 2 +-
sysdeps/sparc/sparc64/dl-machine.h | 2 +-
sysdeps/x86_64/dl-machine.h | 2 +-
32 files changed, 862 insertions(+), 92 deletions(-)
create mode 100644 sysdeps/aarch64/tst-audit28.c
create mode 100644 sysdeps/aarch64/tst-audit28mod.c
create mode 100644 sysdeps/aarch64/tst-audit28mod.h
create mode 100644 sysdeps/aarch64/tst-auditmod28.c
diff --git a/elf/do-rel.h b/elf/do-rel.h
index c3368f09ab..8ae7bacebe 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -43,7 +43,7 @@ static inline void __attribute__ ((always_inline))
elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) reladdr, ElfW(Addr) relsize,
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative,
- int lazy, int skip_ifunc)
+ int lazy, int profile, int skip_ifunc)
{
const ElfW(Rel) *r = (const void *) reladdr;
const ElfW(Rel) *end = (const void *) (reladdr + relsize);
@@ -70,13 +70,13 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
}
else
# endif
- elf_machine_lazy_rel (map, scope, l_addr, r, skip_ifunc);
+ elf_machine_lazy_rel (map, scope, l_addr, r, profile, skip_ifunc);
# ifdef ELF_MACHINE_IRELATIVE
if (r2 != NULL)
for (; r2 <= end2; ++r2)
if (ELFW(R_TYPE) (r2->r_info) == ELF_MACHINE_IRELATIVE)
- elf_machine_lazy_rel (map, scope, l_addr, r2, skip_ifunc);
+ elf_machine_lazy_rel (map, scope, l_addr, r2, profile, skip_ifunc);
# endif
}
else
diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h
index f619615e5c..d1e83d8b8c 100644
--- a/elf/dynamic-link.h
+++ b/elf/dynamic-link.h
@@ -54,11 +54,13 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
static inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
+ int profile,
int skip_ifunc);
# else
static inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
+ int profile,
int skip_ifunc);
# endif
#endif
@@ -78,7 +80,8 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
consumes precisely the very end of the DT_REL*, or DT_JMPREL and DT_REL*
are completely separate and there is a gap between them. */
-# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, skip_ifunc, test_rel) \
+# define _ELF_DYNAMIC_DO_RELOC(RELOC, reloc, map, scope, do_lazy, do_profile, \
+ skip_ifunc, test_rel) \
do { \
struct { ElfW(Addr) start, size; \
__typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \
@@ -120,6 +123,7 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ranges[ranges_index].size, \
ranges[ranges_index].nrelative, \
ranges[ranges_index].lazy, \
+ do_profile, \
skip_ifunc); \
} while (0)
@@ -131,19 +135,21 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
# if ! ELF_MACHINE_NO_REL
# include "do-rel.h"
-# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) \
- _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
+# define ELF_DYNAMIC_DO_REL(map, scope, lazy, profiling, skip_ifunc) \
+ _ELF_DYNAMIC_DO_RELOC (REL, Rel, map, scope, lazy, profiling, \
+ skip_ifunc, _ELF_CHECK_REL)
# else
-# define ELF_DYNAMIC_DO_REL(map, scope, lazy, skip_ifunc) /* Nothing to do. */
+# define ELF_DYNAMIC_DO_REL(map, scope, lazy, profiling, skip_ifunc) /* Nothing to do. */
# endif
# if ! ELF_MACHINE_NO_RELA
# define DO_RELA
# include "do-rel.h"
-# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) \
- _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, skip_ifunc, _ELF_CHECK_REL)
+# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, profiling, skip_ifunc) \
+ _ELF_DYNAMIC_DO_RELOC (RELA, Rela, map, scope, lazy, profiling, skip_ifunc, \
+ _ELF_CHECK_REL)
# else
-# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, skip_ifunc) /* Nothing to do. */
+# define ELF_DYNAMIC_DO_RELA(map, scope, lazy, profiling, skip_ifunc) /* Nothing to do. */
# endif
/* This can't just be an inline function because GCC is too dumb
@@ -152,8 +158,10 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
do { \
int edr_lazy = elf_machine_runtime_setup ((map), (scope), (lazy), \
(consider_profile)); \
- ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, skip_ifunc); \
- ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, skip_ifunc); \
+ ELF_DYNAMIC_DO_REL ((map), (scope), edr_lazy, (consider_profile), \
+ skip_ifunc); \
+ ELF_DYNAMIC_DO_RELA ((map), (scope), edr_lazy, (consider_profile), \
+ skip_ifunc); \
} while (0)
#endif
diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
index 7183895d04..a2c64d7d5d 100644
--- a/sysdeps/aarch64/Makefile
+++ b/sysdeps/aarch64/Makefile
@@ -12,13 +12,16 @@ ifeq ($(subdir),elf)
sysdep-dl-routines += dl-bti
tests += tst-audit26 \
- tst-audit27
+ tst-audit27 \
+ tst-audit28
modules-names += \
tst-audit26mod \
tst-auditmod26 \
tst-audit27mod \
- tst-auditmod27
+ tst-auditmod27 \
+ tst-audit28mod \
+ tst-auditmod28
$(objpfx)tst-audit26: $(objpfx)tst-audit26mod.so \
$(objpfx)tst-auditmod26.so
@@ -30,6 +33,15 @@ $(objpfx)tst-audit27: $(objpfx)tst-audit27mod.so \
$(objpfx)tst-audit27mod.so: $(libsupport)
LDFLAGS-tst-audit27 += -Wl,-z,lazy
tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so
+
+$(objpfx)tst-audit28: $(objpfx)tst-audit28mod.so \
+ $(objpfx)tst-auditmod28.so
+CFLAGS-tst-audit28.c += -march=armv8.2-a+sve
+CFLAGS-tst-audit28mod.c += -march=armv8.2-a+sve
+CFLAGS-tst-auditmod28.c += -march=armv8.2-a+sve
+$(objpfx)tst-audit28mod.so: $(libsupport)
+LDFLAGS-tst-audit28 += -Wl,-z,lazy
+tst-audit28-ENV = LD_AUDIT=$(objpfx)tst-auditmod28.so
endif
ifeq ($(subdir),elf)
diff --git a/sysdeps/aarch64/bits/link.h b/sysdeps/aarch64/bits/link.h
index 2af90ca6be..2ad0f5d500 100644
--- a/sysdeps/aarch64/bits/link.h
+++ b/sysdeps/aarch64/bits/link.h
@@ -25,6 +25,7 @@ typedef union
float s;
double d;
long double q;
+ long double *z;
} La_aarch64_vector;
/* Registers for entry into PLT on AArch64. */
@@ -34,6 +35,8 @@ typedef struct La_aarch64_regs
La_aarch64_vector lr_vreg[8];
uint64_t lr_sp;
uint64_t lr_lr;
+ uint8_t lr_sve;
+ uint16_t *lr_sve_pregs[4];
} La_aarch64_regs;
/* Return values for calls from PLT on AArch64. */
@@ -43,6 +46,7 @@ typedef struct La_aarch64_retval
uint64_t lrv_xreg[8];
/* Up to eight V registers can be used for a return value. */
La_aarch64_vector lrv_vreg[8];
+ uint8_t lrv_sve;
} La_aarch64_retval;
__BEGIN_DECLS
diff --git a/sysdeps/aarch64/dl-link.sym b/sysdeps/aarch64/dl-link.sym
index 70d153a1d5..9bc56b98ec 100644
--- a/sysdeps/aarch64/dl-link.sym
+++ b/sysdeps/aarch64/dl-link.sym
@@ -10,6 +10,9 @@ DL_OFFSET_RG_X0 offsetof(struct La_aarch64_regs, lr_xreg)
DL_OFFSET_RG_V0 offsetof(struct La_aarch64_regs, lr_vreg)
DL_OFFSET_RG_SP offsetof(struct La_aarch64_regs, lr_sp)
DL_OFFSET_RG_LR offsetof(struct La_aarch64_regs, lr_lr)
+DL_OFFSET_RG_SVE offsetof(struct La_aarch64_regs, lr_sve)
+DL_OFFSET_RG_SVE_PREGS offsetof(struct La_aarch64_regs, lr_sve_pregs)
DL_OFFSET_RV_X0 offsetof(struct La_aarch64_retval, lrv_xreg)
DL_OFFSET_RV_V0 offsetof(struct La_aarch64_retval, lrv_vreg)
+DL_OFFSET_RV_SVE offsetof(struct La_aarch64_retval, lrv_sve)
diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
index 0d5ad218c1..a039a0c32c 100644
--- a/sysdeps/aarch64/dl-machine.h
+++ b/sysdeps/aarch64/dl-machine.h
@@ -69,6 +69,9 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
ElfW(Addr) *got;
extern void _dl_runtime_resolve (ElfW(Word));
extern void _dl_runtime_profile (ElfW(Word));
+#if HAVE_AARCH64_SVE_ASM
+ extern void _dl_runtime_profile_sve (ElfW(Word));
+#endif
got = (ElfW(Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
if (got[1])
@@ -85,7 +88,12 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
end in this function. */
if ( profile)
{
- got[2] = (ElfW(Addr)) &_dl_runtime_profile;
+#if HAVE_AARCH64_SVE_ASM
+ if (GLRO(dl_hwcap) & HWCAP_SVE)
+ got[2] = (ElfW(Addr)) &_dl_runtime_profile_sve;
+ else
+#endif
+ got[2] = (ElfW(Addr)) &_dl_runtime_profile;
if (GLRO(dl_profile) != NULL
&& _dl_name_match_p (GLRO(dl_profile), l))
@@ -383,6 +391,7 @@ __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr,
const ElfW(Rela) *reloc,
+ int profile,
int skip_ifunc)
{
ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
@@ -390,7 +399,8 @@ elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
/* Check for unexpected PLT reloc type. */
if (__builtin_expect (r_type == AARCH64_R(JUMP_SLOT), 1))
{
- if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL))
+ if (__glibc_unlikely (map->l_info[DT_AARCH64 (VARIANT_PCS)] != NULL)
+ && profile == 0)
{
/* Check the symbol table for variant PCS symbols. */
const Elf_Symndx symndx = ELFW (R_SYM) (reloc->r_info);
diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S
index 0d540651d4..0aee1fbf3d 100644
--- a/sysdeps/aarch64/dl-trampoline.S
+++ b/sysdeps/aarch64/dl-trampoline.S
@@ -205,6 +205,9 @@ _dl_runtime_profile:
cfi_rel_offset (q6, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 0)
cfi_rel_offset (q7, OFFSET_RG + DL_OFFSET_RG_V0 + 32*3 + 16)
+ strb wzr, [x29, #OFFSET_RG + DL_OFFSET_RG_SVE]
+ strb wzr, [x29, #OFFSET_RV + DL_OFFSET_RV_SVE]
+
add x0, x29, #SF_SIZE + 16
ldr x1, [x29, #OFFSET_LR]
stp x0, x1, [x29, #OFFSET_RG + DL_OFFSET_RG_SP]
@@ -339,5 +342,299 @@ _dl_runtime_profile:
cfi_endproc
.size _dl_runtime_profile, .-_dl_runtime_profile
-#endif
.previous
+
+
+# define HWCAP_SVE 22
+# define ZCR_ELx_LEN_MASK 0x1ff
+
+# if HAVE_AARCH64_SVE_ASM
+ .arch armv8.2-a+sve
+ .globl _dl_runtime_profile_sve
+ .type _dl_runtime_profile_sve, #function
+ cfi_startproc
+ .align 2
+_dl_runtime_profile_sve:
+# if HAVE_AARCH64_PAC_RET
+ PACIASP
+ cfi_window_save
+# else
+ BTI_C
+# endif
+ /* AArch64 we get called with:
+ ip0 &PLTGOT[2]
+ ip1 temp(dl resolver entry point)
+ [sp, #8] lr
+ [sp, #0] &PLTGOT[n]
+
+ Stack frame layout:
+ [sp, #...] lr
+ [sp, #...] &PLTGOT[n]
+ -------------------------
+ TODO
+ [sp, # 0] x29, lr <- x29
+ */
+
+# define OFFSET_SVE_T1 16
+# define OFFSET_SVE_SAVED_CALL_X0 OFFSET_SVE_T1 + 8
+# define OFFSET_SVE_FS OFFSET_SVE_SAVED_CALL_X0 + 16
+# define OFFSET_SVE_RV OFFSET_SVE_FS + 8
+# define OFFSET_SVE_RG OFFSET_SVE_RV + DL_SIZEOF_RV
+/* Maximum supported z and pregisters size in bytes. */
+# define SIZEOF_SVE_Z_REG 512
+# define SIZEOF_SVE_P_REG SIZEOF_SVE_Z_REG / 8
+/* z0-z7 for argument passing. */
+# define SIZEOF_SVE_RG_Z 8 * SIZEOF_SVE_Z_REG
+/* p0-p3 for argument passing. */
+# define SIZEOF_SVE_RG_P 4 * SIZEOF_SVE_P_REG
+/* z0-z7 for function return. */
+# define SIZEOF_SVE_RV_P 8 * SIZEOF_SVE_Z_REG
+/* SVE registers contents for La_aarch64_regs.lr_vreg */
+# define OFFSET_SVE_RG_Z OFFSET_SVE_RG + DL_SIZEOF_RG
+/* SVE registers contents for La_aarch64.regs.lr_sve_pregs */
+# define OFFSET_SVE_RG_P OFFSET_SVE_RG_Z + SIZEOF_SVE_RG_Z
+/* SVE registers contents for La_aarch64_retval.lrv_vreg */
+# define OFFSET_SVE_RV_Z OFFSET_SVE_RG_P + SIZEOF_SVE_RG_P
+
+# define SF_SVE_SIZE OFFSET_SVE_RV_Z + SIZEOF_SVE_RV_P
+
+# define OFFSET_SVE_PLTGOTN SF_SVE_SIZE
+# define OFFSET_SVE_LR OFFSET_SVE_PLTGOTN + 8
+
+ .macro save_sve_z_reg zreg idx offset save_addr
+ .ifc \zreg, z0
+ .if \offset < 4096
+ add x0, x29, \offset
+ .else
+ mov x0, \offset
+ add x0, x29, x0
+ .endif
+ .else
+ add x0, x0, SIZEOF_SVE_Z_REG
+ .endif
+ str \zreg, [x0, #0]
+ .if \save_addr == 1
+ str x0, [X29, #OFFSET_RG + DL_OFFSET_RG_V0 + 16*\idx]
+ .else
+ str x0, [X29, #OFFSET_RV + DL_OFFSET_RV_V0 + 16*\idx]
+ .endif
+ .endm
+
+ .macro save_sve_regs offset save_addr
+ save_sve_z_reg z0 0 \offset \save_addr
+ save_sve_z_reg z1 1 \offset \save_addr
+ save_sve_z_reg z2 2 \offset \save_addr
+ save_sve_z_reg z3 3 \offset \save_addr
+ save_sve_z_reg z4 4 \offset \save_addr
+ save_sve_z_reg z5 5 \offset \save_addr
+ save_sve_z_reg z6 6 \offset \save_addr
+ save_sve_z_reg z7 7 \offset \save_addr
+ .if \save_addr == 1
+ add x0, x0, SIZEOF_SVE_P_REG
+ str p0, [x0, #0]
+ add x0, x0, SIZEOF_SVE_P_REG
+ str p1, [x0, #0]
+ add x0, x0, SIZEOF_SVE_P_REG
+ str p2, [x0, #0]
+ add x0, x0, SIZEOF_SVE_P_REG
+ str p3, [x0, #0]
+ .endif
+ .endm
+
+ .macro load_sve_regs offset
+ .if \offset < 4096
+ add x12, x29, \offset
+ .else
+ mov x12, \offset
+ add x12, x29, x12
+ .endif
+ ldr z0, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z1, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z2, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z3, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z4, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z5, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z6, [x12, #0]
+ add x12, x12, SIZEOF_SVE_Z_REG
+ ldr z7, [x12, #0]
+ add x12, x12, SIZEOF_SVE_P_REG
+ ldr p0, [x12, #0]
+ add x12, x12, SIZEOF_SVE_P_REG
+ ldr p1, [x12, #0]
+ add x12, x12, SIZEOF_SVE_P_REG
+ ldr p2, [x12, #0]
+ add x12, x12, SIZEOF_SVE_P_REG
+ ldr p3, [x12, #0]
+ .endm
+
+
+ /* Save arguments. */
+ mov x12, #SF_SVE_SIZE
+ sub sp, sp, x12
+ cfi_adjust_cfa_offset (SF_SVE_SIZE)
+ stp x29, x30, [SP, #0]
+ mov x29, sp
+ cfi_def_cfa_register (x29)
+ cfi_rel_offset (x29, 0)
+ cfi_rel_offset (lr, 8)
+
+ stp x0, x1, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*0]
+ cfi_rel_offset (x0, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*0 + 0)
+ cfi_rel_offset (x1, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*0 + 8)
+ stp x2, x3, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*1]
+ cfi_rel_offset (x2, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*1 + 0)
+ cfi_rel_offset (x3, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*1 + 8)
+ stp x4, x5, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*2]
+ cfi_rel_offset (x4, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*2 + 0)
+ cfi_rel_offset (x5, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*2 + 8)
+ stp x6, x7, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*3]
+ cfi_rel_offset (x6, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*3 + 0)
+ cfi_rel_offset (x7, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*3 + 8)
+ str x8, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*4 + 0]
+ cfi_rel_offset (x8, OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*4 + 0)
+ /* Note 8 bytes of padding is in the stack frame for alignment */
+ save_sve_regs OFFSET_SVE_RG_Z 1
+
+ /* Store the vector length on lr_sve */
+ mov x0, #0
+ addvl x0, x0, #1
+ strb w0, [x29, #OFFSET_RG + DL_OFFSET_RG_SVE]
+ strb w0, [x29, #OFFSET_RV + DL_OFFSET_RV_SVE]
+
+ mov x0, #SF_SVE_SIZE + 16
+ add x0, x29, x0
+ ldr x1, [x29, #OFFSET_SVE_LR]
+ stp x0, x1, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_SP]
+
+ /* Get pointer to linker struct. */
+ ldr PTR_REG (0), [ip0, #-PTR_SIZE]
+
+ /* Prepare to call _dl_profile_fixup(). */
+ ldr x1, [x29, OFFSET_SVE_PLTGOTN] /* Recover &PLTGOT[n] */
+
+ sub x1, x1, ip0
+ add x1, x1, x1, lsl #1
+ lsl x1, x1, #3
+ sub x1, x1, #(RELA_SIZE<<3)
+ lsr x1, x1, #3
+
+ stp x0, x1, [x29, #OFFSET_SVE_SAVED_CALL_X0]
+
+ /* Set up extra args for _dl_profile_fixup */
+ ldr x2, [x29, #OFFSET_SVE_LR] /* load saved LR */
+ add x3, x29, #OFFSET_SVE_RG /* address of La_aarch64_reg */
+ add x4, x29, #OFFSET_SVE_FS /* address of framesize */
+ bl _dl_profile_fixup
+
+ ldr ip0l, [x29, #OFFSET_SVE_FS] /* framesize == 0 */
+ cmp ip0l, #0
+ bge 1f
+ cfi_remember_state
+
+ /* Save the return. */
+ mov ip0, x0
+
+ /* Get arguments and return address back. */
+ ldp x0, x1, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*0]
+ ldp x2, x3, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*1]
+ ldp x4, x5, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*2]
+ ldp x6, x7, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*3]
+ ldr x8, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*4]
+ load_sve_regs OFFSET_SVE_RG_Z
+
+ cfi_def_cfa_register (sp)
+ ldp x29, x30, [x29, #0]
+ cfi_restore (x29)
+ cfi_restore (x30)
+
+# if HAVE_AARCH64_PAC_RET
+ mov x12, SF_SVE_SIZE
+ add sp, sp, x12
+ cfi_adjust_cfa_offset (-SF_SVE_SIZE)
+ AUTIASP
+ cfi_window_save
+ add sp, sp, 16
+ cfi_adjust_cfa_offset (-16)
+# else
+ mov x12, SF_SVE_SIZE + 16
+ add sp, sp, x12
+ cfi_adjust_cfa_offset (- SF_SVE_SIZE - 16)
+# endif
+
+ /* Jump to the newly found address. */
+ br ip0
+
+ cfi_restore_state
+1:
+ /* The new frame size is in ip0. */
+
+ sub PTR_REG (1), PTR_REG (29), ip0l
+ and sp, x1, #0xfffffffffffffff0
+
+ str x0, [x29, #OFFSET_SVE_T1]
+
+ mov x0, sp
+ mov x1, #SF_SVE_SIZE + 16
+ add x1, x29, x1
+ mov x2, ip0
+ bl memcpy
+
+ ldr ip0, [x29, #OFFSET_SVE_T1]
+
+ /* Call the function. */
+ ldp x0, x1, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*0]
+ ldp x2, x3, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*1]
+ ldp x4, x5, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*2]
+ ldp x6, x7, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*3]
+ ldr x8, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*4]
+ load_sve_regs OFFSET_SVE_RG_Z
+ blr ip0
+ stp x0, x1, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*0]
+ stp x2, x3, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*1]
+ stp x4, x5, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*2]
+ stp x6, x7, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*3]
+ str x8, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_X0 + 16*4]
+ save_sve_regs OFFSET_SVE_RV_Z 0
+
+ /* Setup call to pltexit */
+ ldp x0, x1, [x29, #OFFSET_SVE_SAVED_CALL_X0]
+ add x2, x29, #OFFSET_SVE_RG
+ add x3, x29, #OFFSET_SVE_RV
+ bl _dl_audit_pltexit
+
+ ldp x0, x1, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*0]
+ ldp x2, x3, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*1]
+ ldp x4, x5, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*2]
+ ldp x6, x7, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*3]
+ ldr x8, [x29, #OFFSET_SVE_RV + DL_OFFSET_RV_X0 + 16*4]
+ load_sve_regs OFFSET_SVE_RV_Z
+
+ /* LR from within La_aarch64_reg */
+ ldr lr, [x29, #OFFSET_SVE_RG + DL_OFFSET_RG_LR]
+ cfi_restore(lr)
+# if HAVE_AARCH64_PAC_RET
+ /* Note: LR restored from La_aarch64_reg has no PAC. */
+ cfi_window_save
+# endif
+ mov sp, x29
+ cfi_def_cfa_register (sp)
+ ldr x29, [x29, #0]
+ cfi_restore(x29)
+ mov x12, SF_SVE_SIZE + 16
+ add sp, sp, x12
+ cfi_adjust_cfa_offset (- SF_SVE_SIZE - 16)
+
+ br lr
+
+ cfi_endproc
+ .size _dl_runtime_profile_sve, .-_dl_runtime_profile_sve
+ .previous
+# endif /* HAVE_AARCH64_SVE_ASM */
+
+#endif /* !PROF */
diff --git a/sysdeps/aarch64/tst-audit28.c b/sysdeps/aarch64/tst-audit28.c
new file mode 100644
index 0000000000..28ffbd141f
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit28.c
@@ -0,0 +1,44 @@
+/* Check DT_AUDIT for aarch64 ABI specifics.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <string.h>
+#include <support/check.h>
+#include <sys/auxv.h>
+#include "tst-audit28mod.h"
+
+int
+do_test (void)
+{
+ unsigned long hwcap = getauxval (AT_HWCAP);
+ if ((hwcap & HWCAP_SVE) == 0)
+ FAIL_UNSUPPORTED ("system does not support SVE");
+
+ {
+ svint8_t r = tst_audit28_func_sve_args (sve_args_z0 (), sve_args_z1 (),
+ sve_args_z2 (), sve_args_z3 (),
+ sve_args_z4 (), sve_args_z5 (),
+ sve_args_z6 (), sve_args_z7 ());
+ if (!svptest_any (svptrue_b8 (), svcmpeq_s8 (svptrue_b8 (), r, sve_ret ())))
+ FAIL_EXIT1 ("tst_audit28_func_sve_args(): wrong return value");
+ }
+
+ return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/sysdeps/aarch64/tst-audit28mod.c b/sysdeps/aarch64/tst-audit28mod.c
new file mode 100644
index 0000000000..f5e24346b4
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit28mod.c
@@ -0,0 +1,48 @@
+/* Check DT_AUDIT for aarch64 ABI specifics.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <assert.h>
+#include <stdlib.h>
+#include <support/check.h>
+#include "tst-audit28mod.h"
+
+svint8_t
+tst_audit28_func_sve_args (svint8_t z0, svint16_t z1, svint32_t z2,
+ svint64_t z3, svuint8_t z4, svuint16_t z5,
+ svuint32_t z6, svuint64_t z7)
+{
+ assert (svptest_any (svptrue_b8 (), svcmpeq_s8 (svptrue_b8 (),
+ z0, sve_args_z0 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_s16 (svptrue_b16 (),
+ z1, sve_args_z1 ())));
+ assert (svptest_any (svptrue_b32 (), svcmpeq_s32 (svptrue_b32 (),
+ z2, sve_args_z2 ())));
+ assert (svptest_any (svptrue_b64 (), svcmpeq_s64 (svptrue_b64 (),
+ z3, sve_args_z3 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_u8 (svptrue_b8 (),
+ z4, sve_args_z4 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_u16 (svptrue_b16 (),
+ z5, sve_args_z5 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_u32 (svptrue_b32 (),
+ z6, sve_args_z6 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_u64 (svptrue_b64 (),
+ z7, sve_args_z7 ())));
+
+ return sve_ret ();
+}
diff --git a/sysdeps/aarch64/tst-audit28mod.h b/sysdeps/aarch64/tst-audit28mod.h
new file mode 100644
index 0000000000..55e3cdbbc6
--- /dev/null
+++ b/sysdeps/aarch64/tst-audit28mod.h
@@ -0,0 +1,74 @@
+/* Check DT_AUDIT for aarch64 specific ABI.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#ifndef _TST_AUDIT27MOD_H
+#define _TST_AUDIT27MOD_H 1
+
+#include <arm_sve.h>
+
+static inline svint8_t sve_args_z0 (void)
+{
+ return svdup_s8 (INT8_MAX);
+}
+
+static inline svint16_t sve_args_z1 (void)
+{
+ return svdup_s16 (INT16_MAX);
+}
+
+static inline svint32_t sve_args_z2 (void)
+{
+ return svdup_s32 (INT32_MAX);
+}
+
+static inline svint64_t sve_args_z3 (void)
+{
+ return svdup_s64 (INT64_MAX);
+}
+
+static inline svuint8_t sve_args_z4 (void)
+{
+ return svdup_u8 (UINT8_MAX);
+}
+
+static inline svuint16_t sve_args_z5 (void)
+{
+ return svdup_u16 (UINT16_MAX);
+}
+
+static inline svuint32_t sve_args_z6 (void)
+{
+ return svdup_u32 (UINT32_MAX);
+}
+
+static inline svuint64_t sve_args_z7 (void)
+{
+ return svdup_u64 (UINT64_MAX);
+}
+
+static inline svint8_t sve_ret (void)
+{
+ return svdup_s8 (INT8_MIN);
+}
+
+#define INT_ARGS_RET 0x21
+
+svint8_t tst_audit28_func_sve_args (svint8_t z0, svint16_t z1, svint32_t z2, svint64_t z3,
+ svuint8_t z4, svuint16_t z5, svuint32_t z6, svuint64_t z7);
+
+#endif
diff --git a/sysdeps/aarch64/tst-auditmod27.c b/sysdeps/aarch64/tst-auditmod27.c
index b1dbff8330..9a6e23d752 100644
--- a/sysdeps/aarch64/tst-auditmod27.c
+++ b/sysdeps/aarch64/tst-auditmod27.c
@@ -16,18 +16,82 @@
License along with the GNU C Library; if not, see
<https://www.gnu.org/licenses/>. */
+#include <array_length.h>
#include <assert.h>
#include <link.h>
#include <string.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
+#include "tst-audit.h"
#include "tst-audit27mod.h"
#define TEST_NAME "tst-audit27"
#define AUDIT27_COOKIE 0
+static inline float regs_vec_to_float (const La_aarch64_regs *regs, int i)
+{
+ float r;
+ if (regs->lr_sve == 0)
+ r = regs->lr_vreg[i].s;
+ else
+ memcpy (&r, ®s->lr_vreg[i].z[0], sizeof (r));
+ return r;
+}
+
+static inline double regs_vec_to_double (const La_aarch64_regs *regs, int i)
+{
+ double r;
+ if (regs->lr_sve == 0)
+ r = regs->lr_vreg[i].d;
+ else
+ memcpy (&r, ®s->lr_vreg[i].z[0], sizeof (r));
+ return r;
+}
+
+static inline long double regs_vec_to_ldouble (const La_aarch64_regs *regs,
+ int i)
+{
+ long double r;
+ if (regs->lr_sve == 0)
+ r = regs->lr_vreg[i].q;
+ else
+ memcpy (&r, ®s->lr_vreg[i].z[0], sizeof (r));
+ return r;
+}
+
+static inline float ret_vec_to_float (const La_aarch64_retval *regs, int i)
+{
+ float r;
+ if (regs->lrv_sve == 0)
+ r = regs->lrv_vreg[i].s;
+ else
+ memcpy (&r, ®s->lrv_vreg[i].z[0], sizeof (r));
+ return r;
+}
+
+static inline double ret_vec_to_double (const La_aarch64_retval *regs, int i)
+{
+ double r;
+ if (regs->lrv_sve == 0)
+ r = regs->lrv_vreg[i].d;
+ else
+ memcpy (&r, ®s->lrv_vreg[i].z[0], sizeof (r));
+ return r;
+}
+
+static inline long double ret_vec_to_ldouble (const La_aarch64_retval *regs,
+ int i)
+{
+ long double r;
+ if (regs->lrv_sve == 0)
+ r = regs->lrv_vreg[i].q;
+ else
+ memcpy (&r, ®s->lrv_vreg[i].z[0], sizeof (r));
+ return r;
+}
+
unsigned int
la_version (unsigned int v)
{
@@ -47,6 +111,7 @@ la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
}
+
ElfW(Addr)
la_aarch64_gnu_pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
uintptr_t *defcook, La_aarch64_regs *regs,
@@ -55,39 +120,43 @@ la_aarch64_gnu_pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
{
printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
symname, (long int) sym->st_value, ndx, *flags);
+ printf (" regs->lr_sve=%d\n", regs->lr_sve);
+ if (regs->lr_sve > 0)
+ for (int i = 0; i < array_length (regs->lr_vreg); i++)
+ printf (" inregs->lr_vreg[%d]=%p\n", i, regs->lr_vreg[i].z);
if (strcmp (symname, "tst_audit27_func_float") == 0)
{
- assert (regs->lr_vreg[0].s == FUNC_FLOAT_ARG0);
- assert (regs->lr_vreg[1].s == FUNC_FLOAT_ARG1);
- assert (regs->lr_vreg[2].s == FUNC_FLOAT_ARG2);
- assert (regs->lr_vreg[3].s == FUNC_FLOAT_ARG3);
- assert (regs->lr_vreg[4].s == FUNC_FLOAT_ARG4);
- assert (regs->lr_vreg[5].s == FUNC_FLOAT_ARG5);
- assert (regs->lr_vreg[6].s == FUNC_FLOAT_ARG6);
- assert (regs->lr_vreg[7].s == FUNC_FLOAT_ARG7);
+ assert (regs_vec_to_float (regs, 0) == FUNC_FLOAT_ARG0);
+ assert (regs_vec_to_float (regs, 1) == FUNC_FLOAT_ARG1);
+ assert (regs_vec_to_float (regs, 2) == FUNC_FLOAT_ARG2);
+ assert (regs_vec_to_float (regs, 3) == FUNC_FLOAT_ARG3);
+ assert (regs_vec_to_float (regs, 4) == FUNC_FLOAT_ARG4);
+ assert (regs_vec_to_float (regs, 5) == FUNC_FLOAT_ARG5);
+ assert (regs_vec_to_float (regs, 6) == FUNC_FLOAT_ARG6);
+ assert (regs_vec_to_float (regs, 7) == FUNC_FLOAT_ARG7);
}
else if (strcmp (symname, "tst_audit27_func_double") == 0)
{
- assert (regs->lr_vreg[0].d == FUNC_DOUBLE_ARG0);
- assert (regs->lr_vreg[1].d == FUNC_DOUBLE_ARG1);
- assert (regs->lr_vreg[2].d == FUNC_DOUBLE_ARG2);
- assert (regs->lr_vreg[3].d == FUNC_DOUBLE_ARG3);
- assert (regs->lr_vreg[4].d == FUNC_DOUBLE_ARG4);
- assert (regs->lr_vreg[5].d == FUNC_DOUBLE_ARG5);
- assert (regs->lr_vreg[6].d == FUNC_DOUBLE_ARG6);
- assert (regs->lr_vreg[7].d == FUNC_DOUBLE_ARG7);
+ assert (regs_vec_to_double (regs, 0) == FUNC_DOUBLE_ARG0);
+ assert (regs_vec_to_double (regs, 1) == FUNC_DOUBLE_ARG1);
+ assert (regs_vec_to_double (regs, 2) == FUNC_DOUBLE_ARG2);
+ assert (regs_vec_to_double (regs, 3) == FUNC_DOUBLE_ARG3);
+ assert (regs_vec_to_double (regs, 4) == FUNC_DOUBLE_ARG4);
+ assert (regs_vec_to_double (regs, 5) == FUNC_DOUBLE_ARG5);
+ assert (regs_vec_to_double (regs, 6) == FUNC_DOUBLE_ARG6);
+ assert (regs_vec_to_double (regs, 7) == FUNC_DOUBLE_ARG7);
}
else if (strcmp (symname, "tst_audit27_func_ldouble") == 0)
{
- assert (regs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0);
- assert (regs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1);
- assert (regs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2);
- assert (regs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3);
- assert (regs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4);
- assert (regs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5);
- assert (regs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6);
- assert (regs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7);
+ assert (regs_vec_to_ldouble (regs, 0) == FUNC_LDOUBLE_ARG0);
+ assert (regs_vec_to_ldouble (regs, 1) == FUNC_LDOUBLE_ARG1);
+ assert (regs_vec_to_ldouble (regs, 2) == FUNC_LDOUBLE_ARG2);
+ assert (regs_vec_to_ldouble (regs, 3) == FUNC_LDOUBLE_ARG3);
+ assert (regs_vec_to_ldouble (regs, 4) == FUNC_LDOUBLE_ARG4);
+ assert (regs_vec_to_ldouble (regs, 5) == FUNC_LDOUBLE_ARG5);
+ assert (regs_vec_to_ldouble (regs, 6) == FUNC_LDOUBLE_ARG6);
+ assert (regs_vec_to_ldouble (regs, 7) == FUNC_LDOUBLE_ARG7);
}
else
abort ();
@@ -117,48 +186,56 @@ la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
{
printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n",
symname, (long int) sym->st_value, ndx);
+ printf (" inregs->lr_sve=%d\n", inregs->lr_sve);
+ if (inregs->lr_sve > 0)
+ for (int i = 0; i < array_length (inregs->lr_vreg); i++)
+ printf (" inregs->lr_vreg[%d]=%p\n", i, inregs->lr_vreg[i].z);
+ printf (" outregs->lr_sve=%d\n", outregs->lrv_sve);
+ if (outregs->lrv_sve > 0)
+ for (int i = 0; i < array_length (outregs->lrv_vreg); i++)
+ printf (" outregs->lr_vreg[%d]=%p\n", i, outregs->lrv_vreg[i].z);
if (strcmp (symname, "tst_audit27_func_float") == 0)
{
- assert (inregs->lr_vreg[0].s == FUNC_FLOAT_ARG0);
- assert (inregs->lr_vreg[1].s == FUNC_FLOAT_ARG1);
- assert (inregs->lr_vreg[2].s == FUNC_FLOAT_ARG2);
- assert (inregs->lr_vreg[3].s == FUNC_FLOAT_ARG3);
- assert (inregs->lr_vreg[4].s == FUNC_FLOAT_ARG4);
- assert (inregs->lr_vreg[5].s == FUNC_FLOAT_ARG5);
- assert (inregs->lr_vreg[6].s == FUNC_FLOAT_ARG6);
- assert (inregs->lr_vreg[7].s == FUNC_FLOAT_ARG7);
-
- assert (outregs->lrv_vreg[0].s == FUNC_FLOAT_RET);
+ assert (regs_vec_to_float (inregs, 0) == FUNC_FLOAT_ARG0);
+ assert (regs_vec_to_float (inregs, 1) == FUNC_FLOAT_ARG1);
+ assert (regs_vec_to_float (inregs, 2) == FUNC_FLOAT_ARG2);
+ assert (regs_vec_to_float (inregs, 3) == FUNC_FLOAT_ARG3);
+ assert (regs_vec_to_float (inregs, 4) == FUNC_FLOAT_ARG4);
+ assert (regs_vec_to_float (inregs, 5) == FUNC_FLOAT_ARG5);
+ assert (regs_vec_to_float (inregs, 6) == FUNC_FLOAT_ARG6);
+ assert (regs_vec_to_float (inregs, 7) == FUNC_FLOAT_ARG7);
+
+ assert (ret_vec_to_float (outregs, 0) == FUNC_FLOAT_RET);
}
else if (strcmp (symname, "tst_audit27_func_double") == 0)
{
- assert (inregs->lr_vreg[0].d == FUNC_DOUBLE_ARG0);
- assert (inregs->lr_vreg[1].d == FUNC_DOUBLE_ARG1);
- assert (inregs->lr_vreg[2].d == FUNC_DOUBLE_ARG2);
- assert (inregs->lr_vreg[3].d == FUNC_DOUBLE_ARG3);
- assert (inregs->lr_vreg[4].d == FUNC_DOUBLE_ARG4);
- assert (inregs->lr_vreg[5].d == FUNC_DOUBLE_ARG5);
- assert (inregs->lr_vreg[6].d == FUNC_DOUBLE_ARG6);
- assert (inregs->lr_vreg[7].d == FUNC_DOUBLE_ARG7);
-
- assert (outregs->lrv_vreg[0].d == FUNC_DOUBLE_RET);
+ assert (regs_vec_to_double (inregs, 0) == FUNC_DOUBLE_ARG0);
+ assert (regs_vec_to_double (inregs, 1) == FUNC_DOUBLE_ARG1);
+ assert (regs_vec_to_double (inregs, 2) == FUNC_DOUBLE_ARG2);
+ assert (regs_vec_to_double (inregs, 3) == FUNC_DOUBLE_ARG3);
+ assert (regs_vec_to_double (inregs, 4) == FUNC_DOUBLE_ARG4);
+ assert (regs_vec_to_double (inregs, 5) == FUNC_DOUBLE_ARG5);
+ assert (regs_vec_to_double (inregs, 6) == FUNC_DOUBLE_ARG6);
+ assert (regs_vec_to_double (inregs, 7) == FUNC_DOUBLE_ARG7);
+
+ assert (ret_vec_to_double (outregs, 0) == FUNC_DOUBLE_RET);
}
else if (strcmp (symname, "tst_audit27_func_ldouble") == 0)
{
- assert (inregs->lr_vreg[0].q == FUNC_LDOUBLE_ARG0);
- assert (inregs->lr_vreg[1].q == FUNC_LDOUBLE_ARG1);
- assert (inregs->lr_vreg[2].q == FUNC_LDOUBLE_ARG2);
- assert (inregs->lr_vreg[3].q == FUNC_LDOUBLE_ARG3);
- assert (inregs->lr_vreg[4].q == FUNC_LDOUBLE_ARG4);
- assert (inregs->lr_vreg[5].q == FUNC_LDOUBLE_ARG5);
- assert (inregs->lr_vreg[6].q == FUNC_LDOUBLE_ARG6);
- assert (inregs->lr_vreg[7].q == FUNC_LDOUBLE_ARG7);
-
- assert (outregs->lrv_vreg[0].q == FUNC_LDOUBLE_RET);
+ assert (regs_vec_to_ldouble (inregs, 0) == FUNC_LDOUBLE_ARG0);
+ assert (regs_vec_to_ldouble (inregs, 1) == FUNC_LDOUBLE_ARG1);
+ assert (regs_vec_to_ldouble (inregs, 2) == FUNC_LDOUBLE_ARG2);
+ assert (regs_vec_to_ldouble (inregs, 3) == FUNC_LDOUBLE_ARG3);
+ assert (regs_vec_to_ldouble (inregs, 4) == FUNC_LDOUBLE_ARG4);
+ assert (regs_vec_to_ldouble (inregs, 5) == FUNC_LDOUBLE_ARG5);
+ assert (regs_vec_to_ldouble (inregs, 6) == FUNC_LDOUBLE_ARG6);
+ assert (regs_vec_to_ldouble (inregs, 7) == FUNC_LDOUBLE_ARG7);
+
+ assert (ret_vec_to_ldouble (outregs, 0) == FUNC_LDOUBLE_RET);
}
else
- abort ();
+ return 0;
/* Clobber the q registers on exit. */
uint8_t v = 0xff;
diff --git a/sysdeps/aarch64/tst-auditmod28.c b/sysdeps/aarch64/tst-auditmod28.c
new file mode 100644
index 0000000000..53a2162bfb
--- /dev/null
+++ b/sysdeps/aarch64/tst-auditmod28.c
@@ -0,0 +1,193 @@
+/* Check DT_AUDIT for aarch64 specific ABI.
+ Copyright (C) 2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <array_length.h>
+#include <assert.h>
+#include <link.h>
+#include <string.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "tst-audit28mod.h"
+
+#define TEST_NAME "tst-audit28"
+#define TEST_FUNC "tst_audit28_func"
+
+#define AUDIT28_COOKIE 0
+
+unsigned int
+la_version (unsigned int v)
+{
+ return v;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+ const char *p = strrchr (map->l_name, '/');
+ const char *l_name = p == NULL ? map->l_name : p + 1;
+ uintptr_t ck = -1;
+ if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
+ ck = AUDIT28_COOKIE;
+ *cookie = ck;
+ printf ("objopen: %ld, %s [%ld]\n", lmid, l_name, ck);
+ return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+ElfW(Addr)
+la_aarch64_gnu_pltenter (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook, La_aarch64_regs *regs,
+ unsigned int *flags, const char *symname,
+ long int *framesizep)
+{
+ printf ("pltenter: symname=%s, st_value=%#lx, ndx=%u, flags=%u\n",
+ symname, (long int) sym->st_value, ndx, *flags);
+ printf (" regs->lr_sve=%d\n", regs->lr_sve);
+ if (regs->lr_sve > 0)
+ for (int i = 0; i < array_length (regs->lr_vreg); i++)
+ printf (" inregs->lr_vreg[%d]=%p\n", i, regs->lr_vreg[i].z);
+
+
+ if (strcmp (symname, TEST_FUNC "_sve_args") == 0)
+ {
+ svint8_t z0 = svld1_s8 (svptrue_b8 (),
+ (const int8_t *) regs->lr_vreg[0].z);
+ svint16_t z1 = svld1_s16 (svptrue_b16 (),
+ (const int16_t *) regs->lr_vreg[1].z);
+ svint32_t z2 = svld1_s32 (svptrue_b32 (),
+ (const int32_t *) regs->lr_vreg[2].z);
+ svint64_t z3 = svld1_s64 (svptrue_b64 (),
+ (const int64_t *) regs->lr_vreg[3].z);
+ svuint8_t z4 = svld1_u8 (svptrue_b8 (),
+ (const uint8_t *) regs->lr_vreg[4].z);
+ svuint16_t z5 = svld1_u16 (svptrue_b16 (),
+ (const uint16_t *) regs->lr_vreg[5].z);
+ svuint32_t z6 = svld1_u32 (svptrue_b32 (),
+ (const uint32_t *) regs->lr_vreg[6].z);
+ svuint64_t z7 = svld1_u64 (svptrue_b64 (),
+ (const uint64_t *) regs->lr_vreg[7].z);
+ assert (svptest_any (svptrue_b8 (), svcmpeq_s8 (svptrue_b8 (),
+ z0, sve_args_z0 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_s16 (svptrue_b16 (),
+ z1, sve_args_z1 ())));
+ assert (svptest_any (svptrue_b32 (), svcmpeq_s32 (svptrue_b32 (),
+ z2, sve_args_z2 ())));
+ assert (svptest_any (svptrue_b64 (), svcmpeq_s64 (svptrue_b64 (),
+ z3, sve_args_z3 ())));
+ assert (svptest_any (svptrue_b8 (), svcmpeq_u8 (svptrue_b8 (),
+ z4, sve_args_z4 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_u16 (svptrue_b16 (),
+ z5, sve_args_z5 ())));
+ assert (svptest_any (svptrue_b32 (), svcmpeq_u32 (svptrue_b32 (),
+ z6, sve_args_z6 ())));
+ assert (svptest_any (svptrue_b64 (), svcmpeq_u64 (svptrue_b64 (),
+ z7, sve_args_z7 ())));
+ }
+ else
+ abort ();
+
+ /* Clobber the q registers on exit. */
+ uint8_t v = 0xff;
+ asm volatile ("dup z0.b, %w0" : : "r" (v) : "z0");
+ asm volatile ("dup z1.b, %w0" : : "r" (v) : "z1");
+ asm volatile ("dup z2.b, %w0" : : "r" (v) : "z2");
+ asm volatile ("dup z3.b, %w0" : : "r" (v) : "z3");
+ asm volatile ("dup z4.b, %w0" : : "r" (v) : "z4");
+ asm volatile ("dup z5.b, %w0" : : "r" (v) : "z5");
+ asm volatile ("dup z6.b, %w0" : : "r" (v) : "z6");
+ asm volatile ("dup z7.b, %w0" : : "r" (v) : "z7");
+
+ *framesizep = 1024;
+
+ return sym->st_value;
+}
+
+unsigned int
+la_aarch64_gnu_pltexit (ElfW(Sym) *sym, unsigned int ndx, uintptr_t *refcook,
+ uintptr_t *defcook,
+ const struct La_aarch64_regs *inregs,
+ struct La_aarch64_retval *outregs,
+ const char *symname)
+{
+ printf ("pltexit: symname=%s, st_value=%#lx, ndx=%u\n",
+ symname, (long int) sym->st_value, ndx);
+ printf (" inregs->lr_sve=%d\n", inregs->lr_sve);
+ if (inregs->lr_sve > 0)
+ for (int i = 0; i < array_length (inregs->lr_vreg); i++)
+ printf (" inregs->lr_vreg[%d]=%p\n", i, inregs->lr_vreg[i].z);
+ printf (" outregs->lr_sve=%d\n", outregs->lrv_sve);
+ if (outregs->lrv_sve > 0)
+ for (int i = 0; i < array_length (outregs->lrv_vreg); i++)
+ printf (" outregs->lr_vreg[%d]=%p\n", i, outregs->lrv_vreg[i].z);
+
+ if (strcmp (symname, TEST_FUNC "_sve_args") == 0)
+ {
+ svint8_t z0 = svld1_s8 (svptrue_b8 (),
+ (const int8_t *) inregs->lr_vreg[0].z);
+ svint16_t z1 = svld1_s16 (svptrue_b16 (),
+ (const int16_t *) inregs->lr_vreg[1].z);
+ svint32_t z2 = svld1_s32 (svptrue_b32 (),
+ (const int32_t *) inregs->lr_vreg[2].z);
+ svint64_t z3 = svld1_s64 (svptrue_b64 (),
+ (const int64_t *) inregs->lr_vreg[3].z);
+ svuint8_t z4 = svld1_u8 (svptrue_b8 (),
+ (const uint8_t *) inregs->lr_vreg[4].z);
+ svuint16_t z5 = svld1_u16 (svptrue_b16 (),
+ (const uint16_t *) inregs->lr_vreg[5].z);
+ svuint32_t z6 = svld1_u32 (svptrue_b32 (),
+ (const uint32_t *) inregs->lr_vreg[6].z);
+ svuint64_t z7 = svld1_u64 (svptrue_b64 (),
+ (const uint64_t *) inregs->lr_vreg[7].z);
+ assert (svptest_any (svptrue_b8 (), svcmpeq_s8 (svptrue_b8 (),
+ z0, sve_args_z0 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_s16 (svptrue_b16 (),
+ z1, sve_args_z1 ())));
+ assert (svptest_any (svptrue_b32 (), svcmpeq_s32 (svptrue_b32 (),
+ z2, sve_args_z2 ())));
+ assert (svptest_any (svptrue_b64 (), svcmpeq_s64 (svptrue_b64 (),
+ z3, sve_args_z3 ())));
+ assert (svptest_any (svptrue_b8 (), svcmpeq_u8 (svptrue_b8 (),
+ z4, sve_args_z4 ())));
+ assert (svptest_any (svptrue_b16 (), svcmpeq_u16 (svptrue_b16 (),
+ z5, sve_args_z5 ())));
+ assert (svptest_any (svptrue_b32 (), svcmpeq_u32 (svptrue_b32 (),
+ z6, sve_args_z6 ())));
+ assert (svptest_any (svptrue_b64 (), svcmpeq_u64 (svptrue_b64 (),
+ z7, sve_args_z7 ())));
+
+ svint8_t r0 = svld1_s8 (svptrue_b8 (),
+ (const int8_t *) outregs->lrv_vreg[0].z);
+ assert (svptest_any (svptrue_b8 (), svcmpeq_s8 (svptrue_b8 (),
+ r0, sve_ret ())));
+ }
+ else
+ abort ();
+
+ /* Clobber the q registers on exit. */
+ uint8_t v = 0xff;
+ asm volatile ("dup z0.b, %w0" : : "r" (v) : "z0");
+ asm volatile ("dup z1.b, %w0" : : "r" (v) : "z1");
+ asm volatile ("dup z2.b, %w0" : : "r" (v) : "z2");
+ asm volatile ("dup z3.b, %w0" : : "r" (v) : "z3");
+ asm volatile ("dup z4.b, %w0" : : "r" (v) : "z4");
+ asm volatile ("dup z5.b, %w0" : : "r" (v) : "z5");
+ asm volatile ("dup z6.b, %w0" : : "r" (v) : "z6");
+ asm volatile ("dup z7.b, %w0" : : "r" (v) : "z7");
+
+ return 0;
+}
diff --git a/sysdeps/alpha/dl-machine.h b/sysdeps/alpha/dl-machine.h
index 7d6282e599..b9fc286059 100644
--- a/sysdeps/alpha/dl-machine.h
+++ b/sysdeps/alpha/dl-machine.h
@@ -509,7 +509,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf64_Addr l_addr, const Elf64_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf64_Addr * const reloc_addr = (void *)(l_addr + reloc->r_offset);
unsigned long int const r_type = ELF64_R_TYPE (reloc->r_info);
diff --git a/sysdeps/arc/dl-machine.h b/sysdeps/arc/dl-machine.h
index f843ed9bd6..c2ca04181f 100644
--- a/sysdeps/arc/dl-machine.h
+++ b/sysdeps/arc/dl-machine.h
@@ -329,7 +329,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
index 4ecdde4355..b747f5cc3b 100644
--- a/sysdeps/arm/dl-machine.h
+++ b/sysdeps/arm/dl-machine.h
@@ -623,7 +623,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rel *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/csky/dl-machine.h b/sysdeps/csky/dl-machine.h
index 4dfd957877..fa5d42413a 100644
--- a/sysdeps/csky/dl-machine.h
+++ b/sysdeps/csky/dl-machine.h
@@ -343,7 +343,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
static inline void __attribute__ ((unused, always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/hppa/dl-machine.h b/sysdeps/hppa/dl-machine.h
index 7c5d0e9430..d51df3e444 100644
--- a/sysdeps/hppa/dl-machine.h
+++ b/sysdeps/hppa/dl-machine.h
@@ -793,7 +793,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr,
static void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
/* We don't have anything to do here. elf_machine_runtime_setup has
done all the relocs already. */
diff --git a/sysdeps/i386/dl-machine.h b/sysdeps/i386/dl-machine.h
index 2f0dbc27a9..071e4e3d55 100644
--- a/sysdeps/i386/dl-machine.h
+++ b/sysdeps/i386/dl-machine.h
@@ -641,7 +641,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rel *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/ia64/dl-machine.h b/sysdeps/ia64/dl-machine.h
index c9608a51b0..d13c3aa732 100644
--- a/sysdeps/ia64/dl-machine.h
+++ b/sysdeps/ia64/dl-machine.h
@@ -493,7 +493,7 @@ static inline void
__attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf64_Addr l_addr, const Elf64_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned long int r_type = ELF64_R_TYPE (reloc->r_info);
diff --git a/sysdeps/m68k/dl-machine.h b/sysdeps/m68k/dl-machine.h
index 30323d62d4..f14e63f8da 100644
--- a/sysdeps/m68k/dl-machine.h
+++ b/sysdeps/m68k/dl-machine.h
@@ -315,7 +315,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
static inline void __attribute__ ((unused, always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
if (ELF32_R_TYPE (reloc->r_info) == R_68K_JMP_SLOT)
diff --git a/sysdeps/microblaze/dl-machine.h b/sysdeps/microblaze/dl-machine.h
index b8cc5a7fe6..f926f27883 100644
--- a/sysdeps/microblaze/dl-machine.h
+++ b/sysdeps/microblaze/dl-machine.h
@@ -289,7 +289,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
static inline void
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
if (ELF32_R_TYPE (reloc->r_info) == R_MICROBLAZE_JUMP_SLOT)
diff --git a/sysdeps/mips/dl-machine.h b/sysdeps/mips/dl-machine.h
index d7b8341b74..2d19baf84a 100644
--- a/sysdeps/mips/dl-machine.h
+++ b/sysdeps/mips/dl-machine.h
@@ -729,7 +729,7 @@ static inline void
__attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rel) *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELFW(R_TYPE) (reloc->r_info);
diff --git a/sysdeps/nios2/dl-machine.h b/sysdeps/nios2/dl-machine.h
index 430ca5d7ae..b76659d442 100644
--- a/sysdeps/nios2/dl-machine.h
+++ b/sysdeps/nios2/dl-machine.h
@@ -326,7 +326,7 @@ elf_machine_rela_relative (ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
static inline void __attribute__((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
if (ELF32_R_TYPE (reloc->r_info) == R_NIOS2_JUMP_SLOT)
diff --git a/sysdeps/powerpc/powerpc32/dl-machine.h b/sysdeps/powerpc/powerpc32/dl-machine.h
index 8d062951ce..a64ff303f0 100644
--- a/sysdeps/powerpc/powerpc32/dl-machine.h
+++ b/sysdeps/powerpc/powerpc32/dl-machine.h
@@ -449,7 +449,7 @@ elf_machine_rela_relative (Elf32_Addr l_addr, const Elf32_Rela *reloc,
static inline void __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
/* elf_machine_runtime_setup handles this. */
}
diff --git a/sysdeps/powerpc/powerpc64/dl-machine.h b/sysdeps/powerpc/powerpc64/dl-machine.h
index 3a4a21a412..e33e2a231d 100644
--- a/sysdeps/powerpc/powerpc64/dl-machine.h
+++ b/sysdeps/powerpc/powerpc64/dl-machine.h
@@ -1026,7 +1026,7 @@ elf_machine_rela (struct link_map *map, struct r_scope_elem *scope[],
static inline void __attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf64_Addr l_addr, const Elf64_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
/* elf_machine_runtime_setup handles this. */
}
diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
index ce2b3c3875..944213a939 100644
--- a/sysdeps/riscv/dl-machine.h
+++ b/sysdeps/riscv/dl-machine.h
@@ -291,7 +291,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
diff --git a/sysdeps/s390/s390-32/dl-machine.h b/sysdeps/s390/s390-32/dl-machine.h
index c1d9bb41db..41ec0bab02 100644
--- a/sysdeps/s390/s390-32/dl-machine.h
+++ b/sysdeps/s390/s390-32/dl-machine.h
@@ -497,7 +497,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/s390/s390-64/dl-machine.h b/sysdeps/s390/s390-64/dl-machine.h
index d405f01a03..057825f309 100644
--- a/sysdeps/s390/s390-64/dl-machine.h
+++ b/sysdeps/s390/s390-64/dl-machine.h
@@ -451,7 +451,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf64_Addr l_addr, const Elf64_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
diff --git a/sysdeps/sh/dl-machine.h b/sysdeps/sh/dl-machine.h
index d14023e749..66c5046631 100644
--- a/sysdeps/sh/dl-machine.h
+++ b/sysdeps/sh/dl-machine.h
@@ -448,7 +448,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
/* Check for unexpected PLT reloc type. */
diff --git a/sysdeps/sparc/sparc32/dl-machine.h b/sysdeps/sparc/sparc32/dl-machine.h
index 78f53bc499..f0c531d9b7 100644
--- a/sysdeps/sparc/sparc32/dl-machine.h
+++ b/sysdeps/sparc/sparc32/dl-machine.h
@@ -549,7 +549,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf32_Addr l_addr, const Elf32_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf32_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF32_R_TYPE (reloc->r_info);
diff --git a/sysdeps/sparc/sparc64/dl-machine.h b/sysdeps/sparc/sparc64/dl-machine.h
index 3fa79d038f..b280a74c9a 100644
--- a/sysdeps/sparc/sparc64/dl-machine.h
+++ b/sysdeps/sparc/sparc64/dl-machine.h
@@ -659,7 +659,7 @@ static inline void
__attribute__ ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
Elf64_Addr l_addr, const Elf64_Rela *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
Elf64_Addr *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned int r_type = ELF64_R_TYPE (reloc->r_info);
diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
index b1a5297b66..101fc71b84 100644
--- a/sysdeps/x86_64/dl-machine.h
+++ b/sysdeps/x86_64/dl-machine.h
@@ -540,7 +540,7 @@ static inline void
__attribute ((always_inline))
elf_machine_lazy_rel (struct link_map *map, struct r_scope_elem *scope[],
ElfW(Addr) l_addr, const ElfW(Rela) *reloc,
- int skip_ifunc)
+ int profile, int skip_ifunc)
{
ElfW(Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
const unsigned long int r_type = ELFW(R_TYPE) (reloc->r_info);
--
2.32.0
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit
2021-11-15 18:37 ` [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
@ 2021-12-21 14:27 ` Florian Weimer
2021-12-21 14:37 ` Adhemerval Zanella
2021-12-21 16:45 ` Szabolcs Nagy
0 siblings, 2 replies; 89+ messages in thread
From: Florian Weimer @ 2021-12-21 14:27 UTC (permalink / raw)
To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
* Adhemerval Zanella:
> To implement lazy binding is enabled when profiling or auditing used,
> even when STO_AARCH64_VARIANT_PCS is set. Also, to not incur in
> performance penalties on architecture without SVE, the PLT entrypoint
> is set to a newer one, _dl_runtime_profile_sve, which is used iff
> 'hwcap' has HWCAP_SVE bit set.
>
> This should be a fair assumption since SVE has a defined set of
> registers for argument passing and return values. A new ABI with either
> different argument passing or different registers would require a
> different PLT entry, but I assume this would require another symbol flag
> anyway (or at least a different ELF mark to indicate so).
Someone familiar with SVE needs to review this.
The restriction to the currently-specified vector calling convention
seems to be a bit arbitrary to me. To me, STO_AARCH64_VARIANT_PCS
strongly suggests that the toolchain makes every conceivable attempt to
support arbitrary calling conventions, but that's probably just me.
Thanks,
Florian
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit
2021-12-21 14:27 ` Florian Weimer
@ 2021-12-21 14:37 ` Adhemerval Zanella
2021-12-21 16:45 ` Szabolcs Nagy
1 sibling, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 14:37 UTC (permalink / raw)
To: Florian Weimer, Szabolcs Nagy
Cc: libc-alpha, John Mellor-Crummey, Ben Woodard
On 21/12/2021 11:27, Florian Weimer wrote:
> * Adhemerval Zanella:
>
>> To implement lazy binding is enabled when profiling or auditing used,
>> even when STO_AARCH64_VARIANT_PCS is set. Also, to not incur in
>> performance penalties on architecture without SVE, the PLT entrypoint
>> is set to a newer one, _dl_runtime_profile_sve, which is used iff
>> 'hwcap' has HWCAP_SVE bit set.
>>
>> This should be a fair assumption since SVE has a defined set of
>> registers for argument passing and return values. A new ABI with either
>> different argument passing or different registers would require a
>> different PLT entry, but I assume this would require another symbol flag
>> anyway (or at least a different ELF mark to indicate so).
>
> Someone familiar with SVE needs to review this.
>
> The restriction to the currently-specified vector calling convention
> seems to be a bit arbitrary to me. To me, STO_AARCH64_VARIANT_PCS
> strongly suggests that the toolchain makes every conceivable attempt to
> support arbitrary calling conventions, but that's probably just me.
The STO_AARCH64_VARIANT_PCS does suggest compiler might use *any* calling
convention it seems fit for the symbol. I sent the patch initially as
RFC, hopping other ARM developers will suggest that either assuming SVE
calling convention would be fine or if we should not make any assumptions
and save/restore everything.
I can remove it from this patchset and aim to fix on 2.36. The main
problem is would require to bump LAV_VERSION again for aarch64, since
it would require change both La_aarch64_regs and La_aarch64_retval
layout.
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit
2021-12-21 14:27 ` Florian Weimer
2021-12-21 14:37 ` Adhemerval Zanella
@ 2021-12-21 16:45 ` Szabolcs Nagy
2021-12-21 17:08 ` Adhemerval Zanella
1 sibling, 1 reply; 89+ messages in thread
From: Szabolcs Nagy @ 2021-12-21 16:45 UTC (permalink / raw)
To: Florian Weimer; +Cc: Adhemerval Zanella, John Mellor-Crummey, libc-alpha
The 12/21/2021 15:27, Florian Weimer via Libc-alpha wrote:
> * Adhemerval Zanella:
>
> > To implement lazy binding is enabled when profiling or auditing used,
> > even when STO_AARCH64_VARIANT_PCS is set. Also, to not incur in
> > performance penalties on architecture without SVE, the PLT entrypoint
> > is set to a newer one, _dl_runtime_profile_sve, which is used iff
> > 'hwcap' has HWCAP_SVE bit set.
> >
> > This should be a fair assumption since SVE has a defined set of
> > registers for argument passing and return values. A new ABI with either
> > different argument passing or different registers would require a
> > different PLT entry, but I assume this would require another symbol flag
> > anyway (or at least a different ELF mark to indicate so).
>
> Someone familiar with SVE needs to review this.
>
> The restriction to the currently-specified vector calling convention
> seems to be a bit arbitrary to me. To me, STO_AARCH64_VARIANT_PCS
> strongly suggests that the toolchain makes every conceivable attempt to
> support arbitrary calling conventions, but that's probably just me.
thanks for working on this, but yeah this approach does not work:
A PLT hook for STO_AARCH64_VARIANT_PCS symbol has to preserve *all*
registers (except x16,x17,cc), this is the same strict requirement
as linker inserted veneers follow. (historically the dynamic linker
lazy binding code made assumptions about the call convention, but if
there are extern calls with unusual call conventions then this does
not work and it has to behave like the static linker. this is the
meaning of variant_pcs, it is not just for sve calls.)
there is no way to tell which call is an sve call, so i'd suggest
having 2 profile entries: normal and variant_pcs and the latter is
used if a module is marked with DT_AARCH64_VARIANT_PCS and it
preserves all registers.
when "all registers" increase via arch extensions then the PLT hook
code has to be updated, but ideally only the variant_pcs hooks
will require a glibc update to work on a new arch.
e.g. the user callback can take
struct regs {
// base arg regs inline;
...
void *vpcs_regs;
};
where vpcs_regs!=0 for variant_pcs calls and contains all the regs
(in a way that can represent various combinations of arch extensions,
i don't think we have to make it userfriendly to access).
(i think we don't have to get the aarch64 fixes done in 2.35 as this
is a big design work.)
^ permalink raw reply [flat|nested] 89+ messages in thread
* Re: [PATCH v6 20/20] elf: Add SVE support for aarch64 rtld-audit
2021-12-21 16:45 ` Szabolcs Nagy
@ 2021-12-21 17:08 ` Adhemerval Zanella
0 siblings, 0 replies; 89+ messages in thread
From: Adhemerval Zanella @ 2021-12-21 17:08 UTC (permalink / raw)
To: Szabolcs Nagy, Florian Weimer; +Cc: John Mellor-Crummey, libc-alpha
On 21/12/2021 13:45, Szabolcs Nagy wrote:
> The 12/21/2021 15:27, Florian Weimer via Libc-alpha wrote:
>> * Adhemerval Zanella:
>>
>>> To implement lazy binding is enabled when profiling or auditing used,
>>> even when STO_AARCH64_VARIANT_PCS is set. Also, to not incur in
>>> performance penalties on architecture without SVE, the PLT entrypoint
>>> is set to a newer one, _dl_runtime_profile_sve, which is used iff
>>> 'hwcap' has HWCAP_SVE bit set.
>>>
>>> This should be a fair assumption since SVE has a defined set of
>>> registers for argument passing and return values. A new ABI with either
>>> different argument passing or different registers would require a
>>> different PLT entry, but I assume this would require another symbol flag
>>> anyway (or at least a different ELF mark to indicate so).
>>
>> Someone familiar with SVE needs to review this.
>>
>> The restriction to the currently-specified vector calling convention
>> seems to be a bit arbitrary to me. To me, STO_AARCH64_VARIANT_PCS
>> strongly suggests that the toolchain makes every conceivable attempt to
>> support arbitrary calling conventions, but that's probably just me.
>
>
> thanks for working on this, but yeah this approach does not work:
>
> A PLT hook for STO_AARCH64_VARIANT_PCS symbol has to preserve *all*
> registers (except x16,x17,cc), this is the same strict requirement
> as linker inserted veneers follow. (historically the dynamic linker
> lazy binding code made assumptions about the call convention, but if
> there are extern calls with unusual call conventions then this does
> not work and it has to behave like the static linker. this is the
> meaning of variant_pcs, it is not just for sve calls.)
>
> there is no way to tell which call is an sve call, so i'd suggest
> having 2 profile entries: normal and variant_pcs and the latter is
> used if a module is marked with DT_AARCH64_VARIANT_PCS and it
> preserves all registers.
>
> when "all registers" increase via arch extensions then the PLT hook
> code has to be updated, but ideally only the variant_pcs hooks
> will require a glibc update to work on a new arch.
I was afraid we would require a change like that and based on
STO_AARCH64_VARIANT_PCS definition is does seem the only option.
>
> e.g. the user callback can take
>
> struct regs {
> // base arg regs inline;
> ...
> void *vpcs_regs;
> };
> > where vpcs_regs!=0 for variant_pcs calls and contains all the regs
> (in a way that can represent various combinations of arch extensions,
> i don't think we have to make it userfriendly to access).
Yeah, that was one idea I had when coding it. It will make the
_dl_runtime_profile somewhat more complex for SVE, but it the cost
of having a non-specific ABIs for lazy binding.
I think we will need to have this new field on BZ #26643 fix at least,
and chage current code to zero it. It will make it easier to provide
SVE support on 2.36.
>
> (i think we don't have to get the aarch64 fixes done in 2.35 as this
> is a big design work.)
Agreed, I will drop this patch for v7.
^ permalink raw reply [flat|nested] 89+ messages in thread