Bug 17162 - Glibc 2.5 segfault in ld-2.5.so
Summary: Glibc 2.5 segfault in ld-2.5.so
Status: RESOLVED INVALID
Alias: None
Product: glibc
Classification: Unclassified
Component: dynamic-link (show other bugs)
Version: unspecified
: P2 critical
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-07-16 10:27 UTC by Shafreeck Sea
Modified: 2014-07-18 08:21 UTC (History)
0 users

See Also:
Host:
Target:
Build:
Last reconfirmed:
fweimer: security-


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Shafreeck Sea 2014-07-16 10:27:42 UTC
OS: 
Linux xxx.net 2.6.32-2.0.0.6-5 #25 SMP Fri Dec 21 10:09:40 CST 2012 x86_64 x86_64 x86_64 GNU/Linux
CentOS release 5.4 (Final

Glibc:
2.5

dmesg:
php-fpm[10645]: segfault at 2559 ip 000000398a6145b2 sp 00007fff24057f08 error 4 in ld-2.5.so[398a600000+1c000]

backtrace:
#0  0x000000398a607dbb in _dl_map_object () from /lib64/ld-linux-x86-64.so.2
#1  0x000000398a610c4d in dl_open_worker () from /lib64/ld-linux-x86-64.so.2
#2  0x000000398a60ce96 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#3  0x000000398a61064c in _dl_open () from /lib64/ld-linux-x86-64.so.2
#4  0x000000398ab08ab0 in do_dlopen () from /lib64/libc.so.6
#5  0x000000398a60ce96 in _dl_catch_error () from /lib64/ld-linux-x86-64.so.2
#6  0x000000398ab08c17 in __libc_dlopen_mode () from /lib64/libc.so.6
#7  0x000000398aae3960 in __nss_lookup_function () from /lib64/libc.so.6
#8  0x000000398aae42a1 in __nss_next2 () from /lib64/libc.so.6
#9  0x000000398aae9e8e in gethostbyname2_r@@GLIBC_2.2.5 () from /lib64/libc.so.6
#10 0x000000398aabc523 in gaih_inet () from /lib64/libc.so.6
#11 0x000000398aabd62a in getaddrinfo () from /lib64/libc.so.6
#12 0x00007f76008847f2 in Curl_getaddrinfo_ex () from /usr/local/curl/lib/libcurl.so.4
#13 0x00007f760087fd34 in Curl_ipv4_resolve_r () from /usr/local/curl/lib/libcurl.so.4
#14 0x00007f760087fd89 in Curl_getaddrinfo () from /usr/local/curl/lib/libcurl.so.4
#15 0x00007f7600854955 in Curl_resolv () from /usr/local/curl/lib/libcurl.so.4
#16 0x00007f7600854a41 in Curl_resolv_timeout () from /usr/local/curl/lib/libcurl.so.4
#17 0x00007f7600864778 in resolve_server () from /usr/local/curl/lib/libcurl.so.4
#18 0x00007f76008669e0 in create_conn () from /usr/local/curl/lib/libcurl.so.4
#19 0x00007f7600867209 in Curl_connect () from /usr/local/curl/lib/libcurl.so.4
#20 0x00007f76008763eb in Curl_do_perform () from /usr/local/curl/lib/libcurl.so.4
#21 0x00007f7600aa2683 in zif_curl_exec (ht=<value optimized out>, return_value=0x1049998, return_value_ptr=<value optimized out>, this_ptr=<value optimized out>, 
    return_value_used=<value optimized out>) at /usr/src/redhat/BUILD/php-5.3.27/ext/curl/interface.c:2320
#22 0x000000000058b996 in zend_do_fcall_common_helper_SPEC ()
#23 0x000000000058b0ae in execute ()
#24 0x0000000000563109 in zend_execute_scripts ()
#25 0x000000000050fa28 in php_execute_script ()
#26 0x00000000005f53c4 in main ()

I used gdb to try to find out the problem and I found that there is something wrong here in _dl_map_object:
soname = ((const char *) D_PTR (l, l_info[DT_STRTAB])
            + l->l_info[DT_SONAME]->d_un.d_val);

The value of D_PTR (l, l_info[DT_STRTAB]) is the offset of the shared object file without being relocated which caused the segfault .

(gdb) x /10xg 0x7f75f5db71a0 (l_info[DT_STRTAB]) $rax
0x7f75f5db71a0: 0x0000000000000005      0x0000000000001898
0x7f75f5db71b0: 0x0000000000000006      0x0000000000000560
0x7f75f5db71c0: 0x000000000000000a      0x0000000000000cf8
0x7f75f5db71d0: 0x000000000000000b      0x0000000000000018
0x7f75f5db71e0: 0x0000000000000003      0x0000000000216350

(gdb) x /10x 0x00007f75f5db7160 (l_info[DT_SONAME]) $rdx
0x7f75f5db7160: 0x000000000000000e      0x0000000000000cc1
0x7f75f5db7170: 0x000000000000000c      0x0000000000003728
0x7f75f5db7180: 0x000000000000000d      0x00000000000110a8
0x7f75f5db7190: 0x000000006ffffef5      0x0000000000000158
0x7f75f5db71a0: 0x0000000000000005      0x0000000000001898

The soname address is 0x0cc1 + 0x1898 = 0x2559, which is the offset of file :
hexdump -C /usr/local/lib/libzookeeper_mt.so.2.0.0
...
00002550  69 62 63 2e 73 6f 2e 36  00 6c 69 62 7a 6f 6f 6b  |ibc.so.6.libzook|
00002560  65 65 70 65 72 5f 6d 74  2e 73 6f 2e 32 00 47 4c  |eeper_mt.so.2.GL|
...

And libzookeeper_mt.so.2.0.0 in fact was mmaped at :
7f75f5ba1000-7f75f5bb7000 r-xp 00000000 ca:41 15288827                   /usr/local/lib/libzookeeper_mt.so.2.0.0

So the really address is 0x7f75f5ba1000+0x2559
(gdb) x /s  0x7f75f5ba1000+0x2559
0x7f75f5ba3559:  "libzookeeper_mt.so.2"

Is this a bug in glibc ?
Comment 1 Andreas Schwab 2014-07-16 10:41:40 UTC
Glibc 2.5 is no longer maintained.  Please try 2.15 or later.
Comment 2 Shafreeck Sea 2014-07-16 10:59:10 UTC
(In reply to Andreas Schwab from comment #1)
> Glibc 2.5 is no longer maintained.  Please try 2.15 or later.

OK, but I have a question about dynamic loader:
Everything works well when first start up , and something wrong occured after running a long time (months maybe). So I am wondering whether the "so" will be unloaded when not being used after a long time and reloaded when nessaray ?
Comment 3 Shafreeck Sea 2014-07-18 08:21:19 UTC
OK, I have found the reason.
It's not glibc's problem . The segmentation was caused by overwriting a loaded shared object file.