[Sanitizers] UBSan unreachable incompatible with ASan in the presence of `noreturn...
authorJulian Lettner <jlettner@apple.com>
Thu, 24 Jan 2019 01:06:19 +0000 (01:06 +0000)
committerJulian Lettner <jlettner@apple.com>
Thu, 24 Jan 2019 01:06:19 +0000 (01:06 +0000)
commitcea84ab93aeb079a358ab1c8aeba6d9140ef8b47
tree3c059cf1dbc208d26fc1df2547d0a18e18448095
parent970d9d9acc421cc43fa801d2be81328d066200ec
[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
18 files changed:
clang/lib/CodeGen/CGCall.cpp
clang/test/CodeGenCXX/ubsan-unreachable.cpp
compiler-rt/test/ubsan/TestCases/Misc/unreachable_asan-compatibility.c [new file with mode: 0644]
llvm/docs/LangRef.rst
llvm/include/llvm/Bitcode/LLVMBitCodes.h
llvm/include/llvm/IR/Attributes.td
llvm/lib/AsmParser/LLLexer.cpp
llvm/lib/AsmParser/LLParser.cpp
llvm/lib/AsmParser/LLToken.h
llvm/lib/Bitcode/Reader/BitcodeReader.cpp
llvm/lib/Bitcode/Writer/BitcodeWriter.cpp
llvm/lib/IR/Attributes.cpp
llvm/lib/IR/Verifier.cpp
llvm/lib/Transforms/IPO/ForceFunctionAttrs.cpp
llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
llvm/lib/Transforms/Utils/CodeExtractor.cpp
llvm/test/Bitcode/attributes.ll
llvm/test/Instrumentation/AddressSanitizer/instrument-no-return.ll