[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