21
21
#include " cxa_handlers.h"
22
22
#include " private_typeinfo.h"
23
23
#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
+
67
+
68
+ #include " libunwind.h"
24
69
25
70
// TODO: This is a temporary workaround for libc++abi to recognize that it's being
26
71
// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
@@ -527,12 +572,17 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
527
572
namespace
528
573
{
529
574
575
+ typedef const uint8_t * __ptrauth_scan_results_lsd lsd_ptr_t ;
576
+ typedef const uint8_t * __ptrauth_scan_results_action_record action_ptr_t ;
577
+ typedef uintptr_t __ptrauth_scan_results_landingpad_intptr landing_pad_t ;
578
+ typedef void * __ptrauth_scan_results_landingpad landing_pad_ptr_t ;
579
+
530
580
struct scan_results
531
581
{
532
582
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
583
+ action_ptr_t actionRecord; // Currently unused. Retained to ease future maintenance.
584
+ lsd_ptr_t languageSpecificData; // Needed only for __cxa_call_unexpected
585
+ landing_pad_t landingPad; // null -> nothing found, else something found
536
586
void * adjustedPtr; // Used in cxa_exception.cpp
537
587
_Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
538
588
// _URC_FATAL_PHASE2_ERROR,
@@ -541,7 +591,33 @@ struct scan_results
541
591
};
542
592
543
593
} // unnamed namespace
594
+ }
595
+
596
+ namespace {
597
+ // The logical model for casting authenticated function pointers makes
598
+ // it impossible to directly cast them without breaking the authentication,
599
+ // as a result we need this pair of helpers.
600
+ template <typename PtrType>
601
+ void set_landing_pad_as_ptr (scan_results& results, const PtrType& out) {
602
+ union {
603
+ landing_pad_t * as_landing_pad;
604
+ landing_pad_ptr_t * as_pointer;
605
+ } u;
606
+ u.as_landing_pad = &results.landingPad ;
607
+ *u.as_pointer = out;
608
+ }
544
609
610
+ static const landing_pad_ptr_t & get_landing_pad_as_ptr (const scan_results& results) {
611
+ union {
612
+ const landing_pad_t * as_landing_pad;
613
+ const landing_pad_ptr_t * as_pointer;
614
+ } u;
615
+ u.as_landing_pad = &results.landingPad ;
616
+ return *u.as_pointer ;
617
+ }
618
+ } // unnamed namespace
619
+
620
+ extern " C" {
545
621
static
546
622
void
547
623
set_registers (_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -557,7 +633,21 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
557
633
reinterpret_cast <uintptr_t >(unwind_exception));
558
634
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1 ),
559
635
static_cast <uintptr_t >(results.ttypeIndex ));
636
+ #if __has_feature(ptrauth_qualifier)
637
+ auto stack_pointer = _Unwind_GetGR (context, UNW_REG_SP);
638
+ // We manually re-sign the IP as the __ptrauth qualifiers cannot
639
+ // express the required relationship with the destination address
640
+ const auto existingDiscriminator = ptrauth_blend_discriminator (
641
+ &results.landingPad , __ptrauth_scan_results_landingpad_disc);
642
+ unw_word_t newIP /* opaque __ptrauth(ptrauth_key_return_address, stack_pointer, 0) */ =
643
+ (unw_word_t )ptrauth_auth_and_resign (*(void **)&results.landingPad ,
644
+ __ptrauth_scan_results_landingpad_key,
645
+ existingDiscriminator,
646
+ ptrauth_key_return_address, stack_pointer);
647
+ _Unwind_SetIP (context, newIP);
648
+ #else
560
649
_Unwind_SetIP (context, results.landingPad );
650
+ #endif
561
651
}
562
652
563
653
/*
@@ -691,12 +781,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
691
781
// The call sites are ordered in increasing value of start
692
782
uintptr_t start = readEncodedPointer (&callSitePtr, callSiteEncoding);
693
783
uintptr_t length = readEncodedPointer (&callSitePtr, callSiteEncoding);
694
- uintptr_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
784
+ landing_pad_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
695
785
uintptr_t actionEntry = readULEB128 (&callSitePtr);
696
786
if ((start <= ipOffset) && (ipOffset < (start + length)))
697
787
#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
698
788
// ip is 1-based index into this table
699
- uintptr_t landingPad = readULEB128 (&callSitePtr);
789
+ landing_pad_t landingPad = readULEB128 (&callSitePtr);
700
790
uintptr_t actionEntry = readULEB128 (&callSitePtr);
701
791
if (--ip == 0 )
702
792
#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +1025,7 @@ __gxx_personality_v0
935
1025
results.ttypeIndex = exception_header->handlerSwitchValue ;
936
1026
results.actionRecord = exception_header->actionRecord ;
937
1027
results.languageSpecificData = exception_header->languageSpecificData ;
938
- results.landingPad =
939
- reinterpret_cast <uintptr_t >(exception_header->catchTemp );
1028
+ set_landing_pad_as_ptr (results, exception_header->catchTemp );
940
1029
results.adjustedPtr = exception_header->adjustedPtr ;
941
1030
942
1031
// Jump to the handler.
@@ -970,7 +1059,7 @@ __gxx_personality_v0
970
1059
exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
971
1060
exc->actionRecord = results.actionRecord ;
972
1061
exc->languageSpecificData = results.languageSpecificData ;
973
- exc->catchTemp = reinterpret_cast < void *> (results. landingPad );
1062
+ exc->catchTemp = get_landing_pad_as_ptr (results);
974
1063
exc->adjustedPtr = results.adjustedPtr ;
975
1064
#ifdef __WASM_EXCEPTIONS__
976
1065
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments