This is the mail archive of the
glibc-bugs@sourceware.org
mailing list for the glibc project.
[Bug dynamic-link/15271] New: dlmopen()ed shared library with LM_ID_NEWLM crashes if it fails dlsym() twice
- From: "brnguyen at nvidia dot com" <sourceware-bugzilla at sourceware dot org>
- To: glibc-bugs at sourceware dot org
- Date: Tue, 12 Mar 2013 17:22:45 +0000
- Subject: [Bug dynamic-link/15271] New: dlmopen()ed shared library with LM_ID_NEWLM crashes if it fails dlsym() twice
- Auto-submitted: auto-generated
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.