Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bring arm64e/ptrauth support to parity with main upstreaming branch #8946

Open
wants to merge 58 commits into
base: next
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
a42c9e5
[InstCombine] Combine ptrauth intrin. callee into ptrauth bundle.
ahmedbougacha Jul 1, 2024
2222706
[InstCombine] Combine ptrauth constant callee into bundle.
ahmedbougacha Sep 27, 2021
295a755
[AArch64][PAC] Lower auth/resign into checked sequence.
ahmedbougacha Jul 1, 2024
68c6fd9
[AArch64] Add FPAC feature.
ahmedbougacha Oct 24, 2022
5241d61
[AArch64][PAC] Don't emit auth/resign checks when targeting FPAC.
ahmedbougacha Oct 24, 2022
07eccf7
[Docs] Describe function attributes.
ahmedbougacha May 31, 2024
c7a9318
[Docs] Update ARMv8.3 -> Armv8.3-A in arm64e arch subtype doc.
ahmedbougacha Sep 27, 2021
d53af57
[AArch64][PAC] Emit LR auth-failure checks on tail-calls.
ahmedbougacha Jul 1, 2024
5fd1d95
[AArch64][PAC] Emit auth call for tlv access thunk function pointer.
ahmedbougacha Sep 27, 2021
50696ce
[AArch64][PAC] Add MachO support for __DATA,__auth_ptr.
ahmedbougacha Jul 2, 2024
97415e5
[AArch64][PAC] Lower ptrauth constants in code for MachO.
ahmedbougacha Jul 2, 2024
20b7973
[AArch64][PAC] Lower direct authenticated calls to ptrauth constants.
ahmedbougacha Jul 2, 2024
dd78f85
[AArch64][PAC] Lower jump-tables using hardened pseudo.
ahmedbougacha Jul 2, 2024
4c35505
[AArch64][PAC] Handle signed LR in outliner.
ahmedbougacha Mar 27, 2023
0223233
[AArch64][PAC] Emit LR auth-failure checks in the outliner.
TNorthover Sep 27, 2021
c324930
[AArch64][PAC] Select auth+load into LDRA*.
ahmedbougacha Jul 31, 2023
c02689b
[AArch64][PAC] Support return address authentication for frame LR.
ahmedbougacha Jul 2, 2024
5443db3
[AArch64][MachO] Support ptrauth ABI version.
ahmedbougacha Sep 27, 2021
602ddb2
[DWARF] Complete __ptrauth type qualifier support with auth mode.
ahmedbougacha Apr 17, 2024
b8bfae4
[IR] Generalize EmitGEPOffset to not need an actual GEP inst.
ahmedbougacha Sep 27, 2021
ee4321f
[clang][CodeGen] Set KnownNonNull in more places.
ahmedbougacha May 15, 2024
d00e742
[clang][CodeGen] Teach RawAddress/Address about ptrauth.
ahmedbougacha Sep 27, 2021
d68f2ea
[clang] Implement function pointer type discrimination
ahmedbougacha Jul 2, 2024
89e80a6
[clang] Resign type-discriminated function pointers on cast.
ahmedbougacha Jun 27, 2024
28887e6
[clang] Define ptrauth_type_discriminator builtin.
ahmedbougacha Jul 3, 2024
fbb7131
[clang] Define ptrauth_function_pointer_type_discriminator macro.
ahmedbougacha May 25, 2024
c349c07
[clang] Implement the __ptrauth type qualifier.
ahmedbougacha Jul 3, 2024
a39ce68
[clang] Implement pointer authentication for C++ member function poin…
ahmedbougacha Jul 3, 2024
eb8fcc2
[clang] Sign function pointers passed to atexit and __cxa_atexit.
ahmedbougacha Jul 3, 2024
bcd6996
[clang] Sign the dtor passed to __cxa_throw as a void(*)(void*) fptr.
ahmedbougacha Jul 3, 2024
ba1a4a4
[clang][Headers] Define ptrauth_nop_cast.
ahmedbougacha May 24, 2024
82fc01b
[clang][docs] Document the ptrauth security model.
ahmedbougacha Jan 8, 2024
27b1458
[clang][docs] Document language ABI.
ahmedbougacha Jun 3, 2024
7de1c08
[clang][docs] Document language features.
ahmedbougacha Jun 3, 2024
dc06f67
[clang][docs] Document __ptrauth qualifier in more depth.
ahmedbougacha Jun 3, 2024
539b539
[clang][docs] Document standard ABI __ptrauth qualifiers.
ahmedbougacha Jun 3, 2024
a76a00b
[AArch64][PAC] Sign block addresses used in indirectbr.
ahmedbougacha Mar 12, 2024
ee58803
[compiler-rt] Support the arm64e architecture in sanitizer runtimes.
ahmedbougacha Aug 7, 2023
1a9cafe
libunwind/libcxxabi/compiler-rt: arm64e exception handling support.
ahmedbougacha Sep 27, 2021
f5c9969
[Coroutines] Support ptrauth.
ahmedbougacha Sep 27, 2021
c8f83cb
[clang] Peephole ptrauth sign/auth/resign builtins of function pointers.
ahmedbougacha Jun 3, 2024
f2776c8
[clang] Strip function pointers in UBSan type checks.
ahmedbougacha May 24, 2024
d994496
[clang][CodeGen] Sign objc atomic property copy helper fn ptrs.
ahmedbougacha May 24, 2024
e32a2df
[clang] Sign the v-table pointer in ObjC exception RTTI.
ahmedbougacha Sep 27, 2021
37d802a
[clang] Implement pointer authentication for blocks.
ahmedbougacha Jun 21, 2024
5cc1cc3
[clang] Implement pointer authentication for ObjC method lists.
ahmedbougacha Jul 3, 2024
539fced
[clang] Add -fptrauth-objc-isa-masking to mask isa ptrs pre/post auth.
ahmedbougacha May 1, 2024
921369f
[clang] Sign objc isa and super pointers.
ahmedbougacha Jul 3, 2024
a44a312
[clang] Implement the ptrauth_struct type attribute.
ahmedbougacha May 1, 2024
c14d38e
[clang] Add __ptrauth macros to ptrauth.h for the arm64e ABI.
ahmedbougacha Jul 3, 2024
9f4fe03
[AArch64] Add -fbranch-target-identification alias to -mbranch-target…
ahmedbougacha May 23, 2024
bb49e42
[clang][Driver] Enable -fptrauth- ABI flags for arm64e-apple-darwin.
ahmedbougacha Jul 3, 2024
9e7c3f7
[clang] Use has_feature ptrauth in Apple Silicon host triple recognit…
ahmedbougacha Sep 27, 2021
f0a40ac
[clang] Annotate Cleanup to support ptrauth vtable diversity.
ahmedbougacha Dec 12, 2023
71c9ac4
Implement SoftPointerAuth prototype.
ahmedbougacha Jul 3, 2024
5675e40
[IR] Autoupgrade llvm.ptrauth globals to ptrauth constant.
ahmedbougacha Mar 19, 2024
99ccc72
[clang] Remove StableHash, now replaced by libSupport SipHash.
ahmedbougacha Jul 3, 2024
878d4f7
[clang] Remove CodeGen:: ptrauth helpers.
ahmedbougacha Jul 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
988 changes: 791 additions & 197 deletions clang/docs/PointerAuthentication.rst

Large diffs are not rendered by default.

48 changes: 45 additions & 3 deletions clang/include/clang/AST/ASTContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
llvm::StringMap<const Module *> PrimaryModuleNameMap;
llvm::DenseMap<const Module *, const Module *> SameModuleLookupSet;

mutable llvm::DenseMap<QualType, bool> ContainsAuthenticatedNullTypes;

/// The include tree that is being built, if any.
/// See \c FrontendOptions::CASIncludeTreeID.
std::optional<std::string> CASIncludeTreeID;
Expand Down Expand Up @@ -1300,14 +1302,54 @@ class ASTContext : public RefCountedBase<ASTContext> {
/// space.
QualType removeAddrSpaceQualType(QualType T) const;

/// Return the "other" type-specific discriminator for the given type.
uint16_t getPointerAuthTypeDiscriminator(QualType T);

/// Return the "other" discriminator used for the pointer auth schema used for
/// vtable pointers in instances of the requested type.
uint16_t
getPointerAuthVTablePointerDiscriminator(const CXXRecordDecl *RD);

/// Return the "other" type-specific discriminator for the given type.
uint16_t getPointerAuthTypeDiscriminator(QualType T);

/// Return the key of attribute ptrauth_struct on the record. If the attribute
/// isn't on the record, return the none key. If the key argument is value
/// dependent, set the boolean flag to false.
std::pair<bool, unsigned> getPointerAuthStructKey(const RecordDecl *RD) const;

/// Return the discriminator of attribute ptrauth_struct on the record. If the
/// key argument is value dependent, set the boolean flag to false.
std::pair<bool, unsigned>
getPointerAuthStructDisc(const RecordDecl *RD) const;

// Determine whether the type can have qualifier __ptrauth with key
// ptrauth_key_none.
bool canQualifyWithPtrAuthKeyNone(QualType T) const {
QualType PointeeType = T->getPointeeType();

if (PointeeType.isNull())
return true;

// Disallow the qualifier on function pointers.
if (PointeeType->isFunctionType())
return false;

// Disallow the qualifer on classes annotated with attribute ptrauth_struct
// with a key that isn't the none key.
if (auto *RD = PointeeType->getAsRecordDecl()) {
std::pair<bool, unsigned> P = getPointerAuthStructKey(RD);
if (P.first && P.second != PointerAuthKeyNone)
return false;
}

return true;
}

bool hasPointerAuthStructMismatch(const RecordDecl *RD0,
const RecordDecl *RD1) const;

bool typeContainsAuthenticatedNull(QualType) const;
bool typeContainsAuthenticatedNull(const Type *) const;
std::optional<bool> tryTypeContainsAuthenticatedNull(QualType) const;

/// Apply Objective-C protocol qualifiers to the given type.
/// \param allowOnPointerType specifies if we can apply protocol
/// qualifiers on ObjCObjectPointerType. It can be set to true when
Expand Down
4 changes: 4 additions & 0 deletions clang/include/clang/AST/CXXRecordDeclDefinitionBits.def
Original file line number Diff line number Diff line change
Expand Up @@ -249,4 +249,8 @@ FIELD(HasDeclaredCopyAssignmentWithConstParam, 1, MERGE_OR)
/// base classes or fields have a no-return destructor
FIELD(IsAnyDestructorNoReturn, 1, NO_MERGE)

/// Whether this class or any of its direct or indirect base classes are
/// annotated with `ptrauth_struct` that uses a key that isn't the none key.
FIELD(HasSignedClassInHierarchy, 1, NO_MERGE)

#undef FIELD
8 changes: 8 additions & 0 deletions clang/include/clang/AST/DeclCXX.h
Original file line number Diff line number Diff line change
Expand Up @@ -1018,6 +1018,14 @@ class CXXRecordDecl : public RecordDecl {
return data().NeedOverloadResolutionForDestructor;
}

bool hasSignedClassInHierarchy() const {
return data().HasSignedClassInHierarchy;
}

void setHasSignedClassInHierarchy() {
data().HasSignedClassInHierarchy = true;
}

/// Determine whether this class describes a lambda function object.
bool isLambda() const {
// An update record can't turn a non-lambda into a lambda.
Expand Down
46 changes: 0 additions & 46 deletions clang/include/clang/AST/StableHash.h

This file was deleted.

2 changes: 1 addition & 1 deletion clang/include/clang/AST/Stmt.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ class alignas(void *) Stmt {
unsigned : NumExprBits;

LLVM_PREFERRED_TYPE(UnaryExprOrTypeTrait)
unsigned Kind : 3;
unsigned Kind : 4;
LLVM_PREFERRED_TYPE(bool)
unsigned IsType : 1; // true if operand is a type, false if an expression.
};
Expand Down
54 changes: 39 additions & 15 deletions clang/include/clang/AST/Type.h
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,11 @@ class PointerAuthQualifier {
AuthenticatesNullValuesBits = 1,
AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
<< AuthenticatesNullValuesShift,
KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
KeyBits = 10,
RestrictedIntegralShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
RestrictedIntegralBits = 1,
RestrictedIntegralMask = ((1 << RestrictedIntegralBits) - 1) << RestrictedIntegralShift,
KeyShift = RestrictedIntegralShift + RestrictedIntegralBits,
KeyBits = 9,
KeyMask = ((1 << KeyBits) - 1) << KeyShift,
DiscriminatorShift = KeyShift + KeyBits,
DiscriminatorBits = 16,
Expand All @@ -175,32 +178,36 @@ class PointerAuthQualifier {

// bits: |0 |1 |2..3 |4 |
// |Enabled|Address|AuthenticationMode|ISA pointer|
// bits: |5 |6..15| 16...31 |
// |AuthenticatesNull|Key |Discriminator|
// bits: |5 |6 |7..15| 16...31 |
// |AuthenticatesNull|RestrictedIntegral|Key |Discriminator|
uint32_t Data = 0;

// The following static assertions check that each of the 32 bits is present
// exactly in one of the constants.
static_assert((EnabledBits + AddressDiscriminatedBits +
AuthenticationModeBits + IsaPointerBits +
AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
AuthenticatesNullValuesBits + RestrictedIntegralBits +
KeyBits + DiscriminatorBits) ==
32,
"PointerAuthQualifier should be exactly 32 bits");
static_assert((EnabledMask + AddressDiscriminatedMask +
AuthenticationModeMask + IsaPointerMask +
AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
AuthenticatesNullValuesMask + RestrictedIntegralMask +
KeyMask + DiscriminatorMask) ==
0xFFFFFFFF,
"All masks should cover the entire bits");
static_assert((EnabledMask ^ AddressDiscriminatedMask ^
AuthenticationModeMask ^ IsaPointerMask ^
AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
AuthenticatesNullValuesMask ^ RestrictedIntegralMask ^
KeyMask ^ DiscriminatorMask) ==
0xFFFFFFFF,
"All masks should cover the entire bits");

PointerAuthQualifier(unsigned Key, bool IsAddressDiscriminated,
unsigned ExtraDiscriminator,
PointerAuthenticationMode AuthenticationMode,
bool IsIsaPointer, bool AuthenticatesNullValues)
bool IsIsaPointer, bool AuthenticatesNullValues,
bool IsRestrictedIntegral)
: Data(EnabledMask |
(IsAddressDiscriminated
? llvm::to_underlying(AddressDiscriminatedMask)
Expand All @@ -210,7 +217,8 @@ class PointerAuthQualifier {
<< AuthenticationModeShift) |
(ExtraDiscriminator << DiscriminatorShift) |
(IsIsaPointer << IsaPointerShift) |
(AuthenticatesNullValues << AuthenticatesNullValuesShift)) {
(AuthenticatesNullValues << AuthenticatesNullValuesShift) |
(IsRestrictedIntegral << RestrictedIntegralShift)) {
assert(Key <= KeyNoneInternal);
assert(ExtraDiscriminator <= MaxDiscriminator);
assert((Data == 0) ==
Expand All @@ -234,13 +242,13 @@ class PointerAuthQualifier {
static PointerAuthQualifier
Create(unsigned Key, bool IsAddressDiscriminated, unsigned ExtraDiscriminator,
PointerAuthenticationMode AuthenticationMode, bool IsIsaPointer,
bool AuthenticatesNullValues) {
bool AuthenticatesNullValues, bool IsRestrictedIntegral) {
if (Key == PointerAuthKeyNone)
Key = KeyNoneInternal;
assert(Key <= KeyNoneInternal && "out-of-range key value");
return PointerAuthQualifier(Key, IsAddressDiscriminated, ExtraDiscriminator,
AuthenticationMode, IsIsaPointer,
AuthenticatesNullValues);
AuthenticatesNullValues, IsRestrictedIntegral);
}

bool isPresent() const {
Expand Down Expand Up @@ -287,6 +295,10 @@ class PointerAuthQualifier {
return hasKeyNone() ? PointerAuthQualifier() : *this;
}

bool isRestrictedIntegral() const {
return (Data & RestrictedIntegralMask) >> RestrictedIntegralShift;
}

friend bool operator==(PointerAuthQualifier Lhs, PointerAuthQualifier Rhs) {
return Lhs.Data == Rhs.Data;
}
Expand Down Expand Up @@ -828,17 +840,18 @@ class Qualifiers {
static_assert(sizeof(PointerAuthQualifier) == sizeof(uint32_t),
"PointerAuthQualifier must be 32 bits");

static constexpr uint64_t PtrAuthShift = 32;
static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;

static constexpr uint64_t UMask = 0x8;
static constexpr uint64_t UShift = 3;
static constexpr uint64_t GCAttrMask = 0x30;
static constexpr uint64_t GCAttrShift = 4;
static constexpr uint64_t LifetimeMask = 0x1C0;
static constexpr uint64_t LifetimeShift = 6;
static constexpr uint64_t AddressSpaceShift = 9;
static constexpr uint64_t PtrAuthShift = 32;
static constexpr uint64_t PtrAuthMask = uint64_t(0xffffffff) << PtrAuthShift;
static constexpr uint64_t AddressSpaceMask =
~(CVRMask | UMask | GCAttrMask | LifetimeMask | PtrAuthMask);
static constexpr uint64_t AddressSpaceShift = 9;
};

class QualifiersAndAtomic {
Expand Down Expand Up @@ -1477,7 +1490,7 @@ class QualType {
}

bool hasAddressDiscriminatedPointerAuth() const {
if (auto ptrauth = getPointerAuth())
if (auto ptrauth = getPointerAuth().withoutKeyNone())
return ptrauth.isAddressDiscriminated();
return false;
}
Expand Down Expand Up @@ -2530,6 +2543,9 @@ class alignas(TypeAlignment) Type : public ExtQualsTypeCommonBase {
bool isFunctionNoProtoType() const { return getAs<FunctionNoProtoType>(); }
bool isFunctionProtoType() const { return getAs<FunctionProtoType>(); }
bool isPointerType() const;
bool isSignableType(const ASTContext &Ctx) const;
bool isSignablePointerType() const;
bool isSignableIntegerType(const ASTContext &Ctx) const;
bool isAnyPointerType() const; // Any C pointer or ObjC object pointer
bool isCountAttributedType() const;
bool isBlockPointerType() const;
Expand Down Expand Up @@ -8019,6 +8035,14 @@ inline bool Type::isAnyPointerType() const {
return isPointerType() || isObjCObjectPointerType();
}

inline bool Type::isSignableType(const ASTContext &Ctx) const {
return isSignablePointerType() || isSignableIntegerType(Ctx);
}

inline bool Type::isSignablePointerType() const {
return isPointerType() || isObjCClassType() || isObjCQualifiedClassType();
}

inline bool Type::isBlockPointerType() const {
return isa<BlockPointerType>(CanonicalType);
}
Expand Down
13 changes: 11 additions & 2 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -3326,13 +3326,22 @@ def ObjCRequiresPropertyDefs : InheritableAttr {
}

def PointerAuth : TypeAttr {
let Spellings = [CustomKeyword<"__ptrauth">];
let Spellings = [CustomKeyword<"__ptrauth">,
CustomKeyword<"__ptrauth_restricted_intptr">];
let Args = [IntArgument<"Key">,
BoolArgument<"AddressDiscriminated", 1>,
IntArgument<"ExtraDiscriminator", 1>];
IntArgument<"ExtraDiscriminator", 1>,
StringArgument<"AuthenticationMode", 1>];
let Documentation = [PtrAuthDocs];
}

def PointerAuthStruct : InheritableAttr {
let Spellings = [Clang<"ptrauth_struct">];
let Args = [ExprArgument<"Key">, ExprArgument<"Discriminator">];
let Subjects = SubjectList<[Record]>;
let Documentation = [PointerAuthStructDocs];
}

def Unused : InheritableAttr {
let Spellings = [CXX11<"", "maybe_unused", 201603>, GCC<"unused">,
C23<"", "maybe_unused", 202106>];
Expand Down
42 changes: 42 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -1760,6 +1760,7 @@ Also see the documentation for `@available

def PtrAuthDocs : Documentation {
let Category = DocCatVariable;
let Heading = "__ptrauth, __ptrauth_restricted_intptr";
let Content = [{
The ``__ptrauth`` qualifier allows the programmer to directly control
how pointers are signed when they are stored in a particular variable.
Expand Down Expand Up @@ -1917,6 +1918,47 @@ features that implicitly use pointer authentication.
}];
}

def PointerAuthStructDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
The ``ptrauth_struct`` attribute allows programmers to opt in to using signed
pointers for all pointers to a particular struct, union, or C++ class type. In
C++, this also includes references to the type.

The attribute takes two arguments:

- The first argument is the abstract signing key, which should be a constant
from ``<ptrauth.h>``.
- The second argument is a constant discriminator.

These arguments are identical to the arguments to the ``__ptrauth`` qualifier
except that ``ptrauth_struct`` does not take an argument for enabling address
diversity.

.. code-block:: c++

// key=ptrauth_key_process_dependent_data,discriminator=100
struct __attribute__((ptrauth_struct(ptrauth_key_process_dependent_data,100))) S0 {
int f0[4];
};

If a particular pointer to the type is qualified with a ``__ptrauth`` qualifier,
that qualifier takes precedence over ptrauth_struct:

.. code-block:: c++

struct __attribute__((ptrauth_struct(ptrauth_key_process_dependent_data,100))) S0 {
int f0[4];
};

void test(S0 *s0) {
// `p` is signed using `__ptrauth(ptrauth_key_process_dependent_data, 1, 200)`.
S0 * __ptrauth(ptrauth_key_process_dependent_data, 1, 200) p = s0;
}

}];
}

def ExternalSourceSymbolDocs : Documentation {
let Category = DocCatDecl;
let Content = [{
Expand Down
Loading