This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] ld.so: Support moving versioned symbols between sonames [BZ #24741]
- From: Yann Droneaud <ydroneaud at opteya dot com>
- To: Florian Weimer <fweimer at redhat dot com>, libc-alpha at sourceware dot org
- Date: Thu, 27 Jun 2019 18:07:58 +0200
- Subject: Re: [PATCH] ld.so: Support moving versioned symbols between sonames [BZ #24741]
- References: <87woh7t7f7.fsf@oldenburg2.str.redhat.com>
Hi,
Le jeudi 27 juin 2019 à 16:43 +0200, Florian Weimer a écrit :
> 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.
>
> 2019-06-27 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,
> 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 against tst-sonamemove-linkmod1.so.
> (tst-sonamemove.out): Depend on tst-sonamemove-runmod1.so,
> tst-sonamemove-runmod2.so.
> (tst-sonamemove-dlopen.out): Likewise.
> * elf/tst-sonamemove.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.
> * support/xdlfcn.h (xdlvsym): Declare function.
> * support/xdlfcn.c (xdlvsym): Define funciton.
>
> diff --git a/NEWS b/NEWS
> index 8a2fecef47..8cea9f5825 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -34,6 +34,12 @@ Major new features:
> 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 functions clock_gettime, clock_getres, clock_settime,
> diff --git a/elf/Makefile b/elf/Makefile
> index 27a2fa8c14..76b0565054 100644
> --- a/elf/Makefile
> +++ b/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-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 tst-sonamemove-dlopen
tst-sonamemove could be name tst-sonamemove-link to make obvious the
difference with -dlopen.
> # reldep9
> tests-internal += loadtest unload unload2 circleload1 \
> 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-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%,\
> @@ -1410,6 +1412,28 @@ $(objpfx)tst-audit13.out: $(objpfx)tst-audit13mod1.so
> 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: $(objpfx)tst-sonamemove-linkmod1.so
> +$(objpfx)tst-sonamemove.out: \
> + $(objpfx)tst-sonamemove-runmod1.so \
> + $(objpfx)tst-sonamemove-runmod2.so
> +$(objpfx)tst-sonamemove-dlopen: $(libdl)
> +$(objpfx)tst-sonamemove.out: \
> + $(objpfx)tst-sonamemove-runmod1.so \
> + $(objpfx)tst-sonamemove-runmod2.so
> +
The last three lines duplicate those above.
> # Override -z defs, so that we can reference an undefined symbol.
> # Force lazy binding for the same reason.
> LDFLAGS-tst-latepthreadmod.so = \
[...]
> diff --git a/elf/tst-sonamemove-dlopen.c b/elf/tst-sonamemove-dlopen.c
> new file mode 100644
> index 0000000000..c496705044
> --- /dev/null
> +++ b/elf/tst-sonamemove-dlopen.c
> @@ -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>
> diff --git a/elf/tst-sonamemove-linkmod1.c b/elf/tst-sonamemove-linkmod1.c
> new file mode 100644
> index 0000000000..b8a354e5e3
> --- /dev/null
> +++ b/elf/tst-sonamemove-linkmod1.c
> @@ -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)
> +{
> +}
> diff --git a/elf/tst-sonamemove-linkmod1.map b/elf/tst-sonamemove-linkmod1.map
> new file mode 100644
> index 0000000000..8fe5904018
> --- /dev/null
> +++ b/elf/tst-sonamemove-linkmod1.map
> @@ -0,0 +1,3 @@
> +SONAME_MOVE {
> + global: moved_function;
> +};
> diff --git a/elf/tst-sonamemove-runmod1.c b/elf/tst-sonamemove-runmod1.c
> new file mode 100644
> index 0000000000..5c409e2289
> --- /dev/null
> +++ b/elf/tst-sonamemove-runmod1.c
> @@ -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)
> +{
> +}
> diff --git a/elf/tst-sonamemove-runmod1.map b/elf/tst-sonamemove-runmod1.map
> new file mode 100644
> index 0000000000..2ea81c6e6f
> --- /dev/null
> +++ b/elf/tst-sonamemove-runmod1.map
> @@ -0,0 +1,3 @@
> +SONAME_MOVE {
> + global: other_function;
> +};
> diff --git a/elf/tst-sonamemove-runmod2.c b/elf/tst-sonamemove-runmod2.c
> new file mode 100644
> index 0000000000..b5e482eff5
> --- /dev/null
> +++ b/elf/tst-sonamemove-runmod2.c
> @@ -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)
> +{
> +}
> diff --git a/elf/tst-sonamemove-runmod2.map b/elf/tst-sonamemove-runmod2.map
> new file mode 100644
> index 0000000000..8fe5904018
> --- /dev/null
> +++ b/elf/tst-sonamemove-runmod2.map
> @@ -0,0 +1,3 @@
> +SONAME_MOVE {
> + global: moved_function;
> +};
> diff --git a/elf/tst-sonamemove.c b/elf/tst-sonamemove.c
> new file mode 100644
> index 0000000000..a80ebcb36f
> --- /dev/null
> +++ b/elf/tst-sonamemove.c
> @@ -0,0 +1,30 @@
> +/* 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/>;. */
> +
> +/* moved_function is linked against tst-sonamemove-runmod1.so, but the
> + actual implementation is in tst-sonamemove-runmod1.so. */
I found this comment unclear. tst-sonamemove is linked against tst-
sonamemove-linkmod1.so, which has tst-sonamemove-runmod1.so soname.
When tst-sonamemove is run, tst-sonamemove-runmod1.so is loaded, which
imply loading tst-sonamemove-runmod2.so as a dependency. tst-
sonamemove-runmod2.so is where move_function's implementation is.
> +void moved_function (void);
> +
> +static int
> +do_test (void)
> +{
> + moved_function ();
> + return 0;
> +}
> +
> +#include <support/test-driver.c>
Regards.
--
Yann Droneaud
OPTEYA