forked from OSchip/llvm-project
[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
This commit is contained in:
parent
63725df1d6
commit
80022ae2b5
|
@ -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)))
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
}
|
Loading…
Reference in New Issue