https://github.com/ojhunt updated 
https://github.com/llvm/llvm-project/pull/184041

>From f4825c4485407ccbdb123fc200917e9ae46d9f89 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <[email protected]>
Date: Sun, 1 Mar 2026 13:28:10 -0800
Subject: [PATCH] [libunwind][PAC] Defang ptrauth's PC in valid CFI range abort

It turns out making the CFI check a release mode abort causes many,
if not the majority, of JITs to fail during unwinding as they do not
set up CFI sections for their generated code. As a result any JITs
that do nominally support unwinding (and catching) through their JIT
or assembly frames trip this abort.

rdar://170862047
---
 libunwind/src/libunwind.cpp                   | 28 +++++-------
 libunwind/test/cfi_violating_handler.pass.cpp | 44 +++++++++++++++++++
 2 files changed, 55 insertions(+), 17 deletions(-)
 create mode 100644 libunwind/test/cfi_violating_handler.pass.cpp

diff --git a/libunwind/src/libunwind.cpp b/libunwind/src/libunwind.cpp
index a795e68c57859..2128a60c3ac89 100644
--- a/libunwind/src/libunwind.cpp
+++ b/libunwind/src/libunwind.cpp
@@ -131,23 +131,17 @@ _LIBUNWIND_HIDDEN int __unw_set_reg(unw_cursor_t *cursor, 
unw_regnum_t regNum,
       {
         // It is only valid to set the IP within the current function. This is
         // important for ptrauth, otherwise the IP cannot be correctly signed.
-        // The current signature of `value` is via the schema:
-        //   __ptrauth(ptrauth_key_return_address, <<sp>>, 0)
-        // For this to be generally usable we manually re-sign it to the
-        // directly supported schema:
-        //   __ptrauth(ptrauth_key_return_address, 1, 0)
-        unw_word_t
-              __unwind_ptrauth_restricted_intptr(ptrauth_key_return_address, 1,
-                                                 0) authenticated_value;
-        unw_word_t opaque_value = (uint64_t)ptrauth_auth_and_resign(
-            (void *)value, ptrauth_key_return_address, sp,
-            ptrauth_key_return_address, &authenticated_value);
-        memmove(reinterpret_cast<void *>(&authenticated_value),
-                reinterpret_cast<void *>(&opaque_value),
-                sizeof(authenticated_value));
-        if (authenticated_value < info.start_ip ||
-            authenticated_value > info.end_ip)
-          _LIBUNWIND_ABORT("PC vs frame info mismatch");
+        //
+        // However many JITs do not configure CFI frames, so we cannot actually
+        // enforce this - at least not without an extremely expensive syscall.
+        //
+        // For the forseeable future this will need to be a debug only 
assertion
+        // so we just strip and assert to avoid the unnecessary auths in 
release
+        // builds.
+        unw_word_t stripped_value = (unw_word_t)ptrauth_strip(
+            (void *)value, ptrauth_key_return_address);
+        assert(stripped_value >= info.start_ip &&
+               stripped_value <= info.end_ip);
 
         // PC should have been signed with the sp, so we verify that
         // roundtripping does not fail. The `ptrauth_auth_and_resign` is
diff --git a/libunwind/test/cfi_violating_handler.pass.cpp 
b/libunwind/test/cfi_violating_handler.pass.cpp
new file mode 100644
index 0000000000000..78a4b214f624a
--- /dev/null
+++ b/libunwind/test/cfi_violating_handler.pass.cpp
@@ -0,0 +1,44 @@
+// -*- C++ -*-
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+extern "C" int puts(const char*);
+extern "C" void exit(int);
+int randomUnrelatedFunction(){
+  puts("Successfully dispatched to handler unrelated to actual function\n");
+  exit(0);
+  return 0;
+};
+
+extern "C" void _Unwind_SetIP(const void*, const void*);
+extern "C" int __gxx_personality_v0(int,
+                                     int actions,
+                                     __SIZE_TYPE__ ,
+                                     void* , void* context) {
+    if (actions & 1) // Search
+        return 6; // _URC_HANDLER_FOUND
+
+    // Assign to a random unrelated function
+    _Unwind_SetIP(context, (const void*)&randomUnrelatedFunction);
+    return 7; // _URC_INSTALL_CONTEXT;
+}
+
+__attribute__((noinline)) extern "C" void throwAThing() {
+  throw 1;
+}
+
+int main(int, const char **) {
+  try {
+    throwAThing();
+  } catch (int) {
+    puts("Called the wrong handler\n");
+    return 1;
+  }
+  puts("Somehow returned\n");
+  return 1;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to