public inbox for glibc-cvs@sourceware.org
help / color / mirror / Atom feed
* [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734)
@ 2021-07-30 19:25 Adhemerval Zanella
  0 siblings, 0 replies; 6+ messages in thread
From: Adhemerval Zanella @ 2021-07-30 19:25 UTC (permalink / raw)
  To: glibc-cvs

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

commit c3efe8e00969fa869a58d7ef59bba19ac3116d2b
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Jul 28 10:03:00 2021 -0300

    elf: Issue la_symbind() for bind-now (BZ #23734)
    
    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).
    
    Checked on x86_64-linux-gnu and aarch64-linux-gnu.

Diff:
---
 elf/Makefile           |  50 ++++++++++++++++++++++
 elf/dl-reloc.c         |   8 ++--
 elf/do-rel.h           |  62 +++++++++++++++++++++------
 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 +++++++++++++++++++++++++++++++++++++++++++++++++
 20 files changed, 780 insertions(+), 20 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index bbe59176b2..bfed7043a5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -227,6 +227,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 \
@@ -314,6 +315,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 \
@@ -1537,6 +1543,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-reloc.c b/elf/dl-reloc.c
index c6bc1e6b4e..fb47b5939f 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -206,9 +206,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))
@@ -286,8 +284,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 
 #include "dynamic-link.h"
 
-    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
-
 #ifndef PROF
     if (consider_profiling | consider_symbind
 	&& l->l_info[DT_PLTRELSZ] != NULL)
@@ -310,6 +306,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	  }
       }
 #endif
+
+    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
   }
 
   /* Mark the object so we know this work has been done.  */
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 321ac2b359..455e6a8b2e 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,
 	  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)
 		{
@@ -132,11 +141,18 @@ elf_dynamic_do_Rel (struct link_map *map,
 		  continue;
 		}
 #endif
-
-	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
-	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
-			       &map->l_versions[ndx],
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&sym, rversion, ELF_MACHINE_JMP_SLOT);
+		  if (sym != NULL)
+		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+				       r_addr_arg, sym_map);
+		}
+#endif
 	    }
 
 #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
@@ -157,18 +173,36 @@ elf_dynamic_do_Rel (struct link_map *map,
 #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, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&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);
+		}
+# 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 ();
+}


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

* [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734)
@ 2021-11-16 13:58 Adhemerval Zanella
  0 siblings, 0 replies; 6+ messages in thread
From: Adhemerval Zanella @ 2021-11-16 13:58 UTC (permalink / raw)
  To: glibc-cvs

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

commit 8282d4d0bb3be36af6f0fbc4eb331807522084b6
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Jul 28 10:03:00 2021 -0300

    elf: Issue la_symbind() for bind-now (BZ #23734)
    
    The audit callback is not called for binaries built with -Wl,-z,now or
    when LD_BIND_NOW=1 is used.  The PLT tracking callbacks are still not
    issue for such case, since this will would change the expected program
    semantic (where no PTL is expected) and also yield performance
    implications (such as for BZ#15533).
    
    To handle powerpc64 ELFv1 function descriptor, _dl_audit_symbind()
    requires to know whether bind-now is used so the symbol value is
    updated to function text segment instead of the OPD (for lazy binding
    this is done by PPC64_LOAD_FUNCPTR on _dl_runtime_resolve).
    
    Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
    powerpc64-linux-gnu.

Diff:
---
 elf/Makefile                   |  86 +++++++++++++++++++++++++++
 elf/dl-audit.c                 |  19 +++---
 elf/dl-reloc.c                 |   8 +--
 elf/dl-runtime.c               |   4 +-
 elf/do-rel.h                   |  65 ++++++++++++++++-----
 elf/tst-audit24a.c             |  36 ++++++++++++
 elf/tst-audit24amod1.c         |  31 ++++++++++
 elf/tst-audit24amod2.c         |  25 ++++++++
 elf/tst-audit24b.c             |  37 ++++++++++++
 elf/tst-audit24bmod1.c         |  31 ++++++++++
 elf/tst-audit24bmod2.c         |  23 ++++++++
 elf/tst-audit24c.c             |   2 +
 elf/tst-audit24d.c             |  36 ++++++++++++
 elf/tst-audit24dmod1.c         |  33 +++++++++++
 elf/tst-audit24dmod2.c         |  28 +++++++++
 elf/tst-audit24dmod3.c         |  31 ++++++++++
 elf/tst-audit24dmod4.c         |  25 ++++++++
 elf/tst-audit25a.c             | 127 ++++++++++++++++++++++++++++++++++++++++
 elf/tst-audit25b.c             | 128 +++++++++++++++++++++++++++++++++++++++++
 elf/tst-audit25mod1.c          |  30 ++++++++++
 elf/tst-audit25mod2.c          |  30 ++++++++++
 elf/tst-audit25mod3.c          |  22 +++++++
 elf/tst-audit25mod4.c          |  22 +++++++
 elf/tst-auditmod24.h           |  29 ++++++++++
 elf/tst-auditmod24a.c          | 113 ++++++++++++++++++++++++++++++++++++
 elf/tst-auditmod24b.c          | 103 +++++++++++++++++++++++++++++++++
 elf/tst-auditmod24c.c          |   3 +
 elf/tst-auditmod24d.c          | 119 ++++++++++++++++++++++++++++++++++++++
 elf/tst-auditmod25.c           |  78 +++++++++++++++++++++++++
 sysdeps/generic/dl-lookupcfg.h |   3 +
 sysdeps/generic/ldsodefs.h     |   2 +-
 sysdeps/hppa/dl-lookupcfg.h    |   3 +
 sysdeps/ia64/dl-lookupcfg.h    |   3 +
 sysdeps/powerpc/dl-lookupcfg.h |  39 +++++++++++++
 34 files changed, 1344 insertions(+), 30 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index ee4daae0fc..acce163078 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -237,6 +237,12 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit21 \
 	 tst-audit22 \
 	 tst-audit23 \
+	 tst-audit24a \
+	 tst-audit24b \
+	 tst-audit24c \
+	 tst-audit24d \
+	 tst-audit25a \
+	 tst-audit25b \
 #	 reldep9
 tests-internal += loadtest unload unload2 circleload1 \
 	 neededtest neededtest2 neededtest3 neededtest4 \
@@ -388,6 +394,23 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod22 \
 		tst-auditmod23 \
 		tst-audit23mod \
+		tst-auditmod24a \
+		tst-audit24amod1 \
+		tst-audit24amod2 \
+		tst-auditmod24b \
+		tst-audit24bmod1 \
+		tst-audit24bmod2 \
+		tst-auditmod24c \
+		tst-auditmod24d \
+		tst-audit24dmod1 \
+		tst-audit24dmod2 \
+		tst-audit24dmod3 \
+		tst-audit24dmod4 \
+		tst-auditmod25 \
+		tst-audit25mod1 \
+		tst-audit25mod2 \
+		tst-audit25mod3 \
+		tst-audit25mod4 \
 
 # Most modules build with _ISOMAC defined, but those filtered out
 # depend on internal headers.
@@ -1595,6 +1618,69 @@ $(objpfx)tst-audit23.out: $(objpfx)tst-auditmod23.so \
 			  $(objpfx)tst-audit23mod.so
 tst-audit23-ARGS = -- $(host-test-program-cmd)
 
+$(objpfx)tst-audit24a.out: $(objpfx)tst-auditmod24a.so
+$(objpfx)tst-audit24a: $(objpfx)tst-audit24amod1.so \
+		       $(objpfx)tst-audit24amod2.so
+tst-audit24a-ENV = LD_AUDIT=$(objpfx)tst-auditmod24a.so
+LDFLAGS-tst-audit24a = -Wl,-z,now
+
+$(objpfx)tst-audit24b.out: $(objpfx)tst-auditmod24b.so
+$(objpfx)tst-audit24b: $(objpfx)tst-audit24bmod1.so \
+		       $(objpfx)tst-audit24bmod2.so
+$(objpfx)tst-audit24bmod1: $(objpfx)tst-audit24bmod2.so
+# The test check if a library without .gnu.version correctly calls the
+# audit callbacks.  So it uses an explicit link rule to avoid linking
+# against libc.so.
+$(objpfx)tst-audit24bmod1.so: $(objpfx)tst-audit24bmod1.os
+	$(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod1.os \
+	  -Wl,-z,now
+	$(call after-link,$@.new)
+	mv -f $@.new $@
+CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod1)
+$(objpfx)tst-audit24bmod2.so: $(objpfx)tst-audit24bmod2.os
+	$(CC) -nostdlib -nostartfiles -shared -o $@.new $(objpfx)tst-audit24bmod2.os
+	$(call after-link,$@.new)
+	mv -f $@.new $@
+CFLAGS-.os += $(call elide-stack-protector,.os,tst-audit24bmod2)
+tst-audit24b-ENV = LD_AUDIT=$(objpfx)tst-auditmod24b.so
+LDFLAGS-tst-audit24b = -Wl,-z,now
+
+# Same as tst-audit24a, but tests LD_BIND_NOW
+$(objpfx)tst-audit24c.out: $(objpfx)tst-auditmod24c.so
+$(objpfx)tst-audit24c: $(objpfx)tst-audit24amod1.so \
+		       $(objpfx)tst-audit24amod2.so
+tst-audit24c-ENV = LD_BIND_NOW=1 LD_AUDIT=$(objpfx)tst-auditmod24c.so
+LDFLAGS-tst-audit24b = -Wl,-z,lazy
+
+$(objpfx)tst-audit24d.out: $(objpfx)tst-auditmod24d.so
+$(objpfx)tst-audit24d: $(objpfx)tst-audit24dmod1.so \
+		       $(objpfx)tst-audit24dmod2.so
+$(objpfx)tst-audit24dmod1.so: $(objpfx)tst-audit24dmod3.so
+LDFLAGS-tst-audit24dmod1.so = -Wl,-z,now
+$(objpfx)tst-audit24dmod2.so: $(objpfx)tst-audit24dmod4.so
+LDFLAGS-tst-audit24dmod2.so = -Wl,-z,lazy
+tst-audit24d-ENV = LD_AUDIT=$(objpfx)tst-auditmod24d.so
+LDFLAGS-tst-audit24d = -Wl,-z,lazy
+
+$(objpfx)tst-audit25a.out: $(objpfx)tst-auditmod25.so
+$(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \
+		       $(objpfx)tst-audit25mod2.so \
+		       $(objpfx)tst-audit25mod3.so \
+		       $(objpfx)tst-audit25mod4.so
+$(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so
+LDFLAGS-tst-audit25mod1.so = -Wl,-z,now
+$(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so
+LDFLAGS-tst-audit25mod2.so = -Wl,-z,lazy
+tst-audit25a-ARGS = -- $(host-test-program-cmd)
+
+$(objpfx)tst-audit25b.out: $(objpfx)tst-auditmod25.so
+$(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \
+		       $(objpfx)tst-audit25mod2.so \
+		       $(objpfx)tst-audit25mod3.so \
+		       $(objpfx)tst-audit25mod4.so
+LDFLAGS-tst-audit25b = -Wl,-z,now
+tst-audit25b-ARGS = -- $(host-test-program-cmd)
+
 # tst-sonamemove links against an older implementation of the library.
 LDFLAGS-tst-sonamemove-linkmod1.so = \
   -Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index c3569cb357..f080591596 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -190,7 +190,7 @@ rtld_hidden_def (_dl_audit_symbind_alt)
 void
 _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 		   const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
-		   lookup_t result)
+		   lookup_t result, bool bindnow)
 {
   reloc_result->bound = result;
   /* Compute index of the symbol entry in the symbol table of the DSO with the
@@ -219,6 +219,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 
   unsigned int flags = 0;
   struct audit_ifaces *afct = GLRO(dl_audit);
+  uintptr_t new_value = (uintptr_t) sym.st_value;
   for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     {
       /* XXX Check whether both DSOs must request action or only one */
@@ -229,16 +230,16 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 	{
 	  if (afct->symbind != NULL)
 	    {
-	      uintptr_t new_value = afct->symbind (&sym,
-						   reloc_result->boundndx,
-						   &l_state->cookie,
-						   &result_state->cookie,
-						   &flags,
-						   strtab2 + defsym->st_name);
+	      flags |= bindnow ? LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT : 0;
+	      new_value = afct->symbind (&sym, reloc_result->boundndx,
+					 &l_state->cookie,
+					 &result_state->cookie, &flags,
+					 strtab2 + defsym->st_name);
 	      if (new_value != (uintptr_t) sym.st_value)
 		{
 		  flags |= LA_SYMB_ALTVALUE;
-		  sym.st_value = new_value;
+		  sym.st_value = bindnow
+		    ? DL_FIXUP_BINDNOW_ADDR_VALUE (new_value) : new_value;
 		}
 	    }
 
@@ -259,7 +260,7 @@ _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
     }
 
   reloc_result->flags = flags;
-  *value = DL_FIXUP_ADDR_VALUE (sym.st_value);
+  DL_FIXUP_BINDNOW_RELOC (value, new_value, sym.st_value);
 }
 
 void
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
index 64a96c36e8..345809e3e2 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -234,9 +234,7 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 
   /* If DT_BIND_NOW is set relocate all references in this object.  We
      do not do this if we are profiling, of course.  */
-  // XXX Correct for auditing?
-  if (!consider_profiling
-      && __builtin_expect (l->l_info[DT_BIND_NOW] != NULL, 0))
+  if (!consider_profiling && l->l_info[DT_BIND_NOW] != NULL)
     lazy = 0;
 
   if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_RELOC))
@@ -285,8 +283,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
   {
     /* Do the actual relocation of the object's GOT and other data.  */
 
-    ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
-
 #ifndef PROF
     if (consider_profiling | consider_symbind
 	&& l->l_info[DT_PLTRELSZ] != NULL)
@@ -309,6 +305,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	  }
       }
 #endif
+
+    ELF_DYNAMIC_RELOCATE (l, scope, lazy, consider_profiling, skip_ifunc);
   }
 
   /* Mark the object so we know this work has been done.  */
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index 9a38eea7cc..66945b57f8 100644
--- a/elf/dl-runtime.c
+++ b/elf/dl-runtime.c
@@ -146,7 +146,7 @@ _dl_fixup (
       unsigned int init = atomic_load_acquire (&reloc_result->init);
       if (init == 0)
 	{
-	  _dl_audit_symbind (l, reloc_result, sym, &value, result);
+	  _dl_audit_symbind (l, reloc_result, sym, &value, result, false);
 
 	  /* Store the result for later runs.  */
 	  if (__glibc_likely (! GLRO(dl_bind_not)))
@@ -321,7 +321,7 @@ _dl_profile_fixup (
 	 auditing libraries the possibility to change the value and
 	 tell us whether further auditing is wanted.  */
       if (defsym != NULL && GLRO(dl_naudit) > 0)
-	_dl_audit_symbind (l, reloc_result, defsym, &value, result);
+	_dl_audit_symbind (l, reloc_result, defsym, &value, result, false);
 #endif
 
       /* Store the result for later runs.  */
diff --git a/elf/do-rel.h b/elf/do-rel.h
index f441b74919..c3368f09ab 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -16,6 +16,8 @@
    License along with the GNU C Library; if not, see
    <https://www.gnu.org/licenses/>.  */
 
+#include <ldsodefs.h>
+
 /* This file may be included twice, to define both
    `elf_dynamic_do_rel' and `elf_dynamic_do_rela'.  */
 
@@ -121,8 +123,15 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
 	  const ElfW(Half) *const version =
 	    (const void *) D_PTR (map, l_info[VERSYMIDX (DT_VERSYM)]);
 
+#if defined SHARED && !defined RTLD_BOOTSTRAP
+	  size_t ri = 0;
+#endif
 	  for (; r < end; ++r)
 	    {
+	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
+	      const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
+	      void *const r_addr_arg = (void *) (l_addr + r->r_offset);
+	      const struct r_found_version *rversion = &map->l_versions[ndx];
 #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
 	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
 		{
@@ -133,10 +142,20 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
 		}
 #endif
 
-	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
-	      elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)],
-			       &map->l_versions[ndx],
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, scope, r, sym, rversion, r_addr_arg,
+			       skip_ifunc);
+#if defined SHARED && !defined RTLD_BOOTSTRAP
+	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
+		  && map->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (map, scope, &sym, rversion,
+				   ELF_MACHINE_JMP_SLOT);
+		  if (sym != NULL)
+		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+				       r_addr_arg, sym_map, true);
+		}
+#endif
 	    }
 
 #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
@@ -157,18 +176,38 @@ elf_dynamic_do_Rel (struct link_map *map, struct r_scope_elem *scope[],
 #ifndef RTLD_BOOTSTRAP
       else
 	{
+# if defined SHARED && !defined RTLD_BOOTSTRAP
+	  size_t ri = 0;
+# endif
 	  for (; r < end; ++r)
+	    {
+	      const ElfW(Sym) *sym = &symtab[ELFW(R_SYM) (r->r_info)];
+	      void *const r_addr_arg = (void *) (l_addr + r->r_offset);
 # ifdef ELF_MACHINE_IRELATIVE
-	    if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
-	      {
-		if (r2 == NULL)
-		  r2 = r;
-		end2 = r;
-	      }
-	    else
+	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_IRELATIVE)
+		{
+		  if (r2 == NULL)
+		    r2 = r;
+		  end2 = r;
+		  continue;
+		}
 # endif
-	      elf_machine_rel (map, scope, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, scope, r, sym, NULL, r_addr_arg,
+			       skip_ifunc);
+# if defined SHARED && !defined RTLD_BOOTSTRAP
+	      if (ELFW(R_TYPE) (r->r_info) == ELF_MACHINE_JMP_SLOT
+		  && map->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (map, scope, &sym,
+				   (struct r_found_version *) NULL,
+				   ELF_MACHINE_JMP_SLOT);
+		  if (sym != NULL)
+		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+				       r_addr_arg, sym_map, true);
+		}
+# endif
+	    }
 
 # ifdef ELF_MACHINE_IRELATIVE
 	  if (r2 != NULL)
diff --git a/elf/tst-audit24a.c b/elf/tst-audit24a.c
new file mode 100644
index 0000000000..24160f4685
--- /dev/null
+++ b/elf/tst-audit24a.c
@@ -0,0 +1,36 @@
+/* DL_AUDIT test for la_symbind() and bind-now.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+#include <support/support.h>
+
+int tst_audit24amod1_func1 (void);
+int tst_audit24amod1_func2 (void);
+int tst_audit24amod2_func1 (void);
+
+int
+do_test (void)
+{
+  TEST_COMPARE (tst_audit24amod1_func1 (), 1);
+  TEST_COMPARE (tst_audit24amod1_func2 (), 2);
+  TEST_COMPARE (tst_audit24amod2_func1 (), 10);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit24amod1.c b/elf/tst-audit24amod1.c
new file mode 100644
index 0000000000..43d3831677
--- /dev/null
+++ b/elf/tst-audit24amod1.c
@@ -0,0 +1,31 @@
+/* Modules used by tst-audit24a.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24amod1_func1 (void)
+{
+  abort ();
+}
+
+int
+tst_audit24amod1_func2 (void)
+{
+  return 2;
+}
diff --git a/elf/tst-audit24amod2.c b/elf/tst-audit24amod2.c
new file mode 100644
index 0000000000..c995827855
--- /dev/null
+++ b/elf/tst-audit24amod2.c
@@ -0,0 +1,25 @@
+/* Modules used by tst-audit24a.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24amod2_func1 (void)
+{
+  abort ();
+}
diff --git a/elf/tst-audit24b.c b/elf/tst-audit24b.c
new file mode 100644
index 0000000000..44643d64ef
--- /dev/null
+++ b/elf/tst-audit24b.c
@@ -0,0 +1,37 @@
+/* DL_AUDIT test for la_symbind() and bind-now.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* This is similar to tst-audit24a, with the difference this modules
+   does not have the .gnu.version section header.  */
+
+#include <support/check.h>
+#include <support/support.h>
+
+int tst_audit24bmod1_func1 (void);
+int tst_audit24bmod1_func2 (void);
+
+int
+do_test (void)
+{
+  TEST_COMPARE (tst_audit24bmod1_func1 (), 1);
+  TEST_COMPARE (tst_audit24bmod1_func2 (), 2);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit24bmod1.c b/elf/tst-audit24bmod1.c
new file mode 100644
index 0000000000..91c6fa0251
--- /dev/null
+++ b/elf/tst-audit24bmod1.c
@@ -0,0 +1,31 @@
+/* Modules used by tst-audit24c.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+int tst_audit24bmod2_func1 (void);
+
+int
+tst_audit24bmod1_func1 (void)
+{
+  return -1;
+}
+
+int
+tst_audit24bmod1_func2 (void)
+{
+  return tst_audit24bmod2_func1 ();
+}
diff --git a/elf/tst-audit24bmod2.c b/elf/tst-audit24bmod2.c
new file mode 100644
index 0000000000..3baf9e8bd4
--- /dev/null
+++ b/elf/tst-audit24bmod2.c
@@ -0,0 +1,23 @@
+/* Modules used by tst-audit24b.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+int
+tst_audit24bmod2_func1 (void)
+{
+  return -1;
+}
diff --git a/elf/tst-audit24c.c b/elf/tst-audit24c.c
new file mode 100644
index 0000000000..46ed328756
--- /dev/null
+++ b/elf/tst-audit24c.c
@@ -0,0 +1,2 @@
+/* It tests LD_BIND_NOW=1 instead of linking with -Wl,-z,now  */
+#include "tst-audit24a.c"
diff --git a/elf/tst-audit24d.c b/elf/tst-audit24d.c
new file mode 100644
index 0000000000..79b580331a
--- /dev/null
+++ b/elf/tst-audit24d.c
@@ -0,0 +1,36 @@
+/* DL_AUDIT test for la_symbind() and bind-now.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <support/check.h>
+#include <support/support.h>
+
+int tst_audit24dmod1_func1 (void);
+int tst_audit24dmod1_func2 (void);
+int tst_audit24dmod2_func1 (void);
+
+int
+do_test (void)
+{
+  TEST_COMPARE (tst_audit24dmod1_func1 (), 1);
+  TEST_COMPARE (tst_audit24dmod1_func2 (), 32);
+  TEST_COMPARE (tst_audit24dmod2_func1 (), 10);
+
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-audit24dmod1.c b/elf/tst-audit24dmod1.c
new file mode 100644
index 0000000000..792da3b581
--- /dev/null
+++ b/elf/tst-audit24dmod1.c
@@ -0,0 +1,33 @@
+/* Modules used by tst-audit24d.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+int tst_audit24dmod3_func1 (void);
+
+_Noreturn int
+tst_audit24dmod1_func1 (void)
+{
+  abort ();
+}
+
+int
+tst_audit24dmod1_func2 (void)
+{
+  return 2 + tst_audit24dmod3_func1 ();;
+}
diff --git a/elf/tst-audit24dmod2.c b/elf/tst-audit24dmod2.c
new file mode 100644
index 0000000000..8c76257885
--- /dev/null
+++ b/elf/tst-audit24dmod2.c
@@ -0,0 +1,28 @@
+/* Module for tst-audit24d.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+int tst_audit24dmod4_func1 (void);
+
+_Noreturn int
+tst_audit24dmod2_func1 (void)
+{
+  tst_audit24dmod4_func1 ();
+  abort ();
+}
diff --git a/elf/tst-audit24dmod3.c b/elf/tst-audit24dmod3.c
new file mode 100644
index 0000000000..367c776eb5
--- /dev/null
+++ b/elf/tst-audit24dmod3.c
@@ -0,0 +1,31 @@
+/* Module for tst-audit24d.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24dmod3_func1 (void)
+{
+  abort ();
+}
+
+int
+tst_audit24dmod3_func2 (void)
+{
+  return 4;
+}
diff --git a/elf/tst-audit24dmod4.c b/elf/tst-audit24dmod4.c
new file mode 100644
index 0000000000..c994c7cf03
--- /dev/null
+++ b/elf/tst-audit24dmod4.c
@@ -0,0 +1,25 @@
+/* Module for tst-audit24d.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <stdlib.h>
+
+_Noreturn int
+tst_audit24dmod4_func1 (void)
+{
+  abort ();
+}
diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c
new file mode 100644
index 0000000000..e3e7200f85
--- /dev/null
+++ b/elf/tst-audit25a.c
@@ -0,0 +1,127 @@
+/* Check DT_AUDIT and LA_SYMB_NOW.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+void tst_audit25mod1_func1 (void);
+void tst_audit25mod1_func2 (void);
+void tst_audit25mod2_func1 (void);
+void tst_audit25mod2_func2 (void);
+
+static int
+handle_restart (void)
+{
+  tst_audit25mod1_func1 ();
+  tst_audit25mod1_func2 ();
+  tst_audit25mod2_func1 ();
+  tst_audit25mod2_func2 ();
+
+  return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+  size_t lenpre = strlen (pre);
+  size_t lenstr = strlen (str);
+  return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  /* We must have either:
+     - One our fource parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name  */
+
+  if (restart)
+    return handle_restart ();
+
+  setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
+
+  char *spargv[9];
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  spargv[i] = NULL;
+
+  {
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* tst-audit25a is build with -Wl,-z,lazy and tst-audit25mod1 with
+       -Wl,-z,now; so only tst_audit25mod3_func1 should be expected to
+       have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod3_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func1 0\n"
+			 "la_symbind: tst_audit25mod1_func2 0\n"
+			 "la_symbind: tst_audit25mod2_func1 0\n"
+			 "la_symbind: tst_audit25mod4_func1 0\n"
+			 "la_symbind: tst_audit25mod2_func2 0\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  {
+    setenv ("LD_BIND_NOW", "1", 0);
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* With LD_BIND_NOW all symbols are expected to have
+       LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT.  Also the resolution
+       order is done in breadth-first order.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod4_func1 1\n"
+			 "la_symbind: tst_audit25mod3_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func1 1\n"
+			 "la_symbind: tst_audit25mod2_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func2 1\n"
+			 "la_symbind: tst_audit25mod2_func2 1\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c
new file mode 100644
index 0000000000..d497b82d56
--- /dev/null
+++ b/elf/tst-audit25b.c
@@ -0,0 +1,128 @@
+/* Check DT_AUDIT and LA_SYMB_NOW.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+void tst_audit25mod1_func1 (void);
+void tst_audit25mod1_func2 (void);
+void tst_audit25mod2_func1 (void);
+void tst_audit25mod2_func2 (void);
+
+static int
+handle_restart (void)
+{
+  tst_audit25mod1_func1 ();
+  tst_audit25mod1_func2 ();
+  tst_audit25mod2_func1 ();
+  tst_audit25mod2_func2 ();
+
+  return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+  size_t lenpre = strlen (pre);
+  size_t lenstr = strlen (str);
+  return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  /* We must have either:
+     - One our fource parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name  */
+
+  if (restart)
+    return handle_restart ();
+
+  setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
+
+  char *spargv[9];
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  spargv[i] = NULL;
+
+  {
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* tst-audit25a and tst-audit25mod1 are built with -Wl,-z,now, but
+       tst-audit25mod2 is built with -Wl,z,lazy.  So only
+       tst_audit25mod4_func1 (called by tst_audit25mod2_func1) should not
+       have LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod3_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func1 1\n"
+			 "la_symbind: tst_audit25mod2_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func2 1\n"
+			 "la_symbind: tst_audit25mod2_func2 1\n"
+			 "la_symbind: tst_audit25mod4_func1 0\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  {
+    setenv ("LD_BIND_NOW", "1", 0);
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* With LD_BIND_NOW all symbols are expected to have
+       LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT.  Also the resolution
+       order is done in breadth-first order.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod4_func1 1\n"
+			 "la_symbind: tst_audit25mod3_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func1 1\n"
+			 "la_symbind: tst_audit25mod2_func1 1\n"
+			 "la_symbind: tst_audit25mod1_func2 1\n"
+			 "la_symbind: tst_audit25mod2_func2 1\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit25mod1.c b/elf/tst-audit25mod1.c
new file mode 100644
index 0000000000..9aa39ed325
--- /dev/null
+++ b/elf/tst-audit25mod1.c
@@ -0,0 +1,30 @@
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void tst_audit25mod3_func1 (void);
+
+void
+tst_audit25mod1_func1 (void)
+{
+  tst_audit25mod3_func1 ();
+}
+
+void
+tst_audit25mod1_func2 (void)
+{
+}
diff --git a/elf/tst-audit25mod2.c b/elf/tst-audit25mod2.c
new file mode 100644
index 0000000000..6d8e225fcc
--- /dev/null
+++ b/elf/tst-audit25mod2.c
@@ -0,0 +1,30 @@
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void tst_audit25mod4_func1 (void);
+
+void
+tst_audit25mod2_func1 (void)
+{
+  tst_audit25mod4_func1 ();
+}
+
+void
+tst_audit25mod2_func2 (void)
+{
+}
diff --git a/elf/tst-audit25mod3.c b/elf/tst-audit25mod3.c
new file mode 100644
index 0000000000..c0d5977fd8
--- /dev/null
+++ b/elf/tst-audit25mod3.c
@@ -0,0 +1,22 @@
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void
+tst_audit25mod3_func1 (void)
+{
+}
diff --git a/elf/tst-audit25mod4.c b/elf/tst-audit25mod4.c
new file mode 100644
index 0000000000..689ee5138f
--- /dev/null
+++ b/elf/tst-audit25mod4.c
@@ -0,0 +1,22 @@
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void
+tst_audit25mod4_func1 (void)
+{
+}
diff --git a/elf/tst-auditmod24.h b/elf/tst-auditmod24.h
new file mode 100644
index 0000000000..621fd50364
--- /dev/null
+++ b/elf/tst-auditmod24.h
@@ -0,0 +1,29 @@
+/* Auxiliary functions for tst-audit24x.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _TST_AUDITMOD24_H
+#define _TST_AUDITMOD24_H
+
+static void
+check_symbind_flags (unsigned int flags)
+{
+  if ((flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT)) == 0)
+    abort ();
+}
+
+#endif
diff --git a/elf/tst-auditmod24a.c b/elf/tst-auditmod24a.c
new file mode 100644
index 0000000000..09d89269df
--- /dev/null
+++ b/elf/tst-auditmod24a.c
@@ -0,0 +1,113 @@
+/* Audit modules for tst-audit24a.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tst-auditmod24.h>
+
+#define AUDIT24_COOKIE     0x1
+#define AUDIT24MOD1_COOKIE 0x2
+#define AUDIT24MOD2_COOKIE 0x3
+
+#ifndef TEST_NAME
+# define TEST_NAME "tst-audit24a"
+#endif
+#ifndef TEST_MOD
+# define TEST_MOD TEST_NAME
+#endif
+#ifndef TEST_FUNC
+# define TEST_FUNC "tst_audit24a"
+#endif
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  const char *p = strrchr (map->l_name, '/');
+  const char *l_name = p == NULL ? map->l_name : p + 1;
+  uintptr_t ck = -1;
+  if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
+    ck = AUDIT24MOD1_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
+    ck = AUDIT24MOD2_COOKIE;
+  else if (strcmp (l_name, TEST_NAME) == 0)
+    ck = AUDIT24_COOKIE;
+
+  *cookie = ck;
+  return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+static int
+tst_func1 (void)
+{
+  return 1;
+}
+
+static int
+tst_func2 (void)
+{
+  return 10;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#endif
+{
+  if (*refcook == AUDIT24_COOKIE)
+    {
+      if (*defcook == AUDIT24MOD1_COOKIE)
+	{
+	  /* Check if bind-now symbols are advertised to not call the PLT
+	     hooks.  */
+	  check_symbind_flags (*flags);
+
+	  if (strcmp (symname, TEST_FUNC "mod1_func1") == 0)
+	    return (uintptr_t) tst_func1;
+	  else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0)
+	    return sym->st_value;
+	  abort ();
+	}
+      if (*defcook == AUDIT24MOD2_COOKIE
+	  && (strcmp (symname, TEST_FUNC "mod2_func1") == 0))
+	{
+	  check_symbind_flags (*flags);
+
+	  return (uintptr_t) tst_func2;
+	}
+
+      /* malloc functions.  */
+      return sym->st_value;
+    }
+
+  abort ();
+}
diff --git a/elf/tst-auditmod24b.c b/elf/tst-auditmod24b.c
new file mode 100644
index 0000000000..dd3771ae5b
--- /dev/null
+++ b/elf/tst-auditmod24b.c
@@ -0,0 +1,103 @@
+/* Audit modules for tst-audit24b.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tst-auditmod24.h>
+
+#define TEST_NAME "tst-audit24b"
+#define TEST_FUNC "tst_audit24b"
+
+#define AUDIT24_COOKIE     0x1
+#define AUDIT24MOD1_COOKIE 0x2
+#define AUDIT24MOD2_COOKIE 0x3
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  const char *p = strrchr (map->l_name, '/');
+  const char *l_name = p == NULL ? map->l_name : p + 1;
+  uintptr_t ck = -1;
+  if (strcmp (l_name, TEST_NAME "mod1.so") == 0)
+    ck = AUDIT24MOD1_COOKIE;
+  else if (strcmp (l_name, TEST_NAME "mod2.so") == 0)
+    ck = AUDIT24MOD2_COOKIE;
+  else if (strcmp (l_name, TEST_NAME) == 0)
+    ck = AUDIT24_COOKIE;
+
+  *cookie = ck;
+  return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+static int
+tst_func1 (void)
+{
+  return 1;
+}
+
+static int
+tst_func2 (void)
+{
+  return 2;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#endif
+{
+  if (*refcook == AUDIT24_COOKIE)
+    {
+      if (*defcook == AUDIT24MOD1_COOKIE)
+	  {
+	    if (strcmp (symname, TEST_FUNC "mod1_func1") == 0)
+	      return (uintptr_t) tst_func1;
+	    else if (strcmp (symname, TEST_FUNC "mod1_func2") == 0)
+	      return sym->st_value;
+	    abort ();
+	  }
+      /* malloc functions.  */
+      return sym->st_value;
+    }
+  else if (*refcook == AUDIT24MOD1_COOKIE)
+    {
+      if (*defcook == AUDIT24MOD2_COOKIE
+	  && (strcmp (symname, TEST_FUNC "mod2_func1") == 0))
+	{
+	  check_symbind_flags (*flags);
+	  return (uintptr_t) tst_func2;
+	}
+    }
+
+  abort ();
+}
diff --git a/elf/tst-auditmod24c.c b/elf/tst-auditmod24c.c
new file mode 100644
index 0000000000..67e62c9d33
--- /dev/null
+++ b/elf/tst-auditmod24c.c
@@ -0,0 +1,3 @@
+#define TEST_NAME "tst-audit24c"
+#define TEST_MOD  "tst-audit24a"
+#include "tst-auditmod24a.c"
diff --git a/elf/tst-auditmod24d.c b/elf/tst-auditmod24d.c
new file mode 100644
index 0000000000..67e958f926
--- /dev/null
+++ b/elf/tst-auditmod24d.c
@@ -0,0 +1,119 @@
+/* Audit module for tst-audit24d.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <tst-auditmod24.h>
+
+#define AUDIT24_COOKIE     0x0
+#define AUDIT24MOD1_COOKIE 0x1
+#define AUDIT24MOD2_COOKIE 0x2
+#define AUDIT24MOD3_COOKIE 0x3
+#define AUDIT24MOD4_COOKIE 0x4
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  const char *p = strrchr (map->l_name, '/');
+  const char *l_name = p == NULL ? map->l_name : p + 1;
+  uintptr_t ck = -1;
+  if (strcmp (l_name, "tst-audit24dmod1.so") == 0)
+    ck = AUDIT24MOD1_COOKIE;
+  else if (strcmp (l_name, "tst-audit24dmod2.so") == 0)
+    ck = AUDIT24MOD2_COOKIE;
+  else if (strcmp (l_name, "tst-audit24dmod3.so") == 0)
+    ck = AUDIT24MOD3_COOKIE;
+  else if (strcmp (l_name, "tst-audit24dmod.so") == 0)
+    ck = AUDIT24MOD4_COOKIE;
+  else if (strcmp (l_name, "tst-audit24d") == 0)
+    ck = AUDIT24_COOKIE;
+
+  *cookie = ck;
+  return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+static int
+tst_audit24dmod1_func1 (void)
+{
+  return 1;
+}
+
+static int
+tst_audit24dmod2_func1 (void)
+{
+  return 10;
+}
+
+static int
+tst_audit24dmod3_func1 (void)
+{
+  return 30;
+}
+
+#include <stdio.h>
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#endif
+{
+  if (*refcook == AUDIT24_COOKIE)
+    {
+      if (*defcook == AUDIT24MOD1_COOKIE)
+	  {
+	    if (strcmp (symname, "tst_audit24dmod1_func1") == 0)
+	      return (uintptr_t) tst_audit24dmod1_func1;
+	    else if (strcmp (symname, "tst_audit24dmod1_func2") == 0)
+	      return sym->st_value;
+	    abort ();
+	  }
+      if (*defcook == AUDIT24MOD2_COOKIE
+	  && (strcmp (symname, "tst_audit24dmod2_func1") == 0))
+	return (uintptr_t) tst_audit24dmod2_func1;
+
+      /* malloc functions.  */
+      return sym->st_value;
+    }
+  else if (*refcook == AUDIT24MOD1_COOKIE)
+    {
+      if (*defcook == AUDIT24MOD3_COOKIE
+	  && strcmp (symname, "tst_audit24dmod3_func1") == 0)
+	{
+	  check_symbind_flags (*flags);
+
+	  return (uintptr_t) tst_audit24dmod3_func1;
+	}
+    }
+
+  abort ();
+}
diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c
new file mode 100644
index 0000000000..bfdeadace5
--- /dev/null
+++ b/elf/tst-auditmod25.c
@@ -0,0 +1,78 @@
+/* Audit modules for tst-audit25a.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define AUDIT25_COOKIE     0x1
+#define AUDIT25MOD1_COOKIE 0x2
+#define AUDIT25MOD2_COOKIE 0x3
+#define AUDIT25MOD3_COOKIE 0x2
+#define AUDIT25MOD4_COOKIE 0x3
+
+#define TEST_NAME "tst-audit25"
+#define TEST_MOD  "tst-audit25"
+#define TEST_FUNC "tst_audit25"
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  const char *p = strrchr (map->l_name, '/');
+  const char *l_name = p == NULL ? map->l_name : p + 1;
+  uintptr_t ck = -1;
+  if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
+    ck = AUDIT25MOD1_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
+    ck = AUDIT25MOD2_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod3.so") == 0)
+    ck = AUDIT25MOD3_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod4.so") == 0)
+    ck = AUDIT25MOD4_COOKIE;
+  else if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
+    ck = AUDIT25_COOKIE;
+
+  *cookie = ck;
+  return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#endif
+{
+  if (*refcook != -1 && *defcook != -1)
+    fprintf (stderr, "la_symbind: %s %u\n", symname,
+	     *flags & (LA_SYMB_NOPLTENTER | LA_SYMB_NOPLTEXIT) ? 1 : 0);
+  return sym->st_value;
+}
diff --git a/sysdeps/generic/dl-lookupcfg.h b/sysdeps/generic/dl-lookupcfg.h
index c038c31ce6..a15fd32771 100644
--- a/sysdeps/generic/dl-lookupcfg.h
+++ b/sysdeps/generic/dl-lookupcfg.h
@@ -26,3 +26,6 @@
 #define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
 #define DL_FIXUP_VALUE_ADDR(value) (value)
 #define DL_FIXUP_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+  (*value) = st_value;
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index d419a62dbd..a73859d16e 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1410,7 +1410,7 @@ void _dl_audit_objclose (struct link_map *l, Lmid_t nsid);
 void _dl_audit_preinit (struct link_map *l);
 void _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 			const ElfW(Sym) *defsym, DL_FIXUP_VALUE_TYPE *value,
-			lookup_t result);
+			lookup_t result, bool bindnow);
 void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,
 			    void **value, lookup_t result);
 rtld_hidden_proto (_dl_audit_symbind_alt)
diff --git a/sysdeps/hppa/dl-lookupcfg.h b/sysdeps/hppa/dl-lookupcfg.h
index a9a927f26c..f376965600 100644
--- a/sysdeps/hppa/dl-lookupcfg.h
+++ b/sysdeps/hppa/dl-lookupcfg.h
@@ -80,3 +80,6 @@ void attribute_hidden _dl_unmap (struct link_map *map);
 #define DL_FIXUP_VALUE_CODE_ADDR(value) ((value).ip)
 #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
 #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+  (*value) = *(struct fdesc *) (st_value)
diff --git a/sysdeps/ia64/dl-lookupcfg.h b/sysdeps/ia64/dl-lookupcfg.h
index 58ca32424b..2b8b2fa5db 100644
--- a/sysdeps/ia64/dl-lookupcfg.h
+++ b/sysdeps/ia64/dl-lookupcfg.h
@@ -74,3 +74,6 @@ extern void attribute_hidden _dl_unmap (struct link_map *map);
 
 #define DL_FIXUP_VALUE_ADDR(value) ((uintptr_t) &(value))
 #define DL_FIXUP_ADDR_VALUE(addr) (*(struct fdesc *) (addr))
+#define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+#define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value) \
+  (*value) = *(struct fdesc *) (st_value)
diff --git a/sysdeps/powerpc/dl-lookupcfg.h b/sysdeps/powerpc/dl-lookupcfg.h
new file mode 100644
index 0000000000..43fc94a7f6
--- /dev/null
+++ b/sysdeps/powerpc/dl-lookupcfg.h
@@ -0,0 +1,39 @@
+/* Configuration of lookup functions.  PowerPC version.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#define DL_FIXUP_VALUE_TYPE ElfW(Addr)
+#define DL_FIXUP_MAKE_VALUE(map, addr) (addr)
+#define DL_FIXUP_VALUE_CODE_ADDR(value) (value)
+#define DL_FIXUP_VALUE_ADDR(value) (value)
+#define DL_FIXUP_ADDR_VALUE(addr) (addr)
+#if __WORDSIZE == 64 && _CALL_ELF == 1
+/* We need to correctly set the audit modules value for bind-now.  */
+# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) \
+ (((Elf64_FuncDesc *)(addr))->fd_func)
+# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)	\
+ ({								\
+    Elf64_FuncDesc *opd = (Elf64_FuncDesc *) (value);		\
+    opd->fd_func = (st_value);					\
+    if ((new_value) != (uintptr_t) (st_value))			\
+     opd->fd_toc = ((Elf64_FuncDesc *)(new_value))->fd_toc;	\
+  })
+#else
+# define DL_FIXUP_BINDNOW_ADDR_VALUE(addr) (addr)
+# define DL_FIXUP_BINDNOW_RELOC(value, new_value, st_value)	\
+  (*value) = st_value;
+#endif


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

* [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734)
@ 2021-11-09 18:19 Adhemerval Zanella
  0 siblings, 0 replies; 6+ messages in thread
From: Adhemerval Zanella @ 2021-11-09 18:19 UTC (permalink / raw)
  To: glibc-cvs

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

commit 375b62a2860891a139b0484757a84af516c8a62c
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Jul 28 10:03:00 2021 -0300

    elf: Issue la_symbind() for bind-now (BZ #23734)
    
    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.

Diff:
---
 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(-)

diff --git a/elf/Makefile b/elf/Makefile
index 35b28b992d..5cbf4ed934 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -232,6 +232,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 \
@@ -326,6 +327,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 \
@@ -1588,6 +1594,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


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

* [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734)
@ 2021-09-10 18:26 Adhemerval Zanella
  0 siblings, 0 replies; 6+ messages in thread
From: Adhemerval Zanella @ 2021-09-10 18:26 UTC (permalink / raw)
  To: glibc-cvs

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

commit 01cd9fb64054ba3104c868491d17351d9d8a0b32
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Jul 28 10:03:00 2021 -0300

    elf: Issue la_symbind() for bind-now (BZ #23734)

Diff:
---
 elf/Makefile           |  50 ++++++++++++++++++++++
 elf/dl-reloc.c         |   8 ++--
 elf/do-rel.h           |  62 +++++++++++++++++++++------
 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 +++++++++++++++++++++++++++++++++++++++++++++++++
 20 files changed, 780 insertions(+), 20 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index 3d2c49a157..0cb43f9ca5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -227,6 +227,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 \
@@ -317,6 +318,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 \
@@ -1540,6 +1546,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-reloc.c b/elf/dl-reloc.c
index c6bc1e6b4e..fb47b5939f 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -206,9 +206,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))
@@ -286,8 +284,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 
 #include "dynamic-link.h"
 
-    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
-
 #ifndef PROF
     if (consider_profiling | consider_symbind
 	&& l->l_info[DT_PLTRELSZ] != NULL)
@@ -310,6 +306,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	  }
       }
 #endif
+
+    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
   }
 
   /* Mark the object so we know this work has been done.  */
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 321ac2b359..455e6a8b2e 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,
 	  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)
 		{
@@ -132,11 +141,18 @@ elf_dynamic_do_Rel (struct link_map *map,
 		  continue;
 		}
 #endif
-
-	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
-	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
-			       &map->l_versions[ndx],
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&sym, rversion, ELF_MACHINE_JMP_SLOT);
+		  if (sym != NULL)
+		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+				       r_addr_arg, sym_map);
+		}
+#endif
 	    }
 
 #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
@@ -157,18 +173,36 @@ elf_dynamic_do_Rel (struct link_map *map,
 #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, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&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);
+		}
+# 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 ();
+}


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

* [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734)
@ 2021-08-04 20:54 Adhemerval Zanella
  0 siblings, 0 replies; 6+ messages in thread
From: Adhemerval Zanella @ 2021-08-04 20:54 UTC (permalink / raw)
  To: glibc-cvs

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

commit 94b19ad859e37c197714409620a4911cc3e658fe
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Jul 28 10:03:00 2021 -0300

    elf: Issue la_symbind() for bind-now (BZ #23734)

Diff:
---
 elf/Makefile           |  50 ++++++++++++++++++++++
 elf/dl-reloc.c         |   8 ++--
 elf/do-rel.h           |  62 +++++++++++++++++++++------
 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 +++++++++++++++++++++++++++++++++++++++++++++++++
 20 files changed, 780 insertions(+), 20 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index bbe59176b2..bfed7043a5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -227,6 +227,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 \
@@ -314,6 +315,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 \
@@ -1537,6 +1543,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-reloc.c b/elf/dl-reloc.c
index c6bc1e6b4e..fb47b5939f 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -206,9 +206,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))
@@ -286,8 +284,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 
 #include "dynamic-link.h"
 
-    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
-
 #ifndef PROF
     if (consider_profiling | consider_symbind
 	&& l->l_info[DT_PLTRELSZ] != NULL)
@@ -310,6 +306,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	  }
       }
 #endif
+
+    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
   }
 
   /* Mark the object so we know this work has been done.  */
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 321ac2b359..455e6a8b2e 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,
 	  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)
 		{
@@ -132,11 +141,18 @@ elf_dynamic_do_Rel (struct link_map *map,
 		  continue;
 		}
 #endif
-
-	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
-	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
-			       &map->l_versions[ndx],
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&sym, rversion, ELF_MACHINE_JMP_SLOT);
+		  if (sym != NULL)
+		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+				       r_addr_arg, sym_map);
+		}
+#endif
 	    }
 
 #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
@@ -157,18 +173,36 @@ elf_dynamic_do_Rel (struct link_map *map,
 #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, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&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);
+		}
+# 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 ();
+}


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

* [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734)
@ 2021-08-04 17:48 Adhemerval Zanella
  0 siblings, 0 replies; 6+ messages in thread
From: Adhemerval Zanella @ 2021-08-04 17:48 UTC (permalink / raw)
  To: glibc-cvs

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

commit 9fcd331ffd81e59f29621984fea7da2166d01f32
Author: Adhemerval Zanella <adhemerval.zanella@linaro.org>
Date:   Wed Jul 28 10:03:00 2021 -0300

    elf: Issue la_symbind() for bind-now (BZ #23734)

Diff:
---
 elf/Makefile           |  50 ++++++++++++++++++++++
 elf/dl-reloc.c         |   8 ++--
 elf/do-rel.h           |  62 +++++++++++++++++++++------
 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 +++++++++++++++++++++++++++++++++++++++++++++++++
 20 files changed, 780 insertions(+), 20 deletions(-)

diff --git a/elf/Makefile b/elf/Makefile
index bbe59176b2..bfed7043a5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -227,6 +227,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 \
@@ -314,6 +315,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 \
@@ -1537,6 +1543,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-reloc.c b/elf/dl-reloc.c
index c6bc1e6b4e..fb47b5939f 100644
--- a/elf/dl-reloc.c
+++ b/elf/dl-reloc.c
@@ -206,9 +206,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))
@@ -286,8 +284,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 
 #include "dynamic-link.h"
 
-    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
-
 #ifndef PROF
     if (consider_profiling | consider_symbind
 	&& l->l_info[DT_PLTRELSZ] != NULL)
@@ -310,6 +306,8 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
 	  }
       }
 #endif
+
+    ELF_DYNAMIC_RELOCATE (l, lazy, consider_profiling, skip_ifunc);
   }
 
   /* Mark the object so we know this work has been done.  */
diff --git a/elf/do-rel.h b/elf/do-rel.h
index 321ac2b359..455e6a8b2e 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,
 	  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)
 		{
@@ -132,11 +141,18 @@ elf_dynamic_do_Rel (struct link_map *map,
 		  continue;
 		}
 #endif
-
-	      ElfW(Half) ndx = version[ELFW(R_SYM) (r->r_info)] & 0x7fff;
-	      elf_machine_rel (map, r, &symtab[ELFW(R_SYM) (r->r_info)],
-			       &map->l_versions[ndx],
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&sym, rversion, ELF_MACHINE_JMP_SLOT);
+		  if (sym != NULL)
+		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
+				       r_addr_arg, sym_map);
+		}
+#endif
 	    }
 
 #if defined ELF_MACHINE_IRELATIVE && !defined RTLD_BOOTSTRAP
@@ -157,18 +173,36 @@ elf_dynamic_do_Rel (struct link_map *map,
 #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, r, &symtab[ELFW(R_SYM) (r->r_info)], NULL,
-			       (void *) (l_addr + r->r_offset), skip_ifunc);
+	      elf_machine_rel (map, 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
+		  && l->l_reloc_result != NULL)
+		{
+		  struct link_map *sym_map
+		    = RESOLVE_MAP (&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);
+		}
+# 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 ();
+}


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

end of thread, other threads:[~2021-11-16 13:58 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-30 19:25 [glibc/azanella/ld-audit-fixes] elf: Issue la_symbind() for bind-now (BZ #23734) Adhemerval Zanella
2021-08-04 17:48 Adhemerval Zanella
2021-08-04 20:54 Adhemerval Zanella
2021-09-10 18:26 Adhemerval Zanella
2021-11-09 18:19 Adhemerval Zanella
2021-11-16 13:58 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).