]>
Commit | Line | Data |
---|---|---|
d9a64523 A |
1 | /*===---- ptrauth.h - Pointer authentication -------------------------------=== |
2 | * | |
3 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
4 | * of this software and associated documentation files (the "Software"), to deal | |
5 | * in the Software without restriction, including without limitation the rights | |
6 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
7 | * copies of the Software, and to permit persons to whom the Software is | |
8 | * furnished to do so, subject to the following conditions: | |
9 | * | |
10 | * The above copyright notice and this permission notice shall be included in | |
11 | * all copies or substantial portions of the Software. | |
12 | * | |
13 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
14 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
15 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |
16 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
17 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
18 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
19 | * THE SOFTWARE. | |
20 | * | |
21 | *===-----------------------------------------------------------------------=== | |
22 | */ | |
23 | ||
24 | #ifndef __PTRAUTH_H | |
25 | #define __PTRAUTH_H | |
26 | ||
27 | #include <stdint.h> | |
28 | ||
29 | typedef enum { | |
30 | ptrauth_key_asia = 0, | |
31 | ptrauth_key_asib = 1, | |
32 | ptrauth_key_asda = 2, | |
33 | ptrauth_key_asdb = 3, | |
34 | ||
35 | /* A process-independent key which can be used to sign code pointers. | |
36 | Signing and authenticating with this key is a no-op in processes | |
37 | which disable ABI pointer authentication. */ | |
38 | ptrauth_key_process_independent_code = ptrauth_key_asia, | |
39 | ||
40 | /* A process-specific key which can be used to sign code pointers. | |
41 | Signing and authenticating with this key is enforced even in processes | |
42 | which disable ABI pointer authentication. */ | |
43 | ptrauth_key_process_dependent_code = ptrauth_key_asib, | |
44 | ||
45 | /* A process-independent key which can be used to sign data pointers. | |
46 | Signing and authenticating with this key is a no-op in processes | |
47 | which disable ABI pointer authentication. */ | |
48 | ptrauth_key_process_independent_data = ptrauth_key_asda, | |
49 | ||
50 | /* A process-specific key which can be used to sign data pointers. | |
51 | Signing and authenticating with this key is a no-op in processes | |
52 | which disable ABI pointer authentication. */ | |
53 | ptrauth_key_process_dependent_data = ptrauth_key_asdb, | |
54 | ||
55 | /* The key used to sign C function pointers. | |
56 | The extra data is always 0. */ | |
57 | ptrauth_key_function_pointer = ptrauth_key_process_independent_code, | |
58 | ||
59 | /* The key used to sign return addresses on the stack. | |
60 | The extra data is based on the storage address of the return address. | |
61 | On ARM64, that is always the storage address of the return address plus 8 | |
62 | (or, in other words, the value of the stack pointer on function entry) */ | |
63 | ptrauth_key_return_address = ptrauth_key_process_dependent_code, | |
64 | ||
65 | /* The key used to sign frame pointers on the stack. | |
66 | The extra data is based on the storage address of the frame pointer. | |
67 | On ARM64, that is always the storage address of the frame pointer plus 16 | |
68 | (or, in other words, the value of the stack pointer on function entry) */ | |
69 | ptrauth_key_frame_pointer = ptrauth_key_process_dependent_data, | |
70 | ||
71 | /* The key used to sign block function pointers, including: | |
72 | invocation functions, | |
73 | block object copy functions, | |
74 | block object destroy functions, | |
75 | __block variable copy functions, and | |
76 | __block variable destroy functions. | |
77 | The extra data is always the address at which the function pointer | |
78 | is stored. | |
79 | ||
80 | Note that block object pointers themselves (i.e. the direct | |
81 | representations of values of block-pointer type) are not signed. */ | |
82 | ptrauth_key_block_function = ptrauth_key_asia, | |
83 | ||
84 | /* The key used to sign C++ v-table pointers. | |
85 | The extra data is always 0. */ | |
86 | ptrauth_key_cxx_vtable_pointer = ptrauth_key_asda, | |
87 | ||
88 | /* Other pointers signed under the ABI use private ABI rules. */ | |
89 | ||
90 | } ptrauth_key; | |
91 | ||
92 | /* An integer type of the appropriate size for an extra-data argument. */ | |
93 | typedef uintptr_t ptrauth_extra_data_t; | |
94 | ||
95 | /* An integer type of the appropriate size for a generic signature. */ | |
96 | typedef uintptr_t ptrauth_generic_signature_t; | |
97 | ||
98 | /* A signed pointer value embeds the original pointer together with | |
99 | a signature that attests to the validity of that pointer. Because | |
100 | this signature must use only "spare" bits of the pointer, a | |
101 | signature's validity is probabilistic in practice: it is unlikely | |
102 | but still plausible that an invalidly-derived signature will | |
103 | somehow equal the correct signature and therefore successfully | |
104 | authenticate. Nonetheless, this scheme provides a strong degree | |
105 | of protection against certain kinds of attacks. */ | |
106 | ||
107 | /* Authenticating a pointer that was not signed with the given key | |
108 | and extra-data value will (likely) fail. However, an | |
109 | authentication failure will not lead immediately to a trap. | |
110 | Instead, it will yield a value which is guaranteed to trap | |
111 | if actually dereferenced. */ | |
112 | ||
113 | /* The null function pointer is always the all-zero bit pattern. | |
114 | Signing an all-zero bit pattern will embed a (likely) non-zero | |
115 | signature in the result, and so the result will not seem to be | |
116 | a null function pointer. Authenticating this value will yield | |
117 | a null function pointer back. However, authenticating an | |
118 | all-zero bit pattern will probably fail, because the | |
119 | authentication will expect a (likely) non-zero signature to | |
120 | embedded in the value. | |
121 | ||
122 | Because of this, if a pointer may validly be null, you should | |
123 | check for null before attempting to authenticate it. */ | |
124 | ||
125 | #ifdef __PTRAUTH_INTRINSICS__ | |
126 | ||
127 | /* Strip the signature from a value without authenticating it. | |
128 | ||
129 | If the value is a function pointer, the result will not be a | |
130 | legal function pointer because of the missing signature, and | |
131 | attempting to call it will result in an authentication failure. | |
132 | ||
133 | The value must be an expression of pointer type. | |
134 | The key must be a constant expression of type ptrauth_key. | |
135 | The result will have the same type as the original value. */ | |
136 | #define ptrauth_strip(__value, __key) \ | |
137 | __builtin_ptrauth_strip(__value, __key) | |
138 | ||
139 | /* Blend a pointer and a small integer to form a new extra-data | |
140 | discriminator. Not all bits of the inputs are guaranteed to | |
141 | contribute to the result. | |
142 | ||
143 | On ARM64, only the low 16 bits of the integer will be considered. | |
144 | ||
145 | For the purposes of ptrauth_sign_constant, the result of calling | |
146 | this function is considered a constant expression if the arguments | |
147 | are constant. Some restrictions may be imposed on the pointer. | |
148 | ||
149 | The first argument must be an expression of pointer type. | |
150 | The second argument must be an expression of integer type. | |
151 | The result will have type uintptr_t. */ | |
152 | #define ptrauth_blend_discriminator(__pointer, __integer) \ | |
153 | __builtin_ptrauth_blend_discriminator(__pointer, __integer) | |
154 | ||
cb323159 A |
155 | /* Compute the 16-bit integer discriminator of the given type. |
156 | ||
157 | The argument must be a type. | |
158 | */ | |
f427ee49 | 159 | #if __has_builtin(__builtin_ptrauth_type_discriminator) |
cb323159 A |
160 | #define ptrauth_type_discriminator(__type) \ |
161 | __builtin_ptrauth_type_discriminator(__type) | |
162 | #else | |
163 | #define ptrauth_type_discriminator(__type) ((uintptr_t)0) | |
164 | #endif | |
165 | ||
f427ee49 A |
166 | /* Compute the constant discriminator used by Clang to sign pointers with the |
167 | given C function pointer type. | |
168 | ||
169 | A call to this function is an integer constant expression*/ | |
170 | #if __has_feature(ptrauth_function_pointer_type_discrimination) | |
171 | #define ptrauth_function_pointer_type_discriminator(__type) \ | |
172 | __builtin_ptrauth_type_discriminator(__type) | |
173 | #else | |
174 | #define ptrauth_function_pointer_type_discriminator(__type) ((uintptr_t)0) | |
175 | #endif | |
176 | ||
d9a64523 A |
177 | /* Add a signature to the given pointer value using a specific key, |
178 | using the given extra data as a salt to the signing process. | |
179 | ||
180 | The value must be a constant expression of pointer type. | |
181 | The key must be a constant expression of type ptrauth_key. | |
182 | The extra data must be a constant expression of pointer or integer type; | |
183 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
184 | The result will have the same type as the original value. | |
185 | ||
186 | This is a constant expression if the extra data is an integer or | |
187 | null pointer constant. */ | |
188 | #define ptrauth_sign_constant(__value, __key, __data) \ | |
189 | __builtin_ptrauth_sign_constant(__value, __key, __data) | |
190 | ||
191 | /* Add a signature to the given pointer value using a specific key, | |
192 | using the given extra data as a salt to the signing process. | |
193 | ||
194 | This operation does not authenticate the original value and is | |
195 | therefore potentially insecure if an attacker could possibly | |
196 | control that value. | |
197 | ||
198 | The value must be an expression of pointer type. | |
199 | The key must be a constant expression of type ptrauth_key. | |
200 | The extra data must be an expression of pointer or integer type; | |
201 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
202 | The result will have the same type as the original value. */ | |
203 | #define ptrauth_sign_unauthenticated(__value, __key, __data) \ | |
204 | __builtin_ptrauth_sign_unauthenticated(__value, __key, __data) | |
205 | ||
206 | /* Authenticate a pointer using one scheme and resign it using another. | |
207 | ||
208 | If the result is subsequently authenticated using the new scheme, that | |
209 | authentication is guaranteed to fail if and only if the initial | |
210 | authentication failed. | |
211 | ||
212 | The value must be an expression of pointer type. | |
213 | The key must be a constant expression of type ptrauth_key. | |
214 | The extra data must be an expression of pointer or integer type; | |
215 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
216 | The result will have the same type as the original value. | |
217 | ||
218 | This operation is guaranteed to not leave the intermediate value | |
219 | available for attack before it is re-signed. | |
220 | ||
221 | Do not pass a null pointer to this function. A null pointer | |
222 | will not successfully authenticate. */ | |
223 | #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, __new_data) \ | |
224 | __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, __new_data) | |
225 | ||
226 | /* Authenticate a pointer using one scheme and resign it as a C | |
227 | function pointer. | |
228 | ||
229 | If the result is subsequently authenticated using the new scheme, that | |
230 | authentication is guaranteed to fail if and only if the initial | |
231 | authentication failed. | |
232 | ||
233 | The value must be an expression of function pointer type. | |
234 | The key must be a constant expression of type ptrauth_key. | |
235 | The extra data must be an expression of pointer or integer type; | |
236 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
237 | The result will have the same type as the original value. | |
238 | ||
239 | This operation is guaranteed to not leave the intermediate value | |
240 | available for attack before it is re-signed. Additionally, if this | |
241 | expression is used syntactically as the function expression in a | |
242 | call, only a single authentication will be performed. */ | |
243 | #define ptrauth_auth_function(__value, __old_key, __old_data) \ | |
244 | ptrauth_auth_and_resign(__value, __old_key, __old_data, ptrauth_key_function_pointer, 0) | |
245 | ||
f427ee49 A |
246 | /* Cast a pointer to the given type without changing any signature. |
247 | ||
248 | The type must have the same size as a pointer type. | |
249 | The type of value must have the same size as a pointer type, and will be | |
250 | converted to an rvalue prior to the cast. | |
251 | The result has type given by the first argument. | |
252 | ||
253 | The result has an identical bit-pattern to the input pointer. */ | |
254 | #define ptrauth_nop_cast(__type, __value) \ | |
255 | ({ union { \ | |
256 | typeof(__value) __fptr; \ | |
257 | typeof(__type) __opaque; \ | |
258 | } __storage; \ | |
259 | __storage.__fptr = (__value); \ | |
260 | __storage.__opaque; }) | |
261 | ||
d9a64523 A |
262 | /* Authenticate a data pointer. |
263 | ||
264 | The value must be an expression of non-function pointer type. | |
265 | The key must be a constant expression of type ptrauth_key. | |
266 | The extra data must be an expression of pointer or integer type; | |
267 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
268 | The result will have the same type as the original value. | |
269 | ||
270 | If the authentication fails, dereferencing the resulting pointer | |
271 | will fail. */ | |
272 | #define ptrauth_auth_data(__value, __old_key, __old_data) \ | |
273 | __builtin_ptrauth_auth(__value, __old_key, __old_data) | |
274 | ||
275 | /* Return an extra-discriminator value which can validly be used | |
276 | as the second argument to ptrauth_blend_discriminator or the | |
277 | third argument to the __ptrauth qualifier. | |
278 | ||
279 | The argument must be a string literal. | |
280 | A call to this function is an integer constant expression. */ | |
281 | #define ptrauth_string_discriminator(__string) \ | |
282 | __builtin_ptrauth_string_discriminator(__string) | |
283 | ||
284 | /* Compute a full pointer-width generic signature for the given | |
285 | value, using the given data as a salt. | |
286 | ||
287 | This generic signature is process-independent, but may not be | |
288 | consistent across reboots. | |
289 | ||
290 | This can be used to validate the integrity of arbitrary data | |
291 | by storing a signature for that data together with it. Because | |
292 | the signature is pointer-sized, if the stored signature matches | |
293 | the result of re-signing the current data, a match provides very | |
294 | strong evidence that the data has not been corrupted. | |
295 | ||
296 | The value must be an expression of pointer or integer type; if | |
297 | an integer, it will be coerced to uintptr_t. | |
298 | The extra data must be an expression of pointer or integer type; | |
299 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
300 | The result will have type ptrauth_generic_signature_t. | |
301 | ||
302 | This operation will compute a meaningful signature even in processes | |
303 | which disable ABI pointer authentication. */ | |
304 | #define ptrauth_sign_generic_data(__value, __data) \ | |
305 | __builtin_ptrauth_sign_generic_data(__value, __data) | |
306 | ||
307 | ||
308 | /* Define some standard __ptrauth qualifiers used in the ABI. */ | |
309 | #define __ptrauth_function_pointer \ | |
310 | __ptrauth(ptrauth_key_function_pointer,0,0) | |
311 | #define __ptrauth_return_address \ | |
312 | __ptrauth(ptrauth_key_return_address,1,0) | |
313 | #define __ptrauth_block_invocation_pointer \ | |
314 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
315 | #define __ptrauth_block_copy_helper \ | |
316 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
317 | #define __ptrauth_block_destroy_helper \ | |
318 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
319 | #define __ptrauth_block_byref_copy_helper \ | |
320 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
321 | #define __ptrauth_block_byref_destroy_helper \ | |
322 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
323 | #define __ptrauth_objc_method_list_imp \ | |
324 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
325 | #define __ptrauth_cxx_vtable_pointer \ | |
326 | __ptrauth(ptrauth_key_cxx_vtable_pointer,0,0) | |
327 | #define __ptrauth_cxx_vtt_vtable_pointer \ | |
328 | __ptrauth(ptrauth_key_cxx_vtable_pointer,0,0) | |
329 | #define __ptrauth_swift_heap_object_destructor \ | |
330 | __ptrauth(ptrauth_key_function_pointer,1,0xbbbf) | |
331 | ||
332 | /* Some situations in the C++ and Swift ABIs use declaration-specific | |
333 | or type-specific extra discriminators. */ | |
334 | #define __ptrauth_cxx_virtual_function_pointer(__declkey) \ | |
335 | __ptrauth(ptrauth_key_function_pointer,1,__declkey) | |
336 | #define __ptrauth_swift_function_pointer(__typekey) \ | |
337 | __ptrauth(ptrauth_key_function_pointer,0,__typekey) | |
338 | #define __ptrauth_swift_class_method_pointer(__declkey) \ | |
339 | __ptrauth(ptrauth_key_function_pointer,1,__declkey) | |
340 | #define __ptrauth_swift_protocol_witness_function_pointer(__declkey) \ | |
341 | __ptrauth(ptrauth_key_function_pointer,1,__declkey) | |
342 | #define __ptrauth_swift_value_witness_function_pointer(__key) \ | |
343 | __ptrauth(ptrauth_key_function_pointer,1,__key) | |
344 | ||
345 | #else | |
346 | ||
f427ee49 A |
347 | #define ptrauth_strip(__value, __key) ({ (void)__key; __value; }) |
348 | #define ptrauth_blend_discriminator(__pointer, __integer) ({ (void)__pointer; (void)__integer; (uintptr_t)0; }) | |
cb323159 | 349 | #define ptrauth_type_discriminator(__type) ((uintptr_t)0) |
f427ee49 A |
350 | #define ptrauth_function_pointer_type_discriminator(__type) ((uintptr_t)0) |
351 | #define ptrauth_sign_constant(__value, __key, __data) ({ (void)__key; (void)__data; __value; }) | |
352 | #define ptrauth_sign_unauthenticated(__value, __key, __data) ({ (void)__key; (void)__data; __value; }) | |
353 | #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, __new_data) ({ \ | |
354 | (void)__old_key; \ | |
355 | (void)__old_data; \ | |
356 | (void)__new_key; \ | |
357 | (void)__new_data; \ | |
358 | __value; }) | |
359 | #define ptrauth_auth_function(__value, __old_key, __old_data) ({ (void)__old_key; (void)__old_data; __value; }) | |
360 | #define ptrauth_nop_cast(__type, __value) ((__type)__value) | |
361 | #define ptrauth_auth_data(__value, __old_key, __old_data) ({ (void)__old_key; (void)__old_data; __value; }) | |
362 | #define ptrauth_string_discriminator(__string) ({ (void)__string; (int)0; }) | |
363 | #define ptrauth_sign_generic_data(__value, __data) ({ (void)__value; (void)__data; (ptrauth_generic_signature_t)0; }) | |
d9a64523 A |
364 | |
365 | #define __ptrauth_function_pointer | |
366 | #define __ptrauth_return_address | |
367 | #define __ptrauth_block_invocation_pointer | |
368 | #define __ptrauth_block_copy_helper | |
369 | #define __ptrauth_block_destroy_helper | |
370 | #define __ptrauth_block_byref_copy_helper | |
371 | #define __ptrauth_block_byref_destroy_helper | |
372 | #define __ptrauth_objc_method_list_imp | |
373 | #define __ptrauth_cxx_vtable_pointer | |
374 | #define __ptrauth_cxx_vtt_vtable_pointer | |
375 | #define __ptrauth_swift_heap_object_destructor | |
376 | #define __ptrauth_cxx_virtual_function_pointer(__declkey) | |
377 | #define __ptrauth_swift_function_pointer(__typekey) | |
378 | #define __ptrauth_swift_class_method_pointer(__declkey) | |
379 | #define __ptrauth_swift_protocol_witness_function_pointer(__declkey) | |
380 | #define __ptrauth_swift_value_witness_function_pointer(__key) | |
381 | ||
382 | #endif /* __PTRAUTH_INTRINSICS__ */ | |
383 | ||
384 | #endif /* __PTRAUTH_H */ |