This is the mail archive of the glibc-bugs@sourceware.org mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[Bug dynamic-link/16628] New: Segfault after a binary without pthread dlopen()s a library linked with pthread


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

            Bug ID: 16628
           Summary: Segfault after a binary without pthread dlopen()s a
                    library linked with pthread
           Product: glibc
           Version: 2.12
            Status: NEW
          Severity: normal
          Priority: P2
         Component: dynamic-link
          Assignee: unassigned at sourceware dot org
          Reporter: tudorb at gmail dot com

If the main executable is linked without pthread dlopen()s a shared library
linked with pthread, it causes a memory corruption in the dynamic loader. When
a symbol resolution fails afterwards, you get a segfault rather than a message
on stderr (and clean _exit()).

Explanation:

When the main executable is linked without pthread and it dlopen()s s shared
library linked with pthread, pthread initialization
(__pthread_initialize_minimal_internal) happens during loading, with a dynamic
loader error handler (_dl_catch_error) on the stack.

__pthread_initialize_minimal_internal switches the location of the error
handling jmp_buf (returned by the function at _dl_error_catch_tsd) from the
non-thread-aware one (_dl_initial_error_catch_tsd) to the thread-aware one
(__libc_dl_error_tsd). It also copies the location of the current error
handling buffer, if any, to the thread-specific version. As _dl_catch_error is
on the stack at this point, we store the address of that error handling jmp_buf
into the thread-specific location.

After __pthread_initialize_minimal_internal returns, control eventually reaches
back to _dl_catch_error, which is supposed to restore the previous handler
(which should be NULL). But it restores the previous handler into the wrong
location -- it restores it where it saved it from (the global,
not-thread-specific, location, as returned by _dl_initial_error_catch_tsd), and
we're using the thread-specific location now.

So the thread-specific location now contains garbage. Next time we try to
signal an error from a dl* function, we try to longjmp to that garbage, and we
segfault.

Steps to reproduce (also see attached files):

- create a shared library that has an unresolved symbol and links with pthread
- from a main executable that links without pthread, dlopen the shared library
with RTLD_LAZY
- force the unresolved symbol from the shared library to be resolved.

Attached: a .zip with three files:

b.c: shared library
main.c: main program
mk: script to build them

Tested on 2.12 and 2.17.1.

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]