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

Address Sanitizer fails to intercept function in shared library opened with RTLD_DEEPBIND #611

Open
Keno opened this issue Oct 11, 2015 · 22 comments

Comments

@Keno
Copy link

Keno commented Oct 11, 2015

I just found out that if an application opens a shared library (both built with address sanitizer) using RTLD_DEEPBIND, address sanitizer will fail to intercept the functions called from the so opened shared library. In my particular case, this manifested itself as a strdup which, though originally skipping any interceptors and going into libc, would eventually call asan's allocator. However the same did not happen for free (since it went straight into glibc's free), so it failed to intercept free (or rather there was an allocator mismatch). I am not familiar enough with glibc to say whether this can be fixed or not, but perhaps we could drop the RTLD_DEEPBIND flag in our dlopen interceptor and issue a warning to the user.

@eugenis
Copy link
Contributor

eugenis commented Oct 12, 2015

Interesting. I think this has no chance of working with static-libasan, so we should either remove DEEPBIND or complain about it or both. It works with -shared-libasan with clang but not with gcc, because gcc does not add DT_NEEDED for libasan to shared libraries.

@kcc
Copy link
Contributor

kcc commented Oct 12, 2015

On Mon, Oct 12, 2015 at 9:30 AM, Evgeniy Stepanov [email protected]
wrote:

Interesting. I think this has no chance of working with static-libasan, so
we should either remove DEEPBIND or complain

I'd say we need to complain and exit.
(We may of course, have a flag to guard the logic here, but that's on
overkill)

about it or both. It works with -shared-libasan with clang but not with
gcc, because gcc does not add DT_NEEDED for libasan to shared libraries.


Reply to this email directly or view it on GitHub
#611 (comment).

ffilz pushed a commit to ffilz/nfs-ganesha that referenced this issue Feb 3, 2017
Due to a bug in gcc / libasan
(google/sanitizers#611), you cannot mix
RTLD_DEEPBIND and adderss sanitizing.  The result, if you do, is
allocating using ASAN and freeing using glibc, causing aborts.

If ADDRESS_SANITIZER is on, disable RTLD_DEEPBIND.

Change-Id: Ibaeaa33b7f653673f971ce3dd610d60252dbc220
Signed-off-by: Daniel Gryniewicz <[email protected]>
@yugr
Copy link

yugr commented Feb 15, 2017

Does this boil down to detecting RTLD_DEEPBIND in dlopen interceptor?

@kcc
Copy link
Contributor

kcc commented Feb 16, 2017

I'd guess so.

dtzWill pushed a commit to llvm-mirror/compiler-rt that referenced this issue Mar 9, 2017
… RTLD_DEEPBIND flag

People keep hitting on spurious failures in malloc/free routines when using sanitizers
with shared libraries dlopened with RTLD_DEEPBIND (see google/sanitizers#611 for details).
Let's check for this flag and bail out with warning message instead of failing in random places.

Differential Revision: https://reviews.llvm.org/D30504


git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@297370 91177308-0d34-0410-b5e6-96231b3b80d8
jyknight pushed a commit to jyknight/llvm-monorepo-old1 that referenced this issue Mar 9, 2017
… RTLD_DEEPBIND flag

People keep hitting on spurious failures in malloc/free routines when using sanitizers
with shared libraries dlopened with RTLD_DEEPBIND (see google/sanitizers#611 for details).
Let's check for this flag and bail out with warning message instead of failing in random places.

Differential Revision: https://reviews.llvm.org/D30504

llvm-svn=297370
madhuthorat pushed a commit to madhuthorat/nfs-ganesha that referenced this issue Nov 14, 2017
Due to a bug in gcc / libasan
(google/sanitizers#611), you cannot mix
RTLD_DEEPBIND and adderss sanitizing.  The result, if you do, is
allocating using ASAN and freeing using glibc, causing aborts.

If ADDRESS_SANITIZER is on, disable RTLD_DEEPBIND.

Change-Id: Ibaeaa33b7f653673f971ce3dd610d60252dbc220
Signed-off-by: Daniel Gryniewicz <[email protected]>
Signed-off-by: Madhu Thorat <[email protected]>

Conflicts:
	src/include/config-h.in.cmake
madhuthorat pushed a commit to madhuthorat/nfs-ganesha that referenced this issue Nov 28, 2017
Due to a bug in gcc / libasan
(google/sanitizers#611), you cannot mix
RTLD_DEEPBIND and adderss sanitizing.  The result, if you do, is
allocating using ASAN and freeing using glibc, causing aborts.

If ADDRESS_SANITIZER is on, disable RTLD_DEEPBIND.

Change-Id: Ibaeaa33b7f653673f971ce3dd610d60252dbc220
Signed-off-by: Daniel Gryniewicz <[email protected]>
Signed-off-by: Madhu Thorat <[email protected]>

Conflicts:
	src/include/config-h.in.cmake
@FerCampos
Copy link

Hi!
I have an environment in which I am using an external SDK. This SDK consist of a shared library I link with, and which makes use of dlopen to open other libX.so with RTLD_DEEPBIND flag. I'm not interested at all on sanitize the SDK, I only want to sanitize my own code.

How should I proceed? I'm confused about the different -shared-libasan/-static-libasan options.
As far as I understand, compiling with -static-libasan (GCC6) should inject all the sanitizer code in my binary and should have no effects on non-sanitized SDK, but I get an error on SDK trying to dlopen the .so:
Couldn't load libXXX.so: System error code(-2): libXXX.so: cannot open shared object file: No such file or directory

Using LD_LIBRARY_PATH to allow the SDK finding its libXXX.so I get the famous _int_free SEGV ASAN error. Seems like the SDK is redefining any alloc/free function, so there is a mismatch on symbol resolution (SDK vs Asan).

Looks like linking with -fsanitize=address changes the order of symbols lookup/LD_PATH. I would need to isolate the SDK so it remains using libc or its own implementation (I don't know how internally works and I don't have access to source code neither).

I want this behavior #871 (comment), but I'm not able to make the SDK run when my binary is using asan.

I am open to use blacklist, suppression list, attribute((no_sanitize("address"))) or any other option, but I would like to understand the problem.

Any hints?
Thanks

@kcc
Copy link
Contributor

kcc commented Mar 16, 2018

Frankly, your best choice is to contact the vendor for the SDK and request that they support asan
in whatever environment this SDK is being used.
We've seen cases in the past when a closed-source SDK did something extremely asan-hostile
and there is very little we could do there.

If you can provide a small reproducer, where you replace the SDK with a tiny mock library,
please file a separate bug and we'll take a look (but no promises, such problems are often hard to solve)

sachinpunadikar pushed a commit to sachinpunadikar/nfs-ganesha that referenced this issue Nov 22, 2018
Due to a bug in gcc / libasan
(google/sanitizers#611), you cannot mix
RTLD_DEEPBIND and adderss sanitizing.  The result, if you do, is
allocating using ASAN and freeing using glibc, causing aborts.

If ADDRESS_SANITIZER is on, disable RTLD_DEEPBIND.

Change-Id: Ibaeaa33b7f653673f971ce3dd610d60252dbc220
Signed-off-by: Daniel Gryniewicz <[email protected]>

Conflicts:
	src/include/config-h.in.cmake
malahal pushed a commit to malahal/nfs-ganesha that referenced this issue Mar 9, 2019
Due to a bug in gcc / libasan
(google/sanitizers#611), you cannot mix
RTLD_DEEPBIND and adderss sanitizing.  The result, if you do, is
allocating using ASAN and freeing using glibc, causing aborts.

If ADDRESS_SANITIZER is on, disable RTLD_DEEPBIND.

Change-Id: Ibaeaa33b7f653673f971ce3dd610d60252dbc220
Signed-off-by: Daniel Gryniewicz <[email protected]>
Signed-off-by: Madhu Thorat <[email protected]>

Conflicts:
	src/include/config-h.in.cmake
(cherry picked from commit 2ba269f)
malahal pushed a commit to malahal/nfs-ganesha that referenced this issue Mar 21, 2019
Due to a bug in gcc / libasan
(google/sanitizers#611), you cannot mix
RTLD_DEEPBIND and adderss sanitizing.  The result, if you do, is
allocating using ASAN and freeing using glibc, causing aborts.

If ADDRESS_SANITIZER is on, disable RTLD_DEEPBIND.

Change-Id: Ibaeaa33b7f653673f971ce3dd610d60252dbc220
Signed-off-by: Daniel Gryniewicz <[email protected]>
Signed-off-by: Madhu Thorat <[email protected]>

Conflicts:
	src/include/config-h.in.cmake
(cherry picked from commit 2ba269f)
@jm4R
Copy link

jm4R commented Sep 24, 2019

On Mon, Oct 12, 2015 at 9:30 AM, Evgeniy Stepanov [email protected]
wrote:
I'd say we need to complain and exit.
(We may of course, have a flag to guard the logic here, but that's on
overkill)

Isn't it a good idea to add such flag? In code with a lot of modules this could help a lot as one wouldn't have to recompile some of them.

samba-team-bot pushed a commit to samba-team/samba that referenced this issue Oct 16, 2019
Disable the RTLD_DEEPBIND option for dlopen in LDB and Socket Wrapper when
running with  AddressSanitizer. The RTLD_DEEPBIND option is not compatible
with Address Sanitizer see
google/sanitizers#611

Signed-off-by: Gary Lockyer <[email protected]>
Reviewed-by: Andreas Schneider <[email protected]>

Autobuild-User(master): Andreas Schneider <[email protected]>
Autobuild-Date(master): Wed Oct 16 15:41:41 UTC 2019 on sn-devel-184
@faridosc
Copy link

I am getting this error:

==7741==You are trying to dlopen a /usr/share/icedtea-web/lib/haswell/IcedTeaPlugin.so shared library with RTLD_DEEPBIND flag which is incompatibe with sanitizer runtime (see https://github.com/google/sanitizers/issues/611 for details). If you want to run /usr/share/icedtea-web/lib/haswell/IcedTeaPlugin.so library under sanitizers please remove RTLD_DEEPBIND from dlopen flags.

kovidgoyal added a commit to kovidgoyal/calibre that referenced this issue Sep 26, 2021
This breaks ASAN, see google/sanitizers#611
So, patch it out when installing. Upstream pycryptodome issue:
Legrandin/pycryptodome#376
bmwiedemann referenced this issue in bmwiedemann/openSUSE Oct 18, 2021
https://build.opensuse.org/request/show/925768
by user dirkmueller + dimstar_suse
- update to 3.11.0:
  * GH#512: Especially for very small bit sizes, ``Crypto.Util.number.getPrime()`` was
    occasionally generating primes larger than given the bit size.
  * GH#552: Correct typing annotations for ``PKCS115_Cipher.decrypt()``.
  * GH#555: ``decrypt()`` method of a PKCS#1v1.5 cipher returned a ``bytearray`` instead of ``bytes``.
  * GH#557: External DSA domain parameters were accepted even when the modulus (``p``) was not prime.
    This affected ``Crypto.PublicKey.DSA.generate()`` and ``Crypto.PublicKey.DSA.construct()``.
  * Added cSHAKE128 and cSHAKE256 (of SHA-3 family).
  * GH#558: The flag RTLD_DEEPBIND passed to ``dlopen()`` is not well supported by
    `address sanitizers <https://github.com/google/sanitizers/issues/611>`_.
    It is now possible to set the enviro
bmwiedemann referenced this issue in bmwiedemann/openSUSE Oct 20, 2021
https://build.opensuse.org/request/show/925769
by user dirkmueller + dimstar_suse
- update to 3.11.0:
  * GH#512: Especially for very small bit sizes, ``Crypto.Util.number.getPrime()`` was
    occasionally generating primes larger than given the bit size.
  * GH#552: Correct typing annotations for ``PKCS115_Cipher.decrypt()``.
  * GH#555: ``decrypt()`` method of a PKCS#1v1.5 cipher returned a ``bytearray`` instead of ``bytes``.
  * GH#557: External DSA domain parameters were accepted even when the modulus (``p``) was not prime.
    This affected ``Crypto.PublicKey.DSA.generate()`` and ``Crypto.PublicKey.DSA.construct()``.
  * Added cSHAKE128 and cSHAKE256 (of SHA-3 family).
  * GH#558: The flag RTLD_DEEPBIND passed to ``dlopen()`` is not well supported by
    `address sanitizers <https://github.com/google/sanitizers/issues/611>`_.
    It is now possible to set the enviro
@vrqq
Copy link

vrqq commented Nov 8, 2021

Interesting. I think this has no chance of working with static-libasan, so we should either remove DEEPBIND or complain about it or both. It works with -shared-libasan with clang but not with gcc, because gcc does not add DT_NEEDED for libasan to shared libraries.

Which version of clang could make -shared-libasan and DEEPBIND together?
I have tried clang 11 and 12 with -shared-libsan or -shared-libasan but still got error in runtime:
You are trying to dlopen a /usr/lib64/libssl.so shared library with RTLD_DEEPBIND flag which is incompatible with sanitizer runtime

Can I use [[no_sanitize("address")]] to solve it?

Thanks

=====
btw: The problem I face, is some close source third library who depend on the other library which is not the same version on my host, so, denied the DEEPBIND is a problem for me. (for example loading both OpenSSL 1.0 and 1.1)
I have to use dlopen(RTLD_LOCAL|RTLD_DEEPBIND) in my code, and dlmopen is also have a problem that some code not running on that namespace.

Maybe using blacklist is better than denied RTLD_DEEPBIND?
Just warn and let user to add the relevant files into blacklist.

The other solution is to allow the RTLD_DEEPBIND to .so dynamic library which build with ASAN, so we can implement some shims easily. (such as https://github.com/yugr/Implib.so, https://github.com/dezgeg/libcapsule and other libGL shims)

jollaitbot pushed a commit to sailfishos-mirror/bind9 that referenced this issue Jan 25, 2022
dlopen(3) RTLD_DEEPBIND flag is incompatible with sanitizer runtime
(see google/sanitizers#611 for details).
oerdnj pushed a commit to isc-projects/bind9 that referenced this issue Jan 26, 2022
dlopen(3) RTLD_DEEPBIND flag is incompatible with sanitizer runtime
(see google/sanitizers#611 for details).
@WilliamTambellini
Copy link

Note: asan from gcc6 was ok with DEEPBIND, it started to fail from gcc8 (or 7?).
Has anyone retried with gcc11 ?

@janwilmans
Copy link

tried, gcc-11.2.0 same problem, if a third-party library uses RTLD_DEEPBIND to load a shared library building with TSAN will now make the application report an error and refuse to start .

@janwilmans
Copy link

would it be possible to accept the fact that the code in the shared library can't be checked?
In my case any application that links with this closed sources library can't use sanitizers anymore... It would be nice if I could still check my own code?

@WilliamTambellini
Copy link

Same behavior with gcc11.3.
+1 for @janwilmans proposal.

@AllanZyne
Copy link

I encountered an interesting false-positive. When dlopen(RTLD_DEEPBIND) a shared library which doesn't exist, Address Sanitizer will also die.

@Enna1
Copy link

Enna1 commented Feb 14, 2023

I encountered an interesting false-positive. When dlopen(RTLD_DEEPBIND) a shared library which doesn't exist, Address Sanitizer will also die.

ASan add this check in dlopen interceptor, if flags contain RTLD_DEEPBIND then ASan will report and die.

if (flag & RTLD_DEEPBIND) {
    Report(
        "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"
        " which is incompatible with sanitizer runtime "
        "(see https://github.com/google/sanitizers/issues/611 for details"
        "). If you want to run %s library under sanitizers please remove "
        "RTLD_DEEPBIND from dlopen flags.\n",
        filename, filename);
    Die();
  }

@janwilmans
Copy link

janwilmans commented Feb 14, 2023

llvm/llvm-project@76630d4
added this check and it was well intentioned, however, if the library doesn't exist, there is no problem and the sanitizer still dies. Also the loaded library might never be actually be used (or its use is intentionally avoided, like we do) to allow you to still check your own code.

@AllanZyne
Copy link

AllanZyne commented Feb 16, 2023

I encountered an interesting false-positive. When dlopen(RTLD_DEEPBIND) a shared library which doesn't exist, Address Sanitizer will also die.

ASan add this check in dlopen interceptor, if flags contain RTLD_DEEPBIND then ASan will report and die.

if (flag & RTLD_DEEPBIND) {
    Report(
        "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag"
        " which is incompatible with sanitizer runtime "
        "(see https://github.com/google/sanitizers/issues/611 for details"
        "). If you want to run %s library under sanitizers please remove "
        "RTLD_DEEPBIND from dlopen flags.\n",
        filename, filename);
    Die();
  }

Yes, if the shared library at filename doesn't exist, I think ASan needn't report and die.

@janwilmans
Copy link

janwilmans commented Feb 26, 2023

The message was added because people we getting super weird false positives.
I think the message is very helpful, the Die(), I have removed locally and I just know to that I can expect weirdness if I need this message. Maybe we should just add, ASAN can continue but please don't report issues if you see this message and be aware you can experience false positives from RTLD_DEEPBIND -loaded dynamic libraries.

@janwilmans
Copy link

Frankly, your best choice is to contact the vendor for the SDK and request that they support asan in whatever environment this SDK is being used. We've seen cases in the past when a closed-source SDK did something extremely asan-hostile and there is very little we could do there.

In practice this is very hard, some vendors aren't even aware the are doing this themselves, they load libraries, that load libraries etc. We should have some way to allow the user to sanitize their own code at least...

@ojwb
Copy link

ojwb commented Aug 5, 2023

please remove RTLD_DEEPBIND from dlopen flags

It's intercepting the dlopen() call already, so could asan provide a way to strip out the RTLD_DEEPBIND flag before calling the real dlopen()?

To follow the error message's suggestion and remove the flag it seems one currently has to rebuild the code which uses the flag. In the case I've just hit the problematic dlopen() call is in the PHP interpreter, so that means rebuilding all of PHP in order to use asan on an externally built PHP module. Looking at PHP's code it already avoids using RTLD_DEEPBIND automatically if PHP itself is built with asan or memsan, so if I could tell asan to strip out the flag it ought to work:

# if defined(RTLD_GROUP) && defined(RTLD_WORLD) && defined(RTLD_PARENT)
#  define DL_LOAD(libname)			dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_GROUP | RTLD_WORLD | RTLD_PARENT)
# elif defined(RTLD_DEEPBIND) && !defined(__SANITIZE_ADDRESS__) && !__has_feature(memory_sanitizer)
#  define DL_LOAD(libname)			dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL | RTLD_DEEPBIND)
# else
#  define DL_LOAD(libname)			dlopen(libname, PHP_RTLD_MODE | RTLD_GLOBAL)
# endif

@janwilmans
Copy link

@ojwb RTLD_DEEPBIND is there for a reason, you cannot just remove it and expect it to work ok. Specifically RTLD_DEEPBIND causes symbol lookups to happen in the loaded library and if you remove it, the symbols will be looked up in one of its parents, which is functionally not the same.

erick-xanadu added a commit to PennyLaneAI/catalyst that referenced this issue Oct 20, 2023
See this error message:

You are trying to dlopen a this-file-does-not-exist.so shared
library with RTLD_DEEPBIND flag which is incompatible with sanitizer
runtime (see google/sanitizers#611 for
details). If you want to run this-file-does-not-exist.so library under
sanitizers please remove RTLD_DEEPBIND from dlopen flags.
erick-xanadu added a commit to PennyLaneAI/catalyst that referenced this issue Oct 23, 2023
See this error message:

You are trying to dlopen a this-file-does-not-exist.so shared
library with RTLD_DEEPBIND flag which is incompatible with sanitizer
runtime (see google/sanitizers#611 for
details). If you want to run this-file-does-not-exist.so library under
sanitizers please remove RTLD_DEEPBIND from dlopen flags.
@kotee4ko
Copy link

kotee4ko commented Nov 26, 2023

as a workaround solution:

colordiff --suppress-common-lines -U16 <(objdump -Mintel -dC /usr/lib/x86_64-linux-gnu/libasan.so.8.0.0) <(objdump -Mintel -dC /tmp/libasan.so.8.0.0)

 0000000000060270 <__interceptor_dlopen.part.0>:
    60270:      55                      push   rbp
    60271:      48 89 e5                mov    rbp,rsp
    60274:      41 57                   push   r15
    60276:      41 56                   push   r14
    60278:      41 55                   push   r13
    6027a:      41 54                   push   r12
    6027c:      41 89 f4                mov    r12d,esi
    6027f:      53                      push   rbx
    60280:      48 89 fb                mov    rbx,rdi
    60283:      48 81 ec 28 08 00 00    sub    rsp,0x828
    6028a:      48 8d 05 0b 83 11 00    lea    rax,[rip+0x11830b]        # 17859c <__asan::asan_inited>
    60291:      8b 30                   mov    esi,DWORD PTR [rax]
    60293:      85 f6                   test   esi,esi
    60295:      0f 84 95 01 00 00       je     60430 <__interceptor_dlopen.part.0+0x1c0>
    6029b:      48 85 db                test   rbx,rbx
    6029e:      74 10                   je     602b0 <__interceptor_dlopen.part.0+0x40>
    602a0:      48 8d 05 19 a0 1a 00    lea    rax,[rip+0x1aa019]        # 20a2c0 <__sanitizer::common_flags_dont_use>
    602a7:      80 b8 f5 00 00 00 00    cmp    BYTE PTR [rax+0xf5],0x0
    602ae:      75 50                   jne    60300 <__interceptor_dlopen.part.0+0x90>
    602b0:      48 8d 05 29 4b 11 00    lea    rax,[rip+0x114b29]        # 174de0 <__asan::asan_flags_dont_use_directly>
    602b7:      80 78 59 00             cmp    BYTE PTR [rax+0x59],0x0
    602bb:      0f 85 5f 01 00 00       jne    60420 <__interceptor_dlopen.part.0+0x1b0>
-   602c1:      44 89 e6                mov    esi,r12d
+   602c1:      31 f6                   xor    esi,esi
+   602c3:      90                      nop
    602c4:      48 89 df                mov    rdi,rbx
    602c7:      e8 14 40 09 00          call   f42e0 <__sanitizer::CheckNoDeepBind(char const*, int)>
    602cc:      44 89 e6                mov    esi,r12d
    602cf:      48 89 df                mov    rdi,rbx
    602d2:      ff 15 98 4f 11 00       call   QWORD PTR [rip+0x114f98]        # 175270 <__interception::real_dlopen>
    602d8:      48 89 c3                mov    rbx,rax
    602db:      e8 40 2e 0a 00          call   103120 <__sanitizer::Symbolizer::GetOrInit()>
    602e0:      48 89 c7                mov    rdi,rax
    602e3:      e8 78 1f 0a 00          call   102260 <__sanitizer::Symbolizer::InvalidateModuleList()>
    602e8:      48 8d 65 d8             lea    rsp,[rbp-0x28]
    602ec:      48 89 d8                mov    rax,rbx
    602ef:      5b                      pop    rbx
    602f0:      41 5c                   pop    r12
    602f2:      41 5d                   pop    r13
    602f4:      41 5e                   pop    r14
    602f6:      41 5f                   pop    r15
    602f8:      5d                      pop    rbp
    602f9:      c3                      ret

Please keep in mind, that this patch could break calls to free() in some rare cases, when called from library which was loaded by dlopen()

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

No branches or pull requests