On 10 September 2017 at 15:03, Guillem Jover <guil...@debian.org> wrote: > Control: tag -1 moreinfo > > Hi! > > On Thu, 2017-09-07 at 16:16:49 +0100, Dimitri John Ledkov wrote: >> Package: dpkg >> Version: 1.18.24 >> Severity: important > >> I am attaching the objdump to this bug report. In that log, one can >> see that the highest symbol referenced by Dynamic symbol table is for >> GLIBC_2.17 which is the dependency dpkg-shlibs generates. >> >> However, in the `Version References' section, one can see that >> GLIBC_2.25 is required. >> >> The net result is that libc6 (>= 2.17) is generated, instead of the >> required libc6 (>= 2.25). >> >> The binaries are not executable when e.g. 2.24 glibc is installed and >> fail like so: >> >> # ldd /usr/sbin/NetworkManager >> /usr/sbin/NetworkManager: /lib/x86_64-linux-gnu/libc.so.6: version >> `GLIBC_2.25' not found (required by /usr/sbin/NetworkManager) >> >> I am not sure how glibc managed to generate a Version reference, >> without using any of the dynamic symbols from 2.25. > > I've built and checked the resulting binary, by objdump'ing everything > I could think of, and I was unable to see why the version reference > had been picked up. > >> Reading the code, it seems like maybe dpkg-shlibdeps needs to grow the >> ability to parse "Version References" section of the objdump and use >> version symbols referenced there to bump up requirements just like >> dynamic symbols do? > > Before doing that I'd like to first understand why that is the case, if > it's expected and not a bug in the toolchain or similar. >
That is a very reasonable question. Given that the version dep is 2.25 I went through the glibc abi lists to see what was new in 2.25. A few things from those are referenced in the NetworkManager but unused (e.g. makedev()) and thus did not gain a dep (e.g dropping that function did not result in getting the ABI back lower). However, in the partial embedded copy of systemd there is embeded implementation of explicit_bzero if glibc does not provide one. It seems that NetworkManager included the declaration check too in their configure.ac such that with glibc 2.25+ explicit_bzero from libc starts to be referenced. However, in the end, none of the bits that NetworkManager actual use hit the string_erase function and thus do not call explicit_bzero. Thus it looks like compiler did compile / link usage of explicit_bzero, and eventually dropped it, yet version info persistent to the end binaries/libraries. With the attached patch, builds of network-manager end up not having GLIBC_2.25 version reference. Is this normal toolchain behaviour to not optimise out version references, when all symbols are optimised out? The code is crazy, but I would have expected optimised out things to remove version references too. -- Regards, Dimitri.
Description: Drop code referencing explicit_bzero Author: Dimitri John Ledkov <x...@ubuntu.com> Bug-Debian: https://bugs.debian.org/874585 Bug-Ubuntu: https://bugs.launchpad.net/bugs/1715641 --- a/configure.ac +++ b/configure.ac @@ -62,12 +62,6 @@ AC_CHECK_SIZEOF(dev_t) AC_CHECK_SIZEOF(time_t) -AC_CHECK_DECLS([ - explicit_bzero], - [], [], [[ -#include <string.h> -]]) - dnl dnl translation support dnl --- a/config.h.in +++ b/config.h.in @@ -34,10 +34,6 @@ */ #undef HAVE_DCGETTEXT -/* Define to 1 if you have the declaration of `explicit_bzero', and to 0 if - you don't. */ -#undef HAVE_DECL_EXPLICIT_BZERO - /* Define to 1 if you have the <dlfcn.h> header file. */ #undef HAVE_DLFCN_H --- a/src/systemd/src/basic/string-util.c +++ b/src/systemd/src/basic/string-util.c @@ -825,36 +825,6 @@ return 1; } -#if !HAVE_DECL_EXPLICIT_BZERO -/* - * Pointer to memset is volatile so that compiler must de-reference - * the pointer and can't assume that it points to any function in - * particular (such as memset, which it then might further "optimize") - * This approach is inspired by openssl's crypto/mem_clr.c. - */ -typedef void *(*memset_t)(void *,int,size_t); - -static volatile memset_t memset_func = memset; - -void explicit_bzero(void *p, size_t l) { - memset_func(p, '\0', l); -} -#endif - -char* string_erase(char *x) { - if (!x) - return NULL; - - /* A delicious drop of snake-oil! To be called on memory where - * we stored passphrases or so, after we used them. */ - explicit_bzero(x, strlen(x)); - return x; -} - -char *string_free_erase(char *s) { - return mfree(string_erase(s)); -} - bool string_is_safe(const char *p) { const char *t; --- a/src/systemd/src/basic/string-util.h +++ b/src/systemd/src/basic/string-util.h @@ -189,14 +189,4 @@ return memmem(haystack, haystacklen, needle, needlelen); } -#if !HAVE_DECL_EXPLICIT_BZERO -void explicit_bzero(void *p, size_t l); -#endif - -char *string_erase(char *x); - -char *string_free_erase(char *s); -DEFINE_TRIVIAL_CLEANUP_FUNC(char *, string_free_erase); -#define _cleanup_string_free_erase_ _cleanup_(string_free_erasep) - bool string_is_safe(const char *p) _pure_; --- a/src/systemd/src/basic/strv.c +++ b/src/systemd/src/basic/strv.c @@ -92,15 +92,6 @@ return mfree(l); } -char **strv_free_erase(char **l) { - char **i; - - STRV_FOREACH(i, l) - string_erase(*i); - - return strv_free(l); -} - char **strv_copy(char * const *l) { char **r, **k; --- a/src/systemd/src/basic/strv.h +++ b/src/systemd/src/basic/strv.h @@ -37,10 +37,6 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free); #define _cleanup_strv_free_ _cleanup_(strv_freep) -char **strv_free_erase(char **l); -DEFINE_TRIVIAL_CLEANUP_FUNC(char**, strv_free_erase); -#define _cleanup_strv_free_erase_ _cleanup_(strv_free_erasep) - void strv_clear(char **l); char **strv_copy(char * const *l);