This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug dynamic-link/16628] New: Segfault after a binary without pthread dlopen()s a library linked with pthread
- From: "tudorb at gmail dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Mon, 24 Feb 2014 01:13:41 +0000
- Subject: [Bug dynamic-link/16628] New: Segfault after a binary without pthread dlopen()s a library linked with pthread
- Auto-submitted: auto-generated
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.