-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[runtimes][PAC] Harden unwinding when possible (#138571) #143230
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -30,6 +30,46 @@ EXCEPTION_DISPOSITION _GCC_specific_handler(PEXCEPTION_RECORD, void *, PCONTEXT, | |
_Unwind_Personality_Fn); | ||
#endif | ||
|
||
#if __has_include(<ptrauth.h>) | ||
#include <ptrauth.h> | ||
#endif | ||
|
||
#if defined(__APPLE__) && __has_feature(ptrauth_qualifier) | ||
#if __has_feature(ptrauth_restricted_intptr_qualifier) | ||
#define PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(key, addressDiscriminated, \ | ||
discriminatorString) \ | ||
__ptrauth_restricted_intptr( \ | ||
key, addressDiscriminated, \ | ||
ptrauth_string_discriminator(discriminatorString)) | ||
#else | ||
#define PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(key, addressDiscriminated, \ | ||
discriminatorString) \ | ||
__ptrauth(key, addressDiscriminated, \ | ||
ptrauth_string_discriminator(discriminatorString)) | ||
#endif | ||
#else | ||
#define PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(key, addressDiscriminated, \ | ||
discriminatorString) | ||
#endif | ||
|
||
// Helper wrappers for pointer auth qualifiers because we use a lot of variants | ||
// Suffixes: | ||
// * PDC : ptrauth_key_process_dependent_code | ||
// * RA : ptrauth_key_return_address | ||
// * FN : ptrauth_key_function_pointer | ||
#define PERSONALITY_PTRAUTH_RI_FN(__discriminator) \ | ||
PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_function_pointer, \ | ||
/*__address_discriminated=*/1, \ | ||
__discriminator) | ||
#define PERSONALITY_PTRAUTH_RI_PDC(__discriminator) \ | ||
PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_process_dependent_code, \ | ||
/*__address_discriminated=*/1, \ | ||
__discriminator) | ||
#define PERSONALITY_PTRAUTH_RI_RA(__discriminator) \ | ||
PERSONALITY_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_return_address, \ | ||
/*__address_discriminated=*/1, \ | ||
__discriminator) | ||
|
||
// Pointer encodings documented at: | ||
// http://refspecs.freestandards.org/LSB_1.3.0/gLSB/gLSB/ehframehdr.html | ||
|
||
|
@@ -205,7 +245,8 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( | |
return continueUnwind(exceptionObject, context); | ||
|
||
uintptr_t pc = (uintptr_t)_Unwind_GetIP(context) - 1; | ||
uintptr_t funcStart = (uintptr_t)_Unwind_GetRegionStart(context); | ||
uintptr_t PERSONALITY_PTRAUTH_RI_FN("__gcc_personality_v0'funcStart") | ||
funcStart = (uintptr_t)_Unwind_GetRegionStart(context); | ||
uintptr_t pcOffset = pc - funcStart; | ||
|
||
// Parse LSDA header. | ||
|
@@ -224,11 +265,14 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( | |
const uint8_t *callSiteTableEnd = callSiteTableStart + callSiteTableLength; | ||
const uint8_t *p = callSiteTableStart; | ||
while (p < callSiteTableEnd) { | ||
uintptr_t start = readEncodedPointer(&p, callSiteEncoding); | ||
size_t length = readEncodedPointer(&p, callSiteEncoding); | ||
size_t landingPad = readEncodedPointer(&p, callSiteEncoding); | ||
uintptr_t PERSONALITY_PTRAUTH_RI_PDC("__gcc_personality_v0'start") start = | ||
readEncodedPointer(&p, callSiteEncoding); | ||
size_t PERSONALITY_PTRAUTH_RI_PDC("__gcc_personality_v0'length") length = | ||
readEncodedPointer(&p, callSiteEncoding); | ||
size_t PERSONALITY_PTRAUTH_RI_PDC("__gcc_personality_v0'landingPadOffset") | ||
landingPadOffset = readEncodedPointer(&p, callSiteEncoding); | ||
readULEB128(&p); // action value not used for C code | ||
if (landingPad == 0) | ||
if (landingPadOffset == 0) | ||
continue; // no landing pad for this entry | ||
if ((start <= pcOffset) && (pcOffset < (start + length))) { | ||
// Found landing pad for the PC. | ||
|
@@ -238,7 +282,20 @@ COMPILER_RT_ABI _Unwind_Reason_Code __gcc_personality_v0( | |
_Unwind_SetGR(context, __builtin_eh_return_data_regno(0), | ||
(uintptr_t)exceptionObject); | ||
_Unwind_SetGR(context, __builtin_eh_return_data_regno(1), 0); | ||
_Unwind_SetIP(context, (funcStart + landingPad)); | ||
#define LANDING_PAD_DISCRIMINATOR "__gcc_personality_v0'landingPad" | ||
size_t PERSONALITY_PTRAUTH_RI_RA(LANDING_PAD_DISCRIMINATOR) landingPad = | ||
funcStart + landingPadOffset; | ||
#if defined(__APPLE__) && __has_feature(ptrauth_qualifier) | ||
uintptr_t stack_pointer = _Unwind_GetGR(context, -2); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] It seems like |
||
const uintptr_t existingDiscriminator = ptrauth_blend_discriminator( | ||
&landingPad, ptrauth_string_discriminator(LANDING_PAD_DISCRIMINATOR)); | ||
uintptr_t newIP = (uintptr_t)ptrauth_auth_and_resign( | ||
*(void **)&landingPad, ptrauth_key_function_pointer, | ||
existingDiscriminator, ptrauth_key_return_address, stack_pointer); | ||
_Unwind_SetIP(context, newIP); | ||
#else | ||
_Unwind_SetIP(context, landingPad); | ||
#endif | ||
Comment on lines
+292
to
+298
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to assume #if !__has_feature(ptrauth_returns)
#error Hardened libunwing expects pac-ret
#endif should be perfectly enough for the sake of documentating this dependecy and just to be sure :) But what if we build libunwind on AArch64 with pac-ret, but without extra libunwind hardening ( _Unwind_SetIP(context, newIP);
#elif __has_feature(ptrauth_returns)
// Just sign unprotected newIP with stack pointer and pass it to _Unwind_SetIP
#else
_Unwind_SetIP(context, landingPad);
#endif |
||
return _URC_INSTALL_CONTEXT; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -83,7 +83,13 @@ __llvm_profile_iterate_data(const __llvm_profile_data *Data) { | |
/* This method is only used in value profiler mock testing. */ | ||
COMPILER_RT_VISIBILITY void * | ||
__llvm_get_function_addr(const __llvm_profile_data *Data) { | ||
return Data->FunctionPointer; | ||
void *FP = Data->FunctionPointer; | ||
#if __has_feature(ptrauth_calls) | ||
// This is only used for tests where we compare against what happens to be | ||
// signed pointers. | ||
FP = ptrauth_sign_unauthenticated(FP, VALID_CODE_KEY, 0); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's possible this is a mis-merge/copy - I'll try to work out where VALID_CODE_KEY is expected to come from and ensure that I pull that def in. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Looks like this entire change to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In order to use
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmmm, I'll see if this actually caused any of the bot failures, and if it's not responsible for any I'll try to work out why @kovdan01 @asl do you folk have a vm setup you can test on? I realize I'm currently limited to building for darwin so it's easy for me to luck out on implicit/transitive includes from other places. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@ojhunt Yeah, we have that and we can run llvm-test-suite and some other private pauth-specific tests. And, of course, we have a build of pauth-enabled linux toolchain configured. Basically, having these is the reason why I'm able to add such comments in this PR :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kovdan01 I mean "do you have step by step instructions for a muppet like me that would make it possible for me to build/test locally" :D There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
@ojhunt Ah, thanks for clarifying your question :) Unfortunately, right now our build scripts, instructions, tests, ... are not available publicly. We'll definitely publish them, but right now I guess that we would be happy to test your changes on our side manually. This would, of course, slow down the work on the PR, but at this point it looks like that many of the comments we left actually are relevant for all targets, not only for linux. So, at least for such comments you'll be able to test things using your system w/o our linux-specific stuff. |
||
#endif | ||
return FP; | ||
} | ||
|
||
/* Allocate an array that holds the pointers to the linked lists of | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -32,22 +32,23 @@ | |
#endif | ||
|
||
#if defined(_WIN32) | ||
#if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) || (defined(__MINGW32__) && !defined(_LIBCXXABI_BUILDING_LIBRARY)) | ||
#define _LIBCXXABI_HIDDEN | ||
#define _LIBCXXABI_DATA_VIS | ||
#define _LIBCXXABI_FUNC_VIS | ||
#define _LIBCXXABI_TYPE_VIS | ||
#elif defined(_LIBCXXABI_BUILDING_LIBRARY) | ||
#define _LIBCXXABI_HIDDEN | ||
#define _LIBCXXABI_DATA_VIS __declspec(dllexport) | ||
#define _LIBCXXABI_FUNC_VIS __declspec(dllexport) | ||
#define _LIBCXXABI_TYPE_VIS __declspec(dllexport) | ||
#else | ||
#define _LIBCXXABI_HIDDEN | ||
#define _LIBCXXABI_DATA_VIS __declspec(dllimport) | ||
#define _LIBCXXABI_FUNC_VIS __declspec(dllimport) | ||
#define _LIBCXXABI_TYPE_VIS __declspec(dllimport) | ||
#endif | ||
# if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) || \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's avoid changing the formatting of unrelated pieces of code. It's fine if the clang-format job is not happy -- we haven't run There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not sure how/why/when I changed this formatting because I'd swear I went through trying to remove them all There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I bet I auto-ran clang-format after the bots complained or reflexively pre-push to avoid the bots complain. Sighhhhh |
||
(defined(__MINGW32__) && !defined(_LIBCXXABI_BUILDING_LIBRARY)) | ||
# define _LIBCXXABI_HIDDEN | ||
# define _LIBCXXABI_DATA_VIS | ||
# define _LIBCXXABI_FUNC_VIS | ||
# define _LIBCXXABI_TYPE_VIS | ||
# elif defined(_LIBCXXABI_BUILDING_LIBRARY) | ||
# define _LIBCXXABI_HIDDEN | ||
# define _LIBCXXABI_DATA_VIS __declspec(dllexport) | ||
# define _LIBCXXABI_FUNC_VIS __declspec(dllexport) | ||
# define _LIBCXXABI_TYPE_VIS __declspec(dllexport) | ||
# else | ||
# define _LIBCXXABI_HIDDEN | ||
# define _LIBCXXABI_DATA_VIS __declspec(dllimport) | ||
# define _LIBCXXABI_FUNC_VIS __declspec(dllimport) | ||
# define _LIBCXXABI_TYPE_VIS __declspec(dllimport) | ||
# endif | ||
#else | ||
#if !defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) | ||
#define _LIBCXXABI_HIDDEN __attribute__((__visibility__("hidden"))) | ||
|
@@ -109,4 +110,38 @@ | |
# define _LIBCXXABI_NOEXCEPT noexcept | ||
#endif | ||
|
||
#if __has_include(<ptrauth.h>) | ||
# include <ptrauth.h> | ||
#endif | ||
|
||
#if defined(__APPLE__) && __has_feature(ptrauth_qualifier) | ||
# define _LIBCXXABI_PTRAUTH(__key, __address_discriminated, __discriminator) \ | ||
__ptrauth(__key, __address_discriminated, ptrauth_string_discriminator(__discriminator)) | ||
// This work around is required to support divergence in spelling | ||
// during the ptrauth upstreaming process. | ||
# if __has_feature(ptrauth_restricted_intptr_qualifier) | ||
# define _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, __discriminator) \ | ||
__ptrauth_restricted_intptr(__key, __address_discriminated, ptrauth_string_discriminator(__discriminator)) | ||
# else | ||
# define _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, __discriminator) \ | ||
__ptrauth(__key, __address_discriminated, ptrauth_string_discriminator(__discriminator)) | ||
# endif | ||
#else | ||
# define _LIBCXXABI_PTRAUTH(__key, __address_discriminated, __discriminator) | ||
# define _LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(__key, __address_discriminated, __discriminator) | ||
#endif | ||
|
||
// Helper wrappers for pointer auth qualifiers because we use a lot of variants | ||
// Suffixes: | ||
// * _RI : qualifier is __ptrauth_restricted_intptr | ||
// * PDD : key is ptrauth_key_process_dependent_data | ||
// * FN : key is ptrauth_key_function_pointer | ||
#define _LIBCXXABI_PTRAUTH_PDD(__discriminator) \ | ||
_LIBCXXABI_PTRAUTH(ptrauth_key_process_dependent_data, /*__address_discriminated=*/1, __discriminator) | ||
#define _LIBCXXABI_PTRAUTH_FN(__discriminator) \ | ||
_LIBCXXABI_PTRAUTH(ptrauth_key_function_pointer, /*__address_discriminated=*/1, __discriminator) | ||
#define _LIBCXXABI_PTRAUTH_RI_PDD(__discriminator) \ | ||
_LIBCXXABI_PTRAUTH_RESTRICTED_INTPTR(ptrauth_key_process_dependent_data, /*__address_discriminated=*/1, \ | ||
__discriminator) | ||
|
||
#endif // ____CXXABI_CONFIG_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -47,10 +47,11 @@ 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* _LIBCXXABI_PTRAUTH_FN("__cxa_exception::exceptionDestructor") | ||
exceptionDestructor)(void*); | ||
#endif | ||
std::unexpected_handler unexpectedHandler; | ||
std::terminate_handler terminateHandler; | ||
std::unexpected_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::unexpectedHandler") unexpectedHandler; | ||
std::terminate_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::terminateHandler") terminateHandler; | ||
Comment on lines
+50
to
+54
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these strings (or, strictly speaking, their hashes) part of public ABI? If so, it may be handy to put them into |
||
|
||
__cxa_exception *nextException; | ||
|
||
|
@@ -61,10 +62,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* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::actionRecord") actionRecord; | ||
const unsigned char* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::languageSpecificData") languageSpecificData; | ||
void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::catchTemp") catchTemp; | ||
void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::adjustedPtr") adjustedPtr; | ||
Comment on lines
+65
to
+68
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same here. |
||
#endif | ||
|
||
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI) | ||
|
@@ -79,16 +80,19 @@ 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 tags used in the pointer authentication qualifiers also need to 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. | ||
void* primaryException; | ||
#endif | ||
|
||
std::type_info *exceptionType; | ||
void (_LIBCXXABI_DTOR_FUNC *exceptionDestructor)(void *); | ||
std::unexpected_handler unexpectedHandler; | ||
std::terminate_handler terminateHandler; | ||
void(_LIBCXXABI_DTOR_FUNC* _LIBCXXABI_PTRAUTH_FN("__cxa_exception::exceptionDestructor") | ||
exceptionDestructor)(void*); | ||
std::unexpected_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::unexpectedHandler") unexpectedHandler; | ||
std::terminate_handler _LIBCXXABI_PTRAUTH_FN("__cxa_exception::terminateHandler") terminateHandler; | ||
|
||
__cxa_exception *nextException; | ||
|
||
|
@@ -99,10 +103,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* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::actionRecord") actionRecord; | ||
const unsigned char* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::languageSpecificData") languageSpecificData; | ||
void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::catchTemp") catchTemp; | ||
void* _LIBCXXABI_PTRAUTH_PDD("__cxa_exception::adjustedPtr") adjustedPtr; | ||
#endif | ||
|
||
#if !defined(__LP64__) && !defined(_WIN64) && !defined(_LIBCXXABI_ARM_EHABI) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,6 +22,12 @@ | |
#include "private_typeinfo.h" | ||
#include "unwind.h" | ||
|
||
#if __has_include(<ptrauth.h>) | ||
# include <ptrauth.h> | ||
#endif | ||
|
||
#include "libunwind.h" | ||
|
||
// 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 | ||
// in LLVM 15 -- we can remove this workaround after shipping LLVM 17. Once we remove | ||
|
@@ -527,12 +533,19 @@ get_thrown_object_ptr(_Unwind_Exception* unwind_exception) | |
namespace | ||
{ | ||
|
||
#define _LIBCXXABI_PTRAUTH_KEY ptrauth_key_process_dependent_code | ||
typedef const uint8_t* _LIBCXXABI_PTRAUTH_PDD("scan_results::languageSpecificData") lsd_ptr_t; | ||
typedef const uint8_t* _LIBCXXABI_PTRAUTH_PDD("scan_results::actionRecord") action_ptr_t; | ||
#define _LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC "scan_results::landingPad" | ||
typedef uintptr_t _LIBCXXABI_PTRAUTH_RI_PDD(_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC) landing_pad_t; | ||
typedef void* _LIBCXXABI_PTRAUTH_PDD(_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC) 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, | ||
|
@@ -541,7 +554,33 @@ struct scan_results | |
}; | ||
|
||
} // unnamed namespace | ||
} | ||
|
||
namespace { | ||
// The logical model for casting authenticated function pointers makes | ||
// it impossible to directly cast them without breaking the authentication, | ||
// as a result we need this pair of helpers. | ||
template <typename PtrType> | ||
void set_landing_pad_as_ptr(scan_results& results, const PtrType& out) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @kovdan01 ah yeah, unfortunately that's not sound, but for dumb reasons. The reason I've passed by reference is because the intent is for PtrType to be a ptrauth qualified type on arm64e, and we use a reference to ensure that it remains protected. It might be possible to make this clearer once we have the schema queries upstreamed, because then we could make it explicit that this expects PtrType to be an address discriminated __ptrauth qualified pointer when compiling on arm64e (or whatever other platforms add ptrauth in future) |
||
union { | ||
landing_pad_t* as_landing_pad; | ||
landing_pad_ptr_t* as_pointer; | ||
} u; | ||
u.as_landing_pad = &results.landingPad; | ||
*u.as_pointer = out; | ||
} | ||
|
||
static const landing_pad_ptr_t& get_landing_pad_as_ptr(const scan_results& results) { | ||
union { | ||
const landing_pad_t* as_landing_pad; | ||
const landing_pad_ptr_t* as_pointer; | ||
} u; | ||
u.as_landing_pad = &results.landingPad; | ||
return *u.as_pointer; | ||
} | ||
} // unnamed namespace | ||
|
||
extern "C" { | ||
static | ||
void | ||
set_registers(_Unwind_Exception* unwind_exception, _Unwind_Context* context, | ||
|
@@ -557,7 +596,19 @@ 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 defined(__APPLE__) && __has_feature(ptrauth_qualifier) | ||
auto stack_pointer = _Unwind_GetGR(context, UNW_REG_SP); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. [nit] Possibly incorrect naming style: There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. yeah, I spent a bunch of time trying to get the spellings more consistent but I really wasn't sure :-/ |
||
// 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_string_discriminator(_LIBCXXABI_PTRAUTH_SCANRESULT_LANDINGPAD_DISC)); | ||
unw_word_t newIP = | ||
(unw_word_t)ptrauth_auth_and_resign(*(void**)&results.landingPad, _LIBCXXABI_PTRAUTH_KEY, existingDiscriminator, | ||
ptrauth_key_return_address, stack_pointer); | ||
_Unwind_SetIP(context, newIP); | ||
#else | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as in |
||
_Unwind_SetIP(context, results.landingPad); | ||
#endif | ||
} | ||
|
||
/* | ||
|
@@ -691,12 +742,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__ | ||
|
@@ -935,8 +986,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_as_ptr(results, exception_header->catchTemp); | ||
results.adjustedPtr = exception_header->adjustedPtr; | ||
|
||
// Jump to the handler. | ||
|
@@ -970,7 +1020,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); | ||
exc->catchTemp = get_landing_pad_as_ptr(results); | ||
exc->adjustedPtr = results.adjustedPtr; | ||
#ifdef __WASM_EXCEPTIONS__ | ||
// Wasm only uses a single phase (_UA_SEARCH_PHASE), so save the | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am building this for
aarch64-linux-pauthtest
now and I wonder if it is beneficial to decrease the number of hardcodeddefined(__APPLE__)
guards? Something likenear the top of the file and then use
EXTRA_PTRAUTH_HARDENING
throughout the code instead ofdefined(__APPLE__)
, so that other platforms can opt-in to this hardening by adjusting a single line.Though, the above
EXTRA_PTRAUTH_HARDENING
macro still have to be defined multiple times: separate definitions would probably be required forcompiler-rt/lib/builtins/gcc_personality_v0.c
,libcxxabi
andlibunwind
.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, I wonder if there's any existing precedence for cmake variables the apply to all the runtimes?
Also, given some of the other issues you've hit with building don't expend too much effort trying to build/test - I need to work out what parts I've managed to screw up while building out this PR - some of the issues you've hit seem likely to be me screwing up during the preparation of the PR and I don't want you folk to slog through issues caused by my muppetry