[PATCH 1/8] elf: Fix auditor iteration in _dl_audit_symbind_alt (BZ 34684)

Adhemerval Zanella adhemerval.zanella@linaro.org
Mon Sep 28 18:55:05 GMT 2026


The loop only moved to the next auditor when the current one handled
the binding.  If an earlier auditor did not request it, a later
interested auditor had the earlier auditor's la_symbind called with its
cookies instead, and never saw the dlsym binding itself.

This is a regression from cda4f265c65f.

Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
arm-linux-gnueabihf, alpha-linux-gnu, hppa-linux-gnu,
loongarch64-linux-gnu, mips64el-linux-gnu, powerpc64-linux-gnu,
powerpc64le-linux-gnu, riscv64-linux-gnu, s390x-linux-gnu, and
sparc64-linux-gnu.
---
 elf/Makefile                       | 11 +++++++
 elf/dl-audit.c                     |  6 ++--
 elf/tst-audit-symbind-dlsym-mod.c  | 19 ++++++++++++
 elf/tst-audit-symbind-dlsym.c      | 35 +++++++++++++++++++++
 elf/tst-auditmod-symbind-dlsym-a.c | 50 ++++++++++++++++++++++++++++++
 elf/tst-auditmod-symbind-dlsym-b.c | 50 ++++++++++++++++++++++++++++++
 6 files changed, 168 insertions(+), 3 deletions(-)
 create mode 100644 elf/tst-audit-symbind-dlsym-mod.c
 create mode 100644 elf/tst-audit-symbind-dlsym.c
 create mode 100644 elf/tst-auditmod-symbind-dlsym-a.c
 create mode 100644 elf/tst-auditmod-symbind-dlsym-b.c

diff --git a/elf/Makefile b/elf/Makefile
index 79321d6a91d..9a0cdf42e69 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -406,6 +406,7 @@ tests += \
   tst-align \
   tst-align2 \
   tst-align3 \
+  tst-audit-symbind-dlsym \
   tst-audit-tlsdesc \
   tst-audit-tlsdesc-dlopen \
   tst-audit-tlsdesc-dlopen2 \
@@ -911,6 +912,7 @@ modules-names += \
   tst-alignmod3 \
   tst-array2dep \
   tst-array5dep \
+  tst-audit-symbind-dlsym-mod \
   tst-audit-tlsdesc-mod1 \
   tst-audit-tlsdesc-mod2 \
   tst-audit11mod1 \
@@ -946,6 +948,8 @@ modules-names += \
   tst-auditmanymod7 \
   tst-auditmanymod8 \
   tst-auditmanymod9 \
+  tst-auditmod-symbind-dlsym-a \
+  tst-auditmod-symbind-dlsym-b \
   tst-auditmod-tlsdesc  \
   tst-auditmod-tlsdesc2 \
   tst-auditmod1 \
@@ -2863,6 +2867,13 @@ $(objpfx)tst-audit28.out: $(objpfx)tst-auditmod28.so
 $(objpfx)tst-auditmod28.so: $(libsupport)
 tst-audit28-ENV = LD_AUDIT=$(objpfx)tst-auditmod28.so
 
+$(objpfx)tst-audit-symbind-dlsym.out: \
+  $(objpfx)tst-audit-symbind-dlsym-mod.so \
+  $(objpfx)tst-auditmod-symbind-dlsym-a.so \
+  $(objpfx)tst-auditmod-symbind-dlsym-b.so
+tst-audit-symbind-dlsym-ENV = \
+  LD_AUDIT=$(objpfx)tst-auditmod-symbind-dlsym-a.so:$(objpfx)tst-auditmod-symbind-dlsym-b.so
+
 # tst-sonamemove links against an older implementation of the library.
 LDFLAGS-tst-sonamemove-linkmod1.so = \
   -Wl,--version-script=tst-sonamemove-linkmod1.map \
diff --git a/elf/dl-audit.c b/elf/dl-audit.c
index aadc8ecc797..9c79b175b84 100644
--- a/elf/dl-audit.c
+++ b/elf/dl-audit.c
@@ -165,12 +165,12 @@ _dl_audit_symbind_alt (struct link_map *l, const ElfW(Sym) *ref, void **value,
 	      altvalue = LA_SYMB_ALTVALUE;
 	      sym.st_value = new_value;
 	    }
-
-	  afct = afct->next;
 	}
 
-      *value = (void *) sym.st_value;
+      afct = afct->next;
     }
+
+  *value = (void *) sym.st_value;
 }
 rtld_hidden_def (_dl_audit_symbind_alt)
 
diff --git a/elf/tst-audit-symbind-dlsym-mod.c b/elf/tst-audit-symbind-dlsym-mod.c
new file mode 100644
index 00000000000..08a119e8f92
--- /dev/null
+++ b/elf/tst-audit-symbind-dlsym-mod.c
@@ -0,0 +1,19 @@
+/* Module for tst-audit-symbind-dlsym.
+   Copyright (C) 2026 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/>.  */
+
+const int tst_audit_symbind_dlsym_data[] = { 0, 1, 2 };
diff --git a/elf/tst-audit-symbind-dlsym.c b/elf/tst-audit-symbind-dlsym.c
new file mode 100644
index 00000000000..aa7b162ae5b
--- /dev/null
+++ b/elf/tst-audit-symbind-dlsym.c
@@ -0,0 +1,35 @@
+/* Check la_symbind dispatch for dlsym with multiple auditors.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <dlfcn.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+  void *h = xdlopen ("tst-audit-symbind-dlsym-mod.so", RTLD_NOW);
+  const int *p = xdlsym (h, "tst_audit_symbind_dlsym_data");
+  /* 1 means only the second auditor was called; 2 means the first
+     one was called instead.  */
+  TEST_COMPARE (*p, 1);
+  xdlclose (h);
+  return 0;
+}
+
+#include <support/test-driver.c>
diff --git a/elf/tst-auditmod-symbind-dlsym-a.c b/elf/tst-auditmod-symbind-dlsym-a.c
new file mode 100644
index 00000000000..17fb3bfbe21
--- /dev/null
+++ b/elf/tst-auditmod-symbind-dlsym-a.c
@@ -0,0 +1,50 @@
+/* Auditor for tst-audit-symbind-dlsym that does not request any binding.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <string.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  return 0;
+}
+
+#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 ((*flags & LA_SYMB_DLSYM) != 0
+      && strcmp (symname, "tst_audit_symbind_dlsym_data") == 0)
+    return sym->st_value + 2 * sizeof (int);
+  return sym->st_value;
+}
diff --git a/elf/tst-auditmod-symbind-dlsym-b.c b/elf/tst-auditmod-symbind-dlsym-b.c
new file mode 100644
index 00000000000..196ef5811d7
--- /dev/null
+++ b/elf/tst-auditmod-symbind-dlsym-b.c
@@ -0,0 +1,50 @@
+/* Auditor for tst-audit-symbind-dlsym that requests all bindings.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <link.h>
+#include <string.h>
+
+unsigned int
+la_version (unsigned int version)
+{
+  return LAV_CURRENT;
+}
+
+unsigned int
+la_objopen (struct link_map *map, Lmid_t lmid, uintptr_t *cookie)
+{
+  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)
+#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 ((*flags & LA_SYMB_DLSYM) != 0
+      && strcmp (symname, "tst_audit_symbind_dlsym_data") == 0)
+    return sym->st_value + 1 * sizeof (int);
+  return sym->st_value;
+}
-- 
2.53.0



More information about the Libc-alpha mailing list