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

ASAN should detect if you've accidentally loaded multiple copies of ASAN runtime #918

Open
ezyang opened this issue Feb 20, 2018 · 1 comment

Comments

@ezyang
Copy link

ezyang commented Feb 20, 2018

For the longest time, when I attempted to use ASAN with clang, I got the "Shadow memory range interleaves with an existing memory mapping" error.

(/home/ezyang/Dev/labs/python-ext-env) ezyang@autobox:~/Dev/labs/python-ext$ LD_PRELOAD=/usr/lib/llvm-5.0/lib/clang/5.0.0/lib/linux/libclang_rt.asan-x86_64.so python script.py 
==17683==Shadow memory range interleaves with an existing memory mapping. ASan cannot proceed corr
ectly. ABORTING.
==17683==ASan shadow was supposed to be located in the [0x00007fff7000-0x10007fff7fff] range.
==17683==Process memory map follows:
        0x00007fff7000-0x00008fff7000
        0x00008fff7000-0x02008fff7000
        0x02008fff7000-0x10007fff8000
        0x56532c2df000-0x56532c59d000   /home/ezyang/Dev/labs/python-ext-env/bin/python3.6
        0x56532c79d000-0x56532c7a0000   /home/ezyang/Dev/labs/python-ext-env/bin/python3.6
        0x56532c7a0000-0x56532c803000   /home/ezyang/Dev/labs/python-ext-env/bin/python3.6
        0x56532c803000-0x56532c834000
        0x600000000000-0x602000000000
        0x602000000000-0x602000010000
        0x602000010000-0x602e00000000
        0x602e00000000-0x602e00010000
        0x602e00010000-0x603000000000
[snip]

Perplexingly, I could get gcc working with ASAN, so for a while I wondered if this was just a problem with clang's copy of ASAN (weird, because clang's ASAN is the maintained copy, and gcc's apparently unmaintained.) There are a few existing bugs (e.g. #856) which suggested various causes for the problem, but none seemed applicable in my situation.

Actually, the problem is very simple: I was statically linking my dynamic library (which was being dynamically loaded by Python) with the ASAN runtime, which obviously is not going to work.

"Now, why would anyone ever do that?" It's actually pretty easy to get into this situation:

  1. You want to build a Python C extension with ASAN enabled, but you don't have an ASAN-built copy of Python
  2. You run CFLAGS="-fsanitize=address" python setup.py install" and then run you rest script. When you run your test script, ASAN helpfully tells you "ASan runtime does not come first in initial library list; you should either link runtime to your application or manually preload it with LD_PRELOAD." You add LD_PRELOAD=/path/to/gcc/libasan.so and ASAN works. You are happy.
  3. Next, you decide to do it again with Clang. So you say CC=clang CFLAGS="-fsanitize=address" python setup.py install". Once again, ASAN gives the same "runtime does not come first" message, so you add LD_PRELOAD. BOOM, shadow error.

The PEBKAC, in this case, is assuming that because gcc dynamically links libasan, clang does as well. But the defaults are different: clang defaults to statically linking libasan. And of course the statically linked libasan in the Python extension library is going to be run too late, and if you add the LD_PRELOAD, the statically linked libasan is of course not going to be able get the shadow range it wants, because the preloaded libasan grabbed it already.

I know, it takes forever for fixes in upstream to make their way to distro copies of clang. So I am half writing this post for Google juice, for other poor souls in dynamic linking hell. But it would also be really nice if ASAN didn't suggest LD_PRELOADing from the static runtime, if it's not actually going to work.

P.S. These invocations work for me for building a simple hello world Python extension with the distro-packaged Clang 5.0 on Ubuntu Xenial:

CC=clang-5.0 CXX=clang++-5.0 CFLAGS="-fsanitize=address -shared-libasan" LDSHARED="clang-5.0 -shared" python setup.py install
LD_PRELOAD=/usr/lib/llvm-5.0/lib/clang/5.0.0/lib/linux/libclang_rt.asan-x86_64.so python script.py

Obviously change the paths appropriately depending on your Clang install. (Also, if someone could answer https://stackoverflow.com/questions/48833176/get-location-of-libasan-from-gcc-clang that would also be super helpful :)

@yugr
Copy link

yugr commented Feb 20, 2018

Actually, the problem is very simple: I was statically linking my dynamic library (which was being
dynamically loaded by Python) with the ASAN runtime, which obviously is not going to work.

Yeah, I'm afraid this won't supported mode of work. Suggested approach is in Asaq FAQ:

Q: I've built my shared library with ASan. Can I run it with unsanitized executable?

A: Yes! You'll need to build your library with dynamic version of ASan and then run executable with LD_PRELOAD=path/to/asan/runtime/lib.

but it seems you've figured it out yourself already. This SO post might be helpful too.

But it would also be really nice if ASAN didn't suggest LD_PRELOADing from the static runtime,
if it's not actually going to work.

Agreed, this is really confusing (as is the fact that we fail to detect presence of duplicate Asan runtimes). @chefmax WDYT?

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

2 participants