summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Collingbourne <peter@pcc.me.uk>2019-09-27 01:02:10 +0000
committerPeter Collingbourne <peter@pcc.me.uk>2019-09-27 01:02:10 +0000
commitbd083fac50c327010787396271c799b5cc576090 (patch)
tree445bd1bc7cd19ce43560298f9cddb597c58f1a97
parent8bc91a47c8c1c42eb99c5d6030a0d8c785548f0a (diff)
downloadcompiler-rt-bd083fac50c327010787396271c799b5cc576090.tar.gz
hwasan: Compatibility fixes for short granules.
We can't use short granules with stack instrumentation when targeting older API levels because the rest of the system won't understand the short granule tags stored in shadow memory. Moreover, we need to be able to let old binaries (which won't understand short granule tags) run on a new system that supports short granule tags. Such binaries will call the __hwasan_tag_mismatch function when their outlined checks fail. We can compensate for the binary's lack of support for short granules by implementing the short granule part of the check in the __hwasan_tag_mismatch function. Unfortunately we can't do anything about inline checks, but I don't believe that we can generate these by default on aarch64, nor did we do so when the ABI was fixed. A new function, __hwasan_tag_mismatch_v2, is introduced that lets code targeting the new runtime avoid redoing the short granule check. Because tag mismatches are rare this isn't important from a performance perspective; the main benefit is that it introduces a symbol dependency that prevents binaries targeting the new runtime from running on older (i.e. incompatible) runtimes. Differential Revision: https://reviews.llvm.org/D68059 git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@373035 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/hwasan/hwasan_tag_mismatch_aarch64.S50
-rw-r--r--test/hwasan/TestCases/stack-oob.c8
-rw-r--r--test/hwasan/lit.cfg.py5
3 files changed, 58 insertions, 5 deletions
diff --git a/lib/hwasan/hwasan_tag_mismatch_aarch64.S b/lib/hwasan/hwasan_tag_mismatch_aarch64.S
index 92f627480..4c060a61e 100644
--- a/lib/hwasan/hwasan_tag_mismatch_aarch64.S
+++ b/lib/hwasan/hwasan_tag_mismatch_aarch64.S
@@ -51,14 +51,60 @@
// +---------------------------------+ <-- [x30 / SP]
// This function takes two arguments:
-// * x0: The address of read/write instruction that caused HWASan check fail.
-// * x1: The tag size.
+// * x0: The data address.
+// * x1: The encoded access info for the failing access.
+// This function has two entry points. The first, __hwasan_tag_mismatch, is used
+// by clients that were compiled without short tag checks (i.e. binaries built
+// by older compilers and binaries targeting older runtimes). In this case the
+// outlined tag check will be missing the code handling short tags (which won't
+// be used in the binary's own stack variables but may be used on the heap
+// or stack variables in other binaries), so the check needs to be done here.
+//
+// The second, __hwasan_tag_mismatch_v2, is used by binaries targeting newer
+// runtimes. This entry point bypasses the short tag check since it will have
+// already been done as part of the outlined tag check. Since tag mismatches are
+// uncommon, there isn't a significant performance benefit to being able to
+// bypass the check; the main benefits are that we can sometimes avoid
+// clobbering the x17 register in error reports, and that the program will have
+// a runtime dependency on the __hwasan_tag_mismatch_v2 symbol therefore it will
+// fail to start up given an older (i.e. incompatible) runtime.
.section .text
.file "hwasan_tag_mismatch_aarch64.S"
.global __hwasan_tag_mismatch
.type __hwasan_tag_mismatch, %function
__hwasan_tag_mismatch:
+ // Compute the granule position one past the end of the access.
+ mov x16, #1
+ and x17, x1, #0xf
+ lsl x16, x16, x17
+ and x17, x0, #0xf
+ add x17, x16, x17
+
+ // Load the shadow byte again and check whether it is a short tag within the
+ // range of the granule position computed above.
+ ubfx x16, x0, #4, #52
+ ldrb w16, [x9, x16]
+ cmp w16, #0xf
+ b.hi __hwasan_tag_mismatch_v2
+ cmp w16, w17
+ b.lo __hwasan_tag_mismatch_v2
+
+ // Load the real tag from the last byte of the granule and compare against
+ // the pointer tag.
+ orr x16, x0, #0xf
+ ldrb w16, [x16]
+ cmp x16, x0, lsr #56
+ b.ne __hwasan_tag_mismatch_v2
+
+ // Restore x0, x1 and sp to their values from before the __hwasan_tag_mismatch
+ // call and resume execution.
+ ldp x0, x1, [sp], #256
+ ret
+
+.global __hwasan_tag_mismatch_v2
+.type __hwasan_tag_mismatch_v2, %function
+__hwasan_tag_mismatch_v2:
CFI_STARTPROC
// Set the CFA to be the return address for caller of __hwasan_check_*. Note
diff --git a/test/hwasan/TestCases/stack-oob.c b/test/hwasan/TestCases/stack-oob.c
index ba7493092..8c8c11055 100644
--- a/test/hwasan/TestCases/stack-oob.c
+++ b/test/hwasan/TestCases/stack-oob.c
@@ -1,4 +1,8 @@
+// RUN: %clang_hwasan_oldrt -DSIZE=2 -O0 %s -o %t && %run %t
+// RUN: %clang_hwasan -DSIZE=2 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clang_hwasan_oldrt -DSIZE=15 -O0 %s -o %t && %run %t
// RUN: %clang_hwasan -DSIZE=15 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clang_hwasan_oldrt -DSIZE=16 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clang_hwasan -DSIZE=16 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clang_hwasan -DSIZE=64 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
// RUN: %clang_hwasan -DSIZE=0x1000 -O0 %s -o %t && not %run %t 2>&1 | FileCheck %s
@@ -16,9 +20,9 @@ int f() {
}
int main() {
- return f();
+ f();
// CHECK: READ of size 1 at
- // CHECK: #0 {{.*}} in f{{.*}}stack-oob.c:15
+ // CHECK: #0 {{.*}} in f{{.*}}stack-oob.c:19
// CHECK: is located in stack of threa
diff --git a/test/hwasan/lit.cfg.py b/test/hwasan/lit.cfg.py
index eead83219..ee67a261d 100644
--- a/test/hwasan/lit.cfg.py
+++ b/test/hwasan/lit.cfg.py
@@ -18,9 +18,11 @@ if config.target_arch == 'x86_64':
# equivalent target feature implemented on x86_64.
clang_hwasan_common_cflags += ["-mcmodel=large"]
clang_hwasan_cflags = clang_hwasan_common_cflags + ["-mllvm", "-hwasan-globals",
+ "-mllvm", "-hwasan-use-short-granules",
"-mllvm", "-hwasan-instrument-landing-pads=0",
"-mllvm", "-hwasan-instrument-personality-functions"]
-clang_hwasan_oldrt_cflags = clang_hwasan_common_cflags + ["-mllvm", "-hwasan-instrument-landing-pads=1",
+clang_hwasan_oldrt_cflags = clang_hwasan_common_cflags + ["-mllvm", "-hwasan-use-short-granules=0",
+ "-mllvm", "-hwasan-instrument-landing-pads=1",
"-mllvm", "-hwasan-instrument-personality-functions=0"]
clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags
@@ -31,6 +33,7 @@ def build_invocation(compile_flags):
config.substitutions.append( ("%clangxx ", build_invocation(clang_cxxflags)) )
config.substitutions.append( ("%clang_hwasan ", build_invocation(clang_hwasan_cflags)) )
+config.substitutions.append( ("%clang_hwasan_oldrt ", build_invocation(clang_hwasan_oldrt_cflags)) )
config.substitutions.append( ("%clangxx_hwasan ", build_invocation(clang_hwasan_cxxflags)) )
config.substitutions.append( ("%clangxx_hwasan_oldrt ", build_invocation(clang_hwasan_oldrt_cxxflags)) )
config.substitutions.append( ("%compiler_rt_libdir", config.compiler_rt_libdir) )