summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEvgeniy Stepanov <eugeni.stepanov@gmail.com>2018-08-16 20:46:41 +0000
committerEvgeniy Stepanov <eugeni.stepanov@gmail.com>2018-08-16 20:46:41 +0000
commit8bb383f1fbb83588fe901a507e485254256886ed (patch)
treef83d5576d89c0cfadbbcb47e346e1ac6f0a30c67
parent89e833c6623394eceab109241722561daba7fd4c (diff)
downloadbcm5719-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.h7
-rw-r--r--compiler-rt/lib/hwasan/hwasan.cc18
-rw-r--r--compiler-rt/lib/hwasan/hwasan_interface_internal.h3
-rw-r--r--compiler-rt/test/hwasan/TestCases/longjmp.cc28
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
+}
OpenPOWER on IntegriCloud