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);

Reply via email to