[Sanitizers] UBSan unreachable incompatible with ASan in the presence of noreturn calls
Summary:
UBSan wants to detect when unreachable code is actually reached, so it
adds instrumentation before every `unreachable` instruction. However,
the optimizer will remove code after calls to functions marked with
`noreturn`. To avoid this UBSan removes `noreturn` from both the call
instruction as well as from the function itself. Unfortunately, ASan
relies on this annotation to unpoison the stack by inserting calls to
`_asan_handle_no_return` before `noreturn` functions. This is important
for functions that do not return but access the the stack memory, e.g.,
unwinder functions *like* `longjmp` (`longjmp` itself is actually
"double-proofed" via its interceptor). The result is that when ASan and
UBSan are combined, the `noreturn` attributes are missing and ASan
cannot unpoison the stack, so it has false positives when stack
unwinding is used.
Changes:
# UBSan now adds the `expect_noreturn` attribute whenever it removes
the `noreturn` attribute from a function
# ASan additionally checks for the presence of this attribute
Generated code:
```
call void @__asan_handle_no_return // Additionally inserted to avoid false positives
call void @longjmp
call void @__asan_handle_no_return
call void @__ubsan_handle_builtin_unreachable
unreachable
```
The second call to `__asan_handle_no_return` is redundant. This will be
cleaned up in a follow-up patch.
rdar://problem/40723397
Reviewers: delcypher, eugenis
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D56624
llvm-svn: 352003
This commit is contained in:
@@ -1186,8 +1186,8 @@ static uint64_t getRawAttributeMask(Attribute::AttrKind Val) {
|
||||
case Attribute::NoCfCheck: return 1ULL << 57;
|
||||
case Attribute::OptForFuzzing: return 1ULL << 58;
|
||||
case Attribute::ShadowCallStack: return 1ULL << 59;
|
||||
case Attribute::SpeculativeLoadHardening:
|
||||
return 1ULL << 60;
|
||||
case Attribute::SpeculativeLoadHardening: return 1ULL << 60;
|
||||
case Attribute::ExpectNoReturn: return 1ULL << 61;
|
||||
case Attribute::Dereferenceable:
|
||||
llvm_unreachable("dereferenceable attribute not supported in raw format");
|
||||
break;
|
||||
@@ -1366,6 +1366,8 @@ static Attribute::AttrKind getAttrFromCode(uint64_t Code) {
|
||||
return Attribute::NoRedZone;
|
||||
case bitc::ATTR_KIND_NO_RETURN:
|
||||
return Attribute::NoReturn;
|
||||
case bitc::ATTR_KIND_EXPECT_NO_RETURN:
|
||||
return Attribute::ExpectNoReturn;
|
||||
case bitc::ATTR_KIND_NOCF_CHECK:
|
||||
return Attribute::NoCfCheck;
|
||||
case bitc::ATTR_KIND_NO_UNWIND:
|
||||
|
||||
Reference in New Issue
Block a user