Skip to content

Commit 98244c4

Browse files
authored
[libc++] Upstream ptrauth support in libc++ and libc++abi (#84573)
This is an exact upstreaming of the downstream diff. Minor simplifications can be made in the future but upstreaming as-is will make it easier for us to deal with downstream merge conflicts. Partially fixes #83805
1 parent 52b1843 commit 98244c4

File tree

3 files changed

+44
-1
lines changed

3 files changed

+44
-1
lines changed

libcxx/include/typeinfo

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,19 @@ struct __type_info_implementations {
275275
__impl;
276276
};
277277

278-
class _LIBCPP_EXPORTED_FROM_ABI type_info {
278+
# if defined(__arm64__) && __has_cpp_attribute(clang::ptrauth_vtable_pointer)
279+
# if __has_feature(ptrauth_type_info_discriminated_vtable_pointer)
280+
# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
281+
[[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]]
282+
# else
283+
# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
284+
[[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]]
285+
# endif
286+
# else
287+
# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH
288+
# endif
289+
290+
class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info {
279291
type_info& operator=(const type_info&);
280292
type_info(const type_info&);
281293

libcxx/src/include/overridable_function.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@
1313
#include <__config>
1414
#include <cstdint>
1515

16+
#if defined(__arm64e__) && __has_feature(ptrauth_calls)
17+
# include <ptrauth.h>
18+
#endif
19+
1620
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
1721
# pragma GCC system_header
1822
#endif
@@ -81,6 +85,14 @@ _LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) no
8185
uintptr_t __end = reinterpret_cast<uintptr_t>(&__lcxx_override_end);
8286
uintptr_t __ptr = reinterpret_cast<uintptr_t>(__fptr);
8387

88+
#if defined(__arm64e__) && __has_feature(ptrauth_calls)
89+
// We must pass a void* to ptrauth_strip since it only accepts a pointer type. Also, in particular,
90+
// we must NOT pass a function pointer, otherwise we will strip the function pointer, and then attempt
91+
// to authenticate and re-sign it when casting it to a uintptr_t again, which will fail because we just
92+
// stripped the function pointer. See rdar://122927845.
93+
__ptr = reinterpret_cast<uintptr_t>(ptrauth_strip(reinterpret_cast<void*>(__ptr), ptrauth_key_function_pointer));
94+
#endif
95+
8496
// Finally, the function was overridden if it falls outside of the section's bounds.
8597
return __ptr < __start || __ptr > __end;
8698
}

libcxxabi/src/private_typeinfo.cpp

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,21 @@
5151
#include <atomic>
5252
#endif
5353

54+
#if __has_feature(ptrauth_calls)
55+
#include <ptrauth.h>
56+
#endif
57+
58+
59+
template<typename T>
60+
static inline
61+
T *
62+
get_vtable(T *vtable) {
63+
#if __has_feature(ptrauth_calls)
64+
vtable = ptrauth_strip(vtable, ptrauth_key_cxx_vtable_pointer);
65+
#endif
66+
return vtable;
67+
}
68+
5469
static inline
5570
bool
5671
is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
@@ -103,6 +118,7 @@ void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr
103118
info->dynamic_type = *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
104119
#else
105120
void **vtable = *static_cast<void ** const *>(static_ptr);
121+
vtable = get_vtable(vtable);
106122
info->offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
107123
info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
108124
info->dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
@@ -561,6 +577,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
561577
offset_to_base = __offset_flags >> __offset_shift;
562578
if (is_virtual) {
563579
const char* vtable = *static_cast<const char* const*>(adjustedPtr);
580+
vtable = get_vtable(vtable);
564581
offset_to_base = update_offset_to_base(vtable, offset_to_base);
565582
}
566583
} else if (!is_virtual) {
@@ -1501,6 +1518,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info,
15011518
if (__offset_flags & __virtual_mask)
15021519
{
15031520
const char* vtable = *static_cast<const char*const*>(current_ptr);
1521+
vtable = get_vtable(vtable);
15041522
offset_to_base = update_offset_to_base(vtable, offset_to_base);
15051523
}
15061524
__base_type->search_above_dst(info, dst_ptr,
@@ -1521,6 +1539,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
15211539
if (__offset_flags & __virtual_mask)
15221540
{
15231541
const char* vtable = *static_cast<const char*const*>(current_ptr);
1542+
vtable = get_vtable(vtable);
15241543
offset_to_base = update_offset_to_base(vtable, offset_to_base);
15251544
}
15261545
__base_type->search_below_dst(info,

0 commit comments

Comments
 (0)