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
