2121#include " cxa_handlers.h"
2222#include " private_typeinfo.h"
2323#include " unwind.h"
24+ #include " libunwind.h"
25+
26+ #if __has_include(<ptrauth.h>)
27+ # include < ptrauth.h>
28+ #endif
29+
30+ #if __has_extension(ptrauth_qualifier)
31+ // The actual value of the discriminators listed below is not important.
32+ // The derivation of the constants is only being included for the purpose
33+ // of maintaining a record of how they were originally produced.
34+
35+ // ptrauth_string_discriminator("scan_results::languageSpecificData") == 0xE50D)
36+ #define __ptrauth_scan_results_lsd \
37+ __ptrauth (ptrauth_key_process_dependent_code, 1 , 0xE50D )
38+
39+ // ptrauth_string_discriminator("scan_results::actionRecord") == 0x9823
40+ #define __ptrauth_scan_results_action_record \
41+ __ptrauth (ptrauth_key_process_dependent_code, 1 , 0x9823 )
42+
43+ // scan result is broken up as we have a manual re-sign that requires each component
44+ #define __ptrauth_scan_results_landingpad_key ptrauth_key_process_dependent_code
45+ // ptrauth_string_discriminator("scan_results::landingPad") == 0xD27C
46+ #define __ptrauth_scan_results_landingpad_disc 0xD27C
47+ #define __ptrauth_scan_results_landingpad \
48+ __ptrauth (__ptrauth_scan_results_landingpad_key, 1 , __ptrauth_scan_results_landingpad_disc)
49+
50+ #if __has_extension(__ptrauth_restricted_intptr)
51+ #define __ptrauth_scan_results_landingpad_intptr \
52+ __ptrauth_restricted_intptr (__ptrauth_scan_results_landingpad_key, 1 , \
53+ __ptrauth_scan_results_landingpad_disc)
54+ #else
55+ #define __ptrauth_scan_results_landingpad_intptr \
56+ __ptrauth (__ptrauth_scan_results_landingpad_key, 1 , \
57+ __ptrauth_scan_results_landingpad_disc)
58+ #endif
59+
60+ #else
61+ #define __ptrauth_scan_results_lsd
62+ #define __ptrauth_scan_results_action_record
63+ #define __ptrauth_scan_results_landingpad
64+ #define __ptrauth_scan_results_landingpad_intptr
65+ #endif
66+
2467
2568// TODO: This is a temporary workaround for libc++abi to recognize that it's being
2669// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
@@ -527,12 +570,17 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
527570namespace
528571{
529572
573+ typedef const uint8_t * __ptrauth_scan_results_lsd lsd_ptr_t ;
574+ typedef const uint8_t * __ptrauth_scan_results_action_record action_ptr_t ;
575+ typedef uintptr_t __ptrauth_scan_results_landingpad_intptr landing_pad_t ;
576+ typedef void * __ptrauth_scan_results_landingpad landing_pad_ptr_t ;
577+
530578struct scan_results
531579{
532580 int64_t ttypeIndex; // > 0 catch handler, < 0 exception spec handler, == 0 a cleanup
533- const uint8_t * actionRecord; // Currently unused. Retained to ease future maintenance.
534- const uint8_t * languageSpecificData; // Needed only for __cxa_call_unexpected
535- uintptr_t landingPad; // null -> nothing found, else something found
581+ action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
582+ lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
583+ landing_pad_t landingPad; // null -> nothing found, else something found
536584 void * adjustedPtr; // Used in cxa_exception.cpp
537585 _Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
538586 // _URC_FATAL_PHASE2_ERROR,
@@ -541,7 +589,33 @@ struct scan_results
541589};
542590
543591} // unnamed namespace
592+ }
593+
594+ namespace {
595+ // The logical model for casting authenticated function pointers makes
596+ // it impossible to directly cast them without breaking the authentication,
597+ // as a result we need this pair of helpers.
598+ template <typename PtrType>
599+ void set_landing_pad_as_ptr (scan_results& results, const PtrType& out) {
600+ union {
601+ landing_pad_t * as_landing_pad;
602+ landing_pad_ptr_t * as_pointer;
603+ } u;
604+ u.as_landing_pad = &results.landingPad ;
605+ *u.as_pointer = out;
606+ }
544607
608+ static const landing_pad_ptr_t & get_landing_pad_as_ptr (const scan_results& results) {
609+ union {
610+ const landing_pad_t * as_landing_pad;
611+ const landing_pad_ptr_t * as_pointer;
612+ } u;
613+ u.as_landing_pad = &results.landingPad ;
614+ return *u.as_pointer ;
615+ }
616+ } // unnamed namespace
617+
618+ extern " C" {
545619static
546620void
547621set_registers (_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -557,7 +631,21 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
557631 reinterpret_cast <uintptr_t >(unwind_exception));
558632 _Unwind_SetGR (context, __builtin_eh_return_data_regno (1 ),
559633 static_cast <uintptr_t >(results.ttypeIndex ));
634+ #if __has_feature(ptrauth_qualifier)
635+ auto stack_pointer = _Unwind_GetGR (context, UNW_REG_SP);
636+ // We manually re-sign the IP as the __ptrauth qualifiers cannot
637+ // express the required relationship with the destination address
638+ const auto existingDiscriminator = ptrauth_blend_discriminator (
639+ &results.landingPad , __ptrauth_scan_results_landingpad_disc);
640+ unw_word_t newIP /* opaque __ptrauth(ptrauth_key_return_address, stack_pointer, 0) */ =
641+ (unw_word_t )ptrauth_auth_and_resign (*(void **)&results.landingPad ,
642+ __ptrauth_scan_results_landingpad_key,
643+ existingDiscriminator,
644+ ptrauth_key_return_address, stack_pointer);
645+ _Unwind_SetIP (context, newIP);
646+ #else
560647 _Unwind_SetIP (context, results.landingPad );
648+ #endif
561649}
562650
563651/*
@@ -691,12 +779,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
691779 // The call sites are ordered in increasing value of start
692780 uintptr_t start = readEncodedPointer (&callSitePtr, callSiteEncoding);
693781 uintptr_t length = readEncodedPointer (&callSitePtr, callSiteEncoding);
694- uintptr_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
782+ landing_pad_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
695783 uintptr_t actionEntry = readULEB128 (&callSitePtr);
696784 if ((start <= ipOffset) && (ipOffset < (start + length)))
697785#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
698786 // ip is 1-based index into this table
699- uintptr_t landingPad = readULEB128 (&callSitePtr);
787+ landing_pad_t landingPad = readULEB128 (&callSitePtr);
700788 uintptr_t actionEntry = readULEB128 (&callSitePtr);
701789 if (--ip == 0 )
702790#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +1023,7 @@ __gxx_personality_v0
9351023 results.ttypeIndex = exception_header->handlerSwitchValue ;
9361024 results.actionRecord = exception_header->actionRecord ;
9371025 results.languageSpecificData = exception_header->languageSpecificData ;
938- results.landingPad =
939- reinterpret_cast <uintptr_t >(exception_header->catchTemp );
1026+ set_landing_pad_as_ptr (results, exception_header->catchTemp );
9401027 results.adjustedPtr = exception_header->adjustedPtr ;
9411028
9421029 // Jump to the handler.
@@ -970,7 +1057,7 @@ __gxx_personality_v0
9701057 exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
9711058 exc->actionRecord = results.actionRecord ;
9721059 exc->languageSpecificData = results.languageSpecificData ;
973- exc->catchTemp = reinterpret_cast < void *> (results. landingPad );
1060+ exc->catchTemp = get_landing_pad_as_ptr (results);
9741061 exc->adjustedPtr = results.adjustedPtr ;
9751062#ifdef __WASM_EXCEPTIONS__
9761063 // Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments