diff options
-rw-r--r-- | lib/hwasan/hwasan_tag_mismatch_aarch64.S | 50 | ||||
-rw-r--r-- | test/hwasan/TestCases/stack-oob.c | 8 | ||||
-rw-r--r-- | test/hwasan/lit.cfg.py | 5 |
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) ) |