Skip to content

Commit

Permalink
[libc++] Upstream ptrauth support in libc++ and libc++abi (#84573)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
ldionne authored Apr 3, 2024
1 parent 52b1843 commit 98244c4
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 1 deletion.
14 changes: 13 additions & 1 deletion libcxx/include/typeinfo
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,19 @@ struct __type_info_implementations {
__impl;
};

class _LIBCPP_EXPORTED_FROM_ABI type_info {
# if defined(__arm64__) && __has_cpp_attribute(clang::ptrauth_vtable_pointer)
# if __has_feature(ptrauth_type_info_discriminated_vtable_pointer)
# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
[[clang::ptrauth_vtable_pointer(process_independent, address_discrimination, type_discrimination)]]
# else
# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH \
[[clang::ptrauth_vtable_pointer(process_independent, no_address_discrimination, no_extra_discrimination)]]
# endif
# else
# define _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH
# endif

class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_TYPE_INFO_VTABLE_POINTER_AUTH type_info {
type_info& operator=(const type_info&);
type_info(const type_info&);

Expand Down
12 changes: 12 additions & 0 deletions libcxx/src/include/overridable_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@
#include <__config>
#include <cstdint>

#if defined(__arm64e__) && __has_feature(ptrauth_calls)
# include <ptrauth.h>
#endif

#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
# pragma GCC system_header
#endif
Expand Down Expand Up @@ -81,6 +85,14 @@ _LIBCPP_HIDE_FROM_ABI bool __is_function_overridden(_Ret (*__fptr)(_Args...)) no
uintptr_t __end = reinterpret_cast<uintptr_t>(&__lcxx_override_end);
uintptr_t __ptr = reinterpret_cast<uintptr_t>(__fptr);

#if defined(__arm64e__) && __has_feature(ptrauth_calls)
// We must pass a void* to ptrauth_strip since it only accepts a pointer type. Also, in particular,
// we must NOT pass a function pointer, otherwise we will strip the function pointer, and then attempt
// to authenticate and re-sign it when casting it to a uintptr_t again, which will fail because we just
// stripped the function pointer. See rdar://122927845.
__ptr = reinterpret_cast<uintptr_t>(ptrauth_strip(reinterpret_cast<void*>(__ptr), ptrauth_key_function_pointer));
#endif

// Finally, the function was overridden if it falls outside of the section's bounds.
return __ptr < __start || __ptr > __end;
}
Expand Down
19 changes: 19 additions & 0 deletions libcxxabi/src/private_typeinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,21 @@
#include <atomic>
#endif

#if __has_feature(ptrauth_calls)
#include <ptrauth.h>
#endif


template<typename T>
static inline
T *
get_vtable(T *vtable) {
#if __has_feature(ptrauth_calls)
vtable = ptrauth_strip(vtable, ptrauth_key_cxx_vtable_pointer);
#endif
return vtable;
}

static inline
bool
is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp)
Expand Down Expand Up @@ -103,6 +118,7 @@ void dyn_cast_get_derived_info(derived_object_info* info, const void* static_ptr
info->dynamic_type = *(reinterpret_cast<const __class_type_info* const*>(ptr_to_ti_proxy));
#else
void **vtable = *static_cast<void ** const *>(static_ptr);
vtable = get_vtable(vtable);
info->offset_to_derived = reinterpret_cast<ptrdiff_t>(vtable[-2]);
info->dynamic_ptr = static_cast<const char*>(static_ptr) + info->offset_to_derived;
info->dynamic_type = static_cast<const __class_type_info*>(vtable[-1]);
Expand Down Expand Up @@ -561,6 +577,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info,
offset_to_base = __offset_flags >> __offset_shift;
if (is_virtual) {
const char* vtable = *static_cast<const char* const*>(adjustedPtr);
vtable = get_vtable(vtable);
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
} else if (!is_virtual) {
Expand Down Expand Up @@ -1501,6 +1518,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info,
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(current_ptr);
vtable = get_vtable(vtable);
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
__base_type->search_above_dst(info, dst_ptr,
Expand All @@ -1521,6 +1539,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info,
if (__offset_flags & __virtual_mask)
{
const char* vtable = *static_cast<const char*const*>(current_ptr);
vtable = get_vtable(vtable);
offset_to_base = update_offset_to_base(vtable, offset_to_base);
}
__base_type->search_below_dst(info,
Expand Down

0 comments on commit 98244c4

Please sign in to comment.