@@ -575,9 +575,9 @@ typedef void *__ptrauth_scan_results_landingpad landing_pad_ptr_t;
575575struct scan_results
576576{
577577 int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
578- action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
579- lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
580- landing_pad_t landingPad; // null -> nothing found, else something found
578+ action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
579+ lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
580+ landing_pad_t landingPad; // null -> nothing found, else something found
581581 void * adjustedPtr; // Used in cxa_exception.cpp
582582 _Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
583583 // _URC_FATAL_PHASE2_ERROR,
@@ -586,38 +586,7 @@ struct scan_results
586586};
587587
588588} // unnamed namespace
589- } // extern "C"
590-
591- #if !defined(_LIBCXXABI_ARM_EHABI)
592- namespace {
593- // The logical model for casting authenticated function pointers makes
594- // it impossible to directly cast them without breaking the authentication,
595- // as a result we need this pair of helpers.
596- //
597- // __ptrauth_nop_cast cannot be used here as the authentication schemas include
598- // address diversification.
599- template <typename PtrType>
600- void set_landing_pad_as_ptr (scan_results& results, const PtrType& landingPad) {
601- union {
602- landing_pad_t * as_landing_pad;
603- landing_pad_ptr_t * as_pointer;
604- } u;
605- u.as_landing_pad = &results.landingPad ;
606- *u.as_pointer = landingPad;
607- }
608589
609- static const landing_pad_ptr_t & get_landing_pad_as_ptr (const scan_results& results) {
610- union {
611- const landing_pad_t * as_landing_pad;
612- const landing_pad_ptr_t * as_pointer;
613- } u;
614- u.as_landing_pad = &results.landingPad ;
615- return *u.as_pointer ;
616- }
617- } // unnamed namespace
618- #endif
619-
620- extern " C" {
621590static
622591void
623592set_registers (_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -638,10 +607,14 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
638607 // We manually re-sign the IP as the __ptrauth qualifiers cannot
639608 // express the required relationship with the destination address
640609 const auto existingDiscriminator =
641- ptrauth_blend_discriminator (&results.landingPad , __ptrauth_scan_results_landingpad_disc);
610+ ptrauth_blend_discriminator (&results.landingPad ,
611+ __ptrauth_scan_results_landingpad_disc);
642612 unw_word_t newIP /* opaque __ptrauth(ptrauth_key_return_address, stackPointer, 0) */ =
643- (unw_word_t )ptrauth_auth_and_resign (*(void * const *)&results.landingPad , __ptrauth_scan_results_landingpad_key,
644- existingDiscriminator, ptrauth_key_return_address, stackPointer);
613+ (unw_word_t )ptrauth_auth_and_resign (*(void * const *)&results.landingPad ,
614+ __ptrauth_scan_results_landingpad_key,
615+ existingDiscriminator,
616+ ptrauth_key_return_address,
617+ stackPointer);
645618 _Unwind_SetIP (context, newIP);
646619#else
647620 _Unwind_SetIP (context, results.landingPad );
@@ -991,6 +964,57 @@ _UA_CLEANUP_PHASE
991964*/
992965
993966#if !defined(_LIBCXXABI_ARM_EHABI)
967+
968+ // We use these helper functions to work around the behavior of casting between
969+ // integers (even those that are authenticated) and authenticated pointers.
970+ // Because the schemas being used are address discriminated we cannot use a
971+ // trivial value union to coerce the types so instead we perform the re-signing
972+ // manually.
973+ using __cxa_catch_temp_type = decltype (__cxa_exception::catchTemp);
974+ static inline void set_landing_pad (scan_results& results,
975+ const __cxa_catch_temp_type& source) {
976+ #if __has_feature(ptrauth_calls)
977+ const uintptr_t sourceDiscriminator =
978+ ptrauth_blend_discriminator (&source, __ptrauth_cxxabi_catch_temp_disc);
979+ const uintptr_t targetDiscriminator =
980+ ptrauth_blend_discriminator (&results.landingPad ,
981+ __ptrauth_scan_results_landingpad_disc);
982+ uintptr_t reauthenticatedLandingPad =
983+ (uintptr_t )ptrauth_auth_and_resign (*reinterpret_cast <void * const *>(&source),
984+ __ptrauth_cxxabi_catch_temp_key,
985+ sourceDiscriminator,
986+ __ptrauth_scan_results_landingpad_key,
987+ targetDiscriminator);
988+ memmove (reinterpret_cast <void *>(&results.landingPad ),
989+ reinterpret_cast <void *>(&reauthenticatedLandingPad),
990+ sizeof (reauthenticatedLandingPad));
991+ #else
992+ results.landingPad = reinterpret_cast <landing_pad_t >(source);
993+ #endif
994+ }
995+
996+ static inline void get_landing_pad (__cxa_catch_temp_type &dest,
997+ const scan_results &results) {
998+ #if __has_feature(ptrauth_calls)
999+ const uintptr_t sourceDiscriminator =
1000+ ptrauth_blend_discriminator (&results.landingPad ,
1001+ __ptrauth_scan_results_landingpad_disc);
1002+ const uintptr_t targetDiscriminator =
1003+ ptrauth_blend_discriminator (&dest, __ptrauth_cxxabi_catch_temp_disc);
1004+ uintptr_t reauthenticatedPointer =
1005+ (uintptr_t )ptrauth_auth_and_resign (*reinterpret_cast <void * const *>(&results.landingPad ),
1006+ __ptrauth_scan_results_landingpad_key,
1007+ sourceDiscriminator,
1008+ __ptrauth_cxxabi_catch_temp_key,
1009+ targetDiscriminator);
1010+ memmove (reinterpret_cast <void *>(&dest),
1011+ reinterpret_cast <void *>(&reauthenticatedPointer),
1012+ sizeof (reauthenticatedPointer));
1013+ #else
1014+ dest = reinterpret_cast <__cxa_catch_temp_type>(results.landingPad );
1015+ #endif
1016+ }
1017+
9941018#ifdef __WASM_EXCEPTIONS__
9951019_Unwind_Reason_Code __gxx_personality_wasm0
9961020#elif defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)
@@ -1023,7 +1047,7 @@ __gxx_personality_v0
10231047 results.ttypeIndex = exception_header->handlerSwitchValue ;
10241048 results.actionRecord = exception_header->actionRecord ;
10251049 results.languageSpecificData = exception_header->languageSpecificData ;
1026- set_landing_pad_as_ptr (results, exception_header->catchTemp );
1050+ set_landing_pad (results, exception_header->catchTemp );
10271051 results.adjustedPtr = exception_header->adjustedPtr ;
10281052
10291053 // Jump to the handler.
@@ -1057,7 +1081,7 @@ __gxx_personality_v0
10571081 exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
10581082 exc->actionRecord = results.actionRecord ;
10591083 exc->languageSpecificData = results.languageSpecificData ;
1060- exc->catchTemp = get_landing_pad_as_ptr ( results);
1084+ get_landing_pad ( exc->catchTemp , results);
10611085 exc->adjustedPtr = results.adjustedPtr ;
10621086#ifdef __WASM_EXCEPTIONS__
10631087 // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments