From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17739 invoked by alias); 24 Feb 2014 01:13:47 -0000 Mailing-List: contact glibc-bugs-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: glibc-bugs-owner@sourceware.org Received: (qmail 17705 invoked by uid 48); 24 Feb 2014 01:13:43 -0000 From: "tudorb at gmail dot com" To: glibc-bugs@sourceware.org Subject: [Bug dynamic-link/16628] New: Segfault after a binary without pthread dlopen()s a library linked with pthread Date: Mon, 24 Feb 2014 01:13:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: glibc X-Bugzilla-Component: dynamic-link X-Bugzilla-Version: 2.12 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: tudorb at gmail dot com X-Bugzilla-Status: NEW X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at sourceware dot org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2014-02/txt/msg00718.txt.bz2 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.