Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

dlopen with RTLD_DEEPBIND causes crash #1148

Open
gusain opened this issue Sep 20, 2019 · 7 comments
Open

dlopen with RTLD_DEEPBIND causes crash #1148

gusain opened this issue Sep 20, 2019 · 7 comments

Comments

@gusain
Copy link

gusain commented Sep 20, 2019

test.tar.gz

After spending good amount of time on a crash which originates from third party software which is complete blackbox, I finally understand what went wrong and I have created a tiny test case for it.
Steps to reproduce:
% untar
% make all TCMALLOC_STATIC_LIB=
% a.out

And it crashes like this

*** glibc detected *** ./a.out: free(): invalid pointer: 0x0000000001bc6018 ***
======= Backtrace: =========
/lib64/libc.so.6[0x3250a75e5e]
/lib64/libc.so.6[0x3250a78cad]
./libtest.so(destroy+0x18)[0x7f7770afa1fb]
./a.out[0x4042e1]
/lib64/libc.so.6(__libc_start_main+0x100)[0x3250a1ed20]
./a.out[0x4040c9]
======= Memory map: ========
00400000-00403000 r--p 00000000 08:03 669993                             /tmp/small/a.out
00403000-00423000 r-xp 00003000 08:03 669993                             /tmp/small/a.out
00423000-00430000 r--p 00023000 08:03 669993                             /tmp/small/a.out
00431000-00432000 r--p 00030000 08:03 669993                             /tmp/small/a.out
00432000-00433000 rw-p 00031000 08:03 669993                             /tmp/small/a.out
00433000-005df000 rw-p 00000000 00:00 0 
013b3000-01cd5000 rw-p 00000000 00:00 0                                  [heap]
3250600000-3250620000 r-xp 00000000 08:03 395074                         /lib64/ld-2.12.so
3250820000-3250821000 r--p 00020000 08:03 395074                         /lib64/ld-2.12.so
3250821000-3250822000 rw-p 00021000 08:03 395074                         /lib64/ld-2.12.so
3250822000-3250823000 rw-p 00000000 00:00 0 
3250a00000-3250b8b000 r-xp 00000000 08:03 395091                         /lib64/libc-2.12.so
3250b8b000-3250d8a000 ---p 0018b000 08:03 395091                         /lib64/libc-2.12.so
3250d8a000-3250d8e000 r--p 0018a000 08:03 395091                         /lib64/libc-2.12.so
3250d8e000-3250d90000 rw-p 0018e000 08:03 395091                         /lib64/libc-2.12.so
3250d90000-3250d94000 rw-p 00000000 00:00 0 
3250e00000-3250e17000 r-xp 00000000 08:03 426826                         /lib64/libpthread-2.12.so
3250e17000-3251017000 ---p 00017000 08:03 426826                         /lib64/libpthread-2.12.so
3251017000-3251018000 r--p 00017000 08:03 426826                         /lib64/libpthread-2.12.so
3251018000-3251019000 rw-p 00018000 08:03 426826                         /lib64/libpthread-2.12.so
3251019000-325101d000 rw-p 00000000 00:00 0 
3251200000-3251202000 r-xp 00000000 08:03 426837                         /lib64/libdl-2.12.so
3251202000-3251402000 ---p 00002000 08:03 426837                         /lib64/libdl-2.12.so
3251402000-3251403000 r--p 00002000 08:03 426837                         /lib64/libdl-2.12.so
3251403000-3251404000 rw-p 00003000 08:03 426837                         /lib64/libdl-2.12.so
3251e00000-3251e83000 r-xp 00000000 08:03 426839                         /lib64/libm-2.12.so
3251e83000-3252082000 ---p 00083000 08:03 426839                         /lib64/libm-2.12.so
3252082000-3252083000 r--p 00082000 08:03 426839                         /lib64/libm-2.12.so
3252083000-3252084000 rw-p 00083000 08:03 426839                         /lib64/libm-2.12.so
3255200000-3255216000 r-xp 00000000 08:03 426840                         /lib64/libgcc_s-4.4.7-20120601.so.1
3255216000-3255415000 ---p 00016000 08:03 426840                         /lib64/libgcc_s-4.4.7-20120601.so.1
3255415000-3255416000 rw-p 00015000 08:03 426840                         /lib64/libgcc_s-4.4.7-20120601.so.1
7f7770744000-7f7770749000 rw-p 00000000 00:00 0 
7f7770749000-7f77708d1000 r-xp 00000000 00:23 1837379                    /tool/gcc/8.3.0/lib64/libstdc++.so.6.0.25
7f77708d1000-7f7770ad0000 ---p 00188000 00:23 1837379                    /tool/gcc/8.3.0/lib64/libstdc++.so.6.0.25
7f7770ad0000-7f7770adb000 r--p 00187000 00:23 1837379                    /tool/gcc/8.3.0/lib64/libstdc++.so.6.0.25
7f7770adb000-7f7770add000 rw-p 00192000 00:23 1837379                    /tool/gcc/8.3.0/lib64/libstdc++.so.6.0.25
7f7770add000-7f7770ae2000 rw-p 00000000 00:00 0 
7f7770af8000-7f7770af9000 rw-p 00000000 00:00 0 
7f7770af9000-7f7770afa000 r--p 00000000 08:03 669992                     /tmp/small/libtest.so
7f7770afa000-7f7770afb000 r-xp 00001000 08:03 669992                     /tmp/small/libtest.so
7f7770afb000-7f7770afc000 r--p 00002000 08:03 669992                     /tmp/small/libtest.so
7f7770afc000-7f7770afd000 r--p 00002000 08:03 669992                     /tmp/small/libtest.so
7f7770afd000-7f7770afe000 rw-p 00003000 08:03 669992                     /tmp/small/libtest.so
7f7770afe000-7f7770aff000 rw-p 00000000 00:00 0 
7ffc3fc25000-7ffc3fc3a000 rw-p 00000000 00:00 0                          [stack]
7ffc3fcdc000-7ffc3fcdd000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]
Abort

Reason for crash is that malloc/free definition from shared library libtest.so comes from libc.so while malloc definition from shared library libc.so (for strdup) comes from tcmalloc, and when libc free tries to free tc alloced block, it crashes.

In my opinion, all malloc/free should have come from tcmalloc and there would have been no problem whatsoever.

@gusain
Copy link
Author

gusain commented Sep 20, 2019

Now, when I know this issue, it looks like others have also faced it with other memory manager (jemalloc) and it seems like jemalloc has fix for it (I verified it on small test and it works and works as I suggested earlier)
https://bugzilla.mozilla.org/show_bug.cgi?id=493541

@alk
Copy link
Contributor

alk commented Feb 10, 2020

Thanks for report. Notably that mozilla ticket is 11 years old. Also glibc has deprecated those hooks long time ago.

So gperftools dropped usage of those hooks in this commit: 7822b5b

So I am not sure how to help you, maybe don't use RTLD_DEEPBIND ?

@gusain
Copy link
Author

gusain commented Feb 10, 2020

Thanks for your comment.

So I am not sure how to help you, maybe don't use RTLD_DEEPBIND ?

What you see is a small hand-crafted test case after debugging crash which involves third party licensing library code which obfuscates debugging symbols. And this RTLD_DEEPBIND comes from inside third party code.
For this problem, malloc hooks appear to be the only way to fix this problem (if RTLD_DEEPBIND has to stay).

@alk
Copy link
Contributor

alk commented Feb 11, 2020

I understand. Thing is, glibc folks promised they'll soon shoot glibc's hooks.

@gusain
Copy link
Author

gusain commented Feb 11, 2020

Any suggestions how to make progress on this issue ?

@codonell
Copy link

There are two solutions:

  • Use a single malloc e.g. tcmalloc as the malloc for the entire application i.e. don't mix allocators.
  • Do not leak pointers between malloc implementations.

These are advanced topics for application design, and you cannot assume that you can freely change allocators like this or use RTLD_DEEPBIND without carefully architecting the application.

While glibc makes it possible to replace the system allocator it doesn't mean that this will work in all conceivable scenarios without additional design work. Likewise dlmopen can cause similar problems with namespaces leaking pointers from different allocators.

@gusain
Copy link
Author

gusain commented Feb 11, 2020

Use a single malloc e.g. tcmalloc as the malloc for the entire application i.e. don't mix allocators.

Can you please explain it ? Please note that I intend to use tcmalloc as the "malloc" for entire application but there is a third party software which calls dlopen with RTLD_DEEPBIND and calls glibc pt malloc. It's clear that even tcmalloc would have worked fine but just because of DEEPBIND it gets malloc from glibc.

Do not leak pointers between malloc implementations.

My earlier comment applies to this point as well; I don't want to switch memory managers but I need some way to force it. I can't change third party software.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants