2

我最近在调试产品中的崩溃,并确定原因是 glibc 和 tcmalloc 暴露的内存分配符号冲突。我编写了以下示例代码来暴露此问题:

#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <assert.h>
#include <stdlib.h>

int main()
{
        struct addrinfo hints = {0}, *res = NULL;
        hints.ai_family = AF_UNSPEC;
        hints.ai_socktype = SOCK_STREAM;
        int rc = getaddrinfo("myserver", NULL, &hints, &res);
        assert(rc == 0);
        return 0;
}

我使用以下命令编译它:

g++ temp.cpp -g -lresolv

我使用以下命令执行了程序:

LD_PRELOAD=/path/to/libtcmalloc_minimal.so.4 ./a.out

该程序因以下堆栈而崩溃:

#0 0x00007ffff6c7c875 in *__GI_raise (sig=) at ../nptl/sysdeps/unix/sysv/linux/raise.c:64

#1 0x00007ffff6c7de51 在 *__GI_abort () at abort.c:92

#2 0x00007ffff6cbd8bf in __libc_message (do_abort=2, fmt=0x7ffff6d8c460 "*** glibc detected *** %s: %s: 0x%s ***\n") at ../sysdeps/unix/sysv/linux/ libc_fatal.c:186

#3 0x00007ffff6cc30c8 in malloc_printerr (action=2, str=0x7ffff6d88fec "free(): invalid pointer", ptr=) at malloc.c:6282

#4 0x00007ffff6cc810c in *__GI___libc_free (mem=) at malloc.c:3733

#5 0x00007ffff6839e89 in _nss_dns_gethostbyname4_r (name=0x400814 "myserver", pat=0x7fffffffdfa8, buffer=0x7fffffffd9b0 "myserver.mydomain.com", buflen=1024, errnop=0x7fffffffdfbc, herrnop=0x7fffffffdf98, ttlp=0x0) at nss_dns/dns-host .c:341

#6 0x00007ffff6d11917 in gaih_inet (name=0x400814 "myserver", service=0x7fffffffdf88, req=0x7ffffffffe1d0, pai=0x7ffffffffe160, naddrs=0x7ffffffffe168) at ../sysdeps/posix/getaddrinfo.c:880

#7 0x00007ffff6d14301 in *__GI_getaddrinfo (name=0x400814 "myserver", service=0x0, hints=0x7ffffffffe1d0, pai=0x7ffffffffe200) at ../sysdeps/posix/getaddrinfo.c:2452

#8 0x00000000004006f0 在 main () at temp.cpp:12

原因是 from 调用的函数free()是from ,而对应的函数是from调用的。tcmalloc 的地址和函数正在进入导致这次崩溃的 GOT。如果我不将我的程序链接到._nss_dns_gethostbyname4_r()libnss_dns.solibc.somalloc()libresolv.solibtcmalloc_minimal.somalloc()free()libresolv.solibresolv.so

现在我的问题。是否有任何文档解释如何安全地使用 tcmalloc 来避免这样的崩溃?

4

1 回答 1

3

glibc 有一些用于插入的文档malloc

不过,这里肯定有其他事情发生。典型的 glibc 和 glibc 构建将正确地做到这一点(即使在任何一个包的相当旧的版本中)。

我最好的猜测是您正在使用一些RTLD_DEEPBIND用于 NSS 模块的SUSE glibc 变体。这会导致interposition的一个已知问题malloc。SUSE 建议RTLD_DEEPBIND=0环境变量设置为解决方法。

于 2018-06-15T11:49:45.620 回答