public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v5 00/22] Multiple rtld-audit fixes
@ 2021-11-09 18:33 Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
                   ` (21 more replies)
  0 siblings, 22 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 UTC (permalink / raw)
  To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard

This patchset fixes most of the rtld-audit issues brought by John
Mellor-Crummey [1] while trying to use it along with the HPCToolkit.
This should cover all the issues listed as 'Tier 1' [2] (although the
aarch64 SVE is marked as RFC) and also most of the 'Tier2' issue
(BZ#28096 inclusive) which prevents the use of some glibc function
that uses TLS internally on the audit module.

On this set I also added a possible fix for the aarch64 SVE, although
there is some issues regarding STO_AARCH64_VARIANT_PCS.

I also pushed this patch on a personal branch [3].

There is also some point brough by John Melloc-Crummey documents that
I don't have a straighforward answer so I haven't added on this
patchset:

  1 la_activity(LA_ACT_ADD) is never called for auditor namespaces,
     even though la_objopen and la_activity(LA_ACT_CONSISTENT) are.

  There is no easy solution for this: we need at least to load the
  *first* auditor to actually issue the la_activity(LA_ACT_ADD).  It
  means that it would *only* work for subsequent audit modules, and
  adding this specific semantic is confusing and does not really
  improve things (it only helps when multiple audit modules are used).

  2. la_objopen is called for the main binary and for ld.so before the
     first la_activity(LA_ACT_ADD) call.  This contradicts the pattern
     found in a successful dlopen (where la_activity(LA_ACT_ADD)
     precedes la_objopen).

  The constrain here is we need to handle DT_AUDIT and DT_DEPAUDIT
  dynamic tags, which means we need to first load the executable in
  memory to parse the required audit modules.  So we need to first parse
  the dynamic audit tags, load the audit modules, and then load the
  object itself.

  3. For non-PIE executables the base address listed in link_map->l_addr
     for the main application binary is 0, even though dladdr is able to
     recover the correct offset. La_objopen is affected by this.

  This would require to change an internal semantic for link_map->l_addr.
  This is not straighfoward and I am not sure about the direct gains.

I have checked the patches on x86_64, i686, aarch64, armv7, powerpc64,
powerpc64le, and powerpc.

[1] https://sourceware.org/pipermail/libc-alpha/2021-June/127636.html
[2] https://docs.google.com/document/d/1dVaDBdzySecxQqD6hLLzDrEF18M1UtjDna9gL5BWWI0/edit#
[3] https://sourceware.org/git/?p=glibc.git;a=shortlog;h=refs/heads/azanella/ld-audit-fixes

Changes from v4:
  - Added a fix for constructors if executable has a soname of a
    dependency
  - Rebased against master.

Changes from v3
  - Added a aarch64 SVE RFC patch.
  - Fixed an issue with bind-now fix on powerpc64 ELFv1.
  - Rebased against master.

Changes from v2
  - Refactored rtld-audit code to move common come to dl-audit.c.
  - Issue audit la_objopen() for vDSO.
  - Isseu la_activity during application exit.
  - Issue la_symbind() for bind-now (BZ #23734).
  - Fix runtime linker auditing on aarch64 (BZ #26643)

Changes from v1
  - Fixed -fstack-protector-all tst-auditmod17.
  - Simplify the _dl_call_libc_early_init call the 'Fix audit
    regression' patch.
  - Remove symbind check fr BZ#15333.
  - Added the BZ#28096 fix.

Adhemerval Zanella (20):
  elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
  elf: Add audit tests for modules with TLSDESC
  elf: Do not fail for failed dlopem on audit modules (BZ #28061)
  elf: Fix initial-exec TLS access on audit modules (BZ #28096)
  elf: Add _dl_audit_objopen
  elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid
  elf: Add _dl_audit_objsearch
  elf: Add _dl_audit_objclose
  elf: Add _dl_audit_symbind_alt and _dl_audit_symbind
  elf: Add _dl_audit_preinit
  elf: Add _dl_audit_pltenter
  elf: Add _dl_audit_pltexit
  elf: Issue audit la_objopen() for vDSO
  elf: Run constructors if executable has a soname of a dependency
  elf: Add main application on main_map l_name
  elf: Add la_activity during application exit
  elf: Issue la_symbind() for bind-now (BZ #23734)
  elf: Add LA_SYMB_BINDNOW
  elf: Move LAV_CURRENT to link_lavcurrent.h
  elf: Add SVE support for aarch64 rtld-audit

Ben Woodard (1):
  elf: Fix runtime linker auditing on aarch64 (BZ #26643)

Vivek Das Mohapatra (1):
  elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)

 NEWS                                      |   4 +
 bits/link_lavcurrent.h                    |  25 ++
 csu/libc-start.c                          |  23 +-
 dlfcn/Makefile                            |   4 +-
 dlfcn/tst-dladdr-self.c                   |  55 +++
 elf/Makefile                              | 126 ++++++-
 elf/Versions                              |   1 +
 elf/dl-addr.c                             |   5 -
 elf/dl-audit.c                            | 394 ++++++++++++++++++++++
 elf/dl-close.c                            |  74 +---
 elf/dl-dst.h                              |   2 +-
 elf/dl-fini.c                             |  25 +-
 elf/dl-init.c                             |   3 +-
 elf/dl-load.c                             | 112 ++----
 elf/dl-misc.c                             |   1 +
 elf/dl-object.c                           |  20 +-
 elf/dl-open.c                             |  22 +-
 elf/dl-reloc.c                            |  26 +-
 elf/dl-runtime.c                          | 244 ++------------
 elf/dl-sym-post.h                         |  47 +--
 elf/dl-tls.c                              |  16 +-
 elf/do-rel.h                              |  71 +++-
 elf/dso-sort-tests-1.def                  |   5 +-
 elf/dynamic-link.h                        |  26 +-
 elf/link.h                                |   7 +-
 elf/rtld.c                                |  81 +----
 elf/setup-vdso.h                          |   2 +-
 elf/tst-audit-tlsdesc-audit.c             |  23 ++
 elf/tst-audit-tlsdesc-dlopen.c            |  67 ++++
 elf/tst-audit-tlsdesc.c                   |  60 ++++
 elf/tst-audit18a.c                        |  39 +++
 elf/tst-audit18b.c                        |  94 ++++++
 elf/tst-audit18bmod.c                     |  23 ++
 elf/tst-audit18mod.c                      |  17 +
 elf/tst-audit19.c                         |  25 ++
 elf/tst-audit20.c                         | 129 +++++++
 elf/tst-audit20mod.c                      |  26 ++
 elf/tst-audit21.c                         |  42 +++
 elf/tst-audit22.c                         | 123 +++++++
 elf/tst-audit23.c                         | 161 +++++++++
 elf/tst-audit23mod.c                      |  23 ++
 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                        | 126 +++++++
 elf/tst-audit25b.c                        | 127 +++++++
 elf/tst-audit25mod1.c                     |  30 ++
 elf/tst-audit25mod2.c                     |  30 ++
 elf/tst-audit25mod3.c                     |  22 ++
 elf/tst-audit25mod4.c                     |  22 ++
 elf/tst-auditmod-tlsdesc1.c               |  41 +++
 elf/tst-auditmod-tlsdesc2.c               |  33 ++
 elf/tst-auditmod18a.c                     |  23 ++
 elf/tst-auditmod18b.c                     |  46 +++
 elf/tst-auditmod19.c                      |  57 ++++
 elf/tst-auditmod20.c                      |  73 ++++
 elf/tst-auditmod21.c                      |  69 ++++
 elf/tst-auditmod22.c                      |  65 ++++
 elf/tst-auditmod23.c                      |  78 +++++
 elf/tst-auditmod24a.c                     | 104 ++++++
 elf/tst-auditmod24b.c                     |  99 ++++++
 elf/tst-auditmod24c.c                     |   3 +
 elf/tst-auditmod24d.c                     | 114 +++++++
 elf/tst-auditmod25.c                      |  77 +++++
 gmon/gmon.c                               |  10 +-
 include/dlfcn.h                           |   1 +
 include/link.h                            |   4 +
 sysdeps/aarch64/Makefile                  |  32 ++
 sysdeps/aarch64/bits/link.h               |  28 +-
 sysdeps/aarch64/bits/link_lavcurrent.h    |  25 ++
 sysdeps/aarch64/dl-link.sym               |   7 +-
 sysdeps/aarch64/dl-machine.h              |  14 +-
 sysdeps/aarch64/dl-trampoline.S           | 391 +++++++++++++++++++--
 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-audit28.c             |  44 +++
 sysdeps/aarch64/tst-audit28mod.c          |  48 +++
 sysdeps/aarch64/tst-audit28mod.h          |  74 ++++
 sysdeps/aarch64/tst-auditmod26.c          |  98 ++++++
 sysdeps/aarch64/tst-auditmod27.c          | 252 ++++++++++++++
 sysdeps/aarch64/tst-auditmod28.c          | 193 +++++++++++
 sysdeps/alpha/dl-machine.h                |   2 +-
 sysdeps/alpha/dl-trampoline.S             |   8 +-
 sysdeps/arc/dl-machine.h                  |   2 +-
 sysdeps/arm/dl-machine.h                  |   2 +-
 sysdeps/arm/dl-trampoline.S               |   2 +-
 sysdeps/csky/dl-machine.h                 |   2 +-
 sysdeps/generic/dl-fixup-attribute.h      |  24 ++
 sysdeps/generic/dl-lookupcfg.h            |   1 +
 sysdeps/generic/ldsodefs.h                |  30 ++
 sysdeps/hppa/dl-machine.h                 |   2 +-
 sysdeps/hppa/dl-runtime.c                 |   2 +-
 sysdeps/hppa/dl-trampoline.S              |   6 +-
 sysdeps/i386/dl-fixup-attribute.h         |  30 ++
 sysdeps/i386/dl-machine.h                 |  25 +-
 sysdeps/i386/dl-trampoline.S              |   2 +-
 sysdeps/ia64/dl-machine.h                 |   2 +-
 sysdeps/ia64/dl-trampoline.S              |  16 +-
 sysdeps/m68k/dl-machine.h                 |   2 +-
 sysdeps/m68k/dl-trampoline.S              |   2 +-
 sysdeps/microblaze/dl-machine.h           |   2 +-
 sysdeps/mips/dl-machine.h                 |   2 +-
 sysdeps/nios2/dl-machine.h                |   2 +-
 sysdeps/powerpc/dl-lookupcfg.h            |  30 ++
 sysdeps/powerpc/powerpc32/dl-machine.h    |   2 +-
 sysdeps/powerpc/powerpc64/dl-machine.h    |   2 +-
 sysdeps/powerpc/powerpc64/dl-trampoline.S |   4 +-
 sysdeps/riscv/dl-machine.h                |   2 +-
 sysdeps/s390/s390-32/dl-machine.h         |   2 +-
 sysdeps/s390/s390-32/dl-trampoline.h      |   4 +-
 sysdeps/s390/s390-64/dl-machine.h         |   2 +-
 sysdeps/s390/s390-64/dl-trampoline.h      |   2 +-
 sysdeps/sh/dl-machine.h                   |   2 +-
 sysdeps/sh/dl-trampoline.S                |   4 +-
 sysdeps/sparc/sparc32/dl-machine.h        |   2 +-
 sysdeps/sparc/sparc32/dl-trampoline.S     |   2 +-
 sysdeps/sparc/sparc64/dl-machine.h        |   2 +-
 sysdeps/sparc/sparc64/dl-trampoline.S     |   2 +-
 sysdeps/x86_64/dl-machine.h               |   2 +-
 sysdeps/x86_64/dl-runtime.h               |   2 +-
 sysdeps/x86_64/dl-trampoline.h            |   6 +-
 134 files changed, 4941 insertions(+), 718 deletions(-)
 create mode 100644 bits/link_lavcurrent.h
 create mode 100644 dlfcn/tst-dladdr-self.c
 create mode 100644 elf/dl-audit.c
 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-audit18a.c
 create mode 100644 elf/tst-audit18b.c
 create mode 100644 elf/tst-audit18bmod.c
 create mode 100644 elf/tst-audit18mod.c
 create mode 100644 elf/tst-audit19.c
 create mode 100644 elf/tst-audit20.c
 create mode 100644 elf/tst-audit20mod.c
 create mode 100644 elf/tst-audit21.c
 create mode 100644 elf/tst-audit22.c
 create mode 100644 elf/tst-audit23.c
 create mode 100644 elf/tst-audit23mod.c
 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-auditmod-tlsdesc1.c
 create mode 100644 elf/tst-auditmod-tlsdesc2.c
 create mode 100644 elf/tst-auditmod18a.c
 create mode 100644 elf/tst-auditmod18b.c
 create mode 100644 elf/tst-auditmod19.c
 create mode 100644 elf/tst-auditmod20.c
 create mode 100644 elf/tst-auditmod21.c
 create mode 100644 elf/tst-auditmod22.c
 create mode 100644 elf/tst-auditmod23.c
 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/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-audit28.c
 create mode 100644 sysdeps/aarch64/tst-audit28mod.c
 create mode 100644 sysdeps/aarch64/tst-audit28mod.h
 create mode 100644 sysdeps/aarch64/tst-auditmod26.c
 create mode 100644 sysdeps/aarch64/tst-auditmod27.c
 create mode 100644 sysdeps/aarch64/tst-auditmod28.c
 create mode 100644 sysdeps/generic/dl-fixup-attribute.h
 create mode 100644 sysdeps/i386/dl-fixup-attribute.h
 create mode 100644 sysdeps/powerpc/dl-lookupcfg.h

-- 
2.32.0


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 12:11   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
                   ` (20 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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          |   9 ++
 elf/dl-reloc.c        |  18 +++-
 elf/dl-runtime.c      | 188 ++++++++++++++++++++++++------------------
 elf/rtld.c            |   8 +-
 elf/tst-audit18a.c    |  39 +++++++++
 elf/tst-audit18b.c    |  94 +++++++++++++++++++++
 elf/tst-audit18bmod.c |  23 ++++++
 elf/tst-audit18mod.c  |  17 ++++
 elf/tst-auditmod18a.c |  23 ++++++
 elf/tst-auditmod18b.c |  46 +++++++++++
 include/link.h        |   2 +
 12 files changed, 384 insertions(+), 87 deletions(-)
 create mode 100644 elf/tst-audit18a.c
 create mode 100644 elf/tst-audit18b.c
 create mode 100644 elf/tst-audit18bmod.c
 create mode 100644 elf/tst-audit18mod.c
 create mode 100644 elf/tst-auditmod18a.c
 create mode 100644 elf/tst-auditmod18b.c

diff --git a/NEWS b/NEWS
index 82b7016aef..18a9d7fb5e 100644
--- a/NEWS
+++ b/NEWS
@@ -180,6 +180,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 72004484db..bad18f2d11 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -225,6 +225,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \
 	 tst-dlopenfail-2 \
 	 tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
+	 tst-audit18a tst-audit18b \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -313,6 +314,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-unique1mod1 tst-unique1mod2 \
 		tst-unique2mod1 tst-unique2mod2 \
 		tst-auditmod9a tst-auditmod9b \
+		tst-auditmod18a tst-auditmod18b tst-audit18bmod \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1537,6 +1539,13 @@ $(objpfx)tst-audit16-cmp.out: tst-audit16.exp $(objpfx)tst-audit16.out
 	cmp $^ > $@; \
 	$(evaluate-test)
 
+$(objpfx)tst-audit18a.out: $(objpfx)tst-auditmod18a.so
+tst-audit18a-ENV = LD_AUDIT=$(objpfx)tst-auditmod18a.so
+
+$(objpfx)tst-audit18b.out: $(objpfx)tst-auditmod18b.so
+$(objpfx)tst-audit18b: $(objpfx)tst-audit18bmod.so
+tst-audit18b-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..27f792b7b2 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -203,11 +203,25 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
   const char *errstring = NULL;
   int lazy = reloc_mode & RTLD_LAZY;
   int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
+  bool consider_symbind = false;
 
 #ifdef SHARED
   /* 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
@@ -272,7 +286,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 61c260ddb8..b0c788eb22 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -44,6 +44,84 @@
 # define ARCH_FIXUP_ATTRIBUTE
 #endif
 
+#ifdef SHARED
+static 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
+
 /* 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
@@ -139,6 +217,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;
@@ -297,84 +406,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 be2d5d8e74..8953347b00 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-audit18a.c b/elf/tst-audit18a.c
new file mode 100644
index 0000000000..36b781f9be
--- /dev/null
+++ b/elf/tst-audit18a.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-audit18b.c b/elf/tst-audit18b.c
new file mode 100644
index 0000000000..300197ca2e
--- /dev/null
+++ b/elf/tst-audit18b.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-audit18bmod.c b/elf/tst-audit18bmod.c
new file mode 100644
index 0000000000..9ffdcd8f3f
--- /dev/null
+++ b/elf/tst-audit18bmod.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-audit18mod.c b/elf/tst-audit18mod.c
new file mode 100644
index 0000000000..b6eb3731ee
--- /dev/null
+++ b/elf/tst-audit18mod.c
@@ -0,0 +1,17 @@
+/* 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/>.  */
diff --git a/elf/tst-auditmod18a.c b/elf/tst-auditmod18a.c
new file mode 100644
index 0000000000..2296382a1c
--- /dev/null
+++ b/elf/tst-auditmod18a.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-auditmod18b.c b/elf/tst-auditmod18b.c
new file mode 100644
index 0000000000..52bb88c7d7
--- /dev/null
+++ b/elf/tst-auditmod18b.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] 57+ messages in thread

* [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 13:55   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061) Adhemerval Zanella
                   ` (19 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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  | 23 ++++++++++++
 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, 238 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 bad18f2d11..bd1a0f79b4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -384,6 +384,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..53993830c9
--- /dev/null
+++ b/elf/tst-audit-tlsdesc-audit.c
@@ -0,0 +1,23 @@
+/* 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/>.  */
+
+unsigned int
+la_version (unsigned int version)
+{
+  return version;
+}
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] 57+ messages in thread

* [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061)
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:51   ` H.J. Lu
  2021-11-10 14:00   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
                   ` (18 subsequent siblings)
  21 siblings, 2 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 see if the state is
consistent since it is _dt_main() that reset is.  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-audit19.c    | 25 +++++++++++++++++++
 elf/tst-auditmod19.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 87 insertions(+), 2 deletions(-)
 create mode 100644 elf/tst-audit19.c
 create mode 100644 elf/tst-auditmod19.c

diff --git a/elf/Makefile b/elf/Makefile
index bd1a0f79b4..96db0b4322 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -226,6 +226,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-dlopenfail-2 \
 	 tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
 	 tst-audit18a tst-audit18b \
+	 tst-audit19 \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -315,6 +316,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-unique2mod1 tst-unique2mod2 \
 		tst-auditmod9a tst-auditmod9b \
 		tst-auditmod18a tst-auditmod18b tst-audit18bmod \
+		tst-auditmod19 \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1560,6 +1562,9 @@ $(objpfx)tst-audit18b.out: $(objpfx)tst-auditmod18b.so
 $(objpfx)tst-audit18b: $(objpfx)tst-audit18bmod.so
 tst-audit18b-ARGS = -- $(host-test-program-cmd)
 
+$(objpfx)tst-audit19.out: $(objpfx)tst-auditmod19.so
+tst-audit19-ENV = LD_AUDIT=$(objpfx)tst-auditmod19.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 6ea5dd2457..00f6d8cfcc 100644
--- a/elf/dl-open.c
+++ b/elf/dl-open.c
@@ -932,8 +932,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-audit19.c b/elf/tst-audit19.c
new file mode 100644
index 0000000000..6f39ccee86
--- /dev/null
+++ b/elf/tst-audit19.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-auditmod19.c b/elf/tst-auditmod19.c
new file mode 100644
index 0000000000..c57e50ee4e
--- /dev/null
+++ b/elf/tst-auditmod19.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] 57+ messages in thread

* [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (2 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061) Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 14:15   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
                   ` (17 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 UTC (permalink / raw)
  To: libc-alpha, Florian Weimer
  Cc: John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra

From: Vivek Das Mohapatra <vivek@collabora.com>

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.

Co-authored-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
---
 elf/Makefile         |   6 ++
 elf/dl-load.c        |   7 ++-
 elf/tst-audit20.c    | 129 +++++++++++++++++++++++++++++++++++++++++++
 elf/tst-audit20mod.c |  26 +++++++++
 elf/tst-auditmod20.c |  73 ++++++++++++++++++++++++
 5 files changed, 239 insertions(+), 2 deletions(-)
 create mode 100644 elf/tst-audit20.c
 create mode 100644 elf/tst-audit20mod.c
 create mode 100644 elf/tst-auditmod20.c

diff --git a/elf/Makefile b/elf/Makefile
index 96db0b4322..4758cb23c4 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -227,6 +227,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
 	 tst-audit18a tst-audit18b \
 	 tst-audit19 \
+	 tst-audit20 \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -317,6 +318,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod9a tst-auditmod9b \
 		tst-auditmod18a tst-auditmod18b tst-audit18bmod \
 		tst-auditmod19 \
+		tst-auditmod20 tst-audit20mod \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1565,6 +1567,10 @@ tst-audit18b-ARGS = -- $(host-test-program-cmd)
 $(objpfx)tst-audit19.out: $(objpfx)tst-auditmod19.so
 tst-audit19-ENV = LD_AUDIT=$(objpfx)tst-auditmod19.so
 
+$(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so \
+			  $(objpfx)tst-audit20mod.so
+tst-audit20-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..72298776f6 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1067,8 +1067,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
 	  && __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)
+	  /* Do not call the functions for any auditing object and also do not
+	     try to call auditing functions if the namespace is currently
+	     empty.  This happens when opening the first DSO in a new
+	     namespace.  */
+	  if (head != NULL && head->l_auditing == 0)
 	    {
 	      struct audit_ifaces *afct = GLRO(dl_audit);
 	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
diff --git a/elf/tst-audit20.c b/elf/tst-audit20.c
new file mode 100644
index 0000000000..215ae17fdd
--- /dev/null
+++ b/elf/tst-audit20.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-audit20mod.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-auditmod20.so", 0);
+  struct support_capture_subprocess result
+    = support_capture_subprogram (spargv[0], spargv);
+  support_capture_subprocess_check (&result, "tst-audit20", 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-audit20mod.c b/elf/tst-audit20mod.c
new file mode 100644
index 0000000000..f229c4139b
--- /dev/null
+++ b/elf/tst-audit20mod.c
@@ -0,0 +1,26 @@
+/* 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 <fcntl.h>
+#include <gnu/lib-names.h>
+
+int
+foo (void)
+{
+  return 10;
+}
diff --git a/elf/tst-auditmod20.c b/elf/tst-auditmod20.c
new file mode 100644
index 0000000000..182992e9fd
--- /dev/null
+++ b/elf/tst-auditmod20.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] 57+ messages in thread

* [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (3 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 13:23   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 06/22] elf: Add _dl_audit_objopen Adhemerval Zanella
                   ` (16 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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         |  5 ++++
 elf/dl-object.c      |  3 ++
 elf/dl-tls.c         | 16 +++++++---
 elf/rtld.c           |  2 ++
 elf/tst-audit21.c    | 42 +++++++++++++++++++++++++++
 elf/tst-auditmod21.c | 69 ++++++++++++++++++++++++++++++++++++++++++++
 include/link.h       |  2 ++
 7 files changed, 135 insertions(+), 4 deletions(-)
 create mode 100644 elf/tst-audit21.c
 create mode 100644 elf/tst-auditmod21.c

diff --git a/elf/Makefile b/elf/Makefile
index 4758cb23c4..861e83236e 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -228,6 +228,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit18a tst-audit18b \
 	 tst-audit19 \
 	 tst-audit20 \
+	 tst-audit21 \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -319,6 +320,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod18a tst-auditmod18b tst-audit18bmod \
 		tst-auditmod19 \
 		tst-auditmod20 tst-audit20mod \
+		tst-auditmod21 \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1571,6 +1573,9 @@ $(objpfx)tst-audit20.out: $(objpfx)tst-auditmod20.so \
 			  $(objpfx)tst-audit20mod.so
 tst-audit20-ARGS = -- $(host-test-program-cmd)
 
+$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21.so
+tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21.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 8953347b00..db1817655f 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;
 }
 
 /* Notify the the audit modules that the object MAP has already been
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-auditmod21.c b/elf/tst-auditmod21.c
new file mode 100644
index 0000000000..e6248622f4
--- /dev/null
+++ b/elf/tst-auditmod21.c
@@ -0,0 +1,69 @@
+/* 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;
+
+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;
+  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/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] 57+ messages in thread

* [PATCH v5 06/22] elf: Add _dl_audit_objopen
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (4 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 16:51   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 07/22] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
                   ` (15 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 861e83236e..013d698b3e 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 72298776f6..572378e0ca 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1520,22 +1520,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 db1817655f..7179c71188 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1059,25 +1059,6 @@ ERROR: audit interface '%s' requires version %d (maximum supported version %d);
   dlmargs.map->l_dont_set_tls_static = 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)
@@ -1096,8 +1077,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] 57+ messages in thread

* [PATCH v5 07/22] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (5 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 06/22] elf: Add _dl_audit_objopen Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 16:59   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 08/22] elf: Add _dl_audit_objsearch Adhemerval Zanella
                   ` (14 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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.

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              | 28 +++++---------------
 elf/dl-open.c              | 20 +-------------
 elf/rtld.c                 | 31 ++--------------------
 sysdeps/generic/ldsodefs.h |  7 +++++
 6 files changed, 48 insertions(+), 115 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 572378e0ca..be9880f131 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1062,28 +1062,12 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
   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 and also do not
-	     try to call auditing functions if the namespace is currently
-	     empty.  This happens when opening the first DSO in a new
-	     namespace.  */
-	  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)
-		    afct->activity (&link_map_audit_state (head, cnt)->cookie,
-				    LA_ACT_ADD);
-
-		  afct = afct->next;
-		}
-	    }
-	}
+      /* Auditing checkpoint: we are going to add new objects.  Do not call
+	 the functions for any auditing object and also do not try to call
+	 auditing functions if the namespace is currently empty.  This
+	 happens when opening the first DSO in a new namespace.  */
+      if ((mode & __RTLD_AUDIT) == 0)
+	_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 00f6d8cfcc..4f4d72e325 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 7179c71188..faba319e5c 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -1755,18 +1755,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
@@ -2447,23 +2436,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] 57+ messages in thread

* [PATCH v5 08/22] elf: Add _dl_audit_objsearch
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (6 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 07/22] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 09/22] elf: Add _dl_audit_objclose Adhemerval Zanella
                   ` (13 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 be9880f131..4a0ff9d010 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1600,33 +1600,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)
@@ -2064,36 +2039,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] 57+ messages in thread

* [PATCH v5 09/22] elf: Add _dl_audit_objclose
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (7 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 08/22] elf: Add _dl_audit_objsearch Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 10/22] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Adhemerval Zanella
                   ` (12 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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] 57+ messages in thread

* [PATCH v5 10/22] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (8 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 09/22] elf: Add _dl_audit_objclose Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 11/22] elf: Add _dl_audit_preinit Adhemerval Zanella
                   ` (11 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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-runtime.c           |  77 -----------------------
 elf/dl-sym-post.h          |  47 +-------------
 sysdeps/generic/ldsodefs.h |   6 ++
 5 files changed, 130 insertions(+), 123 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-runtime.c b/elf/dl-runtime.c
index b0c788eb22..bfbe8f4be4 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -44,83 +44,6 @@
 # define ARCH_FIXUP_ATTRIBUTE
 #endif
 
-#ifdef SHARED
-static 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
 
 /* This function is called through a special trampoline from the PLT the
    first time each PLT entry is called.  We must perform the relocation
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] 57+ messages in thread

* [PATCH v5 11/22] elf: Add _dl_audit_preinit
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (9 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 10/22] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 12/22] elf: Add _dl_audit_pltenter Adhemerval Zanella
                   ` (10 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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] 57+ messages in thread

* [PATCH v5 12/22] elf: Add _dl_audit_pltenter
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (10 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 11/22] elf: Add _dl_audit_preinit Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 13/22] elf: Add _dl_audit_pltexit Adhemerval Zanella
                   ` (9 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 bfbe8f4be4..c3fc6777ff 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -352,78 +352,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] 57+ messages in thread

* [PATCH v5 13/22] elf: Add _dl_audit_pltexit
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (11 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 12/22] elf: Add _dl_audit_pltenter Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
                   ` (8 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 c3fc6777ff..011e6d645d 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
@@ -53,7 +45,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,
@@ -180,7 +172,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,
@@ -364,52 +357,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] 57+ messages in thread

* [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (12 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 13/22] elf: Add _dl_audit_pltexit Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-11 17:50   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
                   ` (7 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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    | 119 +++++++++++++++++++++++++++++++++++++++++++
 elf/tst-auditmod22.c |  37 ++++++++++++++
 include/dlfcn.h      |   1 +
 7 files changed, 180 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 013d698b3e..f0af543719 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -229,6 +229,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit19 \
 	 tst-audit20 \
 	 tst-audit21 \
+	 tst-audit22 \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -321,6 +322,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod19 \
 		tst-auditmod20 tst-audit20mod \
 		tst-auditmod21 \
+		tst-auditmod22 \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1576,6 +1578,9 @@ tst-audit20-ARGS = -- $(host-test-program-cmd)
 $(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21.so
 tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21.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..c1b301c4cc
--- /dev/null
+++ b/elf/tst-audit22.c
@@ -0,0 +1,119 @@
+/* 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: %" PRIxPTR "\n", vdso_addr);
+  return 0;
+}
+
+static unsigned long int
+parse_address (const char *str)
+{
+  char *endptr;
+  long int ret;
+  errno = 0;
+  ret = strtol (str, &endptr, 10);
+  TEST_COMPARE (errno, 0);
+  TEST_VERIFY (ret >= 0 && ret <= INT_MAX);
+  return ret;
+}
+
+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);
+
+  unsigned long vdso_process = 0;
+  unsigned long 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: "));
+    }
+
+  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..02275bed57
--- /dev/null
+++ b/elf/tst-auditmod22.c
@@ -0,0 +1,37 @@
+/* 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 <stdio.h>
+#include <sys/auxv.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
+    fprintf (stderr, "vdso found: %" PRIxPTR "\n", (uintptr_t) 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] 57+ messages in thread

* [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (13 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-11 12:30   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 16/22] elf: Add main application on main_map l_name Adhemerval Zanella
                   ` (6 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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            | 9 +++++++--
 elf/dso-sort-tests-1.def | 5 ++++-
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/elf/dl-load.c b/elf/dl-load.c
index 4a0ff9d010..d585e1795d 100644
--- a/elf/dl-load.c
+++ b/elf/dl-load.c
@@ -1998,13 +1998,18 @@ _dl_map_object (struct link_map *loader, const char *name,
   assert (nsid >= 0);
   assert (nsid < GL(dl_nns));
 
+  /* Special case: trying to map itself.  */
+  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] 57+ messages in thread

* [PATCH v5 16/22] elf: Add main application on main_map l_name
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (14 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-11 12:39   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 17/22] elf: Add la_activity during application exit Adhemerval Zanella
                   ` (5 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 c1b301c4cc..7718e3e959 100644
--- a/elf/tst-audit22.c
+++ b/elf/tst-audit22.c
@@ -94,6 +94,7 @@ do_test (int argc, char *argv[])
 
   unsigned long vdso_process = 0;
   unsigned long vdso_audit = 0;
+  bool mainapp_found = false;
 
   FILE *out = fmemopen (result.err.buffer, result.err.length, "r");
   TEST_VERIFY (out != NULL);
@@ -105,9 +106,12 @@ do_test (int argc, char *argv[])
 	vdso_process = parse_address (buffer + strlen ("vdso: "));
       else if (startswith (buffer, "vdso found: "))
 	vdso_audit = parse_address (buffer + strlen ("vdso found: "));
+      else if (startswith (buffer, "mainapp found"))
+	mainapp_found = true;
     }
 
   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 02275bed57..a4921f35de 100644
--- a/elf/tst-auditmod22.c
+++ b/elf/tst-auditmod22.c
@@ -19,6 +19,7 @@
 #include <link.h>
 #include <inttypes.h>
 #include <stdio.h>
+#include <string.h>
 #include <sys/auxv.h>
 
 unsigned int
@@ -30,6 +31,13 @@ la_version (unsigned int version)
 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;
+    if (strcmp (l_name, "tst-audit22") == 0)
+      fprintf (stderr, "mainapp found\n");
+  }
+
   if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
     fprintf (stderr, "vdso found: %" PRIxPTR "\n", (uintptr_t) map->l_addr);
 
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] 57+ messages in thread

* [PATCH v5 17/22] elf: Add la_activity during application exit
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (15 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 16/22] elf: Add main application on main_map l_name Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-11 12:50   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
                   ` (4 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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         |   6 ++
 elf/dl-fini.c        |   9 +++
 elf/tst-audit23.c    | 161 +++++++++++++++++++++++++++++++++++++++++++
 elf/tst-audit23mod.c |  23 +++++++
 elf/tst-auditmod23.c |  78 +++++++++++++++++++++
 5 files changed, 277 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 f0af543719..4e45b6729e 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -230,6 +230,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit20 \
 	 tst-audit21 \
 	 tst-audit22 \
+	 tst-audit23 \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -323,6 +324,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod20 tst-audit20mod \
 		tst-auditmod21 \
 		tst-auditmod22 \
+		tst-auditmod23 tst-audit23mod \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1581,6 +1583,10 @@ tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21.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..41bb4cb367
--- /dev/null
+++ b/elf/tst-audit23.c
@@ -0,0 +1,161 @@
+/* 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 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)  */
+  enum { max_objs = 5 };
+  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)
+	{
+	  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..20ef19945d
--- /dev/null
+++ b/elf/tst-auditmod23.c
@@ -0,0 +1,78 @@
+/* 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>
+
+static uintptr_t vdso_addr;
+
+unsigned int
+la_version (unsigned int version)
+{
+  vdso_addr = getauxval (AT_SYSINFO_EHDR);
+  /* The main_map for the executable returns 0 for l_addr.  */
+  if (vdso_addr == 0)
+    vdso_addr = -1;
+  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)
+{
+  if (map->l_addr == vdso_addr)
+    return 0;
+
+  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] 57+ messages in thread

* [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734)
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (16 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 17/22] elf: Add la_activity during application exit Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-11 17:39   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 19/22] elf: Add LA_SYMB_BINDNOW Adhemerval Zanella
                   ` (3 subsequent siblings)
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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 ODP (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                   |  50 +++++++++++++++
 elf/dl-audit.c                 |   5 +-
 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-auditmod22.c           |  22 ++++++-
 elf/tst-auditmod24a.c          | 104 ++++++++++++++++++++++++++++++
 elf/tst-auditmod24b.c          |  99 ++++++++++++++++++++++++++++
 elf/tst-auditmod24c.c          |   3 +
 elf/tst-auditmod24d.c          | 114 +++++++++++++++++++++++++++++++++
 sysdeps/generic/dl-lookupcfg.h |   1 +
 sysdeps/generic/ldsodefs.h     |   2 +-
 sysdeps/powerpc/dl-lookupcfg.h |  30 +++++++++
 25 files changed, 821 insertions(+), 24 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-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 sysdeps/powerpc/dl-lookupcfg.h

diff --git a/elf/Makefile b/elf/Makefile
index 4e45b6729e..9453bfd6bf 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -231,6 +231,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit21 \
 	 tst-audit22 \
 	 tst-audit23 \
+	 tst-audit24a tst-audit24b tst-audit24c tst-audit24d \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -325,6 +326,11 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod21 \
 		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 \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1587,6 +1593,50 @@ $(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
+
 # 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..4540d93913 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
@@ -238,7 +238,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 	      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;
 		}
 	    }
 
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 27f792b7b2..6a53f57146 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -232,9 +232,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))
@@ -283,8 +281,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)
@@ -307,6 +303,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 011e6d645d..666256a215 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -147,7 +147,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)))
@@ -322,7 +322,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-auditmod22.c b/elf/tst-auditmod22.c
index a4921f35de..9b17039a5d 100644
--- a/elf/tst-auditmod22.c
+++ b/elf/tst-auditmod22.c
@@ -41,5 +41,25 @@ la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
   if (map->l_addr == getauxval (AT_SYSINFO_EHDR))
     fprintf (stderr, "vdso found: %" PRIxPTR "\n", (uintptr_t) map->l_addr);
 
-  return 0;
+  return 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)
+{
+  fprintf (stderr, "%s: %s\n", __func__, symname);
+  return sym->st_value;
+}
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+{
+  fprintf (stderr, "%s: %s\n", __func__, symname);
+  return sym->st_value;
+}
+#endif
diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c
new file mode 100644
index 0000000000..4b5cc2ec5e
--- /dev/null
+++ b/elf/tst-auditmod24a.c
@@ -0,0 +1,104 @@
+/* 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>
+
+#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)
+	  {
+	    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))
+	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..33129104c5
--- /dev/null
+++ b/elf/tst-auditmod24b.c
@@ -0,0 +1,99 @@
+/* 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>
+
+#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))
+	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..3ed4c772a2
--- /dev/null
+++ b/elf/tst-auditmod24d.c
@@ -0,0 +1,114 @@
+/* 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 <stdio.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;
+}
+
+#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)
+	return (uintptr_t) tst_audit24dmod3_func1;
+    }
+
+  abort ();
+}
diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h
index c038c31ce6..4ab6187372 100644
--- a/sysdeps/generic/dl-lookupcfg.h
+++ b/sysdeps/generic/dl-lookupcfg.h
@@ -26,3 +26,4 @@
 #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)
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/powerpc/dl-lookupcfg.h b/sysdeps/powerpc/dl-lookupcfg.h
new file mode 100644
index 0000000000..96f5b50e81
--- /dev/null
+++ b/sysdeps/powerpc/dl-lookupcfg.h
@@ -0,0 +1,30 @@
+/* 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)
+#else
+# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#endif
-- 
2.32.0


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v5 19/22] elf: Add LA_SYMB_BINDNOW
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (17 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h Adhemerval Zanella
                   ` (2 subsequent siblings)
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 UTC (permalink / raw)
  To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard

The warn the audit library that la_symbind() is being invoked in a
bind-now manner, a new LA_SYMB_BINDNOW is added.  It warns that
LA_SYMB_NOPLTENTER nor LA_SYMB_NOPLTEXIT has any effect on PLT
tracking.

Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
---
 elf/Makefile          |  22 ++++++++
 elf/dl-audit.c        |   2 +-
 elf/link.h            |   5 +-
 elf/tst-audit25a.c    | 126 +++++++++++++++++++++++++++++++++++++++++
 elf/tst-audit25b.c    | 127 ++++++++++++++++++++++++++++++++++++++++++
 elf/tst-audit25mod1.c |  30 ++++++++++
 elf/tst-audit25mod2.c |  30 ++++++++++
 elf/tst-audit25mod3.c |  22 ++++++++
 elf/tst-audit25mod4.c |  22 ++++++++
 elf/tst-auditmod25.c  |  77 +++++++++++++++++++++++++
 10 files changed, 461 insertions(+), 2 deletions(-)
 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-auditmod25.c

diff --git a/elf/Makefile b/elf/Makefile
index 9453bfd6bf..3172219386 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -232,6 +232,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit22 \
 	 tst-audit23 \
 	 tst-audit24a tst-audit24b tst-audit24c tst-audit24d \
+	 tst-audit25a tst-audit25b \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -331,6 +332,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod24c \
 		tst-auditmod24d tst-audit24dmod1 tst-audit24dmod2 \
 		tst-audit24dmod3 tst-audit24dmod4 \
+		tst-auditmod25 tst-audit25mod1 tst-audit25mod2 \
+		tst-audit25mod3 tst-audit25mod4 \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1637,6 +1640,25 @@ 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 4540d93913..09243a0aa3 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -217,7 +217,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 
   const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]);
 
-  unsigned int flags = 0;
+  unsigned int flags = bindnow ? LA_SYMB_BINDNOW : 0;
   struct audit_ifaces *afct = GLRO(dl_audit);
   for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     {
diff --git a/elf/link.h b/elf/link.h
index 200d40c9c6..67ab2495cc 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -148,8 +148,11 @@ enum
     LA_SYMB_NOPLTEXIT = 0x02,	/* la_pltexit will not be called.  */
     LA_SYMB_STRUCTCALL = 0x04,	/* Return value is a structure.  */
     LA_SYMB_DLSYM = 0x08,	/* Binding due to dlsym call.  */
-    LA_SYMB_ALTVALUE = 0x10	/* Value has been changed by a previous
+    LA_SYMB_ALTVALUE = 0x10,	/* Value has been changed by a previous
 				   la_symbind call.  */
+    LA_SYMB_BINDNOW = 0x20,	/* The symbol is resolved at loading time
+				   and it will not call neither la_pltenter
+				   not la_pltexit.  */
   };
 
 struct dl_phdr_info
diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c
new file mode 100644
index 0000000000..88962091cd
--- /dev/null
+++ b/elf/tst-audit25a.c
@@ -0,0 +1,126 @@
+/* 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_BINDNOW.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod3_func1 32\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_BINDNOW.
+       Also the resolution order is done in breadth-first order.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod4_func1 32\n"
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 32\n"
+			 "la_symbind: tst_audit25mod2_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func2 32\n"
+			 "la_symbind: tst_audit25mod2_func2 32\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..ca441b7ac3
--- /dev/null
+++ b/elf/tst-audit25b.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 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_BINDNOW.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 32\n"
+			 "la_symbind: tst_audit25mod2_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func2 32\n"
+			 "la_symbind: tst_audit25mod2_func2 32\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_BINDNOW.
+       Also the resolution order is done in breadth-first order.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod4_func1 32\n"
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 32\n"
+			 "la_symbind: tst_audit25mod2_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func2 32\n"
+			 "la_symbind: tst_audit25mod2_func2 32\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-auditmod25.c b/elf/tst-auditmod25.c
new file mode 100644
index 0000000000..70b8ec4552
--- /dev/null
+++ b/elf/tst-auditmod25.c
@@ -0,0 +1,77 @@
+/* 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);
+  return sym->st_value;
+}
-- 
2.32.0


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (18 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 19/22] elf: Add LA_SYMB_BINDNOW Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-11 17:42   ` Florian Weimer
  2021-11-09 18:33 ` [PATCH v5 21/22] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
  2021-11-09 18:33 ` [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 UTC (permalink / raw)
  To: libc-alpha, Florian Weimer; +Cc: John Mellor-Crummey, Ben Woodard

No functional change.
---
 bits/link_lavcurrent.h | 25 +++++++++++++++++++++++++
 elf/Makefile           |  2 +-
 elf/link.h             |  2 +-
 3 files changed, 27 insertions(+), 2 deletions(-)
 create mode 100644 bits/link_lavcurrent.h

diff --git a/bits/link_lavcurrent.h b/bits/link_lavcurrent.h
new file mode 100644
index 0000000000..44fbea1e80
--- /dev/null
+++ b/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	1
diff --git a/elf/Makefile b/elf/Makefile
index 3172219386..1a7e851dfa 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -21,7 +21,7 @@ subdir		:= elf
 
 include ../Makeconfig
 
-headers		= elf.h bits/elfclass.h link.h bits/link.h
+headers		= elf.h bits/elfclass.h link.h bits/link.h bits/link_lavcurrent.h
 routines	= $(all-dl-routines) dl-support dl-iteratephdr \
 		  dl-addr dl-addr-obj enbl-secure dl-profstub \
 		  dl-origin dl-libc dl-sym dl-sysdep dl-error \
diff --git a/elf/link.h b/elf/link.h
index 67ab2495cc..debbcd2fcb 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -113,7 +113,7 @@ struct link_map
 #ifdef __USE_GNU
 
 /* Version numbers for la_version handshake interface.  */
-#define LAV_CURRENT	1
+#include <bits/link_lavcurrent.h>
 
 /* Activity types signaled through la_activity.  */
 enum
-- 
2.32.0


^ permalink raw reply	[flat|nested] 57+ messages in thread

* [PATCH v5 21/22] elf: Fix runtime linker auditing on aarch64 (BZ #26643)
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (19 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-09 18:33 ` [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
  21 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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] 57+ messages in thread

* [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit
  2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
                   ` (20 preceding siblings ...)
  2021-11-09 18:33 ` [PATCH v5 21/22] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
@ 2021-11-09 18:33 ` Adhemerval Zanella
  2021-11-10 13:52   ` Florian Weimer
  21 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:33 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, &regs->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        | 296 +++++++++++++++++++++++++
 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, 860 insertions(+), 91 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..6025de64ee 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]
@@ -341,3 +344,296 @@ _dl_runtime_profile:
 	.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  */
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, &regs->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, &regs->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, &regs->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, &regs->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, &regs->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, &regs->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] 57+ messages in thread

* Re: [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061)
  2021-11-09 18:33 ` [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061) Adhemerval Zanella
@ 2021-11-09 18:51   ` H.J. Lu
  2021-11-11 17:24     ` Adhemerval Zanella
  2021-11-10 14:00   ` Florian Weimer
  1 sibling, 1 reply; 57+ messages in thread
From: H.J. Lu @ 2021-11-09 18:51 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: GNU C Library, Florian Weimer, John Mellor-Crummey

On Tue, Nov 9, 2021 at 10:35 AM Adhemerval Zanella via Libc-alpha
<libc-alpha@sourceware.org> wrote:
>
> 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.

Did you mean dlmopen in subject?

> 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 see if the state is
> consistent since it is _dt_main() that reset is.  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-audit19.c    | 25 +++++++++++++++++++
>  elf/tst-auditmod19.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 87 insertions(+), 2 deletions(-)
>  create mode 100644 elf/tst-audit19.c
>  create mode 100644 elf/tst-auditmod19.c
>
> diff --git a/elf/Makefile b/elf/Makefile
> index bd1a0f79b4..96db0b4322 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -226,6 +226,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
>          tst-dlopenfail-2 \
>          tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
>          tst-audit18a tst-audit18b \
> +        tst-audit19 \
>          tst-single_threaded tst-single_threaded-pthread \
>          tst-tls-ie tst-tls-ie-dlmopen argv0test \
>          tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
> @@ -315,6 +316,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
>                 tst-unique2mod1 tst-unique2mod2 \
>                 tst-auditmod9a tst-auditmod9b \
>                 tst-auditmod18a tst-auditmod18b tst-audit18bmod \
> +               tst-auditmod19 \
>                 $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
>                   tst-nodelete-uniquemod tst-nodelete-rtldmod \
>                   tst-nodelete-zmod \
> @@ -1560,6 +1562,9 @@ $(objpfx)tst-audit18b.out: $(objpfx)tst-auditmod18b.so
>  $(objpfx)tst-audit18b: $(objpfx)tst-audit18bmod.so
>  tst-audit18b-ARGS = -- $(host-test-program-cmd)
>
> +$(objpfx)tst-audit19.out: $(objpfx)tst-auditmod19.so
> +tst-audit19-ENV = LD_AUDIT=$(objpfx)tst-auditmod19.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 6ea5dd2457..00f6d8cfcc 100644
> --- a/elf/dl-open.c
> +++ b/elf/dl-open.c
> @@ -932,8 +932,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-audit19.c b/elf/tst-audit19.c
> new file mode 100644
> index 0000000000..6f39ccee86
> --- /dev/null
> +++ b/elf/tst-audit19.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-auditmod19.c b/elf/tst-auditmod19.c
> new file mode 100644
> index 0000000000..c57e50ee4e
> --- /dev/null
> +++ b/elf/tst-auditmod19.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
>


-- 
H.J.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
  2021-11-09 18:33 ` [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
@ 2021-11-10 12:11   ` Florian Weimer
  2021-11-10 19:53     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 12:11 UTC (permalink / raw)
  To: Adhemerval Zanella
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Alexander Monakov

* Adhemerval Zanella:

> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
> index 0d5b727c64..27f792b7b2 100644
> --- a/elf/dl-reloc.c
> +++ b/elf/dl-reloc.c
> @@ -203,11 +203,25 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>    const char *errstring = NULL;
>    int lazy = reloc_mode & RTLD_LAZY;
>    int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
> +  bool consider_symbind = false;

This needs __attribute__ ((unused)) or some fairly complex preprocessor
conditional.  Otherwise, the profiling builds performed by
build-many-glibcs.py fail.

>  #ifdef SHARED
>    /* 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
> @@ -272,7 +286,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 61c260ddb8..b0c788eb22 100644
> --- a/elf/dl-runtime.c
> +++ b/elf/dl-runtime.c
> @@ -44,6 +44,84 @@
>  # define ARCH_FIXUP_ATTRIBUTE
>  #endif
>  
> +#ifdef SHARED
> +static 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)
> +{

Maybe start out with moving this function to elf/dl-audit.c (like it
happens later)?  It will make it easier to review the changes.

What are the actual function changes for _dl_audit_symbind?  The diff
isn't very readable even with diff -uw.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
  2021-11-09 18:33 ` [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
@ 2021-11-10 13:23   ` Florian Weimer
  2021-11-11 18:54     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 13:23 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 4758cb23c4..861e83236e 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile

> +$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21.so
> +tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21.so

This is needed to fix a Hurd build failure:

$(objpfx)tst-audit21: $(shared-thread-library)

> 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/rtld.c b/elf/rtld.c
> index 8953347b00..db1817655f 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;
>  }
>  
>  /* Notify the the audit modules that the object MAP has already been

I'm not sure if this actually works.  As far as I understand it,
everything in an audit namespace needs this special treatment, and not
just the audit module itself.

I think we shuld add a parameter to _dl_allocate_tls_init and that
indicates the initialization should only be applied to objects in the
base namespace.  This way, initialization is also skipped for dlopen'ed
modules in an audit namespace.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit
  2021-11-09 18:33 ` [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
@ 2021-11-10 13:52   ` Florian Weimer
  2021-11-15 17:04     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 13:52 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S
> index 0d540651d4..6025de64ee 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]

I think OFFSET_RG is only defined for !PROF, so this leads to a build
failure:

[…] /home/bmg/build/glibcs/aarch64-linux-gnu/glibc/elf/dl-trampoline.op
../sysdeps/aarch64/dl-trampoline.S: Assembler messages:
../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
[…]

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC
  2021-11-09 18:33 ` [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
@ 2021-11-10 13:55   ` Florian Weimer
  2021-11-11 19:18     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 13:55 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 bad18f2d11..bd1a0f79b4 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -384,6 +384,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

Do we need to check have-mtls-dialect-gnu2 here?

> diff --git a/elf/tst-audit-tlsdesc-audit.c b/elf/tst-audit-tlsdesc-audit.c
> new file mode 100644
> index 0000000000..53993830c9
> --- /dev/null
> +++ b/elf/tst-audit-tlsdesc-audit.c

> +unsigned int
> +la_version (unsigned int version)
> +{
> +  return version;
> +}

Why not LAV_CURRENT?  We should lead by good example.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061)
  2021-11-09 18:33 ` [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061) Adhemerval Zanella
  2021-11-09 18:51   ` H.J. Lu
@ 2021-11-10 14:00   ` Florian Weimer
  2021-11-11 17:29     ` Adhemerval Zanella
  1 sibling, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 14:00 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> So the assert() on _dl_open() can not really see if the state is
> consistent since it is _dt_main() that reset is.  This patch removes
> the assert.

H.J. also mentioned the dlmopen typo.  “since it is _dt_main() that
reset is” seems to have multiple typos, too.

Patch itself looks okay.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-09 18:33 ` [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
@ 2021-11-10 14:15   ` Florian Weimer
  2021-11-11 11:51     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 14:15 UTC (permalink / raw)
  To: Adhemerval Zanella
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra

* Adhemerval Zanella:

> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 9f4fa9617d..72298776f6 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -1067,8 +1067,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>  	  && __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)
> +	  /* Do not call the functions for any auditing object and also do not
> +	     try to call auditing functions if the namespace is currently
> +	     empty.  This happens when opening the first DSO in a new
> +	     namespace.  */
> +	  if (head != NULL && head->l_auditing == 0)
>  	    {
>  	      struct audit_ifaces *afct = GLRO(dl_audit);
>  	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)

As far as I can tell, using GL(dl_ns)[nsid]._ns_loaded for la_activity
is a completely arbitrary choice.  I think we should use
&GL(dl_ns)[nsid] for secondary namespace instead, and keep
GL(dl_ns)[LM_ID_BASE]._ns_loaded for backwards compatibility.

This will allow us to generate an LA_ACT_ADD event for an empty
namespace.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 06/22] elf: Add _dl_audit_objopen
  2021-11-09 18:33 ` [PATCH v5 06/22] elf: Add _dl_audit_objopen Adhemerval Zanella
@ 2021-11-10 16:51   ` Florian Weimer
  0 siblings, 0 replies; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 16:51 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> 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 */

Typos: “is a[n] audit module[]”

Patch looks reasonable, thanks.

Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 07/22] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid
  2021-11-09 18:33 ` [PATCH v5 07/22] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
@ 2021-11-10 16:59   ` Florian Weimer
  0 siblings, 0 replies; 57+ messages in thread
From: Florian Weimer @ 2021-11-10 16:59 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> It consolidates the code required to call la_activity() audit
> callback.

This needs adjustment if we use a different cookie for identifying
namespaces.

Otherwise looks good.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533)
  2021-11-10 12:11   ` Florian Weimer
@ 2021-11-10 19:53     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-10 19:53 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Alexander Monakov



On 10/11/2021 09:11, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
>> index 0d5b727c64..27f792b7b2 100644
>> --- a/elf/dl-reloc.c
>> +++ b/elf/dl-reloc.c
>> @@ -203,11 +203,25 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
>>    const char *errstring = NULL;
>>    int lazy = reloc_mode & RTLD_LAZY;
>>    int skip_ifunc = reloc_mode & __RTLD_NOIFUNC;
>> +  bool consider_symbind = false;
> 
> This needs __attribute__ ((unused)) or some fairly complex preprocessor
> conditional.  Otherwise, the profiling builds performed by
> build-many-glibcs.py fail.

Right, I rarely test with profiling enabled. I will check this out.

> 
>>  #ifdef SHARED
>>    /* 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
>> @@ -272,7 +286,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 61c260ddb8..b0c788eb22 100644
>> --- a/elf/dl-runtime.c
>> +++ b/elf/dl-runtime.c
>> @@ -44,6 +44,84 @@
>>  # define ARCH_FIXUP_ATTRIBUTE
>>  #endif
>>  
>> +#ifdef SHARED
>> +static 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)
>> +{
> 
> Maybe start out with moving this function to elf/dl-audit.c (like it
> happens later)?  It will make it easier to review the changes.

OK, I will refactor the patchset to make the elf/dl-audit.c ones first.

> 
> What are the actual function changes for _dl_audit_symbind?  The diff
> isn't very readable even with diff -uw.

There is none in fact, I move to its own function because it is not used
in two places.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-10 14:15   ` Florian Weimer
@ 2021-11-11 11:51     ` Adhemerval Zanella
  2021-11-11 12:02       ` Florian Weimer
  0 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 11:51 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra



On 10/11/2021 11:15, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>> index 9f4fa9617d..72298776f6 100644
>> --- a/elf/dl-load.c
>> +++ b/elf/dl-load.c
>> @@ -1067,8 +1067,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>>  	  && __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)
>> +	  /* Do not call the functions for any auditing object and also do not
>> +	     try to call auditing functions if the namespace is currently
>> +	     empty.  This happens when opening the first DSO in a new
>> +	     namespace.  */
>> +	  if (head != NULL && head->l_auditing == 0)
>>  	    {
>>  	      struct audit_ifaces *afct = GLRO(dl_audit);
>>  	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
> 
> As far as I can tell, using GL(dl_ns)[nsid]._ns_loaded for la_activity
> is a completely arbitrary choice.  I think we should use
> &GL(dl_ns)[nsid] for secondary namespace instead, and keep
> GL(dl_ns)[LM_ID_BASE]._ns_loaded for backwards compatibility.
> 
> This will allow us to generate an LA_ACT_ADD event for an empty
> namespace.

I am not really following you here, '&GL(dl_ns)[nsid]' is just the container
here, we need to iterate over the 'link_maps' within it.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-11 11:51     ` Adhemerval Zanella
@ 2021-11-11 12:02       ` Florian Weimer
  2021-11-11 12:25         ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 12:02 UTC (permalink / raw)
  To: Adhemerval Zanella
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra

* Adhemerval Zanella:

> On 10/11/2021 11:15, Florian Weimer wrote:
>> * Adhemerval Zanella:
>> 
>>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>>> index 9f4fa9617d..72298776f6 100644
>>> --- a/elf/dl-load.c
>>> +++ b/elf/dl-load.c
>>> @@ -1067,8 +1067,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>>>  	  && __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)
>>> +	  /* Do not call the functions for any auditing object and also do not
>>> +	     try to call auditing functions if the namespace is currently
>>> +	     empty.  This happens when opening the first DSO in a new
>>> +	     namespace.  */
>>> +	  if (head != NULL && head->l_auditing == 0)
>>>  	    {
>>>  	      struct audit_ifaces *afct = GLRO(dl_audit);
>>>  	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
>> 
>> As far as I can tell, using GL(dl_ns)[nsid]._ns_loaded for la_activity
>> is a completely arbitrary choice.  I think we should use
>> &GL(dl_ns)[nsid] for secondary namespace instead, and keep
>> GL(dl_ns)[LM_ID_BASE]._ns_loaded for backwards compatibility.
>> 
>> This will allow us to generate an LA_ACT_ADD event for an empty
>> namespace.
>
> I am not really following you here, '&GL(dl_ns)[nsid]' is just the container
> here, we need to iterate over the 'link_maps' within it.

Hmm.  I had a peeked at the Solaris documentation, and it says that
LA_ACT_ADD uses the head link map of the namespace as a cookie.

I really dislike that we produce a LA_ACT_DELETE without the
corresponding LA_ACT_ADD due to this issue.

Can we use the link map allocated used _dl_new_object as the cookie if
the namespace is empty?  This seems like the right thing to do here.
The allocation happens just a few lines further down.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-11 12:02       ` Florian Weimer
@ 2021-11-11 12:25         ` Adhemerval Zanella
  2021-11-11 12:33           ` Florian Weimer
  0 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 12:25 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra



On 11/11/2021 09:02, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> On 10/11/2021 11:15, Florian Weimer wrote:
>>> * Adhemerval Zanella:
>>>
>>>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>>>> index 9f4fa9617d..72298776f6 100644
>>>> --- a/elf/dl-load.c
>>>> +++ b/elf/dl-load.c
>>>> @@ -1067,8 +1067,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
>>>>  	  && __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)
>>>> +	  /* Do not call the functions for any auditing object and also do not
>>>> +	     try to call auditing functions if the namespace is currently
>>>> +	     empty.  This happens when opening the first DSO in a new
>>>> +	     namespace.  */
>>>> +	  if (head != NULL && head->l_auditing == 0)
>>>>  	    {
>>>>  	      struct audit_ifaces *afct = GLRO(dl_audit);
>>>>  	      for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
>>>
>>> As far as I can tell, using GL(dl_ns)[nsid]._ns_loaded for la_activity
>>> is a completely arbitrary choice.  I think we should use
>>> &GL(dl_ns)[nsid] for secondary namespace instead, and keep
>>> GL(dl_ns)[LM_ID_BASE]._ns_loaded for backwards compatibility.
>>>
>>> This will allow us to generate an LA_ACT_ADD event for an empty
>>> namespace.
>>
>> I am not really following you here, '&GL(dl_ns)[nsid]' is just the container
>> here, we need to iterate over the 'link_maps' within it.
> 
> Hmm.  I had a peeked at the Solaris documentation, and it says that
> LA_ACT_ADD uses the head link map of the namespace as a cookie.
> 
> I really dislike that we produce a LA_ACT_DELETE without the
> corresponding LA_ACT_ADD due to this issue.
> 
> Can we use the link map allocated used _dl_new_object as the cookie if
> the namespace is empty?  This seems like the right thing to do here.
> The allocation happens just a few lines further down.

But afaiu the LA_ACT_ADD activity is to inform already loaded objects
that a new object is being processed.  Both man-pages and Solaris
documentation states 'objects are *being added*...', so I think passing
the cookie of the new allocated is not what the interface is suppose
to do.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency
  2021-11-09 18:33 ` [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
@ 2021-11-11 12:30   ` Florian Weimer
  2021-11-12 19:02     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 12:30 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
>
> Checked on x86_64-linux-gnu.
> ---
>  elf/dl-load.c            | 9 +++++++--
>  elf/dso-sort-tests-1.def | 5 ++++-
>  2 files changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/elf/dl-load.c b/elf/dl-load.c
> index 4a0ff9d010..d585e1795d 100644
> --- a/elf/dl-load.c
> +++ b/elf/dl-load.c
> @@ -1998,13 +1998,18 @@ _dl_map_object (struct link_map *loader, const char *name,
>    assert (nsid >= 0);
>    assert (nsid < GL(dl_nns));
>  
> +  /* Special case: trying to map itself.  */
> +  if (name[0] == '\0')
> +    return GL(dl_ns)[nsid]._ns_loaded;

Can you expand the comment a bit?  As far as I can see, "" corresponds
to a NULL argument for dlopen, and we interpret that as returning the
head object of the namespace.  The head link map must exist because the
dlopen call with NULL/"" has to come from some.

Do you know if we have explict tests for this behavior?

The change itself looks okay.  The reference count is updated by the
caller in elf/dl-open.c.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-11 12:25         ` Adhemerval Zanella
@ 2021-11-11 12:33           ` Florian Weimer
  2021-11-11 13:02             ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 12:33 UTC (permalink / raw)
  To: Adhemerval Zanella
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra

* Adhemerval Zanella:

>> Hmm.  I had a peeked at the Solaris documentation, and it says that
>> LA_ACT_ADD uses the head link map of the namespace as a cookie.
>> 
>> I really dislike that we produce a LA_ACT_DELETE without the
>> corresponding LA_ACT_ADD due to this issue.
>> 
>> Can we use the link map allocated used _dl_new_object as the cookie if
>> the namespace is empty?  This seems like the right thing to do here.
>> The allocation happens just a few lines further down.
>
> But afaiu the LA_ACT_ADD activity is to inform already loaded objects
> that a new object is being processed.  Both man-pages and Solaris
> documentation states 'objects are *being added*...', so I think passing
> the cookie of the new allocated is not what the interface is suppose
> to do.

It's the only way to get a matching LA_ACT_DELETE call with the same
cookie.  It's not particularly clean, I agree, but I think it's better
than a dropped LA_ACT_ADD.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 16/22] elf: Add main application on main_map l_name
  2021-11-09 18:33 ` [PATCH v5 16/22] elf: Add main application on main_map l_name Adhemerval Zanella
@ 2021-11-11 12:39   ` Florian Weimer
  2021-11-12 19:30     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 12:39 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.

_dl_argv[0] is not a path name.

After “bash -c 'exec -a not-a-real-path cat'”, we have this:

(gdb) print _dl_argv[0]
$1 = 0x7ffc1feaf3de "not-a-real-path"

I think dladdr is wrong to use this as a path.

I think in practice l_name == "" means that the link map is for the main
executable.  This seems particularly relevant given that the public part
of the link map does not expose lt_executable.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 17/22] elf: Add la_activity during application exit
  2021-11-09 18:33 ` [PATCH v5 17/22] elf: Add la_activity during application exit Adhemerval Zanella
@ 2021-11-11 12:50   ` Florian Weimer
  2021-11-12 19:32     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 12:50 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> la_activity() is not called during application exit, even though
> la_objclose is.

Patch looks okay to me.

Just a nit:


> diff --git a/elf/tst-auditmod23.c b/elf/tst-auditmod23.c
> new file mode 100644
> index 0000000000..20ef19945d
> --- /dev/null
> +++ b/elf/tst-auditmod23.c

> +  if (map_desc == NULL)
> +    abort();

Missing space.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062)
  2021-11-11 12:33           ` Florian Weimer
@ 2021-11-11 13:02             ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 13:02 UTC (permalink / raw)
  To: Florian Weimer
  Cc: libc-alpha, John Mellor-Crummey, Ben Woodard, Vivek Das Mohapatra



On 11/11/2021 09:33, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>>> Hmm.  I had a peeked at the Solaris documentation, and it says that
>>> LA_ACT_ADD uses the head link map of the namespace as a cookie.
>>>
>>> I really dislike that we produce a LA_ACT_DELETE without the
>>> corresponding LA_ACT_ADD due to this issue.
>>>
>>> Can we use the link map allocated used _dl_new_object as the cookie if
>>> the namespace is empty?  This seems like the right thing to do here.
>>> The allocation happens just a few lines further down.
>>
>> But afaiu the LA_ACT_ADD activity is to inform already loaded objects
>> that a new object is being processed.  Both man-pages and Solaris
>> documentation states 'objects are *being added*...', so I think passing
>> the cookie of the new allocated is not what the interface is suppose
>> to do.
> 
> It's the only way to get a matching LA_ACT_DELETE call with the same
> cookie.  It's not particularly clean, I agree, but I think it's better
> than a dropped LA_ACT_ADD.

I think we can move the la_activity (LA_ACT_ADD) *after*
_dl_add_to_namespace_list() on _dl_map_object_from_fd(), so the 
GL(dl_ns)[nsid]._ns_loaded is always valid and it will call both
LA_ACT_ADD and LA_ACT_DELETE will a consistent set of cookies.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061)
  2021-11-09 18:51   ` H.J. Lu
@ 2021-11-11 17:24     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 17:24 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library, Florian Weimer, John Mellor-Crummey



On 09/11/2021 15:51, H.J. Lu wrote:
> On Tue, Nov 9, 2021 at 10:35 AM Adhemerval Zanella via Libc-alpha
> <libc-alpha@sourceware.org> wrote:
>>
>> 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.
> 
> Did you mean dlmopen in subject?

Yes, I have fixed it.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061)
  2021-11-10 14:00   ` Florian Weimer
@ 2021-11-11 17:29     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 17:29 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 10/11/2021 11:00, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> So the assert() on _dl_open() can not really see if the state is
>> consistent since it is _dt_main() that reset is.  This patch removes
>> the assert.
> 
> H.J. also mentioned the dlmopen typo.  “since it is _dt_main() that
> reset is” seems to have multiple typos, too.

Ack.

> 
> Patch itself looks okay.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734)
  2021-11-09 18:33 ` [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
@ 2021-11-11 17:39   ` Florian Weimer
  2021-11-15 14:20     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 17:39 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> 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 ODP (for lazy binding
> this is done by PPC64_LOAD_FUNCPTR on _dl_runtime_resolve).

Typo: OPD (I think)

This needs updates to sysdeps/hppa/dl-lookupcfg.h and
sysdeps/ia64/dl-lookupcfg.h as well.  Presently these two targets fail
to build.

> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
> index c3569cb357..4540d93913 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
> @@ -238,7 +238,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
>  	      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;
>  		}
>  	    }

I think if PLT enter/exit hooks are not available, we should set
LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT in flags before calling the
symbind callback.

I find DL_FIXUP_BINDNOW_ADDR_VALUE very confusing.  Why is it safe to
extract just the code address from the function descriptor?

In the future, I want to call symbind for all symbol bindings.
Basically, I want to remove

> +	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT

eventually, and add symbind callbacks for dlsym lookups.  Hopefully we
can make these changes compatible.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h
  2021-11-09 18:33 ` [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h Adhemerval Zanella
@ 2021-11-11 17:42   ` Florian Weimer
  2021-11-15 14:21     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 17:42 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> No functional change.
> ---
>  bits/link_lavcurrent.h | 25 +++++++++++++++++++++++++
>  elf/Makefile           |  2 +-
>  elf/link.h             |  2 +-
>  3 files changed, 27 insertions(+), 2 deletions(-)
>  create mode 100644 bits/link_lavcurrent.h

Looks okay.  I think this can go in right now.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO
  2021-11-09 18:33 ` [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
@ 2021-11-11 17:50   ` Florian Weimer
  2021-11-11 20:16     ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-11 17:50 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

> +static int
> +handle_restart (void)
> +{
> +  fprintf (stderr, "vdso: %" PRIxPTR "\n", vdso_addr);
> +  return 0;
> +}
> +
> +static unsigned long int
> +parse_address (const char *str)
> +{
> +  char *endptr;
> +  long int ret;
> +  errno = 0;
> +  ret = strtol (str, &endptr, 10);
> +  TEST_COMPARE (errno, 0);
> +  TEST_VERIFY (ret >= 0 && ret <= INT_MAX);
> +  return ret;
> +}

Doesn't parse_address always produce 0 fpr PRIxPTR values because
reading stops at the 'x'?  Maybe use printf and scanf with %p instead?

The rest of the patch looks okay to me.  Placement of the audit call
seems reasonable.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
  2021-11-10 13:23   ` Florian Weimer
@ 2021-11-11 18:54     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 18:54 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 10/11/2021 10:23, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> diff --git a/elf/Makefile b/elf/Makefile
>> index 4758cb23c4..861e83236e 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
> 
>> +$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21.so
>> +tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21.so
> 
> This is needed to fix a Hurd build failure:
> 
> $(objpfx)tst-audit21: $(shared-thread-library)

Ack.

> 
>> 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/rtld.c b/elf/rtld.c
>> index 8953347b00..db1817655f 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;
>>  }
>>  
>>  /* Notify the the audit modules that the object MAP has already been
> 
> I'm not sure if this actually works.  As far as I understand it,
> everything in an audit namespace needs this special treatment, and not
> just the audit module itself.

Yes, and since each audit modules is loaded with LM_ID_NEWLM it means
all its dependencies.  Adding some instrumentation, it works on the audit
modules does have some dependencies:

$ ldd /home/azanella/Projects/glibc/build/x86_64-linux-gnu/elf/tst-auditmod21a.so
        linux-vdso.so.1 (0x00007fff4a172000)
        /home/azanella/Projects/glibc/build/x86_64-linux-gnu/elf/tst-auditmod21b.so (0x00007fcd11fa5000)
        libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fcd11d61000)
        /lib64/ld-linux-x86-64.so.2 (0x00007fcd11fb1000)

$ LD_AUDIT=elf/tst-auditmod21a.so elf/ld.so --library-path . elf/tst-audit21
   2281374:     [../elf/dl-tls.c:603] map->l_name= l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=elf/tst-auditmod21a.so l_dont_set_tls_static=1
   2281374:     [../elf/dl-tls.c:603] map->l_name=/home/azanella/Projects/glibc/build/x86_64-linux-gnu/elf/tst-auditmod21b.so l_dont_set_tls_static=1
   2281374:     [../elf/dl-tls.c:603] map->l_name=./libc.so.6 l_dont_set_tls_static=1
   2281374:     [../elf/dl-tls.c:603] map->l_name=/home/azanella/Projects/glibc/build/x86_64-linux-gnu/elf/tst-auditmod21c.so l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=./libc.so.6 l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name= l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=elf/tst-auditmod21a.so l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=/home/azanella/Projects/glibc/build/x86_64-linux-gnu/elf/tst-auditmod21b.so l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=./libc.so.6 l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=/home/azanella/Projects/glibc/build/x86_64-linux-gnu/elf/tst-auditmod21c.so l_dont_set_tls_static=0
   2281374:     [../elf/dl-tls.c:603] map->l_name=./libc.so.6 l_dont_set_tls_static=0

The l_dont_set_tls_static should be set for the audit module and its
dependencies.

> 
> I think we shuld add a parameter to _dl_allocate_tls_init and that
> indicates the initialization should only be applied to objects in the
> base namespace.  This way, initialization is also skipped for dlopen'ed
> modules in an audit namespace.

I am not sure if this would be best solution, I will check whether 
dlopen does work with this patch.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC
  2021-11-10 13:55   ` Florian Weimer
@ 2021-11-11 19:18     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 19:18 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 10/11/2021 10:55, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> diff --git a/elf/Makefile b/elf/Makefile
>> index bad18f2d11..bd1a0f79b4 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -384,6 +384,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
> 
> Do we need to check have-mtls-dialect-gnu2 here?

It already does (line 387 above).

> 
>> diff --git a/elf/tst-audit-tlsdesc-audit.c b/elf/tst-audit-tlsdesc-audit.c
>> new file mode 100644
>> index 0000000000..53993830c9
>> --- /dev/null
>> +++ b/elf/tst-audit-tlsdesc-audit.c
> 
>> +unsigned int
>> +la_version (unsigned int version)
>> +{
>> +  return version;
>> +}
> 
> Why not LAV_CURRENT?  We should lead by good example.

Ack.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO
  2021-11-11 17:50   ` Florian Weimer
@ 2021-11-11 20:16     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-11 20:16 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 11/11/2021 14:50, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> +static int
>> +handle_restart (void)
>> +{
>> +  fprintf (stderr, "vdso: %" PRIxPTR "\n", vdso_addr);
>> +  return 0;
>> +}
>> +
>> +static unsigned long int
>> +parse_address (const char *str)
>> +{
>> +  char *endptr;
>> +  long int ret;
>> +  errno = 0;
>> +  ret = strtol (str, &endptr, 10);
>> +  TEST_COMPARE (errno, 0);
>> +  TEST_VERIFY (ret >= 0 && ret <= INT_MAX);
>> +  return ret;
>> +}
> 
> Doesn't parse_address always produce 0 fpr PRIxPTR values because
> reading stops at the 'x'?  Maybe use printf and scanf with %p instead?

It is indeed better, I will change it.

> 
> The rest of the patch looks okay to me.  Placement of the audit call
> seems reasonable.
> 
> Thanks,
> Florian
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency
  2021-11-11 12:30   ` Florian Weimer
@ 2021-11-12 19:02     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-12 19:02 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 11/11/2021 09:30, 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
>>
>> Checked on x86_64-linux-gnu.
>> ---
>>  elf/dl-load.c            | 9 +++++++--
>>  elf/dso-sort-tests-1.def | 5 ++++-
>>  2 files changed, 11 insertions(+), 3 deletions(-)
>>
>> diff --git a/elf/dl-load.c b/elf/dl-load.c
>> index 4a0ff9d010..d585e1795d 100644
>> --- a/elf/dl-load.c
>> +++ b/elf/dl-load.c
>> @@ -1998,13 +1998,18 @@ _dl_map_object (struct link_map *loader, const char *name,
>>    assert (nsid >= 0);
>>    assert (nsid < GL(dl_nns));
>>  
>> +  /* Special case: trying to map itself.  */
>> +  if (name[0] == '\0')
>> +    return GL(dl_ns)[nsid]._ns_loaded;
> 
> Can you expand the comment a bit?  As far as I can see, "" corresponds
> to a NULL argument for dlopen, and we interpret that as returning the
> head object of the namespace.  The head link map must exist because the
> dlopen call with NULL/"" has to come from some.

I have changed to:

  /* 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.  */

> 
> Do you know if we have explict tests for this behavior?

Yes, dlfcn/tststatic4 (I have to add this special case for this).

> 
> The change itself looks okay.  The reference count is updated by the
> caller in elf/dl-open.c.
> 
> Thanks,
> Florian
> 

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 16/22] elf: Add main application on main_map l_name
  2021-11-11 12:39   ` Florian Weimer
@ 2021-11-12 19:30     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-12 19:30 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 11/11/2021 09:39, 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.
> 
> _dl_argv[0] is not a path name.
> 
> After “bash -c 'exec -a not-a-real-path cat'”, we have this:
> 
> (gdb) print _dl_argv[0]
> $1 = 0x7ffc1feaf3de "not-a-real-path"

This is what program_invocation_name/__progname  (initialized at __init_misc())
assumes.  I think it is a fair assumption, since by convention the first string 
in argv on execve() is the filename associated with the file being executed.

Also, if users really want something different to use as the program name
they can use argv[0] which will be aligned in the various APIs.

> 
> I think dladdr is wrong to use this as a path.

I don't think so, glibc itself uses it in multiples places to get the 
program name and also exports program_invocation_name/program_invocation_short_name
as GNU extensions.  Another option would to read /proc/self/cmdline, but I don'
think this would be really an improvement (and it is not easily override by
the users).

> 
> I think in practice l_name == "" means that the link map is for the main
> executable.  This seems particularly relevant given that the public part
> of the link map does not expose lt_executable.

This is one reason I consider to not expose this in the link_map, however I
still think to align la_objopen(), dladdr() and dlinfo() seems to be a better
QoI than asking users to check program_invocation_name.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 17/22] elf: Add la_activity during application exit
  2021-11-11 12:50   ` Florian Weimer
@ 2021-11-12 19:32     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-12 19:32 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 11/11/2021 09:50, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> la_activity() is not called during application exit, even though
>> la_objclose is.
> 
> Patch looks okay to me.
> 
> Just a nit:
> 
> 
>> diff --git a/elf/tst-auditmod23.c b/elf/tst-auditmod23.c
>> new file mode 100644
>> index 0000000000..20ef19945d
>> --- /dev/null
>> +++ b/elf/tst-auditmod23.c
> 
>> +  if (map_desc == NULL)
>> +    abort();
> 
> Missing space.

Ack.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734)
  2021-11-11 17:39   ` Florian Weimer
@ 2021-11-15 14:20     ` Adhemerval Zanella
  2021-11-15 14:23       ` Florian Weimer
  0 siblings, 1 reply; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 14:20 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 11/11/2021 14:39, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> 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 ODP (for lazy binding
>> this is done by PPC64_LOAD_FUNCPTR on _dl_runtime_resolve).
> 
> Typo: OPD (I think)
>

Ack.
 
> This needs updates to sysdeps/hppa/dl-lookupcfg.h and
> sysdeps/ia64/dl-lookupcfg.h as well.  Presently these two targets fail
> to build.

I have fixed and also tested on ia64 (which leads to some fixed on
other new audit tests). I am still figuring out why hppa fails.

> 
>> diff --git a/elf/dl-audit.c b/elf/dl-audit.c
>> index c3569cb357..4540d93913 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
>> @@ -238,7 +238,8 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
>>  	      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;
>>  		}
>>  	    }
> 
> I think if PLT enter/exit hooks are not available, we should set
> LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT in flags before calling the
> symbind callback.

It does make sense indeed.

> 
> I find DL_FIXUP_BINDNOW_ADDR_VALUE very confusing.  Why is it safe to
> extract just the code address from the function descriptor?

That's my understanding because at this point st.st_value points to code
address, not OPD address.

> 
> In the future, I want to call symbind for all symbol bindings.
> Basically, I want to remove
> 
>> +	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
> 
> eventually, and add symbind callbacks for dlsym lookups.  Hopefully we
> can make these changes compatible.

I think we will need still handle powerpc64 ELFv1 OPD, but I think it should
be feasible.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h
  2021-11-11 17:42   ` Florian Weimer
@ 2021-11-15 14:21     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 14:21 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 11/11/2021 14:42, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> No functional change.
>> ---
>>  bits/link_lavcurrent.h | 25 +++++++++++++++++++++++++
>>  elf/Makefile           |  2 +-
>>  elf/link.h             |  2 +-
>>  3 files changed, 27 insertions(+), 2 deletions(-)
>>  create mode 100644 bits/link_lavcurrent.h
> 
> Looks okay.  I think this can go in right now.

Alright, I will push this before send a newer version.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734)
  2021-11-15 14:20     ` Adhemerval Zanella
@ 2021-11-15 14:23       ` Florian Weimer
  2021-11-15 15:54         ` Adhemerval Zanella
  0 siblings, 1 reply; 57+ messages in thread
From: Florian Weimer @ 2021-11-15 14:23 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard

* Adhemerval Zanella:

>> I find DL_FIXUP_BINDNOW_ADDR_VALUE very confusing.  Why is it safe to
>> extract just the code address from the function descriptor?
>
> That's my understanding because at this point st.st_value points to code
> address, not OPD address.

But the resulting function descriptor will not contain the right TOC
address, I think.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734)
  2021-11-15 14:23       ` Florian Weimer
@ 2021-11-15 15:54         ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 15:54 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 15/11/2021 11:23, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>>> I find DL_FIXUP_BINDNOW_ADDR_VALUE very confusing.  Why is it safe to
>>> extract just the code address from the function descriptor?
>>
>> That's my understanding because at this point st.st_value points to code
>> address, not OPD address.
> 
> But the resulting function descriptor will not contain the right TOC
> address, I think.

Right, we need to update the toc in such case, as elf_machine_fixup_plt
does for _dl_fixup. I will fix it.

^ permalink raw reply	[flat|nested] 57+ messages in thread

* Re: [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit
  2021-11-10 13:52   ` Florian Weimer
@ 2021-11-15 17:04     ` Adhemerval Zanella
  0 siblings, 0 replies; 57+ messages in thread
From: Adhemerval Zanella @ 2021-11-15 17:04 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha, John Mellor-Crummey, Ben Woodard



On 10/11/2021 10:52, Florian Weimer wrote:
> * Adhemerval Zanella:
> 
>> diff --git a/sysdeps/aarch64/dl-trampoline.S b/sysdeps/aarch64/dl-trampoline.S
>> index 0d540651d4..6025de64ee 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]
> 
> I think OFFSET_RG is only defined for !PROF, so this leads to a build
> failure:
> 
> […] /home/bmg/build/glibcs/aarch64-linux-gnu/glibc/elf/dl-trampoline.op
> ../sysdeps/aarch64/dl-trampoline.S: Assembler messages:
> ../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
> ../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
> ../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
> ../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
> ../sysdeps/aarch64/dl-trampoline.S:503: Error: undefined symbol OFFSET_RG used as an immediate value
> […]

Thanks for catching it, in fact _dl_runtime_profile_sve should only be built for !PROF.

^ permalink raw reply	[flat|nested] 57+ messages in thread

end of thread, other threads:[~2021-11-15 17:04 UTC | newest]

Thread overview: 57+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-11-09 18:33 [PATCH v5 00/22] Multiple rtld-audit fixes Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 01/22] elf: Avoid unnecessary slowdown from profiling with audit (BZ#15533) Adhemerval Zanella
2021-11-10 12:11   ` Florian Weimer
2021-11-10 19:53     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 02/22] elf: Add audit tests for modules with TLSDESC Adhemerval Zanella
2021-11-10 13:55   ` Florian Weimer
2021-11-11 19:18     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 03/22] elf: Do not fail for failed dlopem on audit modules (BZ #28061) Adhemerval Zanella
2021-11-09 18:51   ` H.J. Lu
2021-11-11 17:24     ` Adhemerval Zanella
2021-11-10 14:00   ` Florian Weimer
2021-11-11 17:29     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 04/22] elf: Suppress audit calls when a (new) namespace is empty (BZ #28062) Adhemerval Zanella
2021-11-10 14:15   ` Florian Weimer
2021-11-11 11:51     ` Adhemerval Zanella
2021-11-11 12:02       ` Florian Weimer
2021-11-11 12:25         ` Adhemerval Zanella
2021-11-11 12:33           ` Florian Weimer
2021-11-11 13:02             ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 05/22] elf: Fix initial-exec TLS access on audit modules (BZ #28096) Adhemerval Zanella
2021-11-10 13:23   ` Florian Weimer
2021-11-11 18:54     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 06/22] elf: Add _dl_audit_objopen Adhemerval Zanella
2021-11-10 16:51   ` Florian Weimer
2021-11-09 18:33 ` [PATCH v5 07/22] elf: Add _dl_audit_activity_map and _dl_audit_activity_nsid Adhemerval Zanella
2021-11-10 16:59   ` Florian Weimer
2021-11-09 18:33 ` [PATCH v5 08/22] elf: Add _dl_audit_objsearch Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 09/22] elf: Add _dl_audit_objclose Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 10/22] elf: Add _dl_audit_symbind_alt and _dl_audit_symbind Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 11/22] elf: Add _dl_audit_preinit Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 12/22] elf: Add _dl_audit_pltenter Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 13/22] elf: Add _dl_audit_pltexit Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 14/22] elf: Issue audit la_objopen() for vDSO Adhemerval Zanella
2021-11-11 17:50   ` Florian Weimer
2021-11-11 20:16     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 15/22] elf: Run constructors if executable has a soname of a dependency Adhemerval Zanella
2021-11-11 12:30   ` Florian Weimer
2021-11-12 19:02     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 16/22] elf: Add main application on main_map l_name Adhemerval Zanella
2021-11-11 12:39   ` Florian Weimer
2021-11-12 19:30     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 17/22] elf: Add la_activity during application exit Adhemerval Zanella
2021-11-11 12:50   ` Florian Weimer
2021-11-12 19:32     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 18/22] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
2021-11-11 17:39   ` Florian Weimer
2021-11-15 14:20     ` Adhemerval Zanella
2021-11-15 14:23       ` Florian Weimer
2021-11-15 15:54         ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 19/22] elf: Add LA_SYMB_BINDNOW Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 20/22] elf: Move LAV_CURRENT to link_lavcurrent.h Adhemerval Zanella
2021-11-11 17:42   ` Florian Weimer
2021-11-15 14:21     ` Adhemerval Zanella
2021-11-09 18:33 ` [PATCH v5 21/22] elf: Fix runtime linker auditing on aarch64 (BZ #26643) Adhemerval Zanella
2021-11-09 18:33 ` [RFC v5 22/22] elf: Add SVE support for aarch64 rtld-audit Adhemerval Zanella
2021-11-10 13:52   ` Florian Weimer
2021-11-15 17:04     ` Adhemerval Zanella

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).