[compiler-rt] 80022ae - [UBSan] Fix vptr checks on arm64e

Julian Lettner via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 16 16:09:15 PDT 2020


Author: Julian Lettner
Date: 2020-04-16T16:09:05-07:00
New Revision: 80022ae2b58e7c2d51e7705d39a8ab546ac7de85

URL: https://github.com/llvm/llvm-project/commit/80022ae2b58e7c2d51e7705d39a8ab546ac7de85
DIFF: https://github.com/llvm/llvm-project/commit/80022ae2b58e7c2d51e7705d39a8ab546ac7de85.diff

LOG: [UBSan] Fix vptr checks on arm64e

Fix UBSan's vptr checks in the presence of arm64e pointer signing.

Radar-Id: rdar://61786404

Reviewed By: vsk

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

Added: 
    compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-ptrauth-unauthenticated.cpp

Modified: 
    compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cpp
    compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cpp b/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cpp
index 97846d4dd434..465aa6476ad0 100644
--- a/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cpp
+++ b/compiler-rt/lib/ubsan/ubsan_type_hash_itanium.cpp
@@ -17,6 +17,10 @@
 
 #include "sanitizer_common/sanitizer_common.h"
 
+#if __has_feature(ptrauth_calls)
+#include <ptrauth.h>
+#endif
+
 // The following are intended to be binary compatible with the definitions
 // given in the Itanium ABI. We make no attempt to be ODR-compatible with
 // those definitions, since existing ABI implementations aren't.
@@ -194,6 +198,9 @@ struct VtablePrefix {
   std::type_info *TypeInfo;
 };
 VtablePrefix *getVtablePrefix(void *Vtable) {
+#if __has_feature(ptrauth_calls)
+  Vtable = ptrauth_auth_data(Vtable, ptrauth_key_cxx_vtable_pointer, 0);
+#endif
   VtablePrefix *Vptr = reinterpret_cast<VtablePrefix*>(Vtable);
   VtablePrefix *Prefix = Vptr - 1;
   if (!IsAccessibleMemoryRange((uptr)Prefix, sizeof(VtablePrefix)))

diff  --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
index 0e3d0d8592ab..ef8f22e311e5 100644
--- a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
+++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-corrupted-vtable-itanium.cpp
@@ -1,12 +1,15 @@
-// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr,null -g %s -O3 -o %t
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
 // RUN: not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-CORRUPTED-VTABLE --strict-whitespace
 
 // UNSUPPORTED: windows-msvc
 // REQUIRES: stable-runtime, cxxabi
-#include <cstddef>
 
 #include <typeinfo>
 
+#if __has_feature(ptrauth_calls)
+#include <ptrauth.h>
+#endif
+
 struct S {
   S() {}
   ~S() {}
@@ -24,15 +27,23 @@ int main(int argc, char **argv) {
   // offset is too large or too small.
   S Obj;
   void *Ptr = &Obj;
-  VtablePrefix* RealPrefix = reinterpret_cast<VtablePrefix*>(
-      *reinterpret_cast<void**>(Ptr)) - 1;
+  void *VtablePtr = *reinterpret_cast<void**>(Ptr);
+#if __has_feature(ptrauth_calls)
+  VtablePtr = ptrauth_strip(VtablePtr, 0);
+#endif
+  VtablePrefix* Prefix = reinterpret_cast<VtablePrefix*>(VtablePtr) - 1;
 
-  VtablePrefix Prefix[2];
-  Prefix[0].Offset = 1<<21; // Greater than VptrMaxOffset
-  Prefix[0].TypeInfo = RealPrefix->TypeInfo;
+  VtablePrefix FakePrefix[2];
+  FakePrefix[0].Offset = 1<<21; // Greater than VptrMaxOffset
+  FakePrefix[0].TypeInfo = Prefix->TypeInfo;
 
   // Hack Vtable ptr for Obj.
-  *reinterpret_cast<void**>(Ptr) = static_cast<void*>(&Prefix[1]);
+  void *FakeVtablePtr = static_cast<void*>(&FakePrefix[1]);
+#if __has_feature(ptrauth_calls)
+  FakeVtablePtr = ptrauth_sign_unauthenticated(
+      FakeVtablePtr, ptrauth_key_cxx_vtable_pointer, 0);
+#endif
+  *reinterpret_cast<void**>(Ptr) = FakeVtablePtr;
 
   // CHECK-CORRUPTED-VTABLE: vptr-corrupted-vtable-itanium.cpp:[[@LINE+3]]:16: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'S'
   // CHECK-CORRUPTED-VTABLE-NEXT: [[PTR]]: note: object has a possibly invalid vptr: abs(offset to top) too big

diff  --git a/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-ptrauth-unauthenticated.cpp b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-ptrauth-unauthenticated.cpp
new file mode 100644
index 000000000000..6061cfc457fc
--- /dev/null
+++ b/compiler-rt/test/ubsan/TestCases/TypeCheck/vptr-ptrauth-unauthenticated.cpp
@@ -0,0 +1,31 @@
+// Test that we don't crash for vtable pointers with an invalid ptrauth
+// signature which includes unauthenticated vtable pointers.
+
+// RUN: %clangxx -frtti -fsanitize=vptr -fno-sanitize-recover=vptr -g %s -O3 -o %t
+// RUN: not %run %t 2>&1 | FileCheck %s
+
+// TODO(yln): introduce 'ptrauth' lit feature
+// REQUIRES: stable-runtime, cxxabi, arch=arm64e
+
+#include <typeinfo>
+#include <ptrauth.h>
+
+struct S {
+  S() {}
+  ~S() {}
+  virtual int v() { return 0; }
+};
+
+int main(int argc, char **argv) {
+  S Obj;
+  void *Ptr = &Obj;
+  void **VtablePtrPtr = reinterpret_cast<void **>(&Obj);
+  // Hack Obj: the unauthenticated Vtable ptr will trigger an auth failure in the runtime.
+  void *UnauthenticatedVtablePtr = ptrauth_strip(*VtablePtrPtr, 0);
+  *VtablePtrPtr = UnauthenticatedVtablePtr;
+
+  // CHECK: vptr-ptrauth-unauthenticated.cpp:[[@LINE+3]]:16: runtime error: member call on address [[PTR:0x[0-9a-f]*]] which does not point to an object of type 'S'
+  // CHECK: [[PTR]]: note: object has invalid vptr
+  S *Ptr2 = reinterpret_cast<S *>(Ptr);
+  return Ptr2->v();
+}


        


More information about the llvm-commits mailing list