https://github.com/kovdan01 created https://github.com/llvm/llvm-project/pull/173765
For Apple's arm64e or Linux's pauthtest, `Registers_arm64::link_reg_t` type is `__ptrauth`-qualified. When passing a value of such a type to a function accepting non-`__ptrauth`-qualified parameter with `pint_t` type, an authentication is performed. So, the corresponding callee argument does not contain an embedded signature, making it prone to substitution if spilled to the stack. This patch prevents early authentication of signed values of `link_reg_t` type by passing them as const l-value references instead of passing by value with type `pint_t`. This way, the callee would operate with a `__ptrauth`-qualified value containing a signature, allowing to detect a substitution if the value is spilled to the stack. >From 9ddab0cf0b8a4e6af8895ac60718b084a3675f45 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <[email protected]> Date: Sun, 28 Dec 2025 13:35:34 +0300 Subject: [PATCH] [PAC][libunwind] Pass ptrauth-qualified values as const references For Apple's arm64e or Linux's pauthtest, `Registers_arm64::link_reg_t` type is `__ptrauth`-qualified. When passing a value of such a type to a function accepting non-`__ptrauth`-qualified parameter with `pint_t` type, an authentication is performed. So, the corresponding callee argument does not contain an embedded signature, making it prone to substitution if spilled to the stack. This patch prevents early authentication of signed values of `link_reg_t` type by passing them as const l-value references instead of passing by value with type `pint_t`. This way, the callee would operate with a `__ptrauth`-qualified value containing a signature, allowing to detect a substitution if the value is spilled to the stack. --- libunwind/src/AddressSpace.hpp | 18 +++++++++++------- libunwind/src/DwarfParser.hpp | 15 ++++++++++----- libunwind/src/EHHeaderParser.hpp | 6 ++++-- libunwind/src/UnwindCursor.hpp | 11 ++++++----- 4 files changed, 31 insertions(+), 19 deletions(-) diff --git a/libunwind/src/AddressSpace.hpp b/libunwind/src/AddressSpace.hpp index 63f9cb367ec0c..6d204a1402c07 100644 --- a/libunwind/src/AddressSpace.hpp +++ b/libunwind/src/AddressSpace.hpp @@ -202,10 +202,12 @@ class _LIBUNWIND_HIDDEN LocalAddressSpace { pint_t getEncodedP(pint_t &addr, pint_t end, uint8_t encoding, pint_t datarelBase = 0, pint_t *resultAddr = nullptr); - bool findFunctionName(pint_t addr, char *buf, size_t bufLen, + template <typename T> + bool findFunctionName(const T &addr, char *buf, size_t bufLen, unw_word_t *offset); - bool findUnwindSections(pint_t targetAddr, UnwindInfoSections &info); - bool findOtherFDE(pint_t targetAddr, pint_t &fde); + template <typename T> + bool findUnwindSections(const T &targetAddr, UnwindInfoSections &info); + template <typename T> bool findOtherFDE(const T &targetAddr, pint_t &fde); static LocalAddressSpace sThisAddressSpace; }; @@ -497,8 +499,8 @@ static int findUnwindSectionsByPhdr(struct dl_phdr_info *pinfo, #endif // defined(_LIBUNWIND_USE_DL_ITERATE_PHDR) - -inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, +template <typename T> +inline bool LocalAddressSpace::findUnwindSections(const T &targetAddr, UnwindInfoSections &info) { #ifdef __APPLE__ dyld_unwind_sections dyldInfo; @@ -669,14 +671,16 @@ inline bool LocalAddressSpace::findUnwindSections(pint_t targetAddr, return false; } -inline bool LocalAddressSpace::findOtherFDE(pint_t targetAddr, pint_t &fde) { +template <typename T> +inline bool LocalAddressSpace::findOtherFDE(const T &targetAddr, pint_t &fde) { // TO DO: if OS has way to dynamically register FDEs, check that. (void)targetAddr; (void)fde; return false; } -inline bool LocalAddressSpace::findFunctionName(pint_t addr, char *buf, +template <typename T> +inline bool LocalAddressSpace::findFunctionName(const T &addr, char *buf, size_t bufLen, unw_word_t *offset) { #if _LIBUNWIND_USE_DLADDR diff --git a/libunwind/src/DwarfParser.hpp b/libunwind/src/DwarfParser.hpp index 2b04ae2831f9a..a062b5bbd31ab 100644 --- a/libunwind/src/DwarfParser.hpp +++ b/libunwind/src/DwarfParser.hpp @@ -160,14 +160,16 @@ class CFI_Parser { } }; - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, + template <typename T> + static bool findFDE(A &addressSpace, const T &pc, pint_t ehSectionStart, size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo); static const char *decodeFDE(A &addressSpace, pint_t fdeStart, FDE_Info *fdeInfo, CIE_Info *cieInfo, bool useCIEInfo = false); + template <typename T> static bool parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, + const CIE_Info &cieInfo, const T &upToPC, int arch, PrologInfo *results); static const char *parseCIE(A &addressSpace, pint_t cie, CIE_Info *cieInfo); @@ -239,7 +241,8 @@ const char *CFI_Parser<A>::decodeFDE(A &addressSpace, pint_t fdeStart, /// Scan an eh_frame section to find an FDE for a pc template <typename A> -bool CFI_Parser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehSectionStart, +template <typename T> +bool CFI_Parser<A>::findFDE(A &addressSpace, const T &pc, pint_t ehSectionStart, size_t sectionLength, pint_t fdeHint, FDE_Info *fdeInfo, CIE_Info *cieInfo) { //fprintf(stderr, "findFDE(0x%llX)\n", (long long)pc); @@ -451,10 +454,12 @@ const char *CFI_Parser<A>::parseCIE(A &addressSpace, pint_t cie, /// "run" the DWARF instructions and create the abstract PrologInfo for an FDE template <typename A> +template <typename T> bool CFI_Parser<A>::parseFDEInstructions(A &addressSpace, const FDE_Info &fdeInfo, - const CIE_Info &cieInfo, pint_t upToPC, - int arch, PrologInfo *results) { + const CIE_Info &cieInfo, + const T &upToPC, int arch, + PrologInfo *results) { // Alloca is used for the allocation of the rememberStack entries. It removes // the dependency on new/malloc but the below for loop can not be refactored // into functions. Entry could be saved during the processing of a CIE and diff --git a/libunwind/src/EHHeaderParser.hpp b/libunwind/src/EHHeaderParser.hpp index 0662a1321e2c7..9f60985eb70e5 100644 --- a/libunwind/src/EHHeaderParser.hpp +++ b/libunwind/src/EHHeaderParser.hpp @@ -37,7 +37,8 @@ template <typename A> class EHHeaderParser { static bool decodeEHHdr(A &addressSpace, pint_t ehHdrStart, pint_t ehHdrEnd, EHHeaderInfo &ehHdrInfo); - static bool findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, + template <typename T> + static bool findFDE(A &addressSpace, const T &pc, pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser<A>::FDE_Info *fdeInfo, typename CFI_Parser<A>::CIE_Info *cieInfo); @@ -112,7 +113,8 @@ bool EHHeaderParser<A>::decodeTableEntry( } template <typename A> -bool EHHeaderParser<A>::findFDE(A &addressSpace, pint_t pc, pint_t ehHdrStart, +template <typename T> +bool EHHeaderParser<A>::findFDE(A &addressSpace, const T &pc, pint_t ehHdrStart, uint32_t sectionLength, typename CFI_Parser<A>::FDE_Info *fdeInfo, typename CFI_Parser<A>::CIE_Info *cieInfo) { diff --git a/libunwind/src/UnwindCursor.hpp b/libunwind/src/UnwindCursor.hpp index afa0cae790377..c7d3e4ca85e91 100644 --- a/libunwind/src/UnwindCursor.hpp +++ b/libunwind/src/UnwindCursor.hpp @@ -121,7 +121,7 @@ class _LIBUNWIND_HIDDEN DwarfFDECache { typedef typename A::pint_t pint_t; public: static constexpr pint_t kSearchAll = static_cast<pint_t>(-1); - static pint_t findFDE(pint_t mh, pint_t pc); + template <typename T> static pint_t findFDE(pint_t mh, const T &pc); static void add(pint_t mh, pint_t ip_start, pint_t ip_end, pint_t fde); static void removeAllIn(pint_t mh); static void iterateCacheEntries(void (*func)(unw_word_t ip_start, @@ -174,8 +174,9 @@ bool DwarfFDECache<A>::_registeredForDyldUnloads = false; #endif template <typename A> +template <typename T> typename DwarfFDECache<A>::pint_t DwarfFDECache<A>::findFDE(pint_t mh, - pint_t pc) { + const T &pc) { pint_t result = 0; _LIBUNWIND_LOG_IF_FALSE(_lock.lock_shared()); for (entry *p = _buffer; p < _bufferUsed; ++p) { @@ -1060,7 +1061,7 @@ class UnwindCursor : public AbstractUnwindCursor{ #if defined(_LIBUNWIND_SUPPORT_DWARF_UNWIND) bool getInfoFromFdeCie(const typename CFI_Parser<A>::FDE_Info &fdeInfo, const typename CFI_Parser<A>::CIE_Info &cieInfo, - pint_t pc, uintptr_t dso_base); + const typename R::link_reg_t &pc, uintptr_t dso_base); bool getInfoFromDwarfSection(const typename R::link_reg_t &pc, const UnwindInfoSections §s, uint32_t fdeSectionOffsetHint = 0); @@ -1730,8 +1731,8 @@ bool UnwindCursor<A, R>::getInfoFromEHABISection( template <typename A, typename R> bool UnwindCursor<A, R>::getInfoFromFdeCie( const typename CFI_Parser<A>::FDE_Info &fdeInfo, - const typename CFI_Parser<A>::CIE_Info &cieInfo, pint_t pc, - uintptr_t dso_base) { + const typename CFI_Parser<A>::CIE_Info &cieInfo, + const typename R::link_reg_t &pc, uintptr_t dso_base) { typename CFI_Parser<A>::PrologInfo prolog; if (CFI_Parser<A>::parseFDEInstructions(_addressSpace, fdeInfo, cieInfo, pc, R::getArch(), &prolog)) { _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
