public inbox for glibc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug dynamic-link/16628] New: Segfault after a binary without pthread dlopen()s a library linked with pthread
@ 2014-02-24  1:13 tudorb at gmail dot com
  2014-02-24  1:14 ` [Bug dynamic-link/16628] " tudorb at gmail dot com
                   ` (6 more replies)
  0 siblings, 7 replies; 8+ messages in thread
From: tudorb at gmail dot com @ 2014-02-24  1:13 UTC (permalink / raw)
  To: glibc-bugs

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.


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

end of thread, other threads:[~2015-02-18 14:45 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-24  1:13 [Bug dynamic-link/16628] New: Segfault after a binary without pthread dlopen()s a library linked with pthread tudorb at gmail dot com
2014-02-24  1:14 ` [Bug dynamic-link/16628] " tudorb at gmail dot com
2014-02-24  1:16 ` tudorb at gmail dot com
2014-02-24  4:51 ` bugdal at aerifal dot cx
2014-02-24 20:19 ` carlos at redhat dot com
2014-03-14 14:14 ` amonakov at gmail dot com
2014-06-13  8:09 ` fweimer at redhat dot com
2015-02-18 14:45 ` 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).