Skip to content

Commit 58d86bc

Browse files
committed
arm64e/ptrauth: objc isa signing.
1 parent 77f4db4 commit 58d86bc

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+917
-51
lines changed

clang/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,8 @@ option(CLANG_ENABLE_ARCMT "Build ARCMT." ON)
410410
option(CLANG_ENABLE_STATIC_ANALYZER
411411
"Include static analyzer in clang binary." ON)
412412

413+
option(CLANG_ENABLE_PTRAUTH_OBJC_ISA "Objc isa/super pointer authentication for clang/ptrauth.h: when enabled, can default to sign-and-strip or sign-and-auth based on target" OFF)
414+
413415
option(CLANG_ENABLE_PROTO_FUZZER "Build Clang protobuf fuzzer." OFF)
414416

415417
if(NOT CLANG_ENABLE_STATIC_ANALYZER AND CLANG_ENABLE_ARCMT)

clang/docs/PointerAuthentication.rst

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ It is possible to tweak the behaviour of pointer authentication using the `optio
108108

109109
- authentication mode: ``strip``, ``sign-and-strip``, ``sign-and-auth``. These control whether authentication codes are ignored completely (``strip``), whether values are signed but not authenticated (``sign-and-strip``), or the default of full authentication (``sign-and-auth``).
110110

111+
- ``isa-pointer``: This is used to indicate that the target value is an Objective-C isa pointer, and needs to mask out objective-c tag bits prior to signing or authenticating the value.
112+
111113
- ``authenticates-null-values``: Enables full signing and authentication of null values. The default behaviour of pointer authentication is to not sign or authenticate null values. This option ensures that all values, including null values, will always be signed and authenticated.
112114

113115
.. _Signing schemas:
@@ -814,7 +816,10 @@ Objective-C method lists sign methods with the ``IA`` key using address diversit
814816

815817
The Objective-C runtime provides additional protection to methods that have been loaded into the Objective-C method cache; this protection is private to the runtime.
816818

817-
Pointer authentication cannot protect against access-path atacks against the Objective-C ``isa`` pointer, through which all dispatch occurs, because of compatibility requirements and existing and important usage of high bits in the pointer.
819+
Objective-C ``isa`` and ``super`` pointers
820+
~~~~~~~~~~~~~~~~~~~~~~~~
821+
822+
Objective-C ``isa`` and ``super`` pointers are both signed with the ``DA`` key with constant discriminators of 0x6AE1 and 0x25DA respectively.
818823

819824
Swift class methods
820825
~~~~~~~~~~~~~~~~~~~

clang/include/clang/AST/Type.h

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -153,47 +153,51 @@ class PointerAuthQualifier {
153153
AuthenticationModeBits = 2,
154154
AuthenticationModeMask = ((1 << AuthenticationModeBits) - 1)
155155
<< AuthenticationModeShift,
156-
AuthenticatesNullValuesShift = AuthenticationModeShift + AuthenticationModeBits,
156+
IsaPointerShift = AuthenticationModeShift + AuthenticationModeBits,
157+
IsaPointerBits = 1,
158+
IsaPointerMask = ((1 << IsaPointerBits) - 1) << IsaPointerShift,
159+
AuthenticatesNullValuesShift = IsaPointerShift + IsaPointerBits,
157160
AuthenticatesNullValuesBits = 1,
158161
AuthenticatesNullValuesMask = ((1 << AuthenticatesNullValuesBits) - 1)
159162
<< AuthenticatesNullValuesShift,
160163
KeyShift = AuthenticatesNullValuesShift + AuthenticatesNullValuesBits,
161-
KeyBits = 11,
164+
KeyBits = 10,
162165
KeyMask = ((1 << KeyBits) - 1) << KeyShift,
163166
DiscriminatorShift = KeyShift + KeyBits,
164167
DiscriminatorBits = 16,
165168
DiscriminatorMask = ((1 << DiscriminatorBits) - 1) << DiscriminatorShift,
166169
};
167170

168-
// bits: |0 |1 |2..3 |4 |5..15| 16...31 |
169-
// |Enabled|Address|AuthenticationMode|AuthenticatesNull|Key |Discriminator|
171+
// bits: |0 |1 |2..3 |4 |5 |6..15| 16...31 |
172+
// |Enabled|Address|AuthenticationMode|ISA pointer|AuthenticatesNull|Key |Discriminator|
170173
uint32_t Data;
171174

172175
static_assert((EnabledBits + AddressDiscriminatedBits +
173-
AuthenticationModeBits + KeyBits +
174-
AuthenticatesNullValuesBits + DiscriminatorBits) ==
176+
AuthenticationModeBits + IsaPointerBits +
177+
AuthenticatesNullValuesBits + KeyBits + DiscriminatorBits) ==
175178
32,
176179
"PointerAuthQualifier should be exactly 32 bits");
177180
static_assert((EnabledMask + AddressDiscriminatedMask +
178-
AuthenticationModeMask + KeyMask +
179-
AuthenticatesNullValuesMask + DiscriminatorMask) ==
181+
AuthenticationModeMask + IsaPointerMask +
182+
AuthenticatesNullValuesMask + KeyMask + DiscriminatorMask) ==
180183
0xFFFFFFFF,
181184
"All masks should cover the entire bits");
182185
static_assert((EnabledMask ^ AddressDiscriminatedMask ^
183-
AuthenticationModeMask ^ KeyMask ^
184-
AuthenticatesNullValuesMask ^ DiscriminatorMask) ==
186+
AuthenticationModeMask ^ IsaPointerMask ^
187+
AuthenticatesNullValuesMask ^ KeyMask ^ DiscriminatorMask) ==
185188
0xFFFFFFFF,
186189
"All masks should cover the entire bits");
187190

188191
PointerAuthQualifier(unsigned key, bool isAddressDiscriminated,
189192
unsigned extraDiscriminator,
190193
PointerAuthenticationMode authenticationMode,
191-
bool authenticatesNullValues)
194+
bool isIsaPointer, bool authenticatesNullValues)
192195
: Data(EnabledMask |
193196
(isAddressDiscriminated ? AddressDiscriminatedMask : 0) |
194197
(key << KeyShift) |
195198
(unsigned(authenticationMode) << AuthenticationModeShift) |
196199
(extraDiscriminator << DiscriminatorShift) |
200+
(isIsaPointer << IsaPointerShift) |
197201
(authenticatesNullValues << AuthenticatesNullValuesShift)) {
198202
assert(key <= KeyNoneInternal);
199203
assert(extraDiscriminator <= MaxDiscriminator);
@@ -215,13 +219,13 @@ class PointerAuthQualifier {
215219

216220
static PointerAuthQualifier
217221
Create(int key, bool isAddressDiscriminated, unsigned extraDiscriminator,
218-
PointerAuthenticationMode authenticationMode,
222+
PointerAuthenticationMode authenticationMode, bool isIsaPointer,
219223
bool authenticatesNullValues) {
220224
if (key == PointerAuthKeyNone)
221225
key = KeyNoneInternal;
222226
assert((key >= 0 && key <= KeyNoneInternal) && "out-of-range key value");
223227
return PointerAuthQualifier(key, isAddressDiscriminated, extraDiscriminator,
224-
authenticationMode,
228+
authenticationMode, isIsaPointer,
225229
authenticatesNullValues);
226230
}
227231

@@ -255,6 +259,11 @@ class PointerAuthQualifier {
255259
AuthenticationModeShift);
256260
}
257261

262+
bool isIsaPointer() const {
263+
assert(isPresent());
264+
return (Data & IsaPointerMask) >> IsaPointerShift;
265+
}
266+
258267
bool authenticatesNullValues() const {
259268
assert(isPresent());
260269
return (Data & AuthenticatesNullValuesMask) >> AuthenticatesNullValuesShift;

clang/include/clang/Basic/Features.def

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ FEATURE(ptrauth_qualifier, LangOpts.PointerAuthIntrinsics)
104104
FEATURE(ptrauth_qualifier_authentication_mode, LangOpts.PointerAuthIntrinsics)
105105
FEATURE(ptrauth_restricted_intptr_qualifier, LangOpts.PointerAuthIntrinsics)
106106
FEATURE(ptrauth_calls, LangOpts.PointerAuthCalls)
107+
// While we deploy phases, ptrauth_objc_isa is equivalent to ptrauth_objc_isa_signs, i.e., phase 1 or 2.
108+
// Long-term, it is intended to be the only feature, once we can get rid of phases.
109+
FEATURE(ptrauth_objc_isa, LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::SignAndStrip || LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::SignAndAuth)
110+
FEATURE(ptrauth_objc_isa_strips, LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::Strip || LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::SignAndStrip)
111+
FEATURE(ptrauth_objc_isa_signs, LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::SignAndStrip || LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::SignAndAuth)
112+
FEATURE(ptrauth_objc_isa_authenticates, LangOpts.getPointerAuthObjcIsaAuthentication() == PointerAuthenticationMode::SignAndAuth)
107113
FEATURE(ptrauth_objc_signable_class, true)
108114
FEATURE(ptrauth_objc_method_list_pointer, LangOpts.PointerAuthCalls)
109115
FEATURE(ptrauth_vtable_pointer_address_discrimination, LangOpts.PointerAuthVTPtrAddressDiscrimination)
@@ -112,6 +118,7 @@ FEATURE(ptrauth_returns, LangOpts.PointerAuthReturns)
112118
FEATURE(ptrauth_member_function_pointer_type_discrimination, LangOpts.PointerAuthCalls)
113119
FEATURE(ptrauth_function_pointer_type_discrimination, LangOpts.FunctionPointerTypeDiscrimination)
114120
FEATURE(ptrauth_signed_block_descriptors, LangOpts.PointerAuthBlockDescriptorPointers)
121+
FEATURE(ptrauth_objc_isa_masking, LangOpts.PointerAuthObjcIsaMasking)
115122
FEATURE(swiftasynccc,
116123
PP.getTargetInfo().checkCallingConvention(CC_SwiftAsync) ==
117124
clang::TargetInfo::CCCR_OK)

clang/include/clang/Basic/LangOptions.def

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@ LANGOPT(PointerAuthReturns, 1, 0, "return pointer authentication")
166166
LANGOPT(PointerAuthAuthTraps, 1, 0, "pointer authentication failure traps")
167167
LANGOPT(PointerAuthVTPtrAddressDiscrimination, 1, 0, "incorporate address discrimination in authenticated vtable pointers")
168168
LANGOPT(PointerAuthVTPtrTypeDiscrimination, 1, 0, "incorporate type discrimination in authenticated vtable pointers")
169+
ENUM_LANGOPT(PointerAuthObjcIsaAuthentication, PointerAuthenticationMode, 2,
170+
PointerAuthenticationMode::None, "authentication mode for objc isa")
171+
LANGOPT(PointerAuthObjcIsaMasking, 1, 0, "pre- and post-authentication masking for Objective-C isa pointer")
169172
LANGOPT(SoftPointerAuth , 1, 0, "software emulation of pointer authentication")
170173
LANGOPT(PointerAuthBlockDescriptorPointers, 1, 0, "enable signed block descriptors")
171174
VALUE_LANGOPT(PointerAuthABIVersion, 32, 0, "pointer authentication ABI version")

clang/include/clang/Basic/LangOptions.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@ static constexpr llvm::StringLiteral PointerAuthenticationOptionSignAndStrip =
4242
"sign-and-strip";
4343
static constexpr llvm::StringLiteral PointerAuthenticationOptionSignAndAuth =
4444
"sign-and-auth";
45+
static constexpr llvm::StringLiteral PointerAuthenticationOptionIsaPointer =
46+
"isa-pointer";
4547
static constexpr llvm::StringLiteral
4648
PointerAuthenticationOptionAuthenticatesNullValues =
4749
"authenticates-null-values";

clang/include/clang/Basic/PointerAuthOptions.h

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,14 @@ namespace clang {
2929
/// ptrauth_string_discriminator("method_list_t")
3030
constexpr uint16_t MethodListPointerConstantDiscriminator = 0xC310;
3131

32+
/// Constant discriminator to be used with objective-c isa pointers. The value
33+
/// is ptrauth_string_discriminator("isa")
34+
constexpr uint16_t IsaPointerConstantDiscriminator = 0x6AE1;
35+
36+
/// Constant discriminator to be used with objective-c superclass pointers.
37+
/// The value is ptrauth_string_discriminator("objc_class:superclass")
38+
constexpr uint16_t SuperPointerConstantDiscriminator = 0xB5AB;
39+
3240
/// Constant discriminator to be used with block descriptor pointers. The value
3341
/// is ptrauth_string_discriminator("block_descriptor")
3442
constexpr uint16_t BlockDescriptorConstantDiscriminator = 0xC0BB;
@@ -54,7 +62,8 @@ class PointerAuthSchema {
5462
CXXVirtualFunctionPointers = 5,
5563
CXXMemberFunctionPointers = 6,
5664
ObjCMethodListPointer = 7,
57-
BlockDescriptorPointers = 8,
65+
ObjCIsaPointer = 8,
66+
BlockDescriptorPointers = 9,
5867
};
5968

6069
/// Hardware pointer-signing keys in ARM8.3.
@@ -85,6 +94,7 @@ class PointerAuthSchema {
8594
private:
8695
Kind TheKind : 2;
8796
unsigned IsAddressDiscriminated : 1;
97+
unsigned IsIsaPointer : 1;
8898
unsigned AuthenticatesNullValues : 1;
8999
PointerAuthenticationMode SelectedAuthenticationMode : 2;
90100
Discrimination DiscriminationKind : 2;
@@ -98,8 +108,10 @@ class PointerAuthSchema {
98108
PointerAuthenticationMode authenticationMode,
99109
Discrimination otherDiscrimination,
100110
std::optional<uint16_t> constantDiscriminator = std::nullopt,
111+
bool isIsaPointer = false,
101112
bool authenticatesNullValues = false)
102113
: TheKind(Kind::Soft), IsAddressDiscriminated(isAddressDiscriminated),
114+
IsIsaPointer(isIsaPointer),
103115
AuthenticatesNullValues(authenticatesNullValues),
104116
SelectedAuthenticationMode(authenticationMode),
105117
DiscriminationKind(otherDiscrimination), Key(unsigned(key)) {
@@ -114,8 +126,10 @@ class PointerAuthSchema {
114126
PointerAuthenticationMode authenticationMode,
115127
Discrimination otherDiscrimination,
116128
std::optional<uint16_t> constantDiscriminator = std::nullopt,
129+
bool isIsaPointer = false,
117130
bool authenticatesNullValues = false)
118131
: TheKind(Kind::ARM8_3), IsAddressDiscriminated(isAddressDiscriminated),
132+
IsIsaPointer(isIsaPointer),
119133
AuthenticatesNullValues(authenticatesNullValues),
120134
SelectedAuthenticationMode(authenticationMode),
121135
DiscriminationKind(otherDiscrimination), Key(unsigned(key)) {
@@ -134,16 +148,17 @@ class PointerAuthSchema {
134148
: PointerAuthSchema(key, isAddressDiscriminated,
135149
PointerAuthenticationMode::SignAndAuth,
136150
otherDiscrimination, constantDiscriminator,
137-
authenticatesNullValues) {}
151+
isIsaPointer, authenticatesNullValues) {}
138152

139153
PointerAuthSchema(ARM8_3Key key, bool isAddressDiscriminated,
140154
Discrimination otherDiscrimination,
141155
std::optional<uint16_t> constantDiscriminator = std::nullopt,
156+
bool isIsaPointer = false,
142157
bool authenticatesNullValues = false)
143158
: PointerAuthSchema(key, isAddressDiscriminated,
144159
PointerAuthenticationMode::SignAndAuth,
145160
otherDiscrimination, constantDiscriminator,
146-
authenticatesNullValues) {}
161+
isIsaPointer, authenticatesNullValues) {}
147162

148163
Kind getKind() const { return TheKind; }
149164

@@ -156,6 +171,11 @@ class PointerAuthSchema {
156171
return IsAddressDiscriminated;
157172
}
158173

174+
bool isIsaPointer() const {
175+
assert(getKind() != Kind::None);
176+
return IsIsaPointer;
177+
}
178+
159179
bool authenticatesNullValues() const {
160180
assert(getKind() != Kind::None);
161181
return AuthenticatesNullValues;
@@ -251,6 +271,12 @@ struct PointerAuthOptions {
251271

252272
/// The ABI for C++ member function pointers.
253273
PointerAuthSchema CXXMemberFunctionPointers;
274+
275+
/// The ABI for Objective-C isa pointers.
276+
PointerAuthSchema ObjCIsaPointers;
277+
278+
/// The ABI for Objective-C superclass pointers.
279+
PointerAuthSchema ObjCSuperPointers;
254280
};
255281

256282
} // end namespace clang

clang/include/clang/Config/config.h.cmake

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@
7474
#cmakedefine01 CLANG_ENABLE_OBJC_REWRITER
7575
#cmakedefine01 CLANG_ENABLE_STATIC_ANALYZER
7676

77+
/* Enable objc isa signing ptrauth driver support, based on deployment target */
78+
#cmakedefine01 CLANG_ENABLE_PTRAUTH_OBJC_ISA
79+
7780
/* Spawn a new process clang.exe for the CC1 tool invocation, when necessary */
7881
#cmakedefine01 CLANG_SPAWN_CC1
7982

clang/include/clang/Driver/Options.td

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3893,6 +3893,12 @@ let Group = f_Group in {
38933893
HelpText<"enable signing block descriptors">;
38943894
def fptrauth_function_pointer_type_discrimination : Flag<["-"], "fptrauth-function-pointer-type-discrimination">,
38953895
HelpText<"Enabling type discrimination on C function pointers">;
3896+
def fptrauth_objc_isa : Flag<["-"], "fptrauth-objc-isa">,
3897+
HelpText<"Enable signing and authentication of Objective-C object's 'isa' field">;
3898+
def fptrauth_objc_isa_mode : Joined<["-"], "fptrauth-objc-isa-mode=">,
3899+
HelpText<"Authentication mode for ObjC isa field. Full auth if unspecified">, Values<"strip,sign-and-strip,sign-and-auth">;
3900+
def fptrauth_objc_isa_masking : Flag<["-"], "fptrauth-objc-isa-masking">,
3901+
HelpText<"pre- and post-authentication masking mode of objective-c isa pointers">;
38963902
}
38973903
def fno_ptrauth_intrinsics : Flag<["-"], "fno-ptrauth-intrinsics">;
38983904
def fno_ptrauth_calls : Flag<["-"], "fno-ptrauth-calls">;
@@ -3901,6 +3907,7 @@ let Group = f_Group in {
39013907
def fno_ptrauth_vtable_pointer_address_discrimination : Flag<["-"], "fno-ptrauth-vtable-pointer-address-discrimination">;
39023908
def fno_ptrauth_vtable_pointer_type_discrimination : Flag<["-"], "fno-ptrauth-vtable-pointer-type-discrimination">;
39033909
def fno_ptrauth_soft : Flag<["-"], "fno-ptrauth-soft">;
3910+
def fno_ptrauth_objc_isa : Flag<["-"], "fno-ptrauth-objc-isa">;
39043911
def fno_ptrauth_block_descriptor_pointers : Flag<["-"], "fno-ptrauth-block-descriptor-pointers">;
39053912
def fno_ptrauth_function_pointer_type_discrimination : Flag<["-"], "fno-ptrauth-function-pointer-type-discrimination">;
39063913
}

clang/lib/AST/TypePrinter.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2311,6 +2311,13 @@ void PointerAuthQualifier::print(raw_ostream &OS,
23112311
default:
23122312
break;
23132313
}
2314+
if (isIsaPointer()) {
2315+
if (hasOptions)
2316+
StrOS << ",";
2317+
StrOS << PointerAuthenticationOptionIsaPointer;
2318+
hasOptions = true;
2319+
}
2320+
23142321
if (authenticatesNullValues()) {
23152322
if (hasOptions)
23162323
StrOS << ",";

0 commit comments

Comments
 (0)