From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 27790 invoked by alias); 12 Mar 2013 17:23:15 -0000 Received: (qmail 27724 invoked by uid 48); 12 Mar 2013 17:22:47 -0000 From: "brnguyen at nvidia dot com" To: glibc-bugs@sourceware.org Subject: [Bug dynamic-link/15271] New: dlmopen()ed shared library with LM_ID_NEWLM crashes if it fails dlsym() twice Date: Tue, 12 Mar 2013 17:23: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-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: brnguyen at nvidia 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-Changed-Fields: Message-ID: X-Bugzilla-URL: http://sourceware.org/bugzilla/ Auto-Submitted: auto-generated Content-Type: text/plain; charset="UTF-8" MIME-Version: 1.0 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 X-SW-Source: 2013-03/txt/msg00054.txt.bz2 http://sourceware.org/bugzilla/show_bug.cgi?id=15271 Bug #: 15271 Summary: dlmopen()ed shared library with LM_ID_NEWLM crashes if it fails dlsym() twice Product: glibc Version: unspecified Status: NEW Severity: normal Priority: P2 Component: dynamic-link AssignedTo: unassigned@sourceware.org ReportedBy: brnguyen@nvidia.com Classification: Unclassified Created attachment 6929 --> http://sourceware.org/bugzilla/attachment.cgi?id=6929 Test case, and patch which appears to work around the crash The attached test case loads a dummy DSO using dlmopen() with LM_ID_NEWLM; the library's constructor, in turn, calls dlsym() with bogus symbol names twice. This reproduces a segfault in ld-2.15.so on my 64-bit Ubuntu 12.04 LTS system, kernel 3.2.0-26-generic. I confirmed this also reproduces on an ld.so built from git commit 72a3b700c592d39e0e76cd75b2c5ff483e70e083. Investigating further, it appears that different instances of libc were used to allocate and free the error string used internally by dlerror(). In my reproduction using this test case, with the following maps file: 00400000-00401000 r-xp 00000000 08:11 3722707 /home/brnguyen/bugs/1188502/dlmopen_bug_debug/dlmopen_test 00600000-00601000 r--p 00000000 08:11 3722707 /home/brnguyen/bugs/1188502/dlmopen_bug_debug/dlmopen_test 00601000-00602000 rw-p 00001000 08:11 3722707 /home/brnguyen/bugs/1188502/dlmopen_bug_debug/dlmopen_test 555555554000-555555575000 r-xp 00000000 08:11 3728093 /home/brnguyen/bin/glibc-build/elf/ld.so 555555774000-555555775000 r--p 00020000 08:11 3728093 /home/brnguyen/bin/glibc-build/elf/ld.so 555555775000-555555777000 rw-p 00021000 08:11 3728093 /home/brnguyen/bin/glibc-build/elf/ld.so 555555777000-555555798000 rw-p 00000000 00:00 0 [heap] 7ffff6f8e000-7ffff6f90000 r-xp 00000000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff6f90000-7ffff7190000 ---p 00002000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7190000-7ffff7191000 r--p 00002000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7191000-7ffff7192000 rw-p 00003000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7192000-7ffff7339000 r-xp 00000000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff7339000-7ffff7538000 ---p 001a7000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff7538000-7ffff753c000 r--p 001a6000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff753c000-7ffff753e000 rw-p 001aa000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff753e000-7ffff7542000 rw-p 00000000 00:00 0 7ffff7542000-7ffff763e000 r-xp 00000000 08:11 3729959 /home/brnguyen/bin/glibc-build/lib/libm-2.17.90.so 7ffff763e000-7ffff783e000 ---p 000fc000 08:11 3729959 /home/brnguyen/bin/glibc-build/lib/libm-2.17.90.so 7ffff783e000-7ffff783f000 r--p 000fc000 08:11 3729959 /home/brnguyen/bin/glibc-build/lib/libm-2.17.90.so 7ffff783f000-7ffff7840000 rw-p 000fd000 08:11 3729959 /home/brnguyen/bin/glibc-build/lib/libm-2.17.90.so 7ffff7840000-7ffff7842000 r--p 00000000 08:11 3729060 /home/brnguyen/bin/glibc-build/etc/ld.so.cache 7ffff7842000-7ffff7843000 r-xp 00000000 08:11 3722702 /home/brnguyen/bugs/1188502/dlmopen_bug_debug/dummy.so.1 7ffff7843000-7ffff7a42000 ---p 00001000 08:11 3722702 /home/brnguyen/bugs/1188502/dlmopen_bug_debug/dummy.so.1 7ffff7a42000-7ffff7a43000 rw-p 00000000 08:11 3722702 /home/brnguyen/bugs/1188502/dlmopen_bug_debug/dummy.so.1 7ffff7a43000-7ffff7a46000 rw-p 00000000 00:00 0 7ffff7a46000-7ffff7bed000 r-xp 00000000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff7bed000-7ffff7dec000 ---p 001a7000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff7dec000-7ffff7df0000 r--p 001a6000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff7df0000-7ffff7df2000 rw-p 001aa000 08:11 3416152 /home/brnguyen/bin/glibc-build/libc.so 7ffff7df2000-7ffff7df6000 rw-p 00000000 00:00 0 7ffff7df6000-7ffff7df8000 r-xp 00000000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7df8000-7ffff7ff8000 ---p 00002000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7ff8000-7ffff7ff9000 r--p 00002000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7ff9000-7ffff7ffa000 rw-p 00003000 08:11 3730007 /home/brnguyen/bin/glibc-build/lib/libdl-2.17.90.so 7ffff7ffa000-7ffff7ffb000 rw-p 00000000 00:00 0 7ffff7ffc000-7ffff7ffe000 rw-p 00000000 00:00 0 7ffff7ffe000-7ffff7fff000 r-xp 00000000 00:00 0 [vdso] 7ffffffdd000-7ffffffff000 rw-p 00000000 00:00 0 [stack] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall] elf/dl-error.c:_dl_signal_error(), which allocates the error string, lives in ld.so within the application's namespace: (gdb) p $pc $22 = (void (*)()) 0x555555562161 <_dl_signal_error+113> (gdb) p __GI__dl_find_dso_for_object($pc) $23 = (struct link_map *) 0x5555557759d8 (gdb) p $->l_ns $25 = 0 But the instance of dlfcn/dlerror.c:_dlerror_run() which clears the error lives in libdl.so within the dummy library's new namespace: (gdb) p $pc $27 = (void (*)()) 0x7ffff6f8f460 <_dlerror_run> (gdb) p __GI__dl_find_dso_for_object($pc) $28 = (struct link_map *) 0x555555778020 (gdb) p $->l_ns $30 = 1 For some reason, calling dlerror() in between the two dlsym() calls appears to work around this crash. I attempted to investigate this, but haven't determined why this suppresses the segfault. There is an existing helper function in dlerror.c called check_free(), which first checks if the caller is using the base link map before attempting to free the error string. In the included patch, I have replaced direct invocations of free() with check_free() in _dlerror_run() as well as __dlerror(); I verified this patch fixed the segfault on my system. -- Configure bugmail: http://sourceware.org/bugzilla/userprefs.cgi?tab=email ------- You are receiving this mail because: ------- You are on the CC list for the bug.