+2019-06-28 Florian Weimer <fweimer@redhat.com>
+
+ [BZ #24741]
+ * elf/dl-lookup.c (do_lookup_x): Do not fail if there is a soname
+ mismatch in a versioned symbol reference.
+ (_dl_lookup_symbol_x): Do not report soname mismatch failures.
+ * elf/Makefile [$(build-shared)] (tests): Add tst-sonamemove-link,
+ tst-sonamemove-dlopen.
+ (module-names): Add tst-sonamemove-linkmod1,
+ tst-sonamemove-runmod1, tst-sonamemove-runmod2.
+ (LDFLAGS-tst-sonamemove-linkmod1.so): Set.
+ (LDFLAGS-tst-sonamemove-runmod1.so): Likewise.
+ (LDFLAGS-tst-sonamemove-runmod2.so): Likewise.
+ (tst-sonamemove-runmod1.so): Link against
+ tst-sonamemove-runmod2.so.
+ (tst-sonamemove-link): Link against tst-sonamemove-linkmod1.so.
+ (tst-sonamemove-link.out): Depend on tst-sonamemove-runmod1.so,
+ tst-sonamemove-runmod2.so.
+ (tst-sonamemove-dlopen): Link with -ldl.
+ (tst-sonamemove-dlopen.out): Likewise.
+ * elf/tst-sonamemove-link.c: New file.
+ * elf/tst-sonamemove-dlopen.c: Likewise.
+ * elf/tst-sonamemove-linkmod1.c: Likewise.
+ * elf/tst-sonamemove-linkmod1.map: Likewise.
+ * elf/tst-sonamemove-runmod1.c: Likewise.
+ * elf/tst-sonamemove-runmod1.map: Likewise.
+ * elf/tst-sonamemove-runmod2.c: Likewise.
+ * elf/tst-sonamemove-runmod2.map: Likewise.
+
2019-06-28 Florian Weimer <fweimer@redhat.com>
* support/xdlfcn.h (xdlvsym): Declare function.
pointer subtraction within the allocated object, where results might
overflow the ptrdiff_t type.
+* The dynamic linker no longer refuses to load objects which reference
+ versioned symbols whose implementation has moved to a different soname
+ since the object has been linked. The old error message, symbol
+ FUNCTION-NAME, version SYMBOL-VERSION not defined in file DSO-NAME with
+ link time reference, is gone.
+
Deprecated and removed features, and other changes affecting compatibility:
* The copy_file_range function fails with ENOSYS if the kernel does not
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
- tst-unwind-ctor tst-unwind-main tst-audit13
+ tst-unwind-ctor tst-unwind-main tst-audit13 \
+ tst-sonamemove-link tst-sonamemove-dlopen
# reldep9
tests-internal += loadtest unload unload2 circleload1 \
neededtest neededtest2 neededtest3 neededtest4 \
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib \
- tst-audit13mod1
+ tst-audit13mod1 tst-sonamemove-linkmod1 \
+ tst-sonamemove-runmod1 tst-sonamemove-runmod2
# Most modules build with _ISOMAC defined, but those filtered out
# depend on internal headers.
modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\
LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy
tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so
+# tst-sonamemove links against an older implementation of the library.
+LDFLAGS-tst-sonamemove-linkmod1.so = \
+ -Wl,--version-script=tst-sonamemove-linkmod1.map \
+ -Wl,-soname,tst-sonamemove-runmod1.so
+LDFLAGS-tst-sonamemove-runmod1.so = -Wl,--no-as-needed \
+ -Wl,--version-script=tst-sonamemove-runmod1.map \
+ -Wl,-soname,tst-sonamemove-runmod1.so
+LDFLAGS-tst-sonamemove-runmod2.so = \
+ -Wl,--version-script=tst-sonamemove-runmod2.map \
+ -Wl,-soname,tst-sonamemove-runmod2.so
+$(objpfx)tst-sonamemove-runmod1.so: $(objpfx)tst-sonamemove-runmod2.so
+# Link against the link module, but depend on the run-time modules
+# for execution.
+$(objpfx)tst-sonamemove-link: $(objpfx)tst-sonamemove-linkmod1.so
+$(objpfx)tst-sonamemove-link.out: \
+ $(objpfx)tst-sonamemove-runmod1.so \
+ $(objpfx)tst-sonamemove-runmod2.so
+$(objpfx)tst-sonamemove-dlopen: $(libdl)
+$(objpfx)tst-sonamemove-dlopen.out: \
+ $(objpfx)tst-sonamemove-runmod1.so \
+ $(objpfx)tst-sonamemove-runmod2.so
+
# Override -z defs, so that we can reference an undefined symbol.
# Force lazy binding for the same reason.
LDFLAGS-tst-latepthreadmod.so = \
}
skip:
- /* If this current map is the one mentioned in the verneed entry
- and we have not found a weak entry, it is a bug. */
- if (symidx == STN_UNDEF && version != NULL && version->filename != NULL
- && __glibc_unlikely (_dl_name_match_p (version->filename, map)))
- return -1;
+ ;
}
while (++i < n);
/* Search the relevant loaded objects for a definition. */
for (size_t start = i; *scope != NULL; start = 0, ++scope)
- {
- int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
- ¤t_value, *scope, start, version, flags,
- skip_map, type_class, undef_map);
- if (res > 0)
- break;
-
- if (__glibc_unlikely (res < 0) && skip_map == NULL)
- {
- /* Oh, oh. The file named in the relocation entry does not
- contain the needed symbol. This code is never reached
- for unversioned lookups. */
- assert (version != NULL);
- const char *reference_name = undef_map ? undef_map->l_name : "";
- struct dl_exception exception;
- /* XXX We cannot translate the message. */
- _dl_exception_create_format
- (&exception, DSO_FILENAME (reference_name),
- "symbol %s version %s not defined in file %s"
- " with link time reference%s",
- undef_name, version->name, version->filename,
- res == -2 ? " (no version symbols)" : "");
- _dl_signal_cexception (0, &exception, N_("relocation error"));
- _dl_exception_free (&exception);
- *ref = NULL;
- return 0;
- }
- }
+ if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
+ ¤t_value, *scope, start, version, flags,
+ skip_map, type_class, undef_map) != 0)
+ break;
if (__glibc_unlikely (current_value.s == NULL))
{
--- /dev/null
+/* Check that a moved versioned symbol can be found using dlsym, dlvsym.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+#include <stddef.h>
+#include <support/check.h>
+#include <support/xdlfcn.h>
+
+static int
+do_test (void)
+{
+ /* tst-sonamemove-runmod1.so does not define moved_function, but it
+ depends on tst-sonamemove-runmod2.so, which does. */
+ void *handle = xdlopen ("tst-sonamemove-runmod1.so", RTLD_NOW);
+ TEST_VERIFY (xdlsym (handle, "moved_function") != NULL);
+ TEST_VERIFY (xdlvsym (handle, "moved_function", "SONAME_MOVE") != NULL);
+
+ return 0;
+}
+
+#include <support/test-driver.c>
--- /dev/null
+/* Check that a versioned symbol can move from one library to another.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* At link time, moved_function is bound to the symbol version
+ SONAME_MOVE in tst-sonamemove-runmod1.so, using the
+ tst-sonamemove-linkmod1.so stub object.
+
+ At run time, the process loads the real tst-sonamemove-runmod1.so,
+ which depends on tst-sonamemove-runmod2.so.
+ tst-sonamemove-runmod1.so does not define moved_function, but
+ tst-sonamemove-runmod2.so does.
+
+ The net effect is that the versioned symbol
+ moved_function@SONAME_MOVE moved from the soname
+ tst-sonamemove-linkmod1.so at link time to the soname
+ tst-sonamemove-linkmod2.so at run time. */
+void moved_function (void);
+
+static int
+do_test (void)
+{
+ moved_function ();
+ return 0;
+}
+
+#include <support/test-driver.c>
--- /dev/null
+/* Link interface for (lack of) soname matching in versioned symbol refs.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* This function moved from tst-sonamemove-runmod1.so. This module is
+ intended for linking only, to simulate an old application which was
+ linked against an older version of the library. */
+void
+moved_function (void)
+{
+}
--- /dev/null
+SONAME_MOVE {
+ global: moved_function;
+};
--- /dev/null
+/* Run-time module whose moved_function moved to a library dependency.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* Dummy function to add the required symbol version. */
+void
+other_function (void)
+{
+}
--- /dev/null
+SONAME_MOVE {
+ global: other_function;
+};
--- /dev/null
+/* Run-time module with the actual implementation of moved_function.
+ Copyright (C) 2019 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
+ <http://www.gnu.org/licenses/>. */
+
+/* In the test scenario, this function was originally in
+ tst-sonamemove-runmod1.so. */
+void
+moved_function (void)
+{
+}
--- /dev/null
+SONAME_MOVE {
+ global: moved_function;
+};