mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00:00
ld.so: Support moving versioned symbols between sonames [BZ #24741]
This change should be fully backwards-compatible because the old code aborted the load if a soname mismatch was encountered (instead of searching further for a matching symbol). This means that no different symbols are found. The soname check was explicitly disabled for the skip_map != NULL case. However, this only happens with dl(v)sym and RTLD_NEXT, and those lookups do not come with a verneed entry that could be used for the check. The error check was already explicitly disabled for the skip_map != NULL case, that is, when dl(v)sym was called with RTLD_NEXT. But _dl_vsym always sets filename in the struct r_found_version argument to NULL, so the check was not active anyway. This means that symbol lookup results for the skip_map != NULL case do not change, either.
This commit is contained in:
parent
17432d7150
commit
f0b2132b35
29
ChangeLog
29
ChangeLog
@ -1,3 +1,32 @@
|
|||||||
|
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>
|
2019-06-28 Florian Weimer <fweimer@redhat.com>
|
||||||
|
|
||||||
* support/xdlfcn.h (xdlvsym): Declare function.
|
* support/xdlfcn.h (xdlvsym): Declare function.
|
||||||
|
6
NEWS
6
NEWS
@ -34,6 +34,12 @@ Major new features:
|
|||||||
pointer subtraction within the allocated object, where results might
|
pointer subtraction within the allocated object, where results might
|
||||||
overflow the ptrdiff_t type.
|
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:
|
Deprecated and removed features, and other changes affecting compatibility:
|
||||||
|
|
||||||
* The copy_file_range function fails with ENOSYS if the kernel does not
|
* The copy_file_range function fails with ENOSYS if the kernel does not
|
||||||
|
28
elf/Makefile
28
elf/Makefile
@ -191,7 +191,8 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
|
|||||||
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
|
||||||
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
|
||||||
tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
|
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
|
# reldep9
|
||||||
tests-internal += loadtest unload unload2 circleload1 \
|
tests-internal += loadtest unload unload2 circleload1 \
|
||||||
neededtest neededtest2 neededtest3 neededtest4 \
|
neededtest neededtest2 neededtest3 neededtest4 \
|
||||||
@ -281,7 +282,8 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
|
|||||||
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
|
tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
|
||||||
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
tst-main1mod tst-libc_dlvsym-dso tst-absolute-sym-lib \
|
||||||
tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-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
|
# Most modules build with _ISOMAC defined, but those filtered out
|
||||||
# depend on internal headers.
|
# depend on internal headers.
|
||||||
modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\
|
modules-names-tests = $(filter-out ifuncmod% tst-libc_dlvsym-dso tst-tlsmod%,\
|
||||||
@ -1410,6 +1412,28 @@ $(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so
|
|||||||
LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy
|
LDFLAGS-tst-audit13mod1.so = -Wl,-z,lazy
|
||||||
tst-audit13-ENV = LD_AUDIT=$(objpfx)tst-audit13mod1.so
|
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.
|
# Override -z defs, so that we can reference an undefined symbol.
|
||||||
# Force lazy binding for the same reason.
|
# Force lazy binding for the same reason.
|
||||||
LDFLAGS-tst-latepthreadmod.so = \
|
LDFLAGS-tst-latepthreadmod.so = \
|
||||||
|
@ -536,11 +536,7 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
|
|||||||
}
|
}
|
||||||
|
|
||||||
skip:
|
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);
|
while (++i < n);
|
||||||
|
|
||||||
@ -810,34 +806,10 @@ _dl_lookup_symbol_x (const char *undef_name, struct link_map *undef_map,
|
|||||||
|
|
||||||
/* Search the relevant loaded objects for a definition. */
|
/* Search the relevant loaded objects for a definition. */
|
||||||
for (size_t start = i; *scope != NULL; start = 0, ++scope)
|
for (size_t start = i; *scope != NULL; start = 0, ++scope)
|
||||||
{
|
if (do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
||||||
int res = do_lookup_x (undef_name, new_hash, &old_hash, *ref,
|
¤t_value, *scope, start, version, flags,
|
||||||
¤t_value, *scope, start, version, flags,
|
skip_map, type_class, undef_map) != 0)
|
||||||
skip_map, type_class, undef_map);
|
break;
|
||||||
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 (__glibc_unlikely (current_value.s == NULL))
|
if (__glibc_unlikely (current_value.s == NULL))
|
||||||
{
|
{
|
||||||
|
35
elf/tst-sonamemove-dlopen.c
Normal file
35
elf/tst-sonamemove-dlopen.c
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/* 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>
|
41
elf/tst-sonamemove-link.c
Normal file
41
elf/tst-sonamemove-link.c
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/* 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>
|
25
elf/tst-sonamemove-linkmod1.c
Normal file
25
elf/tst-sonamemove-linkmod1.c
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
}
|
3
elf/tst-sonamemove-linkmod1.map
Normal file
3
elf/tst-sonamemove-linkmod1.map
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SONAME_MOVE {
|
||||||
|
global: moved_function;
|
||||||
|
};
|
23
elf/tst-sonamemove-runmod1.c
Normal file
23
elf/tst-sonamemove-runmod1.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
}
|
3
elf/tst-sonamemove-runmod1.map
Normal file
3
elf/tst-sonamemove-runmod1.map
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SONAME_MOVE {
|
||||||
|
global: other_function;
|
||||||
|
};
|
24
elf/tst-sonamemove-runmod2.c
Normal file
24
elf/tst-sonamemove-runmod2.c
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
}
|
3
elf/tst-sonamemove-runmod2.map
Normal file
3
elf/tst-sonamemove-runmod2.map
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
SONAME_MOVE {
|
||||||
|
global: moved_function;
|
||||||
|
};
|
Loading…
Reference in New Issue
Block a user