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
+
24
67
25
68
// TODO: This is a temporary workaround for libc++abi to recognize that it's being
26
69
// built against LLVM's libunwind. LLVM's libunwind started reporting _LIBUNWIND_VERSION
@@ -527,12 +570,17 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception)
527
570
namespace
528
571
{
529
572
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
+
530
578
struct scan_results
531
579
{
532
580
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
536
584
void * adjustedPtr; // Used in cxa_exception.cpp
537
585
_Unwind_Reason_Code reason; // One of _URC_FATAL_PHASE1_ERROR,
538
586
// _URC_FATAL_PHASE2_ERROR,
@@ -541,7 +589,33 @@ struct scan_results
541
589
};
542
590
543
591
} // 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
+ }
544
607
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" {
545
619
static
546
620
void
547
621
set_registers (_Unwind_Exception* unwind_exception, _Unwind_Context* context,
@@ -557,7 +631,21 @@ set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context,
557
631
reinterpret_cast <uintptr_t >(unwind_exception));
558
632
_Unwind_SetGR (context, __builtin_eh_return_data_regno (1 ),
559
633
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
560
647
_Unwind_SetIP (context, results.landingPad );
648
+ #endif
561
649
}
562
650
563
651
/*
@@ -691,12 +779,12 @@ static void scan_eh_tab(scan_results &results, _Unwind_Action actions,
691
779
// The call sites are ordered in increasing value of start
692
780
uintptr_t start = readEncodedPointer (&callSitePtr, callSiteEncoding);
693
781
uintptr_t length = readEncodedPointer (&callSitePtr, callSiteEncoding);
694
- uintptr_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
782
+ landing_pad_t landingPad = readEncodedPointer (&callSitePtr, callSiteEncoding);
695
783
uintptr_t actionEntry = readULEB128 (&callSitePtr);
696
784
if ((start <= ipOffset) && (ipOffset < (start + length)))
697
785
#else // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
698
786
// ip is 1-based index into this table
699
- uintptr_t landingPad = readULEB128 (&callSitePtr);
787
+ landing_pad_t landingPad = readULEB128 (&callSitePtr);
700
788
uintptr_t actionEntry = readULEB128 (&callSitePtr);
701
789
if (--ip == 0 )
702
790
#endif // __USING_SJLJ_EXCEPTIONS__ || __WASM_EXCEPTIONS__
@@ -935,8 +1023,7 @@ __gxx_personality_v0
935
1023
results.ttypeIndex = exception_header->handlerSwitchValue ;
936
1024
results.actionRecord = exception_header->actionRecord ;
937
1025
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 );
940
1027
results.adjustedPtr = exception_header->adjustedPtr ;
941
1028
942
1029
// Jump to the handler.
@@ -970,7 +1057,7 @@ __gxx_personality_v0
970
1057
exc->handlerSwitchValue = static_cast <int >(results.ttypeIndex );
971
1058
exc->actionRecord = results.actionRecord ;
972
1059
exc->languageSpecificData = results.languageSpecificData ;
973
- exc->catchTemp = reinterpret_cast < void *> (results. landingPad );
1060
+ exc->catchTemp = get_landing_pad_as_ptr (results);
974
1061
exc->adjustedPtr = results.adjustedPtr ;
975
1062
#ifdef __WASM_EXCEPTIONS__
976
1063
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the
0 commit comments