public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug dynamic-link/17769] New: The program interpreter should not call static initializers in PIE binaries
@ 2014-12-28 12:51 stijnv at gmail dot com
  2014-12-28 12:56 ` [Bug dynamic-link/17769] " stijnv at gmail dot com
  2021-12-04 15:25 ` fweimer at redhat dot com
  0 siblings, 2 replies; 3+ messages in thread
From: stijnv at gmail dot com @ 2014-12-28 12:51 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=17769

            Bug ID: 17769
           Summary: The program interpreter should not call static
                    initializers in PIE binaries
           Product: glibc
           Version: 2.19
            Status: NEW
          Keywords: glibc_2.19
          Severity: normal
          Priority: P2
         Component: dynamic-link
          Assignee: unassigned at sourceware dot org
          Reporter: stijnv at gmail dot com

Hello,

I've been seeing the following problem for a while now. It has been posted on
other bugtrackers, e.g.
https://code.google.com/p/chromium/issues/detail?id=394508 , but even though
this particular bugtracker says the problem is fixed, it is not fixed for me.

Whenever gcc compiles a program as PIE, its ELF type is set to ET_DYN. While
this isn't a problem on its own, it does make ld-linux.so falsely believe that
the program is a shared library. Observe for example the following program:

  #include <stdio.h>
  void __attribute__((constructor)) pie_init() {
    printf("I am a PIE binary and this is my constructor!\n");
  }
  int main(int argc, char** argv) {
    printf("Hello!\n");
    return 0;
  }

When compiled as PIE and invoked directly I get:

  $ gcc -ggdb -o i_like_pie -fPIE -pie i_like_pie.c
  $ ./i_like_pie 
  I am a PIE binary and this is my constructor!
  Hello!

This is the expected output. However, when invoked through the interpreter, I
get:

  $ /lib/ld-linux.so.2 ./i_like_pie
  I am a PIE binary and this is my constructor!
  I am a PIE binary and this is my constructor!
  Hello!

This is certainly not the correct output. If the program is not compiled as
PIE, I get the same output in both cases (direct invocation and invocation
through the program interpreter). This is hardly surprising, as the call_init
function, which invokes the initializers checks:

  /* Check for object which constructors we do not run here.  */
  if (__builtin_expect (l->l_name[0], 'a') == '\0'
      && l->l_type == lt_executable)
    return;

For non-PIE binaries, the l_type is indeed lt_executable. For PIE binaries, the
l_type is lt_library. The root cause for this problem lies in elf/rtld.c. If
the program is loaded directly, the interpreter simply creates the main map as
follows:

  /* Create a link_map for the executable itself. 
  This will be what dlopen on "" returns.  */
  main_map = _dl_new_object ((char *) "", "", lt_executable, NULL, 
    __RTLD_OPENEXEC, LM_ID_BASE);

However, if the program is interpreter loads the program instead, it does:

  _dl_map_object (NULL, rtld_progname, lt_library, 0, 
    __RTLD_OPENEXEC, LM_ID_BASE);

  /* ... */
  /* Now the map for the main executable is available.  */
  main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;

The problem here is that _dl_map_object will actually read l_type from the ELF
header, wheras dl_new_object will use whatever l_type you pass to it. I see no
reason why l_type shouldn't be set to lt_executable if a program is loaded
indirecty, even if the program you're attempting to load is in fact a shared
library.

The following patch fixes the problem for me:

$ diff -up glibc-2.19.orig/elf/rtld.c glibc-2.19/elf/rtld.c 
--- glibc-2.19.orig/elf/rtld.c    2014-12-09 16:38:51.929980899 +0100
+++ glibc-2.19/elf/rtld.c    2014-12-28 13:20:18.613821869 +0100
@@ -1085,6 +1085,11 @@ of this helper program; chances are you
       /* Now the map for the main executable is available.  */
       main_map = GL(dl_ns)[LM_ID_BASE]._ns_loaded;

+      /* Make sure that the type for the main binary is lt_executable, 
+     even if it says ET_DYN in the header. This way we won't call the
+     static initializers twice for PIE binaries */
+      main_map->l_type = lt_executable;
+
       if (__builtin_expect (mode, normal) == normal
       && GL(dl_rtld_map).l_info[DT_SONAME] != NULL
       && main_map->l_info[DT_SONAME] != NULL

Regards,
Stijn

-- 
You are receiving this mail because:
You are on the CC list for the bug.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug dynamic-link/17769] The program interpreter should not call static initializers in PIE binaries
  2014-12-28 12:51 [Bug dynamic-link/17769] New: The program interpreter should not call static initializers in PIE binaries stijnv at gmail dot com
@ 2014-12-28 12:56 ` stijnv at gmail dot com
  2021-12-04 15:25 ` fweimer at redhat dot com
  1 sibling, 0 replies; 3+ messages in thread
From: stijnv at gmail dot com @ 2014-12-28 12:56 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=17769

--- Comment #1 from Stijn Volckaert <stijnv at gmail dot com> ---
My apologies for the typo. The following line:

"However, if the program is interpreter loads the program instead, it does:"

should have read:

"However, if the interpreter loads the program instead, it does:"

-- 
You are receiving this mail because:
You are on the CC list for the bug.


^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Bug dynamic-link/17769] The program interpreter should not call static initializers in PIE binaries
  2014-12-28 12:51 [Bug dynamic-link/17769] New: The program interpreter should not call static initializers in PIE binaries stijnv at gmail dot com
  2014-12-28 12:56 ` [Bug dynamic-link/17769] " stijnv at gmail dot com
@ 2021-12-04 15:25 ` fweimer at redhat dot com
  1 sibling, 0 replies; 3+ messages in thread
From: fweimer at redhat dot com @ 2021-12-04 15:25 UTC (permalink / raw)
  To: glibc-bugs

https://sourceware.org/bugzilla/show_bug.cgi?id=17769

Florian Weimer <fweimer at redhat dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
         Resolution|---                         |DUPLICATE
             Status|NEW                         |RESOLVED
                 CC|                            |fweimer at redhat dot com

--- Comment #2 from Florian Weimer <fweimer at redhat dot com> ---
Fixed in commit 798212a01311491d5e14fcda687460b75f8ca286.

*** This bug has been marked as a duplicate of bug 16381 ***

-- 
You are receiving this mail because:
You are on the CC list for the bug.

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2021-12-04 15:25 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-12-28 12:51 [Bug dynamic-link/17769] New: The program interpreter should not call static initializers in PIE binaries stijnv at gmail dot com
2014-12-28 12:56 ` [Bug dynamic-link/17769] " stijnv at gmail dot com
2021-12-04 15:25 ` fweimer at redhat dot com

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).