[compiler-rt] r369721 - hwasan: Untag unwound stack frames by wrapping personality functions.

Peter Collingbourne via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 22 18:28:44 PDT 2019


Author: pcc
Date: Thu Aug 22 18:28:44 2019
New Revision: 369721

URL: http://llvm.org/viewvc/llvm-project?rev=369721&view=rev
Log:
hwasan: Untag unwound stack frames by wrapping personality functions.

One problem with untagging memory in landing pads is that it only works
correctly if the function that catches the exception is instrumented.
If the function is uninstrumented, we have no opportunity to untag the
memory.

To address this, replace landing pad instrumentation with personality function
wrapping. Each function with an instrumented stack has its personality function
replaced with a wrapper provided by the runtime. Functions that did not have
a personality function to begin with also get wrappers if they may be unwound
past. As the unwinder calls personality functions during stack unwinding,
the original personality function is called and the function's stack frame is
untagged by the wrapper if the personality function instructs the unwinder
to keep unwinding. If unwinding stops at a landing pad, the function is
still responsible for untagging its stack frame if it resumes unwinding.

The old landing pad mechanism is preserved for compatibility with old runtimes.

Differential Revision: https://reviews.llvm.org/D66377

Added:
    compiler-rt/trunk/lib/hwasan/hwasan_exceptions.cpp
Modified:
    compiler-rt/trunk/lib/hwasan/CMakeLists.txt
    compiler-rt/trunk/test/hwasan/TestCases/try-catch.cpp
    compiler-rt/trunk/test/hwasan/lit.cfg.py

Modified: compiler-rt/trunk/lib/hwasan/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/CMakeLists.txt?rev=369721&r1=369720&r2=369721&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/CMakeLists.txt (original)
+++ compiler-rt/trunk/lib/hwasan/CMakeLists.txt Thu Aug 22 18:28:44 2019
@@ -5,6 +5,7 @@ set(HWASAN_RTL_SOURCES
   hwasan.cpp
   hwasan_allocator.cpp
   hwasan_dynamic_shadow.cpp
+  hwasan_exceptions.cpp
   hwasan_interceptors.cpp
   hwasan_interceptors_vfork.S
   hwasan_linux.cpp

Added: compiler-rt/trunk/lib/hwasan/hwasan_exceptions.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_exceptions.cpp?rev=369721&view=auto
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_exceptions.cpp (added)
+++ compiler-rt/trunk/lib/hwasan/hwasan_exceptions.cpp Thu Aug 22 18:28:44 2019
@@ -0,0 +1,64 @@
+//===-- hwasan_exceptions.cpp ---------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file is a part of HWAddressSanitizer.
+//
+// HWAddressSanitizer runtime.
+//===----------------------------------------------------------------------===//
+
+#include "hwasan_poisoning.h"
+#include "sanitizer_common/sanitizer_common.h"
+
+#include <unwind.h>
+
+using namespace __hwasan;
+using namespace __sanitizer;
+
+typedef _Unwind_Reason_Code PersonalityFn(int version, _Unwind_Action actions,
+                                          uint64_t exception_class,
+                                          _Unwind_Exception* unwind_exception,
+                                          _Unwind_Context* context);
+
+// Pointers to the _Unwind_GetGR and _Unwind_GetCFA functions are passed in
+// instead of being called directly. This is to handle cases where the unwinder
+// is statically linked and the sanitizer runtime and the program are linked
+// against different unwinders. The _Unwind_Context data structure is opaque so
+// it may be incompatible between unwinders.
+typedef _Unwind_Word GetGRFn(_Unwind_Context* context, int index);
+typedef _Unwind_Word GetCFAFn(_Unwind_Context* context);
+
+extern "C" _Unwind_Reason_Code __hwasan_personality_wrapper(
+    int version, _Unwind_Action actions, uint64_t exception_class,
+    _Unwind_Exception* unwind_exception, _Unwind_Context* context,
+    PersonalityFn* real_personality, GetGRFn* get_gr, GetCFAFn* get_cfa) {
+  _Unwind_Reason_Code rc;
+  if (real_personality)
+    rc = real_personality(version, actions, exception_class, unwind_exception,
+                          context);
+  else
+    rc = _URC_CONTINUE_UNWIND;
+
+  // We only untag frames without a landing pad because landing pads are
+  // responsible for untagging the stack themselves if they resume.
+  //
+  // Here we assume that the frame record appears after any locals. This is not
+  // required by AAPCS but is a requirement for HWASAN instrumented functions.
+  if ((actions & _UA_CLEANUP_PHASE) && rc == _URC_CONTINUE_UNWIND) {
+#if defined(__x86_64__)
+    uptr fp = get_gr(context, 6); // rbp
+#elif defined(__aarch64__)
+    uptr fp = get_gr(context, 29); // x29
+#else
+#error Unsupported architecture
+#endif
+    uptr sp = get_cfa(context);
+    TagMemory(sp, fp - sp, 0);
+  }
+
+  return rc;
+}

Modified: compiler-rt/trunk/test/hwasan/TestCases/try-catch.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/try-catch.cpp?rev=369721&r1=369720&r2=369721&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/try-catch.cpp (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/try-catch.cpp Thu Aug 22 18:28:44 2019
@@ -1,5 +1,7 @@
 // RUN: %clangxx_hwasan %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
-// RUN: %clangxx_hwasan %s -mllvm -hwasan-instrument-landing-pads=0 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=BAD
+// RUN: %clangxx_hwasan -DNO_SANITIZE_F %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
+// RUN: %clangxx_hwasan_oldrt %s -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=GOOD
+// RUN: %clangxx_hwasan_oldrt %s -mllvm -hwasan-instrument-landing-pads=0 -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=BAD
 
 // C++ tests on x86_64 require instrumented libc++/libstdc++.
 // REQUIRES: aarch64-target-arch
@@ -40,6 +42,9 @@ __attribute__((noinline, no_sanitize("hw
 
 
 __attribute__((noinline))
+#ifdef NO_SANITIZE_F
+__attribute__((no_sanitize("hwaddress")))
+#endif
 void f() {
   char x[1000];
   try {

Modified: compiler-rt/trunk/test/hwasan/lit.cfg.py
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/lit.cfg.py?rev=369721&r1=369720&r2=369721&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/lit.cfg.py (original)
+++ compiler-rt/trunk/test/hwasan/lit.cfg.py Thu Aug 22 18:28:44 2019
@@ -11,13 +11,17 @@ config.test_source_root = os.path.dirnam
 # Setup default compiler flags used with -fsanitize=memory option.
 clang_cflags = [config.target_cflags] + config.debug_info_flags
 clang_cxxflags = config.cxx_mode_flags + clang_cflags
-clang_hwasan_cflags = clang_cflags + ["-fsanitize=hwaddress", "-mllvm", "-hwasan-globals", "-fuse-ld=lld"]
+clang_hwasan_oldrt_cflags = clang_cflags + ["-fsanitize=hwaddress", "-fuse-ld=lld"]
 if config.target_arch == 'x86_64':
   # This does basically the same thing as tagged-globals on aarch64. Because
   # the x86_64 implementation is for testing purposes only there is no
   # equivalent target feature implemented on x86_64.
-  clang_hwasan_cflags += ["-mcmodel=large"]
+  clang_hwasan_oldrt_cflags += ["-mcmodel=large"]
+clang_hwasan_cflags = clang_hwasan_oldrt_cflags + ["-mllvm", "-hwasan-globals",
+                                                   "-mllvm", "-hwasan-instrument-landing-pads=0",
+                                                   "-mllvm", "-hwasan-instrument-personality-functions"]
 clang_hwasan_cxxflags = config.cxx_mode_flags + clang_hwasan_cflags
+clang_hwasan_oldrt_cxxflags = config.cxx_mode_flags + clang_hwasan_oldrt_cflags
 
 def build_invocation(compile_flags):
   return " " + " ".join([config.clang] + compile_flags) + " "
@@ -25,6 +29,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( ("%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) )
 
 default_hwasan_opts_str = ':'.join(['disable_allocator_tagging=1', 'random_tags=0'] + config.default_sanitizer_opts)




More information about the llvm-commits mailing list