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 ; |
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 | |
155 | /* Compute the 16-bit integer discriminator of the given type. |
156 | |
157 | The argument must be a type. |
158 | */ |
159 | #if __has_builtin(__builtin_ptrauth_type_discriminator) |
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 | |
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 | |
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 | |
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 | |
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 | |
347 | #define ptrauth_strip(__value, __key) ({ (void)__key; __value; }) |
348 | #define ptrauth_blend_discriminator(__pointer, __integer) ({ (void)__pointer; (void)__integer; (uintptr_t)0; }) |
349 | #define ptrauth_type_discriminator(__type) ((uintptr_t)0) |
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; }) |
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 */ |
385 | |