[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