[PATCH] D55156: [asan] Split -asan-use-private-alias to -asan-use-odr-indicator

Maxim Ostapenko via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Dec 4 00:42:52 PST 2018


m.ostapenko added a comment.

> So I am not sure if there is any value in using aliases without indicators.

Oh, this is a long story... In short: if we don't use private aliases, we'll may have ASan false positives when mixing sanitized and non-sanitized code depending on ordering during linkage.
Consider the following example (from https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68016#c8):

  max at max:/tmp$ cat libfoo.c
  
  long h = 15;
  long f = 4;
  long foo (long *p) {
    return *p;
  }
  
  max at max:/tmp$ cat libbar.c 
  
  extern void abort (void);
  long foo (long *);
  long h = 12;
  long i = 13;
  long f = 5;
  
  int bar () {
    if (foo (&f) != 5 || foo (&h) != 12 || foo (&i) != 13)
      abort ();
    return 0;
  }
  
  max at max:/tmp$ cat main.c
  
  int bar ();
  
  int main () {
    return bar ();
  }
  $ clang libfoo.c -shared -fpic -o libfoo.so  -g -fsanitize=address
  $ clang libbar.c -shared -fpic -o libbar.so -g
  $ clang main.c -c -o main.o
  $ clang main.o  ./libbar.so ./libfoo.so -o main -fsanitize=address
  $ ./main
  
  ==6425==ERROR: AddressSanitizer: global-buffer-overflow on address 0x7efc5f2f2040 at pc 0x7efc5eeef8d1 bp 0x7ffddc2a2ff0 sp 0x7ffddc2a2fe8
  READ of size 8 at 0x7efc5f2f2040 thread T0
      #0 0x7efc5eeef8d0 in foo /tmp/libfoo.c:4:10
      #1 0x7efc5f0f16cf in bar /tmp/libbar.c:8:7
      #2 0x4f1575 in main (/tmp/main+0x4f1575)
      #3 0x7efc5dffc82f in __libc_start_main /build/glibc-Cl5G7W/glibc-2.23/csu/../csu/libc-start.c:291
      #4 0x41a378 in _start (/tmp/main+0x41a378)
  
  0x7efc5f2f2040 is located 0 bytes inside of global variable 'f' defined in 'libfoo.c:2:6' (0x7efc5f2f2040) of size 8
  0x7efc5f2f2040 is located 8 bytes to the right of global variable 'h' defined in 'libfoo.c:1:6' (0x7efc5f2f2030) of size 8
  SUMMARY: AddressSanitizer: global-buffer-overflow /tmp/libfoo.c:4:10 in foo
  Shadow bytes around the buggy address:
    0x0fe00be563b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be563c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be563d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be563e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be563f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  =>0x0fe00be56400: 00 00 00 00 00 00 00 f9[f9]f9 f9 f9 f9 f9 f9 f9
    0x0fe00be56410: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be56420: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be56430: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be56440: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
    0x0fe00be56450: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
  Shadow byte legend (one shadow byte represents 8 application bytes):
    Addressable:           00
    Partially addressable: 01 02 03 04 05 06 07 
    Heap left redzone:       fa
    Freed heap region:       fd
    Stack left redzone:      f1
    Stack mid redzone:       f2
    Stack right redzone:     f3
    Stack after return:      f5
    Stack use after scope:   f8
    Global redzone:          f9
    Global init order:       f6
    Poisoned by user:        f7
    Container overflow:      fc
    Array cookie:            ac
    Intra object redzone:    bb
    ASan internal:           fe
    Left alloca redzone:     ca
    Right alloca redzone:    cb
  ==6425==ABORTING

Here, global symbols 'f' and 'h' are resolved to libbar.so, that is not sanitized. However, when //libfoo.so// registers its "own" globals, it actually poisons //libbar.so's// 'f' and 'h' that are not properly padded.

There also was an issue with LTO, see https://github.com/google/sanitizers/issues/647

We can use private aliases w/o indicators if we don't care about ODR violation and don't want to pay for odr indicators size.

> Can you please elaborate on how it improves "use_odr_indicator"? Do we miss some violations if we "have aliases without indicators" comparing to default:"have no aliases and have no indicators"?
>  Here is a problem. If we just enable -asan-use-private-alias we miss reports which we had on line 10.

That's correct. Right now detector relies on fact that if we have an ODR violation for some pair of globals, when we register the second one, its will be already poisoned (this will be true at least for ELF). So, effectively it checks that we try to poison the same global twice.
However, this won't be the case when we use private aliases, because we won't try to poison one global twice, we'll poison their private aliases that reside in their corresponding DSOs. In this case, even when we have actual ODR violation, we won't be able to catch it.
And here odr indicators come -- they mimic original globals and allow us to detect ODR violation in a pretty similar manner as before, but without poisoning innocent globals from non-instrumented DSOs.


Repository:
  rL LLVM

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D55156/new/

https://reviews.llvm.org/D55156





More information about the llvm-commits mailing list