clang 24.0.0git
ptrauth.h
Go to the documentation of this file.
1/*===---- ptrauth.h - Pointer authentication -------------------------------===
2 *
3 * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 * See https://llvm.org/LICENSE.txt for license information.
5 * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 *
7 *===-----------------------------------------------------------------------===
8 */
9
10#ifndef __PTRAUTH_H
11#define __PTRAUTH_H
12
13typedef enum {
18
19 /* A process-independent key which can be used to sign code pointers. */
21
22 /* A process-specific key which can be used to sign code pointers. */
24
25 /* A process-independent key which can be used to sign data pointers. */
27
28 /* A process-specific key which can be used to sign data pointers. */
30
31 /* The key used to sign return addresses on the stack.
32 The extra data is based on the storage address of the return address.
33 On AArch64, that is always the storage address of the return address + 8
34 (or, in other words, the value of the stack pointer on function entry) */
36
37 /* The key used to sign C function pointers.
38 The extra data is always 0. */
40
41 /* The key used to sign pointers to C++ v-tables. */
43
44 /* The key used to sign metadata pointers to Objective-C method-lists. */
46
47 /* The key used to sign Objective-C isa and super pointers. */
50
51 /* The key used to sign selector pointers */
53
54 /* The key used to sign Objective-C class_ro_t pointers. */
56
57 /* The key used to sign pointers in ELF .init_array/.fini_array. */
59
60 /* Other pointers signed under the ABI use private ABI rules. */
61
63
64/* An integer type of the appropriate size for a discriminator argument. */
65typedef __UINTPTR_TYPE__ ptrauth_extra_data_t;
66
67/* An integer type of the appropriate size for a generic signature. */
68typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
69
70/* A signed pointer value embeds the original pointer together with
71 a signature that attests to the validity of that pointer. Because
72 this signature must use only "spare" bits of the pointer, a
73 signature's validity is probabilistic in practice: it is unlikely
74 but still plausible that an invalidly-derived signature will
75 somehow equal the correct signature and therefore successfully
76 authenticate. Nonetheless, this scheme provides a strong degree
77 of protection against certain kinds of attacks. */
78
79/* Authenticating a pointer that was not signed with the given key
80 and extra-data value will (likely) fail by trapping. */
81
82/* The null function pointer is always the all-zero bit pattern.
83 Signing an all-zero bit pattern will embed a (likely) non-zero
84 signature in the result, and so the result will not seem to be
85 a null function pointer. Authenticating this value will yield
86 a null function pointer back. However, authenticating an
87 all-zero bit pattern will probably fail, because the
88 authentication will expect a (likely) non-zero signature to
89 embedded in the value.
90
91 Because of this, if a pointer may validly be null, you should
92 check for null before attempting to authenticate it with one
93 of these intrinsics. This is not necessary when using the
94 __ptrauth qualifier; the compiler will perform this check
95 automatically. */
96
97#if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__)
98
99/* Strip the signature from a value without authenticating it.
100
101 If the value is a function pointer, the result will not be a
102 legal function pointer because of the missing signature, and
103 attempting to call it will result in an authentication failure.
104
105 The value must be an expression of pointer type.
106 The key must be a constant expression of type ptrauth_key.
107 The result will have the same type as the original value. */
108#define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key)
109
110/* Blend a constant discriminator into the given pointer-like value
111 to form a new discriminator. Not all bits of the inputs are
112 guaranteed to contribute to the result.
113
114 On arm64e, the integer must fall within the range of a uint16_t;
115 other bits may be ignored.
116
117 For the purposes of ptrauth_sign_constant, the result of calling
118 this function is considered a constant expression if the arguments
119 are constant. Some restrictions may be imposed on the pointer.
120
121 The first argument must be an expression of pointer type.
122 The second argument must be an expression of integer type.
123 The result will have type uintptr_t. */
124#define ptrauth_blend_discriminator(__pointer, __integer) \
125 __builtin_ptrauth_blend_discriminator(__pointer, __integer)
126
127/* Return a signed pointer for a constant address in a manner which guarantees
128 a non-attackable sequence.
129
130 The value must be a constant expression of pointer type which evaluates to
131 a non-null pointer.
132 The key must be a constant expression of type ptrauth_key.
133 The extra data must be a constant expression of pointer or integer type;
134 if an integer, it will be coerced to ptrauth_extra_data_t.
135 The result will have the same type as the original value.
136
137 This can be used in constant expressions. */
138#define ptrauth_sign_constant(__value, __key, __data) \
139 __builtin_ptrauth_sign_constant(__value, __key, __data)
140
141/* Add a signature to the given pointer value using a specific key,
142 using the given extra data as a salt to the signing process.
143
144 This operation does not authenticate the original value and is
145 therefore potentially insecure if an attacker could possibly
146 control that value.
147
148 The value must be an expression of pointer type.
149 The key must be a constant expression of type ptrauth_key.
150 The extra data must be an expression of pointer or integer type;
151 if an integer, it will be coerced to ptrauth_extra_data_t.
152 The result will have the same type as the original value. */
153#define ptrauth_sign_unauthenticated(__value, __key, __data) \
154 __builtin_ptrauth_sign_unauthenticated(__value, __key, __data)
155
156/* Authenticate a pointer using one scheme and resign it using another.
157
158 If the result is subsequently authenticated using the new scheme, that
159 authentication is guaranteed to fail if and only if the initial
160 authentication failed.
161
162 The value must be an expression of pointer type.
163 The key must be a constant expression of type ptrauth_key.
164 The extra data must be an expression of pointer or integer type;
165 if an integer, it will be coerced to ptrauth_extra_data_t.
166 The result will have the same type as the original value.
167
168 This operation is guaranteed to not leave the intermediate value
169 available for attack before it is re-signed.
170
171 Do not pass a null pointer to this function. A null pointer
172 will not successfully authenticate.
173
174 This operation traps if the authentication fails. */
175#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
176 __new_data) \
177 __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
178 __new_data)
179
180/* Authenticate a pointer using a PC-based signature scheme and resign
181 it using a different scheme.
182
183 If the result is subsequently authenticated using the new scheme, that
184 authentication is guaranteed to fail if and only if the initial
185 authentication failed.
186
187 The value must be an expression of pointer type.
188 The key must be a constant expression of type ptrauth_key.
189 The extra data must be an expression of pointer or integer type;
190 if an integer, it will be coerced to ptrauth_extra_data_t.
191 The oldpc must be an expression of pointer or integer type representing
192 the PC value where the original signature was created.
193 The result will have the same type as the original value.
194
195 This operation is guaranteed to not leave the intermediate value
196 available for attack before it is re-signed.
197
198 Do not pass a null pointer to this function. A null pointer
199 will not successfully authenticate. */
200#define ptrauth_auth_with_pc_and_resign(__value, __old_key, __old_data, \
201 __old_pc, __new_key, __new_data) \
202 __builtin_ptrauth_auth_with_pc_and_resign(__value, __old_key, __old_data, \
203 __old_pc, __new_key, __new_data)
204
205/* Authenticate a pointer using one scheme, load 32bit value at offset addend
206 from the pointer, and add this value to the pointer, sign using specified
207 scheme.
208
209 If the result is subsequently authenticated using the new scheme, that
210 authentication is guaranteed to fail if and only if the initial
211 authentication failed.
212
213 The value must be an expression of pointer type.
214 The key must be a constant expression of type ptrauth_key.
215 The extra data must be an expression of pointer or integer type;
216 if an integer, it will be coerced to ptrauth_extra_data_t.
217 The addend must be an immediate ptrdiff_t value.
218 The result will have the same type as the original value.
219
220 This operation is guaranteed to not leave the intermediate value
221 available for attack before it is re-signed.
222
223 Do not pass a null pointer to this function. A null pointer
224 will not successfully authenticate. */
225#define ptrauth_auth_load_relative_and_sign(__value, __old_key, __old_data, \
226 __new_key, __new_data, __offset) \
227 __builtin_ptrauth_auth_load_relative_and_sign( \
228 __value, __old_key, __old_data, __new_key, __new_data, __offset)
229
230/* Authenticate a pointer using one scheme and resign it as a C
231 function pointer.
232
233 If the result is subsequently authenticated using the new scheme, that
234 authentication is guaranteed to fail if and only if the initial
235 authentication failed.
236
237 The value must be an expression of function pointer type.
238 The key must be a constant expression of type ptrauth_key.
239 The extra data must be an expression of pointer or integer type;
240 if an integer, it will be coerced to ptrauth_extra_data_t.
241 The result will have the same type as the original value.
242
243 This operation is guaranteed to not leave the intermediate value
244 available for attack before it is re-signed. Additionally, if this
245 expression is used syntactically as the function expression in a
246 call, only a single authentication will be performed. */
247#define ptrauth_auth_function(__value, __old_key, __old_data) \
248 ptrauth_auth_and_resign(__value, __old_key, __old_data, \
249 ptrauth_key_function_pointer, 0)
250
251/* Authenticate a data pointer.
252
253 The value must be an expression of non-function pointer type.
254 The key must be a constant expression of type ptrauth_key.
255 The extra data must be an expression of pointer or integer type;
256 if an integer, it will be coerced to ptrauth_extra_data_t.
257 The result will have the same type as the original value.
258
259 This operation traps if the authentication fails. */
260#define ptrauth_auth_data(__value, __old_key, __old_data) \
261 __builtin_ptrauth_auth(__value, __old_key, __old_data)
262
263/* Compute a constant discriminator from the given string.
264
265 The argument must be a string literal of char character type. The result
266 has type ptrauth_extra_data_t.
267
268 The result value is never zero and always within range for both the
269 __ptrauth qualifier and ptrauth_blend_discriminator.
270
271 This can be used in constant expressions.
272*/
273#define ptrauth_string_discriminator(__string) \
274 __builtin_ptrauth_string_discriminator(__string)
275
276/* Compute a constant discriminator from the given type.
277
278 The result can be used as the second argument to
279 ptrauth_blend_discriminator or the third argument to the
280 __ptrauth qualifier. It has type size_t.
281
282 If the type is a C++ member function pointer type, the result is
283 the discriminator used to signed member function pointers of that
284 type. If the type is a function, function pointer, or function
285 reference type, the result is the discriminator used to sign
286 functions of that type. It is ill-formed to use this macro with any
287 other type.
288
289 A call to this function is an integer constant expression. */
290#define ptrauth_type_discriminator(__type) \
291 __builtin_ptrauth_type_discriminator(__type)
292
293/* Compute the constant discriminator used by Clang to sign pointers with the
294 given C function pointer type.
295
296 A call to this function is an integer constant expression. */
297#if __has_feature(ptrauth_function_pointer_type_discrimination)
298#define ptrauth_function_pointer_type_discriminator(__type) \
299 __builtin_ptrauth_type_discriminator(__type)
300#else
301#define ptrauth_function_pointer_type_discriminator(__type) \
302 ((ptrauth_extra_data_t)0)
303#endif
304
305/* Compute a signature for the given pair of pointer-sized values.
306 The order of the arguments is significant.
307
308 Like a pointer signature, the resulting signature depends on
309 private key data and therefore should not be reliably reproducible
310 by attackers. That means that this can be used to validate the
311 integrity of arbitrary data by storing a signature for that data
312 alongside it, then checking that the signature is still valid later.
313 Data which exceeds two pointers in size can be signed by either
314 computing a tree of generic signatures or just signing an ordinary
315 cryptographic hash of the data.
316
317 The result has type ptrauth_generic_signature_t. However, it may
318 not have as many bits of entropy as that type's width would suggest;
319 some implementations are known to compute a compressed signature as
320 if the arguments were a pointer and a discriminator.
321
322 The arguments must be either pointers or integers; if integers, they
323 will be coerce to uintptr_t. */
324#define ptrauth_sign_generic_data(__value, __data) \
325 __builtin_ptrauth_sign_generic_data(__value, __data)
326
327/* C++ vtable pointer signing class attribute */
328#define ptrauth_cxx_vtable_pointer(key, address_discrimination, \
329 extra_discrimination...) \
330 [[clang::ptrauth_vtable_pointer(key, address_discrimination, \
331 extra_discrimination)]]
332
333/* The value is ptrauth_string_discriminator("init_fini") */
334#define __ptrauth_init_fini_discriminator 0xd9d4
335
336/* Objective-C pointer auth ABI qualifiers */
337#define __ptrauth_objc_method_list_imp \
338 __ptrauth(ptrauth_key_function_pointer, 1, 0)
339
340#if __has_feature(ptrauth_objc_method_list_pointer)
341#define __ptrauth_objc_method_list_pointer \
342 __ptrauth(ptrauth_key_method_list_pointer, 1, 0xC310)
343#else
344#define __ptrauth_objc_method_list_pointer
345#endif
346
347#define __ptrauth_isa_discriminator 0x6AE1
348#define __ptrauth_super_discriminator 0xB5AB
349#define __ptrauth_objc_isa_pointer \
350 __ptrauth(ptrauth_key_objc_isa_pointer, 1, __ptrauth_isa_discriminator)
351#if __has_feature(ptrauth_restricted_intptr_qualifier)
352#define __ptrauth_objc_isa_uintptr \
353 __ptrauth_restricted_intptr(ptrauth_key_objc_isa_pointer, 1, \
354 __ptrauth_isa_discriminator)
355#else
356#define __ptrauth_objc_isa_uintptr \
357 __ptrauth(ptrauth_key_objc_isa_pointer, 1, __ptrauth_isa_discriminator)
358#endif
359
360#define __ptrauth_objc_super_pointer \
361 __ptrauth(ptrauth_key_objc_super_pointer, 1, __ptrauth_super_discriminator)
362
363#define __ptrauth_objc_sel_discriminator 0x57c2
364#if __has_feature(ptrauth_objc_interface_sel)
365#define __ptrauth_objc_sel \
366 __ptrauth(ptrauth_key_objc_sel_pointer, 1, __ptrauth_objc_sel_discriminator)
367#else
368#define __ptrauth_objc_sel
369#endif
370
371#define __ptrauth_objc_class_ro_discriminator 0x61f8
372#define __ptrauth_objc_class_ro \
373 __ptrauth(ptrauth_key_objc_class_ro_pointer, 1, \
374 __ptrauth_objc_class_ro_discriminator)
375
376#if __has_feature(ptrauth_init_fini_address_discrimination)
377#define __ptrauth_init_fini_pointer \
378 __ptrauth(ptrauth_key_init_fini_pointer, 1, __ptrauth_init_fini_discriminator)
379#else
380#define __ptrauth_init_fini_pointer \
381 __ptrauth(ptrauth_key_init_fini_pointer, 0, __ptrauth_init_fini_discriminator)
382#endif
383
384#else
385
386#define ptrauth_strip(__value, __key) \
387 __extension__({ \
388 (void)__key; \
389 __value; \
390 })
391
392#define ptrauth_blend_discriminator(__pointer, __integer) \
393 __extension__({ \
394 (void)__pointer; \
395 (void)__integer; \
396 ((ptrauth_extra_data_t)0); \
397 })
398
399#define ptrauth_sign_constant(__value, __key, __data) \
400 __extension__({ \
401 (void)__key; \
402 (void)__data; \
403 __value; \
404 })
405
406#define ptrauth_sign_unauthenticated(__value, __key, __data) \
407 __extension__({ \
408 (void)__key; \
409 (void)__data; \
410 __value; \
411 })
412
413#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
414 __new_data) \
415 __extension__({ \
416 (void)__old_key; \
417 (void)__old_data; \
418 (void)__new_key; \
419 (void)__new_data; \
420 __value; \
421 })
422
423#define ptrauth_auth_with_pc_and_resign(__value, __old_key, __old_data, \
424 __old_pc, __new_key, __new_data) \
425 __extension__({ \
426 (void)__old_key; \
427 (void)__old_data; \
428 (void)__old_pc; \
429 (void)__new_key; \
430 (void)__new_data; \
431 __value; \
432 })
433
434#define ptrauth_auth_load_relative_and_sign(__value, __old_key, __old_data, \
435 __new_key, __new_data, __offset) \
436 __extension__({ \
437 (void)__old_key; \
438 (void)__old_data; \
439 (void)__new_key; \
440 (void)__new_data; \
441 const char *__value_tmp = (const char *)(__value); \
442 (void *)(__value_tmp + *(const int *)(__value_tmp + (__offset))); \
443 })
444
445#define ptrauth_auth_function(__value, __old_key, __old_data) \
446 __extension__({ \
447 (void)__old_key; \
448 (void)__old_data; \
449 __value; \
450 })
451
452#define ptrauth_auth_data(__value, __old_key, __old_data) \
453 __extension__({ \
454 (void)__old_key; \
455 (void)__old_data; \
456 __value; \
457 })
458
459#define ptrauth_string_discriminator(__string) \
460 __extension__({ \
461 (void)__string; \
462 ((ptrauth_extra_data_t)0); \
463 })
464
465#define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0)
466#define ptrauth_function_pointer_type_discriminator(__type) \
467 ((ptrauth_extra_data_t)0)
468
469#define ptrauth_sign_generic_data(__value, __data) \
470 __extension__({ \
471 (void)__value; \
472 (void)__data; \
473 ((ptrauth_generic_signature_t)0); \
474 })
475
476#define ptrauth_cxx_vtable_pointer(key, address_discrimination, \
477 extra_discrimination...)
478
479#define __ptrauth_objc_isa_pointer
480#define __ptrauth_objc_isa_uintptr
481#define __ptrauth_objc_super_pointer
482
483#endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */
484
485#endif /* __PTRAUTH_H */
__UINTPTR_TYPE__ ptrauth_extra_data_t
Definition ptrauth.h:65
__UINTPTR_TYPE__ ptrauth_generic_signature_t
Definition ptrauth.h:68
ptrauth_key
Definition ptrauth.h:13
@ ptrauth_key_method_list_pointer
Definition ptrauth.h:45
@ ptrauth_key_return_address
Definition ptrauth.h:35
@ ptrauth_key_process_independent_code
Definition ptrauth.h:20
@ ptrauth_key_process_dependent_code
Definition ptrauth.h:23
@ ptrauth_key_process_independent_data
Definition ptrauth.h:26
@ ptrauth_key_cxx_vtable_pointer
Definition ptrauth.h:42
@ ptrauth_key_objc_super_pointer
Definition ptrauth.h:49
@ ptrauth_key_asia
Definition ptrauth.h:14
@ ptrauth_key_init_fini_pointer
Definition ptrauth.h:58
@ ptrauth_key_objc_isa_pointer
Definition ptrauth.h:48
@ ptrauth_key_objc_sel_pointer
Definition ptrauth.h:52
@ ptrauth_key_asda
Definition ptrauth.h:16
@ ptrauth_key_objc_class_ro_pointer
Definition ptrauth.h:55
@ ptrauth_key_asib
Definition ptrauth.h:15
@ ptrauth_key_process_dependent_data
Definition ptrauth.h:29
@ ptrauth_key_function_pointer
Definition ptrauth.h:39
@ ptrauth_key_asdb
Definition ptrauth.h:17