diff options
author | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2018-08-16 20:46:41 +0000 |
---|---|---|
committer | Evgeniy Stepanov <eugeni.stepanov@gmail.com> | 2018-08-16 20:46:41 +0000 |
commit | 8bb383f1fbb83588fe901a507e485254256886ed (patch) | |
tree | f83d5576d89c0cfadbbcb47e346e1ac6f0a30c67 | |
parent | 89e833c6623394eceab109241722561daba7fd4c (diff) | |
download | bcm5719-llvm-8bb383f1fbb83588fe901a507e485254256886ed.tar.gz bcm5719-llvm-8bb383f1fbb83588fe901a507e485254256886ed.zip |
[hwasan] Add __hwasan_handle_longjmp.
Summary:
A callback to annotate longjmp-like code.
Unlike __asan_handle_no_return, in hwasan we can not conservatively
"unpoison" the entire thread stack, because there is no such thing as
unpoisoned memory. Pointer and memory tags must always match.
Reviewers: vitalybuka, kcc
Subscribers: kubamracek, llvm-commits
Differential Revision: https://reviews.llvm.org/D50752
llvm-svn: 339935
-rw-r--r-- | compiler-rt/include/sanitizer/hwasan_interface.h | 7 | ||||
-rw-r--r-- | compiler-rt/lib/hwasan/hwasan.cc | 18 | ||||
-rw-r--r-- | compiler-rt/lib/hwasan/hwasan_interface_internal.h | 3 | ||||
-rw-r--r-- | compiler-rt/test/hwasan/TestCases/longjmp.cc | 28 |
4 files changed, 56 insertions, 0 deletions
diff --git a/compiler-rt/include/sanitizer/hwasan_interface.h b/compiler-rt/include/sanitizer/hwasan_interface.h index 9ca73bc1072..78644aa9d4f 100644 --- a/compiler-rt/include/sanitizer/hwasan_interface.h +++ b/compiler-rt/include/sanitizer/hwasan_interface.h @@ -40,6 +40,13 @@ extern "C" { /// Set pointer tag. Previous tag is lost. void *__hwasan_tag_pointer(const volatile void *p, unsigned char tag); + // Set memory tag from the current SP address to the given address to zero. + // This is meant to annotate longjmp and other non-local jumps. + // This function needs to know the (almost) exact destination frame address; + // clearing shadow for the entire thread stack like __asan_handle_no_return + // does would cause false reports. + void __hwasan_handle_longjmp(const void *sp_dst); + // Print shadow and origin for the memory range to stderr in a human-readable // format. void __hwasan_print_shadow(const volatile void *x, size_t size); diff --git a/compiler-rt/lib/hwasan/hwasan.cc b/compiler-rt/lib/hwasan/hwasan.cc index d4b55836bd2..bb9a8dd7fe3 100644 --- a/compiler-rt/lib/hwasan/hwasan.cc +++ b/compiler-rt/lib/hwasan/hwasan.cc @@ -409,6 +409,24 @@ uptr __hwasan_tag_pointer(uptr p, u8 tag) { return AddTagToPointer(p, tag); } +void __hwasan_handle_longjmp(const void *sp_dst) { + uptr dst = (uptr)sp_dst; + // HWASan does not support tagged SP. + CHECK(GetTagFromPointer(dst) == 0); + + uptr sp = (uptr)__builtin_frame_address(0); + static const uptr kMaxExpectedCleanupSize = 64 << 20; // 64M + if (dst < sp || dst - sp > kMaxExpectedCleanupSize) { + Report( + "WARNING: HWASan is ignoring requested __hwasan_handle_longjmp: " + "stack top: %p; target %p; distance: %p (%zd)\n" + "False positive error reports may follow\n", + (void *)sp, (void *)dst, dst - sp); + return; + } + TagMemory(sp, dst - sp, 0); +} + static const u8 kFallbackTag = 0xBB; u8 __hwasan_generate_tag() { diff --git a/compiler-rt/lib/hwasan/hwasan_interface_internal.h b/compiler-rt/lib/hwasan/hwasan_interface_internal.h index 8aa0ed5d457..12c445409f9 100644 --- a/compiler-rt/lib/hwasan/hwasan_interface_internal.h +++ b/compiler-rt/lib/hwasan/hwasan_interface_internal.h @@ -111,6 +111,9 @@ SANITIZER_INTERFACE_ATTRIBUTE void __hwasan_print_shadow(const void *x, uptr size); SANITIZER_INTERFACE_ATTRIBUTE +void __hwasan_handle_longjmp(const void *sp_dst); + +SANITIZER_INTERFACE_ATTRIBUTE u16 __sanitizer_unaligned_load16(const uu16 *p); SANITIZER_INTERFACE_ATTRIBUTE diff --git a/compiler-rt/test/hwasan/TestCases/longjmp.cc b/compiler-rt/test/hwasan/TestCases/longjmp.cc new file mode 100644 index 00000000000..898b8b3e5ab --- /dev/null +++ b/compiler-rt/test/hwasan/TestCases/longjmp.cc @@ -0,0 +1,28 @@ +// RUN: %clangxx_hwasan -O0 -DNEGATIVE %s -o %t && %run %t 2>&1 +// RUN: %clangxx_hwasan -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s + +// REQUIRES: stable-runtime + +#include <stdlib.h> +#include <assert.h> +#include <sanitizer/hwasan_interface.h> + +__attribute__((noinline)) +int f(void *caller_frame) { + char z[32] = {}; + char *volatile p = z; + // Tag of local is never zero. + assert(__hwasan_tag_pointer(p, 0) != p); +#ifndef NEGATIVE + // This will destroy shadow of "z", and the following load will crash. + __hwasan_handle_longjmp(caller_frame); +#endif + return p[0]; +} + +int main() { + return f(__builtin_frame_address(0)); + // CHECK: READ of size 8 + // CHECK: pointer tag + // CHECK: memory tag 0x0 +} |