summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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) )