https://github.com/asl updated https://github.com/llvm/llvm-project/pull/140276
>From ed3d47d43571d734aa01e9b6dbaa237f653374da Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov <[email protected]> Date: Fri, 16 May 2025 19:25:57 +0300 Subject: [PATCH 1/2] [PAuth] Use different discriminators for __int128_t / __uint128_t / _BitInt(n) compared to other integer types when computing function pointer type discriminator. These parameter types have different parameter passing ABI as compared to ordinary integer types (e.g. require 2 registers instead of 1) and therefore this parameter passing difference could potentially be exploited should function pointer is substituted. --- clang/lib/AST/ASTContext.cpp | 14 ++++++--- .../ptrauth-function-type-discriminator.c | 31 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index a6eb87ab7d8aa..09d949b5e1643 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3506,21 +3506,27 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, // Don't bother discriminating based on these types. case Type::Pipe: - case Type::BitInt: case Type::ConstantMatrix: OS << "?"; return; + case Type::BitInt: { + const auto *BtTy = T->castAs<BitIntType>(); + OS << "D" << (BtTy->isUnsigned() ? "U" : "B") << BtTy->getNumBits() << "_"; + return; + } + case Type::Builtin: { const auto *BTy = T->castAs<BuiltinType>(); - switch (BTy->getKind()) { + const auto Kind = BTy->getKind(); + switch (Kind) { #define SIGNED_TYPE(Id, SingletonId) \ case BuiltinType::Id: \ - OS << "i"; \ + OS << (Kind == BuiltinType::Int128 ? "n" : "i"); \ return; #define UNSIGNED_TYPE(Id, SingletonId) \ case BuiltinType::Id: \ - OS << "i"; \ + OS << (Kind == BuiltinType::UInt128 ? "o" : "i"); \ return; #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: #define BUILTIN_TYPE(Id, SingletonId) diff --git a/clang/test/CodeGen/ptrauth-function-type-discriminator.c b/clang/test/CodeGen/ptrauth-function-type-discriminator.c index 0952c1abf6c07..9bf4a8874c3c3 100644 --- a/clang/test/CodeGen/ptrauth-function-type-discriminator.c +++ b/clang/test/CodeGen/ptrauth-function-type-discriminator.c @@ -65,6 +65,37 @@ void (*fptr3)(void) = __builtin_ptrauth_sign_constant(&external_function, 2, 26) // CHECK: @fptr4 = global ptr ptrauth (ptr @external_function, i32 2, i64 26, ptr @fptr4) void (*fptr4)(void) = __builtin_ptrauth_sign_constant(&external_function, 2, __builtin_ptrauth_blend_discriminator(&fptr4, 26)); +extern void external_function_int(int); +extern void external_function_char(char); +extern void external_function_i128(__int128_t); +extern void external_function_u128(__uint128_t); +extern void external_function_b128(_BitInt(128)); +extern void external_function_b8(_BitInt(8)); + +// Check discriminators of functions taking integer type arguments: + +// - Builtin integer types should be discriminated equally (so, pointer to +// function taking int argument should accept function taking char argument +// - _BitInt types are guaranteed distinct and therefore should be discriminated +// differently +// - __int128_t / __uint128_t are passed differently than char / int / long +// (require two registers instead of one) and therefore should be discriminated +// differently. + +// CHECK: @fptr5 = global ptr ptrauth (ptr @external_function_int, i32 0, i64 2712) +// CHECK: @fptr6 = global ptr ptrauth (ptr @external_function_char, i32 0, i64 2712) +void (*fptr5)(int) = external_function_int; +void (*fptr6)(char) = external_function_char; + +// CHECK: @fptr7 = global ptr ptrauth (ptr @external_function_i128, i32 0, i64 23141) +// CHECK: @fptr8 = global ptr ptrauth (ptr @external_function_u128, i32 0, i64 45743) +// CHECK: @fptr9 = global ptr ptrauth (ptr @external_function_b128, i32 0, i64 17854) +// CHECK: @fptr10 = global ptr ptrauth (ptr @external_function_b8, i32 0, i64 26383) +void (*fptr7)(__int128_t) = external_function_i128; +void (*fptr8)(__uint128_t) = external_function_u128; +void (*fptr9)(_BitInt(128)) = external_function_b128; +void (*fptr10)(_BitInt(8)) = external_function_b8; + // CHECK-LABEL: define{{.*}} void @test_call() void test_call() { // CHECK: [[T0:%.*]] = load ptr, ptr @fnptr, >From 9034dfe720e13e94412ae9ac49c4c26da1f15c8f Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov <[email protected]> Date: Sun, 1 Jun 2025 23:55:32 -0700 Subject: [PATCH 2/2] Make type discrimination of 128-bit types optional --- clang/include/clang/Basic/Features.def | 1 + clang/include/clang/Basic/LangOptions.def | 2 ++ clang/include/clang/Options/Options.td | 2 ++ clang/lib/AST/ASTContext.cpp | 21 ++++++++++---- clang/lib/Driver/ToolChains/Clang.cpp | 3 ++ clang/lib/Frontend/CompilerInvocation.cpp | 4 +++ .../ptrauth-function-type-discriminator.c | 28 ++++++++++++------- 7 files changed, 45 insertions(+), 16 deletions(-) diff --git a/clang/include/clang/Basic/Features.def b/clang/include/clang/Basic/Features.def index f0a9c4889ea2d..aab2aaa18e5c2 100644 --- a/clang/include/clang/Basic/Features.def +++ b/clang/include/clang/Basic/Features.def @@ -164,6 +164,7 @@ FEATURE(ptrauth_indirect_gotos, LangOpts.PointerAuthIndirectGotos) FEATURE(ptrauth_init_fini, LangOpts.PointerAuthInitFini) FEATURE(ptrauth_init_fini_address_discrimination, LangOpts.PointerAuthInitFiniAddressDiscrimination) FEATURE(ptrauth_elf_got, LangOpts.PointerAuthELFGOT) +FEATURE(ptrauth_function_pointer_type_discrimination_128, LangOpts.PointerAuthFunctionTypeDiscrimination128) FEATURE(ptrauth_objc_isa, LangOpts.PointerAuthObjcIsa) FEATURE(ptrauth_objc_interface_sel, LangOpts.PointerAuthObjcInterfaceSel) diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index 1fb491a54a278..8ca0a0de50b56 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -129,6 +129,8 @@ LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, NotCompatible, "incorporate ty LANGOPT(PointerAuthTypeInfoVTPtrDiscrimination, 1, 0, NotCompatible, "incorporate type and address discrimination in authenticated vtable pointers for std::type_info") LANGOPT(PointerAuthFunctionTypeDiscrimination, 1, 0, Benign, "Use type discrimination when signing function pointers") +LANGOPT(PointerAuthFunctionTypeDiscrimination128, 1, 0, NotCompatible, + "Use different discriminators for __int128_t / __uint128_t / _BitInt(n) compared to other integer types when computing function pointer type discriminator") LANGOPT(PointerAuthInitFini, 1, 0, NotCompatible, "sign function pointers in init/fini arrays") LANGOPT(PointerAuthInitFiniAddressDiscrimination, 1, 0, NotCompatible, "incorporate address discrimination in authenticated function pointers in init/fini arrays") diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index b2e32c75e5745..e37ab43b89624 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -4995,6 +4995,8 @@ defm ptrauth_type_info_vtable_pointer_discrimination : OptInCC1FFlag<"ptrauth-type-info-vtable-pointer-discrimination", "Enable type and address discrimination of vtable pointer of std::type_info">; defm ptrauth_function_pointer_type_discrimination : OptInCC1FFlag<"ptrauth-function-pointer-type-discrimination", "Enable type discrimination on C function pointers">; +defm ptrauth_128bit_type_discrimination : OptInCC1FFlag<"ptrauth-128bit-type-discrimination", + "Do not use different discriminators for __int128_t / __uint128_t / _BitInt(n) compared to other integer types when computing function pointer type discriminator">; defm ptrauth_indirect_gotos : OptInCC1FFlag<"ptrauth-indirect-gotos", "Enable signing and authentication of indirect goto targets">; defm ptrauth_init_fini : OptInCC1FFlag<"ptrauth-init-fini", "Enable signing of function pointers in init/fini arrays">; diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp index 09d949b5e1643..1766a52197fb8 100644 --- a/clang/lib/AST/ASTContext.cpp +++ b/clang/lib/AST/ASTContext.cpp @@ -3510,11 +3510,14 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, OS << "?"; return; - case Type::BitInt: { - const auto *BtTy = T->castAs<BitIntType>(); - OS << "D" << (BtTy->isUnsigned() ? "U" : "B") << BtTy->getNumBits() << "_"; + case Type::BitInt: + if (Ctx.getLangOpts().PointerAuthFunctionTypeDiscrimination128) { + const auto *BtTy = T->castAs<BitIntType>(); + OS << "D" << (BtTy->isUnsigned() ? "U" : "B") << BtTy->getNumBits() + << "_"; + } else + OS << "?"; return; - } case Type::Builtin: { const auto *BTy = T->castAs<BuiltinType>(); @@ -3522,11 +3525,17 @@ static void encodeTypeForFunctionPointerAuth(const ASTContext &Ctx, switch (Kind) { #define SIGNED_TYPE(Id, SingletonId) \ case BuiltinType::Id: \ - OS << (Kind == BuiltinType::Int128 ? "n" : "i"); \ + OS << (Kind == BuiltinType::Int128 && \ + Ctx.getLangOpts().PointerAuthFunctionTypeDiscrimination128 \ + ? "n" \ + : "i"); \ return; #define UNSIGNED_TYPE(Id, SingletonId) \ case BuiltinType::Id: \ - OS << (Kind == BuiltinType::UInt128 ? "o" : "i"); \ + OS << (Kind == BuiltinType::UInt128 && \ + Ctx.getLangOpts().PointerAuthFunctionTypeDiscrimination128 \ + ? "o" \ + : "i"); \ return; #define PLACEHOLDER_TYPE(Id, SingletonId) case BuiltinType::Id: #define BUILTIN_TYPE(Id, SingletonId) diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp index a30b01a675b99..af073fc952631 100644 --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -1740,6 +1740,9 @@ void Clang::AddAArch64TargetArgs(const ArgList &Args, options::OPT_fno_ptrauth_function_pointer_type_discrimination); Args.addOptInFlag(CmdArgs, options::OPT_fptrauth_indirect_gotos, options::OPT_fno_ptrauth_indirect_gotos); + Args.addOptInFlag( + CmdArgs, options::OPT_fptrauth_128bit_type_discrimination, + options::OPT_fno_ptrauth_128bit_type_discrimination); } if (Triple.isOSLinux() && Triple.getEnvironment() == llvm::Triple::PAuthTest) { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index 6545307a8c8a7..14e52592f7824 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3603,6 +3603,8 @@ static void GeneratePointerAuthArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_fptrauth_type_info_vtable_pointer_discrimination); if (Opts.PointerAuthFunctionTypeDiscrimination) GenerateArg(Consumer, OPT_fptrauth_function_pointer_type_discrimination); + if (Opts.PointerAuthFunctionTypeDiscrimination128) + GenerateArg(Consumer, OPT_fptrauth_128bit_type_discrimination); if (Opts.PointerAuthInitFini) GenerateArg(Consumer, OPT_fptrauth_init_fini); if (Opts.PointerAuthInitFiniAddressDiscrimination) @@ -3636,6 +3638,8 @@ static void ParsePointerAuthArgs(LangOptions &Opts, ArgList &Args, Args.hasArg(OPT_fptrauth_type_info_vtable_pointer_discrimination); Opts.PointerAuthFunctionTypeDiscrimination = Args.hasArg(OPT_fptrauth_function_pointer_type_discrimination); + Opts.PointerAuthFunctionTypeDiscrimination128 = + Args.hasArg(OPT_fptrauth_128bit_type_discrimination); Opts.PointerAuthInitFini = Args.hasArg(OPT_fptrauth_init_fini); Opts.PointerAuthInitFiniAddressDiscrimination = Args.hasArg(OPT_fptrauth_init_fini_address_discrimination); diff --git a/clang/test/CodeGen/ptrauth-function-type-discriminator.c b/clang/test/CodeGen/ptrauth-function-type-discriminator.c index 9bf4a8874c3c3..280115862d927 100644 --- a/clang/test/CodeGen/ptrauth-function-type-discriminator.c +++ b/clang/test/CodeGen/ptrauth-function-type-discriminator.c @@ -1,18 +1,22 @@ // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC %s +// RUN: -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC,CHECKNO128 %s // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -disable-llvm-passes -emit-llvm -xc++ %s -o- | FileCheck --check-prefix=CHECK %s +// RUN: -disable-llvm-passes -emit-llvm -xc++ %s -o- | FileCheck --check-prefixes=CHECK,CHECKNO128 %s // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics -emit-pch %s -o %t.ast // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64-apple-ios -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -emit-llvm -x ast -o - %t.ast | FileCheck --check-prefixes=CHECK,CHECKC %s +// RUN: -emit-llvm -x ast -o - %t.ast | FileCheck --check-prefixes=CHECK,CHECKC,CHECKNO128 %s +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple arm64e-apple-ios13 -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-128bit-type-discrimination -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC,CHECK128 %s // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC %s +// RUN: -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC,CHECKNO128 %s // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -disable-llvm-passes -emit-llvm -xc++ %s -o- | FileCheck --check-prefix=CHECK %s +// RUN: -disable-llvm-passes -emit-llvm -xc++ %s -o- | FileCheck --check-prefixes=CHECK,CHECKNO128 %s // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics -emit-pch %s -o %t.ast // RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ -// RUN: -emit-llvm -x ast -o - %t.ast | FileCheck --check-prefixes=CHECK,CHECKC %s +// RUN: -emit-llvm -x ast -o - %t.ast | FileCheck --check-prefixes=CHECK,CHECKC,CHECKNO128 %s +// RUN: %clang_cc1 -fptrauth-function-pointer-type-discrimination -triple aarch64-linux-gnu -fptrauth-calls -fptrauth-intrinsics \ +// RUN: -fptrauth-128bit-type-discrimination -disable-llvm-passes -emit-llvm %s -o- | FileCheck --check-prefixes=CHECK,CHECKC,CHECK128 %s #ifdef __cplusplus extern "C" { @@ -87,10 +91,14 @@ extern void external_function_b8(_BitInt(8)); void (*fptr5)(int) = external_function_int; void (*fptr6)(char) = external_function_char; -// CHECK: @fptr7 = global ptr ptrauth (ptr @external_function_i128, i32 0, i64 23141) -// CHECK: @fptr8 = global ptr ptrauth (ptr @external_function_u128, i32 0, i64 45743) -// CHECK: @fptr9 = global ptr ptrauth (ptr @external_function_b128, i32 0, i64 17854) -// CHECK: @fptr10 = global ptr ptrauth (ptr @external_function_b8, i32 0, i64 26383) +// CHECK128: @fptr7 = global ptr ptrauth (ptr @external_function_i128, i32 0, i64 23141) +// CHECK128: @fptr8 = global ptr ptrauth (ptr @external_function_u128, i32 0, i64 45743) +// CHECK128: @fptr9 = global ptr ptrauth (ptr @external_function_b128, i32 0, i64 17854) +// CHECK128: @fptr10 = global ptr ptrauth (ptr @external_function_b8, i32 0, i64 26383) +// CHECKNO128: @fptr7 = global ptr ptrauth (ptr @external_function_i128, i32 0, i64 2712) +// CHECKNO128: @fptr8 = global ptr ptrauth (ptr @external_function_u128, i32 0, i64 2712) +// CHECKNO128: @fptr9 = global ptr ptrauth (ptr @external_function_b128, i32 0, i64 41228) +// CHECKNO128: @fptr10 = global ptr ptrauth (ptr @external_function_b8, i32 0, i64 41228) void (*fptr7)(__int128_t) = external_function_i128; void (*fptr8)(__uint128_t) = external_function_u128; void (*fptr9)(_BitInt(128)) = external_function_b128; _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
