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/15271] New: dlmopen()ed shared library with LM_ID_NEWLM crashes if it fails dlsym() twice


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.


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