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

Crash on ODR between instrumented and non-instrumented libraries #398

Open
GoogleCodeExporter opened this issue Aug 24, 2015 · 4 comments
Open

Comments

@GoogleCodeExporter
Copy link

When the same global variable is defined in ASan-instrumented and in a 
non-instrumented libraries, there is a 50% chance that the linker will pick the 
non-instrumented symbol and __asan_register_globals will attempt to poison 
redzones around it.

Negative effects range from cryptic out-of-bounds reports to startup CHECK 
failures (ex. because the uninstrumented variable is not 32-byte aligned).

I wonder if this can be mitigated by making the reference in asan global 
descriptor point to a local symbol for the same global.

Original issue reported on code.google.com by euge...@google.com on 14 Jul 2015 at 6:09

@GoogleCodeExporter
Copy link
Author

FYI that's what GCC does.

Original comment by tetra2...@gmail.com on 14 Jul 2015 at 7:03

@GoogleCodeExporter
Copy link
Author

Adding Project:AddressSanitizer as part of GitHub migration.

Original comment by ramosian.glider@gmail.com on 30 Jul 2015 at 9:06

  • Added labels: ProjectAddressSanitizer

@GoogleCodeExporter
Copy link
Author

Hm, I've tried the following (draft) patch:

diff --git a/lib/Transforms/Instrumentation/AddressSanitizer.cpp 
b/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index f7b7a71..71b65c3 100644
--- a/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -1338,8 +1338,14 @@ bool 
AddressSanitizerModule::InstrumentGlobals(IRBuilder<> &IRB, Module &M) {
       SourceLoc = ConstantInt::get(IntptrTy, 0);
     }

+    // Create local alias for NewGlobal to avoid crash on ODR between
+    // instrumented and non-instrumented libraries.
+    // https://code.google.com/p/address-sanitizer/issues/detail?id=398
+    auto *GA = GlobalAlias::create(
+        GlobalValue::InternalLinkage, MD.Name + M.getName(), NewGlobal);
+
     Initializers[i] = ConstantStruct::get(
-        GlobalStructTy, ConstantExpr::getPointerCast(NewGlobal, IntptrTy),
+        GlobalStructTy, ConstantExpr::getPointerCast(GA, IntptrTy),
         ConstantInt::get(IntptrTy, SizeInBytes),
         ConstantInt::get(IntptrTy, SizeInBytes + RightRedzoneSize),
         ConstantExpr::getPointerCast(Name, IntptrTy),

on this testcase:

$ cat main.c

int f = 4;
int g = 5;
int foo (int *);
int main ()
{
  return foo (&f) - 4;
}

$ cat libfoo.c

int f = 444;
int g = 555;
int foo (int *p)
{
  return *p;
}

and got interesting results. If we force clang to use external (GNU) AS via 
'-no-integrated-as' option, everything works well:

$ clang -no-integrated-as -fsanitize=address libfoo.c -shared -fpic 
-fsanitize=address -o libfoo.so
$ clang main.c -c -o main.o
$ clang -fsanitize=address main.o ./libfoo.so -o main
$ ASAN_OPTIONS=report_globals=3  ./main 
    #0 0x4b49b7 in __asan_register_globals /home/max/src/llvm/projects/compiler-rt/lib/asan/asan_globals.cc:226
    #1 0x7fb518d1fa0d in asan.module_ctor (libfoo.so+0xa0d)
    #2 0x7fb518f31139 in call_init /build/buildd/eglibc-2.19/elf/dl-init.c:78
    #3 0x7fb518f31222 in call_init /build/buildd/eglibc-2.19/elf/dl-init.c:36
    #4 0x7fb518f31222 in _dl_init /build/buildd/eglibc-2.19/elf/dl-init.c:126
    #5 0x7fb518f22309  (/lib64/ld-linux-x86-64.so.2+0x1309)

=== ID 629145601; 0x7fb518f20100 0x7fb518f20138
==18620==Added Global[0x7fb518f20100]: beg=0x7fb518f20080 size=4/64 name=f 
module=foo.c dyn_init=0
==18620==  location (0x7fb518f1fdf8): name=foo.c[0x7fb518d1fa39], 1 5
==18620==Added Global[0x7fb518f20138]: beg=0x7fb518f200c0 size=4/64 name=g 
module=foo.c dyn_init=0
==18620==  location (0x7fb518f1fe08): name=foo.c[0x7fb518d1fa39], 2 5
==18620==Removed Global[0x7fb518f20100]: beg=0x7fb518f20080 size=4/64 name=f 
module=foo.c dyn_init=0
==18620==  location (0x7fb518f1fdf8): name=foo.c[0x7fb518d1fa39], 1 5
==18620==Removed Global[0x7fb518f20138]: beg=0x7fb518f200c0 size=4/64 name=g 
module=foo.c dyn_init=0
==18620==  location (0x7fb518f1fe08): name=foo.c[0x7fb518d1fa39], 2 5

For f and g, beg is located in libfoo.so and this is fine.

However, when use embedded clang asm, I've got this:

$ clang -fsanitize=address libfoo.c -shared -fpic -fsanitize=address -o 
libfoo.so
$ clang main.c -c -o main.o
$ clang -fsanitize=address main.o ./libfoo.so -o main

$ ASAN_OPTIONS=report_globals=3   ./main 
    #0 0x4b49b7 in __asan_register_globals /home/max/src/llvm/projects/compiler-rt/lib/asan/asan_globals.cc:226
    #1 0x7f09ab41da0d in asan.module_ctor (libfoo.so+0xa0d)
    #2 0x7f09ab62f139 in call_init /build/buildd/eglibc-2.19/elf/dl-init.c:78
    #3 0x7f09ab62f222 in call_init /build/buildd/eglibc-2.19/elf/dl-init.c:36
    #4 0x7f09ab62f222 in _dl_init /build/buildd/eglibc-2.19/elf/dl-init.c:126
    #5 0x7f09ab620309  (/lib64/ld-linux-x86-64.so.2+0x1309)

=== ID 662700033; 0x7f09ab61e100 0x7f09ab61e138
==18635==Added Global[0x7f09ab61e100]: beg=0x00000070bb10 size=4/64 name=f 
module=foo.c dyn_init=0
==18635==  location (0x7f09ab61ddf8): name=foo.c[0x7f09ab41da39], 1 5
==18635==Added Global[0x7f09ab61e138]: beg=0x00000070bb14 size=4/64 name=g 
module=foo.c dyn_init=0
==18635==  location (0x7f09ab61de08): name=foo.c[0x7f09ab41da39], 2 5
==18635==AddressSanitizer CHECK failed: 
/home/max/src/llvm/projects/compiler-rt/lib/asan/asan_globals.cc:146 
"((AddrIsAlignedByGranularity(g->beg))) != (0)" (0x0, 0x0)
    #0 0x4bca0d in __asan::AsanCheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /home/max/src/llvm/projects/compiler-rt/lib/asan/asan_rtl.cc:71
    #1 0x4c3b03 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long) /home/max/src/llvm/projects/compiler-rt/lib/sanitizer_common/sanitizer_common.cc:136
    #2 0x4b520b in RegisterGlobal /home/max/src/llvm/projects/compiler-rt/lib/asan/asan_globals.cc:146
    #3 0x4b520b in __asan_register_globals /home/max/src/llvm/projects/compiler-rt/lib/asan/asan_globals.cc:230
    #4 0x7f09ab41da0d in asan.module_ctor (libfoo.so+0xa0d)
    #5 0x7f09ab62f139 in call_init /build/buildd/eglibc-2.19/elf/dl-init.c:78
    #6 0x7f09ab62f222 in call_init /build/buildd/eglibc-2.19/elf/dl-init.c:36
    #7 0x7f09ab62f222 in _dl_init /build/buildd/eglibc-2.19/elf/dl-init.c:126
    #8 0x7f09ab620309  (/lib64/ld-linux-x86-64.so.2+0x1309)

Here, beg for f and g beg=0x00000070bb**, that is located in main. So, for 
embedded asm local aliases didn't work. I wonder if this is an assembler bug? 
Or maybe there is another way to create local alias that would work with both 
external an embedded as?

Original comment by chefM...@gmail.com on 6 Aug 2015 at 4:39

@GoogleCodeExporter
Copy link
Author

The patch looks good in principle, but it has to work with intergrated-as.
Could you try reproducing the difference in the assembler behavior and file a 
bug with llvm? 

Original comment by euge...@google.com on 7 Aug 2015 at 6:27

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

1 participant