diff mbox series

[v3,18/20] elf: Add LA_SYMB_BINDNOW

Message ID 20210730194715.881900-19-adhemerval.zanella@linaro.org
State New
Headers show
Series Some rtld-audit fixes | expand

Commit Message

Adhemerval Zanella July 30, 2021, 7:47 p.m. UTC
The warn the audit library that la_symbind() is being invoked in a
bind-now manner, a new LA_SYMB_BINDNOW is added.  It warns that
LA_SYMB_NOPLTENTER nor LA_SYMB_NOPLTEXIT has any effect on PLT
tracking.

Checked on x86_64-linux-gnu and aarch64-linux-gnu.
---
 elf/Makefile               |  22 +++++++
 elf/dl-audit.c             |   4 +-
 elf/dl-runtime.c           |   4 +-
 elf/do-rel.h               |   4 +-
 elf/link.h                 |   5 +-
 elf/tst-audit25a.c         | 126 ++++++++++++++++++++++++++++++++++++
 elf/tst-audit25b.c         | 127 +++++++++++++++++++++++++++++++++++++
 elf/tst-audit25mod1.c      |  30 +++++++++
 elf/tst-audit25mod2.c      |  30 +++++++++
 elf/tst-audit25mod3.c      |  22 +++++++
 elf/tst-audit25mod4.c      |  22 +++++++
 elf/tst-auditmod25.c       |  77 ++++++++++++++++++++++
 sysdeps/generic/ldsodefs.h |   2 +-
 13 files changed, 467 insertions(+), 8 deletions(-)
 create mode 100644 elf/tst-audit25a.c
 create mode 100644 elf/tst-audit25b.c
 create mode 100644 elf/tst-audit25mod1.c
 create mode 100644 elf/tst-audit25mod2.c
 create mode 100644 elf/tst-audit25mod3.c
 create mode 100644 elf/tst-audit25mod4.c
 create mode 100644 elf/tst-auditmod25.c
diff mbox series

Patch

diff --git a/elf/Makefile b/elf/Makefile
index bfed7043a5..3e8adeee1d 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -228,6 +228,7 @@  tests += restest1 preloadtest loadfail multiload origtest resolvfail \
 	 tst-audit22 \
 	 tst-audit23 \
 	 tst-audit24a tst-audit24b tst-audit24c tst-audit24d \
+	 tst-audit25a tst-audit25b \
 	 tst-single_threaded tst-single_threaded-pthread \
 	 tst-tls-ie tst-tls-ie-dlmopen argv0test \
 	 tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
@@ -320,6 +321,8 @@  modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
 		tst-auditmod24c \
 		tst-auditmod24d tst-audit24dmod1 tst-audit24dmod2 \
 		tst-audit24dmod3 tst-audit24dmod4 \
+		tst-auditmod25 tst-audit25mod1 tst-audit25mod2 \
+		tst-audit25mod3 tst-audit25mod4 \
 		$(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
 		  tst-nodelete-uniquemod tst-nodelete-rtldmod \
 		  tst-nodelete-zmod \
@@ -1587,6 +1590,25 @@  LDFLAGS-tst-audit24dmod2.so = -Wl,-z,lazy
 tst-audit24d-ENV = LD_AUDIT=$(objpfx)tst-auditmod24d.so
 LDFLAGS-tst-audit24d = -Wl,-z,lazy
 
+$(objpfx)tst-audit25a.out: $(objpfx)tst-auditmod25.so
+$(objpfx)tst-audit25a: $(objpfx)tst-audit25mod1.so \
+		       $(objpfx)tst-audit25mod2.so \
+		       $(objpfx)tst-audit25mod3.so \
+		       $(objpfx)tst-audit25mod4.so
+$(objpfx)tst-audit25mod1.so: $(objpfx)tst-audit25mod3.so
+LDFLAGS-tst-audit25mod1.so = -Wl,-z,now
+$(objpfx)tst-audit25mod2.so: $(objpfx)tst-audit25mod4.so
+LDFLAGS-tst-audit25mod2.so = -Wl,-z,lazy
+tst-audit25a-ARGS = -- $(host-test-program-cmd)
+
+$(objpfx)tst-audit25b.out: $(objpfx)tst-auditmod25.so
+$(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \
+		       $(objpfx)tst-audit25mod2.so \
+		       $(objpfx)tst-audit25mod3.so \
+		       $(objpfx)tst-audit25mod4.so
+LDFLAGS-tst-audit25b = -Wl,-z,now
+tst-audit25b-ARGS = -- $(host-test-program-cmd)
+
 # tst-sonamemove links against an older implementation of the library.
 LDFLAGS-tst-sonamemove-linkmod1.so = \
   -Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index c3569cb357..920057fd1e 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
@@ -217,7 +217,7 @@  _dl_audit_symbind (struct link_map *l, struct reloc_result *reloc_result,
 
   const char *strtab2 = (const void *) D_PTR (result, l_info[DT_STRTAB]);
 
-  unsigned int flags = 0;
+  unsigned int flags = bindnow ? LA_SYMB_BINDNOW : 0;
   struct audit_ifaces *afct = GLRO(dl_audit);
   for (unsigned int cnt = 0; cnt < GLRO(dl_naudit); ++cnt)
     {
diff --git a/elf/dl-runtime.c b/elf/dl-runtime.c
index a0044b6776..e4b2185795 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 455e6a8b2e..af14ed3fb3 100644
--- a/elf/do-rel.h
+++ b/elf/do-rel.h
@@ -150,7 +150,7 @@  elf_dynamic_do_Rel (struct link_map *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);
+				       r_addr_arg, sym_map, true);
 		}
 #endif
 	    }
@@ -199,7 +199,7 @@  elf_dynamic_do_Rel (struct link_map *map,
 				   ELF_MACHINE_JMP_SLOT);
 		  if (sym != NULL)
 		    _dl_audit_symbind (map, &map->l_reloc_result[ri++], sym,
-				       r_addr_arg, sym_map);
+				       r_addr_arg, sym_map, true);
 		}
 # endif
 	    }
diff --git a/elf/link.h b/elf/link.h
index ff3a85c847..a4cd6864ad 100644
--- a/elf/link.h
+++ b/elf/link.h
@@ -131,8 +131,11 @@  enum
     LA_SYMB_NOPLTEXIT = 0x02,	/* la_pltexit will not be called.  */
     LA_SYMB_STRUCTCALL = 0x04,	/* Return value is a structure.  */
     LA_SYMB_DLSYM = 0x08,	/* Binding due to dlsym call.  */
-    LA_SYMB_ALTVALUE = 0x10	/* Value has been changed by a previous
+    LA_SYMB_ALTVALUE = 0x10,	/* Value has been changed by a previous
 				   la_symbind call.  */
+    LA_SYMB_BINDNOW = 0x20,	/* The symbol is resolved at loading time
+				   and it will not call neither la_pltenter
+				   not la_pltexit.  */
   };
 
 struct dl_phdr_info
diff --git a/elf/tst-audit25a.c b/elf/tst-audit25a.c
new file mode 100644
index 0000000000..88962091cd
--- /dev/null
+++ b/elf/tst-audit25a.c
@@ -0,0 +1,126 @@ 
+/* Check DT_AUDIT and LA_SYMB_NOW.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+void tst_audit25mod1_func1 (void);
+void tst_audit25mod1_func2 (void);
+void tst_audit25mod2_func1 (void);
+void tst_audit25mod2_func2 (void);
+
+static int
+handle_restart (void)
+{
+  tst_audit25mod1_func1 ();
+  tst_audit25mod1_func2 ();
+  tst_audit25mod2_func1 ();
+  tst_audit25mod2_func2 ();
+
+  return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+  size_t lenpre = strlen (pre);
+  size_t lenstr = strlen (str);
+  return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  /* We must have either:
+     - One our fource parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name  */
+
+  if (restart)
+    return handle_restart ();
+
+  setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
+
+  char *spargv[9];
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  spargv[i] = NULL;
+
+  {
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* tst-audit25a is build with -Wl,-z,lazy and tst-audit25mod1 with
+       -Wl,-z,now; so only tst_audit25mod3_func1 should be expected to
+       have LA_SYMB_BINDNOW.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 0\n"
+			 "la_symbind: tst_audit25mod1_func2 0\n"
+			 "la_symbind: tst_audit25mod2_func1 0\n"
+			 "la_symbind: tst_audit25mod4_func1 0\n"
+			 "la_symbind: tst_audit25mod2_func2 0\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  {
+    setenv ("LD_BIND_NOW", "1", 0);
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* With LD_BIND_NOW all symbols are expected to have LA_SYMB_BINDNOW.
+       Also the resolution order is done in breadth-first order.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod4_func1 32\n"
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 32\n"
+			 "la_symbind: tst_audit25mod2_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func2 32\n"
+			 "la_symbind: tst_audit25mod2_func2 32\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit25b.c b/elf/tst-audit25b.c
new file mode 100644
index 0000000000..ca441b7ac3
--- /dev/null
+++ b/elf/tst-audit25b.c
@@ -0,0 +1,127 @@ 
+/* Check DT_AUDIT and LA_SYMB_NOW.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <getopt.h>
+#include <limits.h>
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <support/capture_subprocess.h>
+#include <support/check.h>
+#include <support/xstdio.h>
+#include <support/support.h>
+#include <sys/auxv.h>
+
+static int restart;
+#define CMDLINE_OPTIONS \
+  { "restart", no_argument, &restart, 1 },
+
+void tst_audit25mod1_func1 (void);
+void tst_audit25mod1_func2 (void);
+void tst_audit25mod2_func1 (void);
+void tst_audit25mod2_func2 (void);
+
+static int
+handle_restart (void)
+{
+  tst_audit25mod1_func1 ();
+  tst_audit25mod1_func2 ();
+  tst_audit25mod2_func1 ();
+  tst_audit25mod2_func2 ();
+
+  return 0;
+}
+
+static inline bool
+startswith (const char *str, const char *pre)
+{
+  size_t lenpre = strlen (pre);
+  size_t lenstr = strlen (str);
+  return lenstr < lenpre ? false : memcmp (pre, str, lenpre) == 0;
+}
+
+static int
+do_test (int argc, char *argv[])
+{
+  /* We must have either:
+     - One our fource parameters left if called initially:
+       + path to ld.so         optional
+       + "--library-path"      optional
+       + the library path      optional
+       + the application name  */
+
+  if (restart)
+    return handle_restart ();
+
+  setenv ("LD_AUDIT", "tst-auditmod25.so", 0);
+
+  char *spargv[9];
+  int i = 0;
+  for (; i < argc - 1; i++)
+    spargv[i] = argv[i + 1];
+  spargv[i++] = (char *) "--direct";
+  spargv[i++] = (char *) "--restart";
+  spargv[i] = NULL;
+
+  {
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* tst-audit25a and tst-audit25mod1 are built with -Wl,-z,now, but
+       tst-audit25mod2 is built with -Wl,z,lazy.  So only
+       tst_audit25mod4_func1 (called by tst_audit25mod2_func1) should not
+       have LA_SYMB_BINDNOW.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 32\n"
+			 "la_symbind: tst_audit25mod2_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func2 32\n"
+			 "la_symbind: tst_audit25mod2_func2 32\n"
+			 "la_symbind: tst_audit25mod4_func1 0\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  {
+    setenv ("LD_BIND_NOW", "1", 0);
+    struct support_capture_subprocess result
+      = support_capture_subprogram (spargv[0], spargv);
+    support_capture_subprocess_check (&result, "tst-audit25a", 0,
+				      sc_allow_stderr);
+
+    /* With LD_BIND_NOW all symbols are expected to have LA_SYMB_BINDNOW.
+       Also the resolution order is done in breadth-first order.  */
+    TEST_COMPARE_STRING (result.err.buffer,
+			 "la_symbind: tst_audit25mod4_func1 32\n"
+			 "la_symbind: tst_audit25mod3_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func1 32\n"
+			 "la_symbind: tst_audit25mod2_func1 32\n"
+			 "la_symbind: tst_audit25mod1_func2 32\n"
+			 "la_symbind: tst_audit25mod2_func2 32\n");
+
+    support_capture_subprocess_free (&result);
+  }
+
+  return 0;
+}
+
+#define TEST_FUNCTION_ARGV do_test
+#include <support/test-driver.c>
diff --git a/elf/tst-audit25mod1.c b/elf/tst-audit25mod1.c
new file mode 100644
index 0000000000..9aa39ed325
--- /dev/null
+++ b/elf/tst-audit25mod1.c
@@ -0,0 +1,30 @@ 
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void tst_audit25mod3_func1 (void);
+
+void
+tst_audit25mod1_func1 (void)
+{
+  tst_audit25mod3_func1 ();
+}
+
+void
+tst_audit25mod1_func2 (void)
+{
+}
diff --git a/elf/tst-audit25mod2.c b/elf/tst-audit25mod2.c
new file mode 100644
index 0000000000..6d8e225fcc
--- /dev/null
+++ b/elf/tst-audit25mod2.c
@@ -0,0 +1,30 @@ 
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void tst_audit25mod4_func1 (void);
+
+void
+tst_audit25mod2_func1 (void)
+{
+  tst_audit25mod4_func1 ();
+}
+
+void
+tst_audit25mod2_func2 (void)
+{
+}
diff --git a/elf/tst-audit25mod3.c b/elf/tst-audit25mod3.c
new file mode 100644
index 0000000000..c0d5977fd8
--- /dev/null
+++ b/elf/tst-audit25mod3.c
@@ -0,0 +1,22 @@ 
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void
+tst_audit25mod3_func1 (void)
+{
+}
diff --git a/elf/tst-audit25mod4.c b/elf/tst-audit25mod4.c
new file mode 100644
index 0000000000..689ee5138f
--- /dev/null
+++ b/elf/tst-audit25mod4.c
@@ -0,0 +1,22 @@ 
+/* Modules used by tst-audit25.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+void
+tst_audit25mod4_func1 (void)
+{
+}
diff --git a/elf/tst-auditmod25.c b/elf/tst-auditmod25.c
new file mode 100644
index 0000000000..70b8ec4552
--- /dev/null
+++ b/elf/tst-auditmod25.c
@@ -0,0 +1,77 @@ 
+/* Audit modules for tst-audit25a.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+
+#define AUDIT25_COOKIE     0x1
+#define AUDIT25MOD1_COOKIE 0x2
+#define AUDIT25MOD2_COOKIE 0x3
+#define AUDIT25MOD3_COOKIE 0x2
+#define AUDIT25MOD4_COOKIE 0x3
+
+#define TEST_NAME "tst-audit25"
+#define TEST_MOD  "tst-audit25"
+#define TEST_FUNC "tst_audit25"
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  const char *p = strrchr (map->l_name, '/');
+  const char *l_name = p == NULL ? map->l_name : p + 1;
+  uintptr_t ck = -1;
+  if (strcmp (l_name, TEST_MOD "mod1.so") == 0)
+    ck = AUDIT25MOD1_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod2.so") == 0)
+    ck = AUDIT25MOD2_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod3.so") == 0)
+    ck = AUDIT25MOD3_COOKIE;
+  else if (strcmp (l_name, TEST_MOD "mod4.so") == 0)
+    ck = AUDIT25MOD4_COOKIE;
+  else if (strncmp (l_name, TEST_NAME, strlen (TEST_NAME)) == 0)
+    ck = AUDIT25_COOKIE;
+
+  *cookie = ck;
+  return ck == -1 ? 0 : LA_FLG_BINDFROM | LA_FLG_BINDTO;
+}
+
+#if __ELF_NATIVE_CLASS == 64
+uintptr_t
+la_symbind64 (Elf64_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#else
+uintptr_t
+la_symbind32 (Elf32_Sym *sym, unsigned int ndx,
+	      uintptr_t *refcook, uintptr_t *defcook,
+	      unsigned int *flags, const char *symname)
+#endif
+{
+  if (*refcook != -1 && *defcook != -1)
+    fprintf (stderr, "la_symbind: %s %u\n", symname, *flags);
+  return sym->st_value;
+}
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 0958084268..d0d9cf9535 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -1372,7 +1372,7 @@  void _dl_audit_objclose (struct link_map *l, Lmid_t nsid);
    link_map for the symbol resolved.  */
 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);
 /* Same as _dl_audit_symbind(), but called from the dlsym().  The flag
    LA_SYMB_DLSYM will be set before calling la_symbind() callback.  */
 void _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref,