libc6 version 2.19 breaks NSS loading for static binaries

Bug #1821752 reported by Marc Deslauriers on 2019-03-26
6
This bug affects 1 person
Affects Status Importance Assigned to Milestone
eglibc
Fix Released
Medium
eglibc (Debian)
Fix Released
Unknown
eglibc (Ubuntu)
Undecided
Unassigned

it looks like the change landed for bug 16046 broke static dlopening of nss modules. if you try to use getaddrinfo/getpwnam/etc..., they just return errors immediately.

example tests:
$ cat test.c
#include <sys/types.h>
#include <pwd.h>
#include <stdio.h>
int main() {
    void *p = getpwnam("root");
    printf("%p\n", p);
    return p == NULL ? 1 : 0;
}

$ gcc test.c && ./a.out
0x7f6aec59a0e0
$ gcc -static test.c && ./a.out
(nil)

$ cat test.c
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netdb.h>
#include <string.h>

int main(int argc, char *argv[])
{
        const char *host = argv[1];
        int rc;
        struct addrinfo *result = NULL;
        struct addrinfo hint;

        memset(&hint, 0 , sizeof(hint));
        hint.ai_family = AF_INET;
        hint.ai_socktype = SOCK_STREAM;
        hint.ai_flags = AF_UNSPEC;
        rc = getaddrinfo(host, NULL, &hint, &result);
        if (rc || !result) {
                printf("bad address '%s'\n", host);
                return 1;
        } else
                return 0;
}

$ gcc test.c && ./a.out localhost
$ gcc -static test.c && ./a.out localhost
bad address 'localhost'

bisecting more, it looks like it's specifically the change to elf/dl-iteratephdr.c that breaks things (where it changes from a custom dl_iterate_phdr to a weak alias of __dl_iterate_phdr). if i revert that change alone, the tests start working again.

I confirm that the breakage has been introduced by the following commit:

commit 0d23a5c1b1908700d25b7e3c6cece148e19dded4
Author: Maciej W. Rozycki <email address hidden>
Date: Fri Jan 31 17:51:31 2014 +0000

    [BZ #16046] Static dlopen correction fallout fixes.

    Fixes to address issues from BZ #15022 resolution, as follows:

    * TLS updates to csu/libc-tls.c -- we now have a proper main map, so
      there's no longer a need to create a separate fake one to keep TLS
      structures,

    * random updates to elf/dl-close.c -- LM_ID_BASE is now a valid name
      space ID for static executables as well, so assert that we don't
      unload the main map. Similarly dl_nns isn't supposed to be 0 for
      static executables anymore,

    * actual BZ #16046 fix to elf/dl-iteratephdr.c -- the dl_iterate_phdr
      special function for static executables isn't needed anymore, provided
      that l_phdr and l_phnum members of the main map have been properly
      initialized (done in _dl_non_dynamic_init in elf/dl-support.c now),

    * ld.so.cache loader update to elf/dl-load.c --
      GL(dl_ns)[LM_ID_BASE]._ns_loaded is now always initialized in static
      executables so can become the fallback loader map to check for
      DF_1_NODEFLIB, provided that the l_flags_1 member of the main map has
      been properly initialized (done in elf/dl-support.c now); this also
      ensures previous semantics elsewhere in elf/dl-load.c,

    * matching updates to elf/dl-support.c -- to complement the two fixes
      above.

The problem seems to be related to the trusted directories. As long as the generated file elf/trusted-dirs.h contains a path matching the NSS modules location, they are not even load. Changing these paths to not match the NSS modules location make the NSS modules to work again.

Looking more at the code the new behaviour is actually wanted. Statically linked binaries do not lookup in the default lib search patch by default (DF_1_NODEFLIB is defined as "Ignore default lib search path."):

--- a/elf/dl-support.c
+++ b/elf/dl-support.c
@@ -91,6 +91,7 @@ static struct link_map _dl_main_map =
     .l_scope = _dl_main_map.l_scope_mem,
     .l_local_scope = { &_dl_main_map.l_searchlist },
     .l_used = 1,
+ .l_flags_1 = DF_1_NODEFLIB,
     .l_tls_offset = NO_TLS_OFFSET,
     .l_serial = 1,
   };

This means that the dlopen calls from nss/nsswitch.c do not look for the default search path. In addition to that it means that the dlopen behavior for static binaries also has changed and doesn't support loading objects without an absolute path. This is conform to the POSIX specification ("Otherwise, file is used in an implementation-defined manner to yield a pathname."), but do we really want such a behavior change?

Concerning the NSS support we should probably switch it to an absolute path. In the meantime this can be workarounded by using LD_LIBRARY_PATH

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, master has been updated
       via 93bad7c97c7047ecaf7664859e2b49c0fe995443 (commit)
      from f6987f5aa4c2ef7270bcb0a828808bd3db53520b (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=93bad7c97c7047ecaf7664859e2b49c0fe995443

commit 93bad7c97c7047ecaf7664859e2b49c0fe995443
Author: Maciej W. Rozycki <email address hidden>
Date: Fri Sep 25 09:37:12 2015 +0100

    [BZ #17250] Fix static dlopen default library search path

    Fix a regression introduced with commit 0d23a5c1 [Static dlopen
    correction fallout fixes] that caused the default library search path to
    be ignored for modules loaded with dlopen from static executables.

     [BZ #17250]
     * elf/dl-support.c (_dl_main_map): Don't initialize l_flags_1
     member.

-----------------------------------------------------------------------

Summary of changes:
 ChangeLog | 6 ++++++
 NEWS | 12 ++++++------
 elf/dl-support.c | 1 -
 3 files changed, 12 insertions(+), 7 deletions(-)

Fixed on trunk as per the commit message.

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The branch, gentoo/2.22 has been updated
       via adf228f91c11a1bcdf7563d104a2a370d054e482 (commit)
      from ca6a9ce6151759981cc2efd58e053148c7db2fea (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
https://sourceware.org/git/gitweb.cgi?p=glibc.git;h=adf228f91c11a1bcdf7563d104a2a370d054e482

commit adf228f91c11a1bcdf7563d104a2a370d054e482
Author: Maciej W. Rozycki <email address hidden>
Date: Fri Sep 25 09:37:12 2015 +0100

    [BZ #17250] Fix static dlopen default library search path

    Fix a regression introduced with commit 0d23a5c1 [Static dlopen
    correction fallout fixes] that caused the default library search path to
    be ignored for modules loaded with dlopen from static executables.

     [BZ #17250]
     * elf/dl-support.c (_dl_main_map): Don't initialize l_flags_1
     member.

    (cherry picked from commit 93bad7c97c7047ecaf7664859e2b49c0fe995443)

-----------------------------------------------------------------------

Summary of changes:
 elf/dl-support.c | 1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

Download full text (62.9 KiB)

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU C Library master sources".

The annotated tag, glibc-2.23 has been created
        at 10ed3a0ffbb43ce0b0739da4addc747733be5e63 (tag)
   tagging ab30899d880f9741a409cbc0d7a28399bdac21bf (commit)
  replaces glibc-2.22
 tagged by Adhemerval Zanella
        on Thu Feb 18 16:04:58 2016 -0200

- Log -----------------------------------------------------------------
The GNU C Library
=================

The GNU C Library version 2.23 is now available.

The GNU C Library is used as *the* C library in the GNU system and
in GNU/Linux systems, as well as many other systems that use Linux
as the kernel.

The GNU C Library is primarily designed to be a portable
and high performance C library. It follows all relevant
standards including ISO C11 and POSIX.1-2008. It is also
internationalized and has one of the most complete
internationalization interfaces known.

The GNU C Library webpage is at http://www.gnu.org/software/libc/

Packages for the 2.23 release may be downloaded from:
        http://ftpmirror.gnu.org/libc/
        http://ftp.gnu.org/gnu/libc/

The mirror list is at http://www.gnu.org/order/ftp.html

NEWS for version 2.23
=====================

* Unicode 8.0.0 Support: Character encoding, character type info, and
  transliteration tables are all updated to Unicode 8.0.0, using new
  and/or improved generator scripts contributed by Mike FABIAN (Red Hat).
  These updates cause user visible changes, such as the fixes for bugs
  89, 16061, and 18568.

* sched_setaffinity, pthread_setaffinity_np no longer attempt to guess the
  kernel-internal CPU set size. This means that requests that change the
  CPU affinity which failed before (for example, an all-ones CPU mask) will
  now succeed. Applications that need to determine the effective CPU
  affinities need to call sched_getaffinity or pthread_getaffinity_np after
  setting it because the kernel can adjust it (and the previous size check
  would not detect this in the majority of cases).

* The fts.h header can now be used with -D_FILE_OFFSET_BITS=64. With LFS
  the following new symbols are used: fts64_children, fts64_close,
  fts64_open, fts64_read and fts64_set.

* getaddrinfo now detects certain invalid responses on an internal netlink
  socket. If such responses are received, an affected process will
  terminate with an error message of "Unexpected error <number> on netlink
  descriptor <number>" or "Unexpected netlink response of size <number> on
  descriptor <number>". The most likely cause for these errors is a
  multi-threaded application which erroneously closes and reuses the netlink
  file descriptor while it is used by getaddrinfo.

* A defect in the malloc implementation, present since glibc 2.15 (2012) or
  glibc 2.10 via --enable-experimental-malloc (2009), could result in the
  unnecessary serialization of memory allocation requests across threads.
  The defect is now corrected. Users should see a substantial increase in
  the concurent throughput of allocation requests for applications which
  trigger this bug. ...

Changed in eglibc:
importance: Unknown → Medium
status: Unknown → Fix Released
Changed in eglibc (Debian):
status: Unknown → Fix Released
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package eglibc - 2.19-0ubuntu6.15

---------------
eglibc (2.19-0ubuntu6.15) trusty-security; urgency=medium

  * Fix NSS loading for static binaries (LP: #1821752)
    - debian/patches/any/local-static-dlopen-search-path.diff: fix static
      dlopen default library search path in elf/dl-support.c.

 -- Marc Deslauriers <email address hidden> Tue, 26 Mar 2019 09:53:00 -0400

Changed in eglibc (Ubuntu):
status: New → Fix Released
To post a comment you must log in.
This report contains Public information  Edit
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.