https://github.com/kovdan01 created https://github.com/llvm/llvm-project/pull/95203
If both `-fptrauth-init-fini` and `-fptrauth-calls` are passed, sign function pointers in `llvm.global_ctors` and `llvm.global_dtors` with constant discriminator 0xD9D4 (`ptrauth_string_discriminator("init_fini")`) and no address discrimination. >From 9880b6883cd73ab2dcd0efd9ae80805db862c595 Mon Sep 17 00:00:00 2001 From: Daniil Kovalev <dkova...@accesssoftek.com> Date: Wed, 12 Jun 2024 10:28:08 +0300 Subject: [PATCH] [PAC][AArch64] Support init/fini array signing If both `-fptrauth-init-fini` and `-fptrauth-calls` are passed, sign function pointers in `llvm.global_ctors` and `llvm.global_dtors` with constant discriminator 0xD9D4 (`ptrauth_string_discriminator("init_fini")`) and no address discrimination. --- .../include/clang/Basic/PointerAuthOptions.h | 7 +++ clang/lib/CodeGen/CodeGenModule.cpp | 50 +++++++++++-------- clang/lib/Frontend/CompilerInvocation.cpp | 5 ++ clang/lib/Headers/ptrauth.h | 7 +++ clang/test/CodeGen/ptrauth-init-fini.c | 27 ++++++++++ compiler-rt/lib/builtins/crtbegin.c | 16 ++++++ 6 files changed, 92 insertions(+), 20 deletions(-) create mode 100644 clang/test/CodeGen/ptrauth-init-fini.c diff --git a/clang/include/clang/Basic/PointerAuthOptions.h b/clang/include/clang/Basic/PointerAuthOptions.h index 32b179e3f9460..dea8ae439a0eb 100644 --- a/clang/include/clang/Basic/PointerAuthOptions.h +++ b/clang/include/clang/Basic/PointerAuthOptions.h @@ -25,6 +25,10 @@ namespace clang { +/// Constant discriminator to be used with function pointers in .init_array and +/// .fini_array. The value is ptrauth_string_discriminator("init_fini") +constexpr uint16_t InitFiniPointerConstantDiscriminator = 0xD9D4; + constexpr unsigned PointerAuthKeyNone = -1; class PointerAuthSchema { @@ -152,6 +156,9 @@ class PointerAuthSchema { struct PointerAuthOptions { /// The ABI for C function pointers. PointerAuthSchema FunctionPointers; + + /// The ABI for function addresses in .init_array and .fini_array + PointerAuthSchema InitFiniPointers; }; } // end namespace clang diff --git a/clang/lib/CodeGen/CodeGenModule.cpp b/clang/lib/CodeGen/CodeGenModule.cpp index e4774a587707a..6bc6c34a9f524 100644 --- a/clang/lib/CodeGen/CodeGenModule.cpp +++ b/clang/lib/CodeGen/CodeGenModule.cpp @@ -2042,37 +2042,47 @@ void CodeGenModule::AddGlobalDtor(llvm::Function *Dtor, int Priority, void CodeGenModule::EmitCtorList(CtorList &Fns, const char *GlobalName) { if (Fns.empty()) return; - // Ctor function type is void()*. - llvm::FunctionType* CtorFTy = llvm::FunctionType::get(VoidTy, false); - llvm::Type *CtorPFTy = llvm::PointerType::get(CtorFTy, - TheModule.getDataLayout().getProgramAddressSpace()); + const PointerAuthSchema &InitFiniAuthSchema = + getCodeGenOpts().PointerAuth.InitFiniPointers; + assert(!InitFiniAuthSchema || !InitFiniAuthSchema.isAddressDiscriminated()); - // Get the type of a ctor entry, { i32, void ()*, i8* }. - llvm::StructType *CtorStructTy = llvm::StructType::get( - Int32Ty, CtorPFTy, VoidPtrTy); + // Ctor function type is ptr. + llvm::PointerType *PtrTy = llvm::PointerType::get( + getLLVMContext(), TheModule.getDataLayout().getProgramAddressSpace()); + + // Get the type of a ctor entry, { i32, ptr, ptr }. + llvm::StructType *CtorStructTy = llvm::StructType::get(Int32Ty, PtrTy, PtrTy); // Construct the constructor and destructor arrays. - ConstantInitBuilder builder(*this); - auto ctors = builder.beginArray(CtorStructTy); + ConstantInitBuilder Builder(*this); + auto Ctors = Builder.beginArray(CtorStructTy); for (const auto &I : Fns) { - auto ctor = ctors.beginStruct(CtorStructTy); - ctor.addInt(Int32Ty, I.Priority); - ctor.add(I.Initializer); + auto Ctor = Ctors.beginStruct(CtorStructTy); + Ctor.addInt(Int32Ty, I.Priority); + if (InitFiniAuthSchema) { + llvm::Constant *SignedCtorPtr = getConstantSignedPointer( + I.Initializer, InitFiniAuthSchema.getKey(), + /*StorageAddress=*/nullptr, + llvm::ConstantInt::get( + SizeTy, InitFiniAuthSchema.getConstantDiscrimination())); + Ctor.add(SignedCtorPtr); + } else { + Ctor.add(I.Initializer); + } if (I.AssociatedData) - ctor.add(I.AssociatedData); + Ctor.add(I.AssociatedData); else - ctor.addNullPointer(VoidPtrTy); - ctor.finishAndAddTo(ctors); + Ctor.addNullPointer(PtrTy); + Ctor.finishAndAddTo(Ctors); } - auto list = - ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(), - /*constant*/ false, - llvm::GlobalValue::AppendingLinkage); + auto List = Ctors.finishAndCreateGlobal(GlobalName, getPointerAlign(), + /*constant*/ false, + llvm::GlobalValue::AppendingLinkage); // The LTO linker doesn't seem to like it when we set an alignment // on appending variables. Take it off as a workaround. - list->setAlignment(std::nullopt); + List->setAlignment(std::nullopt); Fns.clear(); } diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index b4ca3e413b2c0..53c8fefc871c0 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1468,6 +1468,11 @@ bool CompilerInvocation::setDefaultPointerAuthOptions( // If you change anything here, be sure to update <ptrauth.h>. Opts.FunctionPointers = PointerAuthSchema(Key::ASIA, false, Discrimination::None); + if (LangOpts.PointerAuthInitFini) { + Opts.InitFiniPointers = + PointerAuthSchema(Key::ASIA, false, Discrimination::Constant, + InitFiniPointerConstantDiscriminator); + } } return true; } diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h index aec387153d87c..9bf9eaac312a7 100644 --- a/clang/lib/Headers/ptrauth.h +++ b/clang/lib/Headers/ptrauth.h @@ -42,6 +42,9 @@ typedef enum { The extra data is always 0. */ ptrauth_key_function_pointer = ptrauth_key_process_independent_code, + /* The key used to sign pointers in ELF .init_array/.fini_array. */ + ptrauth_key_init_fini_pointer = ptrauth_key_asia, + /* Other pointers signed under the ABI use private ABI rules. */ } ptrauth_key; @@ -213,6 +216,10 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; #define ptrauth_sign_generic_data(__value, __data) \ __builtin_ptrauth_sign_generic_data(__value, __data) +#define __ptrauth_init_fini_discriminator 0xd9d4 +#define __ptrauth_init_fini_pointer \ + __ptrauth(ptrauth_key_init_fini_pointer, 0, __ptrauth_init_fini_discriminator) + #else #define ptrauth_strip(__value, __key) \ diff --git a/clang/test/CodeGen/ptrauth-init-fini.c b/clang/test/CodeGen/ptrauth-init-fini.c new file mode 100644 index 0000000000000..894e6c84e6347 --- /dev/null +++ b/clang/test/CodeGen/ptrauth-init-fini.c @@ -0,0 +1,27 @@ +// REQUIRES: aarch64-registered-target +// RUN: %clang -target aarch64-elf -march=armv8.3-a+pauth -fptrauth-calls -fptrauth-init-fini \ +// RUN: -S -emit-llvm %s -o - | FileCheck --check-prefix=SIGNED %s +// RUN: %clang -target aarch64-elf -march=armv8.3-a+pauth -fptrauth-calls -fno-ptrauth-init-fini \ +// RUN: -S -emit-llvm %s -o - | FileCheck --check-prefix=UNSIGNED %s +// RUN: %clang -target aarch64-elf -march=armv8.3-a+pauth -fptrauth-init-fini \ +// RUN: -S -emit-llvm %s -o - | FileCheck --check-prefix=UNSIGNED %s + +// SIGNED: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @foo, i32 0, i64 55764), ptr null }] +// SIGNED: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr ptrauth (ptr @bar, i32 0, i64 55764), ptr null }] + +// UNSIGNED: @llvm.global_ctors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @foo, ptr null }] +// UNSIGNED: @llvm.global_dtors = appending global [1 x { i32, ptr, ptr }] [{ i32, ptr, ptr } { i32 65535, ptr @bar, ptr null }] + +volatile int x = 0; + +__attribute__((constructor)) void foo(void) { + x = 42; +} + +__attribute__((destructor)) void bar(void) { + x = 24; +} + +int main() { + return x; +} diff --git a/compiler-rt/lib/builtins/crtbegin.c b/compiler-rt/lib/builtins/crtbegin.c index a0860ca12ea03..143af768de679 100644 --- a/compiler-rt/lib/builtins/crtbegin.c +++ b/compiler-rt/lib/builtins/crtbegin.c @@ -8,6 +8,10 @@ #include <stddef.h> +#if __has_feature(ptrauth_init_fini) +#include <ptrauth.h> +#endif + __attribute__((visibility("hidden"))) void *__dso_handle = &__dso_handle; #ifdef EH_USE_FRAME_REGISTRY @@ -46,8 +50,14 @@ static void __attribute__((used)) __do_init(void) { } #ifdef CRT_HAS_INITFINI_ARRAY +#if __has_feature(ptrauth_init_fini) +__attribute__((section(".init_array"), + used)) static void *__ptrauth_init_fini_pointer __init = + __do_init; +#else __attribute__((section(".init_array"), used)) static void (*__init)(void) = __do_init; +#endif #elif defined(__i386__) || defined(__x86_64__) __asm__(".pushsection .init,\"ax\",@progbits\n\t" "call __do_init\n\t" @@ -103,8 +113,14 @@ static void __attribute__((used)) __do_fini(void) { } #ifdef CRT_HAS_INITFINI_ARRAY +#if __has_feature(ptrauth_init_fini) +__attribute__((section(".fini_array"), + used)) static void *__ptrauth_init_fini_pointer __fini = + __do_fini; +#else __attribute__((section(".fini_array"), used)) static void (*__fini)(void) = __do_fini; +#endif #elif defined(__i386__) || defined(__x86_64__) __asm__(".pushsection .fini,\"ax\",@progbits\n\t" "call __do_fini\n\t" _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits