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 &sects,
                                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

Reply via email to