gopalshankar / address-sanitizer

Automatically exported from code.google.com/p/address-sanitizer
0 stars 0 forks source link

Detect when asan runtime is loaded twice into the same process #240

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Just hit a case when asan runtime gets loaded twice into the same process -- 
it's linked both to executable and one of shared libraries.

It's not that it particularly hard to debug; but may be quite unpleasant for 
end users -- currently it silently deadlocks.

I think there is a simple way to detect such case and output meaningful 
diagnostics. We can define __sanitizer_runtime_loaded symbol, and then do 
dlsym(RTLD_NEXT, "__sanitizer_runtime_loaded"), if it returns non-zero -> 
report double runtime and die.

Original issue reported on code.google.com by dvyu...@google.com on 1 Nov 2013 at 3:51

GoogleCodeExporter commented 9 years ago
Or just perform the check during dynamic initialization

struct Foo {
  Foo() {
    static bool initialized;
    if (initialized) ReportDoubleInitialization();
    initialized = true;
  ]
} global_foo;

Original comment by samso...@google.com on 1 Nov 2013 at 4:36

GoogleCodeExporter commented 9 years ago
Each module has own copy of Foo::Foo::initialized.

Original comment by dvyu...@google.com on 1 Nov 2013 at 4:38

GoogleCodeExporter commented 9 years ago
I think they will be merged by the dynamic linker. Need to check that, though.

Original comment by samso...@google.com on 1 Nov 2013 at 4:43

GoogleCodeExporter commented 9 years ago
This shouldn't be a problem, since the driver doesn't allow to link the runtime 
library to a shared library. If someone does this deliberately, he's shooting 
himself in the foot.

Original comment by ramosian.glider@gmail.com on 1 Nov 2013 at 4:45

GoogleCodeExporter commented 9 years ago
That's exactly to prevent shooting yourself in the foot.
It makes sense to implement if it's really simple. And it seems that it can be 
really simple (few lines of code).

Original comment by dvyu...@google.com on 1 Nov 2013 at 4:49

GoogleCodeExporter commented 9 years ago
Not going to work on this, see very little value. 
If someone feels strong, please reopen, assign to yourself and fix. 

Original comment by konstant...@gmail.com on 27 Dec 2013 at 11:12

GoogleCodeExporter commented 9 years ago
Another case seen in the wild.

Clang-built program with -fsanitize=thread does:
14742 open("/usr/lib/x86_64-linux-gnu/libtsan.so.0", O_RDONLY|O_CLOEXEC) = 3

which is gcc! runtime.

Then the process crashes after double-mapping heap space:

14742 mmap(0x7d0000000000, 1099511627776, PROT_NONE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7d0000000000
14742 mmap(0x7e0000000000, 12288, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7e0000000000
14742 futex(0x7fe5d2eea0d0, FUTEX_WAKE_PRIVATE, 2147483647) = 0
14742 mmap(0x7d0800000000, 65536, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7d0800000000
14742 mmap(0x7d0bffff0000, 65536, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7d0bffff0000
14742 mmap(0x7d6400000000, 131072, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7d6400000000
14742 mmap(0x7d67ffff0000, 65536, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7d67ffff0000
14742 mmap(NULL, 33554432, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 
0) = 0x7fe5cbbf8000
14742 munmap(0x7fe5cbbf8000, 4227072)   = 0
14742 munmap(0x7fe5cd000000, 12550144)  = 0
14742 mmap(0x7d0000000000, 1099511627776, PROT_NONE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS|MAP_NORESERVE, -1, 0) = 0x7d0000000000
14742 mmap(0x7e0000000000, 20480, PROT_READ|PROT_WRITE, 
MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x7e0000000000
14742 --- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_ACCERR, 
si_addr=0x7d080000eff8} ---

A typical user is not capable of dubugging this w/o our help.

Original comment by dvyu...@google.com on 12 Oct 2014 at 7:27

GoogleCodeExporter commented 9 years ago
You can also check whether shadow/heap are mapped already, like ASan does on 
Darwin.

Original comment by gli...@chromium.org on 13 Oct 2014 at 7:21

GoogleCodeExporter commented 9 years ago
(technically on Darwin it only checks for other libraries mapped at shadow 
space, but the idea is the same)

Original comment by ramosian.glider@gmail.com on 13 Oct 2014 at 7:22

GoogleCodeExporter commented 9 years ago
How the hell did we even end up with 2 names for the library?
Common soname would have solved most of these cases.

Original comment by euge...@google.com on 13 Oct 2014 at 7:51

GoogleCodeExporter commented 9 years ago
> How the hell did we even end up with 2 names for the library?

$ clang -fsanitize=thread -ltsan

Original comment by dvyu...@google.com on 13 Oct 2014 at 8:05