-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Comments
Reported by |
Reported by |
Reported by |
Well, since pr24486 was fixed (https://llvm.org/bugs/show_bug.cgi?id=24486), the patch I've posted above works fine for both integrated/GNU as. But if use it as it is, the ODR violation detection would be broken, because globals would have different addresses. There is a long discussion about this in GCC bugzilla (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63888) and I don't know what solution is preferable here. Yury suggested to use names of globals instead of their addresses to detect ODR violation, is it an option here? |
Dunno, maybe. Frankly, I am not motivated to invest time into this because in llvm everything works for the most common case (everything is instrumented) and in GCC the ODR checking is currently disabled. (Right?) |
I'd say that sanitized is an important usecase as well and silently dropping support for it (especially in such an ugly way as in this bug) is a huge step back. How about we pass both global and local addresses to asan_register_global? Local address can then be used for poisoning and global for odr. |
|
Yeah, I meant sanitized library. I'm not sure why you care about ABI breaks but we could keep existing function and just add a new "extended" version to preserve compatibility. Max? |
So, we would just compare names to detect ODR violation? I think this can work (although we can still have ODR violation FP for C and others, but this is a different story). I can prepare a prototype and post it here. |
No, we'll still use global addresses for odr but locals for poisoning. That'll require a change to Asan ABI (register_global function). |
|
LLVM's current approach to poisoning globals may also cause another tricky bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=68016 (yes, we've seen it in production). |
One another approach here:
Cons:
Proc:
I have a prototype for this and if there aren't strong objections here, I'll post it at llvm-commits shortly. |
On the other hand, new globals would be 1-byte bools.
Why? You could still poison copy-relocated global if it's __asan_gen_XXX is present. |
Sorry, I've meant non-sanitized binary and sanitized library use case. For sanitized binary we indeed can poison copy-relocated global. |
Well, this case currently segfaults so I wouldn't treat this as a regression) |
As discussed in google/sanitizers#398, with current implementation of poisoning globals we can have some CHECK failures or false positives in case of mixing instrumented and non-instrumented code due to ASan poisons innocent globals from non-sanitized binary/library. We can use private aliases to avoid such errors. In addition, to preserve ODR violation detection, we introduce new __odr_asan_gen_XXX symbol for each instrumented global that indicates if this global was already registered. To detect ODR violation in runtime, we should only check the value of indicator and report an error if it isn't equal to zero. Differential Revision: http://reviews.llvm.org/D15642 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260075 91177308-0d34-0410-b5e6-96231b3b80d8
As discussed in google/sanitizers#398, with current implementation of poisoning globals we can have some CHECK failures or false positives in case of mixing instrumented and non-instrumented code due to ASan poisons innocent globals from non-sanitized binary/library. We can use private aliases to avoid such errors. In addition, to preserve ODR violation detection, we introduce new __odr_asan_gen_XXX symbol for each instrumented global that indicates if this global was already registered. To detect ODR violation in runtime, we should only check the value of indicator and report an error if it isn't equal to zero. Differential Revision: http://reviews.llvm.org/D15642 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260075 91177308-0d34-0410-b5e6-96231b3b80d8
This should be fixed on trunk now, can we close this? |
Another option is waiting until this is enabled by default. |
@kcc: Do we want to enable |
I think this is the same as https://bugs.llvm.org/show_bug.cgi?id=37545 |
Previously Swift enabled the "UseOdrIndicator" ASan instrumentation mode and gave no option to disable this. This probably wasn't intentional but happened due to the fact the `createModuleAddressSanitizerLegacyPassPass()` function has a default value for the `UseOdrIndicator` parameter of `true` and in Swift we never specified this parameter explicitly. Clang disables the "UseOdrIndicator" mode by default but allows it to be enabled using the `-fsanitize-address-use-odr-indicator` flag. Having "UseOdrIndicator" off by default is probably the right default choice because it bloats the binary. So this patch changes the Swift compiler to match Clang's behavior. This patch disables the "UseOdrIndicator" mode by default but adds a hidden driver and frontend flag (`-sanitize-address-use-odr-indicator`) to enable it. The flag is hidden so that we can remove it in the future if needed. A side of disabling "UseOdrIndicator" is that by we will no longer use private aliases for poisoning globals. Private aliases were introduced to avoid crashes (google/sanitizers#398) due to ODR violations with non-instrumented binaries. On Apple platforms the use of two-level namespaces probably means that using private aliases wasn't ever really necessary to avoid crashes. On platforms with a flat linking namespace (e.g. Linux) using private aliases might matter more but should users actually run into problems they can either: * Fix their environment to remove the ODR, thus avoiding the crash. * Instrument the previously non-instrumented code to avoid the crash. * Use the new `-sanitize-address-use-odr-indicator` flag rdar://problem/69335186
Previously Swift enabled the "UseOdrIndicator" ASan instrumentation mode and gave no option to disable this. This probably wasn't intentional but happened due to the fact the `createModuleAddressSanitizerLegacyPassPass()` function has a default value for the `UseOdrIndicator` parameter of `true` and in Swift we never specified this parameter explicitly. Clang disables the "UseOdrIndicator" mode by default but allows it to be enabled using the `-fsanitize-address-use-odr-indicator` flag. Having "UseOdrIndicator" off by default is probably the right default choice because it bloats the binary. So this patch changes the Swift compiler to match Clang's behavior. This patch disables the "UseOdrIndicator" mode by default but adds a hidden driver and frontend flag (`-sanitize-address-use-odr-indicator`) to enable it. The flag is hidden so that we can remove it in the future if needed. A side of disabling "UseOdrIndicator" is that by we will no longer use private aliases for poisoning globals. Private aliases were introduced to avoid crashes (google/sanitizers#398) due to ODR violations with non-instrumented binaries. On Apple platforms the use of two-level namespaces probably means that using private aliases wasn't ever really necessary to avoid crashes. On platforms with a flat linking namespace (e.g. Linux) using private aliases might matter more but should users actually run into problems they can either: * Fix their environment to remove the ODR, thus avoiding the crash. * Instrument the previously non-instrumented code to avoid the crash. * Use the new `-sanitize-address-use-odr-indicator` flag rdar://problem/69335186
Previously Swift enabled the "UseOdrIndicator" ASan instrumentation mode and gave no option to disable this. This probably wasn't intentional but happened due to the fact the `createModuleAddressSanitizerLegacyPassPass()` function has a default value for the `UseOdrIndicator` parameter of `true` and in Swift we never specified this parameter explicitly. Clang disables the "UseOdrIndicator" mode by default but allows it to be enabled using the `-fsanitize-address-use-odr-indicator` flag. Having "UseOdrIndicator" off by default is probably the right default choice because it bloats the binary. So this patch changes the Swift compiler to match Clang's behavior. This patch disables the "UseOdrIndicator" mode by default but adds a hidden driver and frontend flag (`-sanitize-address-use-odr-indicator`) to enable it. The flag is hidden so that we can remove it in the future if needed. A side effect of disabling "UseOdrIndicator" is that by we will no longer use private aliases for poisoning globals. Private aliases were introduced to avoid crashes (google/sanitizers#398) due to ODR violations with non-instrumented binaries. On Apple platforms the use of two-level namespaces probably means that using private aliases wasn't ever really necessary to avoid crashes. On platforms with a flat linking namespace (e.g. Linux) using private aliases might matter more but should users actually run into problems they can either: * Fix their environment to remove the ODR, thus avoiding the crash. * Instrument the previously non-instrumented code to avoid the crash. * Use the new `-sanitize-address-use-odr-indicator` flag rdar://problem/69335186
This enables odr indicators on all platforms and private aliases on non-Windows. Note that GCC also uses private aliases: this fixes spurious `The following global variable is not properly aligned.` errors for interposed global variables (PR37545 (this patch should allow us to restore D46665) and google/sanitizers#1017) Global variables of non-hasExactDefinition() linkages (i.e. linkonce/linkonce_odr/weak/weak_odr/common/external_weak) are not instrumented. If an instrumented variable gets interposed to an uninstrumented variable due to symbol interposition (e.g. in PR37545, _ZTS1A in foo.so is resolved to _ZTS1A in the executable), there may be a bogus error. With private aliases, the register code will not resolve to a definition in another module, and thus prevent the issue. google/sanitizers#398 Similar to the above, but about an instrumented global variable gets interposed to an uninstrumented global variable (not using address sanitizer) in another module. Cons: negligible size increase. On ELF, this is mainly due to extra `__odr_asan_gen_*` symbols. In relocatable files, private aliases replace some relocations referencing global symbols with .L symbols. This may introduce some STT_SECTION symbols. For lld, with -g0, the size increase is 0.07~0.09% for many configurations I have tested: -O0, -O1, -O2, -O3, -O2 -ffunction-sections -fdata-sections -Wl,--gc-sections. With -g1 or above, the size increase ratio will be even smaller. This replaces D92078. Don't migrate Windows for now: the static data member of a specialization `std::num_put<char>::id` is a weak symbol, as well as its ODR indicator. Unfortunately, link.exe (and lld without -lldmingw) generally doesn't support duplicate weak definitions (weak symbols in different TUs likely pick different defined external symbols and conflict). Differential Revision: https://reviews.llvm.org/D137227
This enables odr indicators on all platforms and private aliases on non-Windows. Note that GCC also uses private aliases: this fixes bogus `The following global variable is not properly aligned.` errors for interposed global variables Fix google/sanitizers#398 Fix google/sanitizers#1017 Fix #36893 (we can restore D46665) Global variables of non-hasExactDefinition() linkages (i.e. linkonce/linkonce_odr/weak/weak_odr/common/external_weak) are not instrumented. If an instrumented variable gets interposed to an uninstrumented variable due to symbol interposition (e.g. in issue 36893, _ZTS1A in foo.so is resolved to _ZTS1A in the executable), there may be a bogus error. With private aliases, the register code will not resolve to a definition in another module, and thus prevent the issue. Cons: minor size increase. This is mainly due to extra `__odr_asan_gen_*` symbols. (ELF) In addition, in relocatable files private aliases replace some relocations referencing global symbols with .L symbols and may introduce some STT_SECTION symbols. For lld, with -g0, the size increase is 0.07~0.09% for many configurations I have tested: -O0, -O1, -O2, -O3, -O2 -ffunction-sections -fdata-sections -Wl,--gc-sections. With -g1 or above, the size increase ratio will be even smaller. This patch obsoletes D92078. Don't migrate Windows for now: the static data member of a specialization `std::num_put<char>::id` is a weak symbol, as well as its ODR indicator. Unfortunately, link.exe (and lld without -lldmingw) generally doesn't support duplicate weak definitions (weak symbols in different TUs likely pick different defined external symbols and conflict). Differential Revision: https://reviews.llvm.org/D137227
This issue can be closed now that -fsanitize-address-use-odr-indicator is the default for non-Windows platforms. |
Originally reported on Google Code with ID 398
Reported by
[email protected]
on 2015-07-14 18:09:45The text was updated successfully, but these errors were encountered: