diff options
Diffstat (limited to 'libcxxabi/src')
-rw-r--r-- | libcxxabi/src/cxa_exception.cpp | 4 | ||||
-rw-r--r-- | libcxxabi/src/cxa_exception.h | 30 | ||||
-rw-r--r-- | libcxxabi/src/cxa_personality.cpp | 129 |
3 files changed, 139 insertions, 24 deletions
diff --git a/libcxxabi/src/cxa_exception.cpp b/libcxxabi/src/cxa_exception.cpp index 92901a8..73ba21c 100644 --- a/libcxxabi/src/cxa_exception.cpp +++ b/libcxxabi/src/cxa_exception.cpp @@ -192,7 +192,9 @@ void *__cxa_allocate_exception(size_t thrown_size) throw() { std::terminate(); __cxa_exception *exception_header = static_cast<__cxa_exception *>((void *)(raw_buffer + header_offset)); - ::memset(exception_header, 0, actual_size); + // We warn on memset to a non-trivially castable type. We might want to + // change that diagnostic to not fire on a trivially obvious zero fill. + ::memset(static_cast<void*>(exception_header), 0, actual_size); return thrown_object_from_cxa_exception(exception_header); } diff --git a/libcxxabi/src/cxa_exception.h b/libcxxabi/src/cxa_exception.h index aba08f2..fa4c4dc 100644 --- a/libcxxabi/src/cxa_exception.h +++ b/libcxxabi/src/cxa_exception.h @@ -47,10 +47,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { // In Wasm, a destructor returns its argument void *(_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); #else - void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); + void (_LIBCXXABI_DTOR_FUNC *__ptrauth_cxxabi_exception_destructor exceptionDestructor)(void *); #endif - std::unexpected_handler unexpectedHandler; - std::terminate_handler terminateHandler; + std::unexpected_handler __ptrauth_cxxabi_unexpected_handler unexpectedHandler; + std::terminate_handler __ptrauth_cxxabi_terminate_handler terminateHandler; __cxa_exception *nextException; @@ -61,10 +61,10 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { int propagationCount; #else int handlerSwitchValue; - const unsigned char *actionRecord; - const unsigned char *languageSpecificData; - void *catchTemp; - void *adjustedPtr; + const unsigned char *__ptrauth_cxxabi_action_record actionRecord; + const unsigned char *__ptrauth_cxxabi_lsd languageSpecificData; + void *__ptrauth_cxxabi_catch_temp catchTemp; + void *__ptrauth_cxxabi_adjusted_ptr adjustedPtr; #endif #if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI) @@ -79,6 +79,8 @@ struct _LIBCXXABI_HIDDEN __cxa_exception { // http://sourcery.mentor.com/archives/cxx-abi-dev/msg01924.html // The layout of this structure MUST match the layout of __cxa_exception, with // primaryException instead of referenceCount. +// The pointer authentication schemas specified here must also match those of +// the corresponding members in __cxa_exception. struct _LIBCXXABI_HIDDEN __cxa_dependent_exception { #if defined(__LP64__) || defined(_WIN64) || defined(_LIBCXXABI_ARM_EHABI) void* reserve; // padding. @@ -86,9 +88,9 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception { #endif std::type_info *exceptionType; - void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); - std::unexpected_handler unexpectedHandler; - std::terminate_handler terminateHandler; + void (_LIBCXXABI_DTOR_FUNC *__ptrauth_cxxabi_exception_destructor exceptionDestructor)(void *); + std::unexpected_handler __ptrauth_cxxabi_unexpected_handler unexpectedHandler; + std::terminate_handler __ptrauth_cxxabi_terminate_handler terminateHandler; __cxa_exception *nextException; @@ -99,10 +101,10 @@ struct _LIBCXXABI_HIDDEN __cxa_dependent_exception { int propagationCount; #else int handlerSwitchValue; - const unsigned char *actionRecord; - const unsigned char *languageSpecificData; - void * catchTemp; - void *adjustedPtr; + const unsigned char *__ptrauth_cxxabi_action_record actionRecord; + const unsigned char *__ptrauth_cxxabi_lsd languageSpecificData; + void *__ptrauth_cxxabi_catch_temp catchTemp; + void *__ptrauth_cxxabi_adjusted_ptr adjustedPtr; #endif #if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI) diff --git a/libcxxabi/src/cxa_personality.cpp b/libcxxabi/src/cxa_personality.cpp index 5f6e75c..b7eb0f2 100644 --- a/libcxxabi/src/cxa_personality.cpp +++ b/libcxxabi/src/cxa_personality.cpp @@ -20,7 +20,47 @@ #include "cxa_exception.h" #include "cxa_handlers.h" #include "private_typeinfo.h" -#include "unwind.h" + +#if __has_feature(ptrauth_calls) + +// CXXABI depends on defintions in libunwind as pointer auth couples the +// definitions +# include "libunwind.h" + +// The actual value of the discriminators listed below is not important. +// The derivation of the constants is only being included for the purpose +// of maintaining a record of how they were originally produced. + +// ptrauth_string_discriminator("scan_results::languageSpecificData") == 0xE50D) +# define __ptrauth_scan_results_lsd __ptrauth(ptrauth_key_process_dependent_code, 1, 0xE50D) + +// ptrauth_string_discriminator("scan_results::actionRecord") == 0x9823 +# define __ptrauth_scan_results_action_record __ptrauth(ptrauth_key_process_dependent_code, 1, 0x9823) + +// scan result is broken up as we have a manual re-sign that requires each component +# define __ptrauth_scan_results_landingpad_key ptrauth_key_process_dependent_code +// ptrauth_string_discriminator("scan_results::landingPad") == 0xD27C +# define __ptrauth_scan_results_landingpad_disc 0xD27C +# define __ptrauth_scan_results_landingpad \ + __ptrauth(__ptrauth_scan_results_landingpad_key, 1, __ptrauth_scan_results_landingpad_disc) + +// `__ptrauth_restricted_intptr` is a feature of apple clang that predates +// support for direct application of `__ptrauth` to integer types. This +// guard is necessary to support compilation with those compiler. +# if __has_extension(ptrauth_restricted_intptr_qualifier) +# define __ptrauth_scan_results_landingpad_intptr \ + __ptrauth_restricted_intptr(__ptrauth_scan_results_landingpad_key, 1, __ptrauth_scan_results_landingpad_disc) +# else +# define __ptrauth_scan_results_landingpad_intptr \ + __ptrauth(__ptrauth_scan_results_landingpad_key, 1, __ptrauth_scan_results_landingpad_disc) +# endif + +#else +# define __ptrauth_scan_results_lsd +# define __ptrauth_scan_results_action_record +# define __ptrauth_scan_results_landingpad +# define __ptrauth_scan_results_landingpad_intptr +#endif // TODO: This is a temporary workaround for libc++abi to recognize that it's being // built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION @@ -527,12 +567,17 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception) namespace { +typedef const uint8_t *__ptrauth_scan_results_lsd lsd_ptr_t; +typedef const uint8_t *__ptrauth_scan_results_action_record action_ptr_t; +typedef uintptr_t __ptrauth_scan_results_landingpad_intptr landing_pad_t; +typedef void *__ptrauth_scan_results_landingpad landing_pad_ptr_t; + struct scan_results { int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup - const uint8_t* actionRecord; // Currently unused. Retained to ease future maintenance. - const uint8_t* languageSpecificData; // Needed only for __cxa_call_unexpected - uintptr_t landingPad; // null -> nothing found, else something found + action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance. + lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected + landing_pad_t landingPad; // null -> nothing found, else something found void* adjustedPtr; // Used in cxa_exception.cpp _Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR, // _URC_FATAL_PHASE2_ERROR, @@ -557,7 +602,23 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, reinterpret_cast<uintptr_t>(unwind_exception)); _Unwind_SetGR(context, __builtin_eh_return_data_regno(1), static_cast<uintptr_t>(results.ttypeIndex)); +#if __has_feature(ptrauth_calls) + auto stackPointer = _Unwind_GetGR(context, UNW_REG_SP); + // We manually re-sign the IP as the __ptrauth qualifiers cannot + // express the required relationship with the destination address + const auto existingDiscriminator = + ptrauth_blend_discriminator(&results.landingPad, + __ptrauth_scan_results_landingpad_disc); + unw_word_t newIP /* opaque __ptrauth(ptrauth_key_return_address, stackPointer, 0) */ = + (unw_word_t)ptrauth_auth_and_resign(*(void* const*)&results.landingPad, + __ptrauth_scan_results_landingpad_key, + existingDiscriminator, + ptrauth_key_return_address, + stackPointer); + _Unwind_SetIP(context, newIP); +#else _Unwind_SetIP(context, results.landingPad); +#endif } /* @@ -691,12 +752,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions, // The call sites are ordered in increasing value of start uintptr_t start = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t length = readEncodedPointer(&callSitePtr, callSiteEncoding); - uintptr_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); + landing_pad_t landingPad = readEncodedPointer(&callSitePtr, callSiteEncoding); uintptr_t actionEntry = readULEB128(&callSitePtr); if ((start <= ipOffset) && (ipOffset < (start + length))) #else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ // ip is 1-based index into this table - uintptr_t landingPad = readULEB128(&callSitePtr); + landing_pad_t landingPad = readULEB128(&callSitePtr); uintptr_t actionEntry = readULEB128(&callSitePtr); if (--ip == 0) #endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__ @@ -903,6 +964,57 @@ _UA_CLEANUP_PHASE */ #if !defined(_LIBCXXABI_ARM_EHABI) + +// We use these helper functions to work around the behavior of casting between +// integers (even those that are authenticated) and authenticated pointers. +// Because the schemas being used are address discriminated we cannot use a +// trivial value union to coerce the types so instead we perform the re-signing +// manually. +using __cxa_catch_temp_type = decltype(__cxa_exception::catchTemp); +static inline void set_landing_pad(scan_results& results, + const __cxa_catch_temp_type& source) { +#if __has_feature(ptrauth_calls) + const uintptr_t sourceDiscriminator = + ptrauth_blend_discriminator(&source, __ptrauth_cxxabi_catch_temp_disc); + const uintptr_t targetDiscriminator = + ptrauth_blend_discriminator(&results.landingPad, + __ptrauth_scan_results_landingpad_disc); + uintptr_t reauthenticatedLandingPad = + (uintptr_t)ptrauth_auth_and_resign(*reinterpret_cast<void* const*>(&source), + __ptrauth_cxxabi_catch_temp_key, + sourceDiscriminator, + __ptrauth_scan_results_landingpad_key, + targetDiscriminator); + memmove(reinterpret_cast<void *>(&results.landingPad), + reinterpret_cast<void *>(&reauthenticatedLandingPad), + sizeof(reauthenticatedLandingPad)); +#else + results.landingPad = reinterpret_cast<landing_pad_t>(source); +#endif +} + +static inline void get_landing_pad(__cxa_catch_temp_type &dest, + const scan_results &results) { +#if __has_feature(ptrauth_calls) + const uintptr_t sourceDiscriminator = + ptrauth_blend_discriminator(&results.landingPad, + __ptrauth_scan_results_landingpad_disc); + const uintptr_t targetDiscriminator = + ptrauth_blend_discriminator(&dest, __ptrauth_cxxabi_catch_temp_disc); + uintptr_t reauthenticatedPointer = + (uintptr_t)ptrauth_auth_and_resign(*reinterpret_cast<void* const*>(&results.landingPad), + __ptrauth_scan_results_landingpad_key, + sourceDiscriminator, + __ptrauth_cxxabi_catch_temp_key, + targetDiscriminator); + memmove(reinterpret_cast<void *>(&dest), + reinterpret_cast<void *>(&reauthenticatedPointer), + sizeof(reauthenticatedPointer)); +#else + dest = reinterpret_cast<__cxa_catch_temp_type>(results.landingPad); +#endif +} + #ifdef __WASM_EXCEPTIONS__ _Unwind_Reason_Code __gxx_personality_wasm0 #elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__) @@ -935,8 +1047,7 @@ __gxx_personality_v0 results.ttypeIndex = exception_header->handlerSwitchValue; results.actionRecord = exception_header->actionRecord; results.languageSpecificData = exception_header->languageSpecificData; - results.landingPad = - reinterpret_cast<uintptr_t>(exception_header->catchTemp); + set_landing_pad(results, exception_header->catchTemp); results.adjustedPtr = exception_header->adjustedPtr; // Jump to the handler. @@ -970,7 +1081,7 @@ __gxx_personality_v0 exc->handlerSwitchValue = static_cast<int>(results.ttypeIndex); exc->actionRecord = results.actionRecord; exc->languageSpecificData = results.languageSpecificData; - exc->catchTemp = reinterpret_cast<void*>(results.landingPad); + get_landing_pad(exc->catchTemp, results); exc->adjustedPtr = results.adjustedPtr; #ifdef __WASM_EXCEPTIONS__ // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the |