diff options
author | Ahmed Bougacha <ahmed@bougacha.org> | 2024-06-21 10:20:15 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-06-21 10:20:15 -0700 |
commit | e23250ecb7e09170e584db60375100790f39fac9 (patch) | |
tree | f5defecd713d2a564250fcc0bc4440341cd19380 /clang/lib | |
parent | ecf2a53407f517a261ee296e1f922c647a13a503 (diff) | |
download | llvm-e23250ecb7e09170e584db60375100790f39fac9.zip llvm-e23250ecb7e09170e584db60375100790f39fac9.tar.gz llvm-e23250ecb7e09170e584db60375100790f39fac9.tar.bz2 |
[clang] Implement function pointer signing and authenticated function calls (#93906)
The functions are currently always signed/authenticated with zero
discriminator.
Co-Authored-By: John McCall <rjmccall@apple.com>
Diffstat (limited to 'clang/lib')
-rw-r--r-- | clang/lib/CodeGen/CGBuiltin.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGCall.h | 24 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExpr.cpp | 17 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGExprConstant.cpp | 19 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGPointerAuth.cpp | 39 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGPointerAuthInfo.h | 99 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.cpp | 21 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 4 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenModule.h | 20 | ||||
-rw-r--r-- | clang/lib/Frontend/CompilerInvocation.cpp | 26 | ||||
-rw-r--r-- | clang/lib/Headers/ptrauth.h | 34 |
12 files changed, 294 insertions, 15 deletions
diff --git a/clang/lib/CodeGen/CGBuiltin.cpp b/clang/lib/CodeGen/CGBuiltin.cpp index 2516ed4..d11e7a9 100644 --- a/clang/lib/CodeGen/CGBuiltin.cpp +++ b/clang/lib/CodeGen/CGBuiltin.cpp @@ -6015,8 +6015,7 @@ RValue CodeGenFunction::EmitBuiltinExpr(const GlobalDecl GD, unsigned BuiltinID, // If this is a predefined lib function (e.g. malloc), emit the call // using exactly the normal call path. if (getContext().BuiltinInfo.isPredefinedLibFunction(BuiltinID)) - return emitLibraryCall( - *this, FD, E, cast<llvm::Constant>(EmitScalarExpr(E->getCallee()))); + return emitLibraryCall(*this, FD, E, CGM.getRawFunctionPointer(FD)); // Check that a call to a target specific builtin has the correct target // features. diff --git a/clang/lib/CodeGen/CGCall.cpp b/clang/lib/CodeGen/CGCall.cpp index a071b16..2b30113 100644 --- a/clang/lib/CodeGen/CGCall.cpp +++ b/clang/lib/CodeGen/CGCall.cpp @@ -5678,6 +5678,9 @@ RValue CodeGenFunction::EmitCall(const CGFunctionInfo &CallInfo, !isa_and_nonnull<FunctionDecl>(TargetDecl)) EmitKCFIOperandBundle(ConcreteCallee, BundleList); + // Add the pointer-authentication bundle. + EmitPointerAuthOperandBundle(ConcreteCallee.getPointerAuthInfo(), BundleList); + if (const FunctionDecl *FD = dyn_cast_or_null<FunctionDecl>(CurFuncDecl)) if (FD->hasAttr<StrictFPAttr>()) // All calls within a strictfp function are marked strictfp diff --git a/clang/lib/CodeGen/CGCall.h b/clang/lib/CodeGen/CGCall.h index 6b676ac..412b44a 100644 --- a/clang/lib/CodeGen/CGCall.h +++ b/clang/lib/CodeGen/CGCall.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_LIB_CODEGEN_CGCALL_H #define LLVM_CLANG_LIB_CODEGEN_CGCALL_H +#include "CGPointerAuthInfo.h" #include "CGValue.h" #include "EHScopeStack.h" #include "clang/AST/ASTFwd.h" @@ -69,6 +70,10 @@ class CGCallee { Last = Virtual }; + struct OrdinaryInfoStorage { + CGCalleeInfo AbstractInfo; + CGPointerAuthInfo PointerAuthInfo; + }; struct BuiltinInfoStorage { const FunctionDecl *Decl; unsigned ID; @@ -85,7 +90,7 @@ class CGCallee { SpecialKind KindOrFunctionPointer; union { - CGCalleeInfo AbstractInfo; + OrdinaryInfoStorage OrdinaryInfo; BuiltinInfoStorage BuiltinInfo; PseudoDestructorInfoStorage PseudoDestructorInfo; VirtualInfoStorage VirtualInfo; @@ -104,10 +109,13 @@ public: /// Construct a callee. Call this constructor directly when this /// isn't a direct call. - CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr) + CGCallee(const CGCalleeInfo &abstractInfo, llvm::Value *functionPtr, + /* FIXME: make parameter pointerAuthInfo mandatory */ + const CGPointerAuthInfo &pointerAuthInfo = CGPointerAuthInfo()) : KindOrFunctionPointer( SpecialKind(reinterpret_cast<uintptr_t>(functionPtr))) { - AbstractInfo = abstractInfo; + OrdinaryInfo.AbstractInfo = abstractInfo; + OrdinaryInfo.PointerAuthInfo = pointerAuthInfo; assert(functionPtr && "configuring callee without function pointer"); assert(functionPtr->getType()->isPointerTy()); } @@ -173,7 +181,11 @@ public: if (isVirtual()) return VirtualInfo.MD; assert(isOrdinary()); - return AbstractInfo; + return OrdinaryInfo.AbstractInfo; + } + const CGPointerAuthInfo &getPointerAuthInfo() const { + assert(isOrdinary()); + return OrdinaryInfo.PointerAuthInfo; } llvm::Value *getFunctionPointer() const { assert(isOrdinary()); @@ -184,6 +196,10 @@ public: KindOrFunctionPointer = SpecialKind(reinterpret_cast<uintptr_t>(functionPtr)); } + void setPointerAuthInfo(CGPointerAuthInfo PointerAuth) { + assert(isOrdinary()); + OrdinaryInfo.PointerAuthInfo = PointerAuth; + } bool isVirtual() const { return KindOrFunctionPointer == SpecialKind::Virtual; diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index 3dfe5e0..534f46d 100644 --- a/clang/lib/CodeGen/CGExpr.cpp +++ b/clang/lib/CodeGen/CGExpr.cpp @@ -2856,22 +2856,22 @@ static LValue EmitGlobalVarDeclLValue(CodeGenFunction &CGF, return LV; } -static llvm::Constant *EmitFunctionDeclPointer(CodeGenModule &CGM, - GlobalDecl GD) { +llvm::Constant *CodeGenModule::getRawFunctionPointer(GlobalDecl GD, + llvm::Type *Ty) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); if (FD->hasAttr<WeakRefAttr>()) { - ConstantAddress aliasee = CGM.GetWeakRefReference(FD); + ConstantAddress aliasee = GetWeakRefReference(FD); return aliasee.getPointer(); } - llvm::Constant *V = CGM.GetAddrOfFunction(GD); + llvm::Constant *V = GetAddrOfFunction(GD, Ty); return V; } static LValue EmitFunctionDeclLValue(CodeGenFunction &CGF, const Expr *E, GlobalDecl GD) { const FunctionDecl *FD = cast<FunctionDecl>(GD.getDecl()); - llvm::Value *V = EmitFunctionDeclPointer(CGF.CGM, GD); + llvm::Constant *V = CGF.CGM.getFunctionPointer(GD); CharUnits Alignment = CGF.getContext().getDeclAlign(FD); return CGF.MakeAddrLValue(V, E->getType(), Alignment, AlignmentSource::Decl); @@ -5506,7 +5506,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) { // name to make it clear it's not the actual builtin. if (CGF.CurFn->getName() != FDInlineName && OnlyHasInlineBuiltinDeclaration(FD)) { - llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD); + llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD); llvm::Function *Fn = llvm::cast<llvm::Function>(CalleePtr); llvm::Module *M = Fn->getParent(); llvm::Function *Clone = M->getFunction(FDInlineName); @@ -5529,7 +5529,7 @@ static CGCallee EmitDirectCallee(CodeGenFunction &CGF, GlobalDecl GD) { return CGCallee::forBuiltin(builtinID, FD); } - llvm::Constant *CalleePtr = EmitFunctionDeclPointer(CGF.CGM, GD); + llvm::Constant *CalleePtr = CGF.CGM.getRawFunctionPointer(GD); if (CGF.CGM.getLangOpts().CUDA && !CGF.CGM.getLangOpts().CUDAIsDevice && FD->hasAttr<CUDAGlobalAttr>()) CalleePtr = CGF.CGM.getCUDARuntime().getKernelStub( @@ -5586,7 +5586,8 @@ CGCallee CodeGenFunction::EmitCallee(const Expr *E) { GD = GlobalDecl(VD); CGCalleeInfo calleeInfo(functionType->getAs<FunctionProtoType>(), GD); - CGCallee callee(calleeInfo, calleePtr); + CGPointerAuthInfo pointerAuth = CGM.getFunctionPointerAuthInfo(functionType); + CGCallee callee(calleeInfo, calleePtr, pointerAuth); return callee; } diff --git a/clang/lib/CodeGen/CGExprConstant.cpp b/clang/lib/CodeGen/CGExprConstant.cpp index bc5f42d..dffb8ce 100644 --- a/clang/lib/CodeGen/CGExprConstant.cpp +++ b/clang/lib/CodeGen/CGExprConstant.cpp @@ -2024,8 +2024,25 @@ ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) { if (D->hasAttr<WeakRefAttr>()) return CGM.GetWeakRefReference(D).getPointer(); + auto PtrAuthSign = [&](llvm::Constant *C) { + CGPointerAuthInfo AuthInfo = CGM.getFunctionPointerAuthInfo(DestType); + + if (AuthInfo) { + if (hasNonZeroOffset()) + return ConstantLValue(nullptr); + + C = applyOffset(C); + C = CGM.getConstantSignedPointer( + C, AuthInfo.getKey(), nullptr, + cast_or_null<llvm::ConstantInt>(AuthInfo.getDiscriminator())); + return ConstantLValue(C, /*applied offset*/ true); + } + + return ConstantLValue(C); + }; + if (auto FD = dyn_cast<FunctionDecl>(D)) - return CGM.GetAddrOfFunction(FD); + return PtrAuthSign(CGM.getRawFunctionPointer(FD)); if (auto VD = dyn_cast<VarDecl>(D)) { // We can never refer to a variable with local storage. diff --git a/clang/lib/CodeGen/CGPointerAuth.cpp b/clang/lib/CodeGen/CGPointerAuth.cpp index e1fb0bd..f0819b0 100644 --- a/clang/lib/CodeGen/CGPointerAuth.cpp +++ b/clang/lib/CodeGen/CGPointerAuth.cpp @@ -17,6 +17,24 @@ using namespace clang; using namespace CodeGen; +/// Return the abstract pointer authentication schema for a pointer to the given +/// function type. +CGPointerAuthInfo CodeGenModule::getFunctionPointerAuthInfo(QualType T) { + const auto &Schema = getCodeGenOpts().PointerAuth.FunctionPointers; + if (!Schema) + return CGPointerAuthInfo(); + + assert(!Schema.isAddressDiscriminated() && + "function pointers cannot use address-specific discrimination"); + + assert(!Schema.hasOtherDiscrimination() && + "function pointers don't support any discrimination yet"); + + return CGPointerAuthInfo(Schema.getKey(), Schema.getAuthenticationMode(), + /*IsaPointer=*/false, /*AuthenticatesNull=*/false, + /*Discriminator=*/nullptr); +} + llvm::Constant * CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, @@ -41,3 +59,24 @@ CodeGenModule::getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::ConstantInt::get(Int32Ty, Key), IntegerDiscriminator, AddressDiscriminator); } + +llvm::Constant *CodeGenModule::getFunctionPointer(llvm::Constant *Pointer, + QualType FunctionType) { + assert(FunctionType->isFunctionType() || + FunctionType->isFunctionReferenceType() || + FunctionType->isFunctionPointerType()); + + if (auto PointerAuth = getFunctionPointerAuthInfo(FunctionType)) + return getConstantSignedPointer( + Pointer, PointerAuth.getKey(), /*StorageAddress=*/nullptr, + cast_or_null<llvm::ConstantInt>(PointerAuth.getDiscriminator())); + + return Pointer; +} + +llvm::Constant *CodeGenModule::getFunctionPointer(GlobalDecl GD, + llvm::Type *Ty) { + const auto *FD = cast<FunctionDecl>(GD.getDecl()); + QualType FuncType = FD->getType(); + return getFunctionPointer(getRawFunctionPointer(GD, Ty), FuncType); +} diff --git a/clang/lib/CodeGen/CGPointerAuthInfo.h b/clang/lib/CodeGen/CGPointerAuthInfo.h new file mode 100644 index 0000000..0a0c11f --- /dev/null +++ b/clang/lib/CodeGen/CGPointerAuthInfo.h @@ -0,0 +1,99 @@ +//===----- CGPointerAuthInfo.h - -------------------------------*- 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 +// +//===----------------------------------------------------------------------===// +// +// Pointer auth info class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H +#define LLVM_CLANG_LIB_CODEGEN_CGPOINTERAUTHINFO_H + +#include "clang/AST/Type.h" +#include "clang/Basic/LangOptions.h" +#include "llvm/IR/Type.h" +#include "llvm/IR/Value.h" + +namespace clang { +namespace CodeGen { + +class CGPointerAuthInfo { +private: + PointerAuthenticationMode AuthenticationMode : 2; + unsigned IsIsaPointer : 1; + unsigned AuthenticatesNullValues : 1; + unsigned Key : 2; + llvm::Value *Discriminator; + +public: + CGPointerAuthInfo() + : AuthenticationMode(PointerAuthenticationMode::None), + IsIsaPointer(false), AuthenticatesNullValues(false), Key(0), + Discriminator(nullptr) {} + CGPointerAuthInfo(unsigned Key, PointerAuthenticationMode AuthenticationMode, + bool IsIsaPointer, bool AuthenticatesNullValues, + llvm::Value *Discriminator) + : AuthenticationMode(AuthenticationMode), IsIsaPointer(IsIsaPointer), + AuthenticatesNullValues(AuthenticatesNullValues), Key(Key), + Discriminator(Discriminator) { + assert(!Discriminator || Discriminator->getType()->isIntegerTy() || + Discriminator->getType()->isPointerTy()); + } + + explicit operator bool() const { return isSigned(); } + + bool isSigned() const { + return AuthenticationMode != PointerAuthenticationMode::None; + } + + unsigned getKey() const { + assert(isSigned()); + return Key; + } + llvm::Value *getDiscriminator() const { + assert(isSigned()); + return Discriminator; + } + + PointerAuthenticationMode getAuthenticationMode() const { + return AuthenticationMode; + } + + bool isIsaPointer() const { return IsIsaPointer; } + + bool authenticatesNullValues() const { return AuthenticatesNullValues; } + + bool shouldStrip() const { + return AuthenticationMode == PointerAuthenticationMode::Strip || + AuthenticationMode == PointerAuthenticationMode::SignAndStrip; + } + + bool shouldSign() const { + return AuthenticationMode == PointerAuthenticationMode::SignAndStrip || + AuthenticationMode == PointerAuthenticationMode::SignAndAuth; + } + + bool shouldAuth() const { + return AuthenticationMode == PointerAuthenticationMode::SignAndAuth; + } + + friend bool operator!=(const CGPointerAuthInfo &LHS, + const CGPointerAuthInfo &RHS) { + return LHS.Key != RHS.Key || LHS.Discriminator != RHS.Discriminator || + LHS.AuthenticationMode != RHS.AuthenticationMode; + } + + friend bool operator==(const CGPointerAuthInfo &LHS, + const CGPointerAuthInfo &RHS) { + return !(LHS != RHS); + } +}; + +} // end namespace CodeGen +} // end namespace clang + +#endif diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 200c40d..650c566 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -861,6 +861,11 @@ void CodeGenFunction::StartFunction(GlobalDecl GD, QualType RetTy, FD->getBody()->getStmtClass() == Stmt::CoroutineBodyStmtClass) SanOpts.Mask &= ~SanitizerKind::Null; + // Add pointer authentication attributes. + const CodeGenOptions &CodeGenOpts = CGM.getCodeGenOpts(); + if (CodeGenOpts.PointerAuth.FunctionPointers) + Fn->addFnAttr("ptrauth-calls"); + // Apply xray attributes to the function (as a string, for now) bool AlwaysXRayAttr = false; if (const auto *XRayAttr = D ? D->getAttr<XRayInstrumentAttr>() : nullptr) { @@ -3042,3 +3047,19 @@ llvm::Value *CodeGenFunction::emitBoolVecConversion(llvm::Value *SrcVec, return Builder.CreateShuffleVector(SrcVec, ShuffleMask, Name); } + +void CodeGenFunction::EmitPointerAuthOperandBundle( + const CGPointerAuthInfo &PointerAuth, + SmallVectorImpl<llvm::OperandBundleDef> &Bundles) { + if (!PointerAuth.isSigned()) + return; + + auto *Key = Builder.getInt32(PointerAuth.getKey()); + + llvm::Value *Discriminator = PointerAuth.getDiscriminator(); + if (!Discriminator) + Discriminator = Builder.getSize(0); + + llvm::Value *Args[] = {Key, Discriminator}; + Bundles.emplace_back("ptrauth", Args); +} diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index cdb5ae66..a9c497b 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -4417,6 +4417,10 @@ public: bool isPointerKnownNonNull(const Expr *E); + void EmitPointerAuthOperandBundle( + const CGPointerAuthInfo &Info, + SmallVectorImpl<llvm::OperandBundleDef> &Bundles); + // Return the copy constructor name with the prefix "__copy_constructor_" // removed. static std::string getNonTrivialCopyConstructorStr(QualType QT, diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h index 04e1a39..99133047 100644 --- a/clang/lib/CodeGen/CodeGenModule.h +++ b/clang/lib/CodeGen/CodeGenModule.h @@ -69,6 +69,7 @@ class Expr; class Stmt; class StringLiteral; class NamedDecl; +class PointerAuthSchema; class ValueDecl; class VarDecl; class LangOptions; @@ -937,6 +938,25 @@ public: // Return the function body address of the given function. llvm::Constant *GetFunctionStart(const ValueDecl *Decl); + /// Return a function pointer for a reference to the given function. + /// This correctly handles weak references, but does not apply a + /// pointer signature. + llvm::Constant *getRawFunctionPointer(GlobalDecl GD, + llvm::Type *Ty = nullptr); + + /// Return the ABI-correct function pointer value for a reference + /// to the given function. This will apply a pointer signature if + /// necessary, caching the result for the given function. + llvm::Constant *getFunctionPointer(GlobalDecl GD, llvm::Type *Ty = nullptr); + + /// Return the ABI-correct function pointer value for a reference + /// to the given function. This will apply a pointer signature if + /// necessary. + llvm::Constant *getFunctionPointer(llvm::Constant *Pointer, + QualType FunctionType); + + CGPointerAuthInfo getFunctionPointerAuthInfo(QualType T); + llvm::Constant * getConstantSignedPointer(llvm::Constant *Pointer, unsigned Key, llvm::Constant *StorageAddress, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index cde4a84..a6d9f42 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1458,6 +1458,29 @@ static void setPGOUseInstrumentor(CodeGenOptions &Opts, Opts.setProfileUse(CodeGenOptions::ProfileClangInstr); } +void CompilerInvocation::setDefaultPointerAuthOptions( + PointerAuthOptions &Opts, const LangOptions &LangOpts, + const llvm::Triple &Triple) { + assert(Triple.getArch() == llvm::Triple::aarch64); + if (LangOpts.PointerAuthCalls) { + using Key = PointerAuthSchema::ARM8_3Key; + using Discrimination = PointerAuthSchema::Discrimination; + // If you change anything here, be sure to update <ptrauth.h>. + Opts.FunctionPointers = + PointerAuthSchema(Key::ASIA, false, Discrimination::None); + } +} + +static void parsePointerAuthOptions(PointerAuthOptions &Opts, + const LangOptions &LangOpts, + const llvm::Triple &Triple, + DiagnosticsEngine &Diags) { + if (!LangOpts.PointerAuthCalls) + return; + + CompilerInvocation::setDefaultPointerAuthOptions(Opts, LangOpts, Triple); +} + void CompilerInvocationBase::GenerateCodeGenArgs(const CodeGenOptions &Opts, ArgumentConsumer Consumer, const llvm::Triple &T, @@ -2153,6 +2176,9 @@ bool CompilerInvocation::ParseCodeGenArgs(CodeGenOptions &Opts, ArgList &Args, Opts.EmitVersionIdentMetadata = Args.hasFlag(OPT_Qy, OPT_Qn, true); + if (!LangOpts->CUDAIsDevice) + parsePointerAuthOptions(Opts.PointerAuth, *LangOpts, T, Diags); + if (Args.hasArg(options::OPT_ffinite_loops)) Opts.FiniteLoops = CodeGenOptions::FiniteLoopsKind::Always; else if (Args.hasArg(options::OPT_fno_finite_loops)) diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h index 6aad9ef..1a4bd02 100644 --- a/clang/lib/Headers/ptrauth.h +++ b/clang/lib/Headers/ptrauth.h @@ -28,6 +28,12 @@ typedef enum { /* A process-specific key which can be used to sign data pointers. */ ptrauth_key_process_dependent_data = ptrauth_key_asdb, + /* The key used to sign C function pointers. + The extra data is always 0. */ + ptrauth_key_function_pointer = ptrauth_key_process_independent_code, + + /* Other pointers signed under the ABI use private ABI rules. */ + } ptrauth_key; /* An integer type of the appropriate size for a discriminator argument. */ @@ -131,6 +137,27 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \ __new_data) +/* Authenticate a pointer using one scheme and resign it as a C + function pointer. + + If the result is subsequently authenticated using the new scheme, that + authentication is guaranteed to fail if and only if the initial + authentication failed. + + The value must be an expression of function pointer type. + The key must be a constant expression of type ptrauth_key. + The extra data must be an expression of pointer or integer type; + if an integer, it will be coerced to ptrauth_extra_data_t. + The result will have the same type as the original value. + + This operation is guaranteed to not leave the intermediate value + available for attack before it is re-signed. Additionally, if this + expression is used syntactically as the function expression in a + call, only a single authentication will be performed. */ +#define ptrauth_auth_function(__value, __old_key, __old_data) \ + ptrauth_auth_and_resign(__value, __old_key, __old_data, \ + ptrauth_key_function_pointer, 0) + /* Authenticate a data pointer. The value must be an expression of non-function pointer type. @@ -217,6 +244,13 @@ typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t; __value; \ }) +#define ptrauth_auth_function(__value, __old_key, __old_data) \ + ({ \ + (void)__old_key; \ + (void)__old_data; \ + __value; \ + }) + #define ptrauth_auth_data(__value, __old_key, __old_data) \ ({ \ (void)__old_key; \ |