]>
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 | */ | |
159 | #if __has_feature(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 | ||
d9a64523 A |
166 | /* Add a signature to the given pointer value using a specific key, |
167 | using the given extra data as a salt to the signing process. | |
168 | ||
169 | The value must be a constant expression of pointer type. | |
170 | The key must be a constant expression of type ptrauth_key. | |
171 | The extra data must be a constant expression of pointer or integer type; | |
172 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
173 | The result will have the same type as the original value. | |
174 | ||
175 | This is a constant expression if the extra data is an integer or | |
176 | null pointer constant. */ | |
177 | #define ptrauth_sign_constant(__value, __key, __data) \ | |
178 | __builtin_ptrauth_sign_constant(__value, __key, __data) | |
179 | ||
180 | /* Add a signature to the given pointer value using a specific key, | |
181 | using the given extra data as a salt to the signing process. | |
182 | ||
183 | This operation does not authenticate the original value and is | |
184 | therefore potentially insecure if an attacker could possibly | |
185 | control that value. | |
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 result will have the same type as the original value. */ | |
192 | #define ptrauth_sign_unauthenticated(__value, __key, __data) \ | |
193 | __builtin_ptrauth_sign_unauthenticated(__value, __key, __data) | |
194 | ||
195 | /* Authenticate a pointer using one scheme and resign it using another. | |
196 | ||
197 | If the result is subsequently authenticated using the new scheme, that | |
198 | authentication is guaranteed to fail if and only if the initial | |
199 | authentication failed. | |
200 | ||
201 | The value must be an expression of pointer type. | |
202 | The key must be a constant expression of type ptrauth_key. | |
203 | The extra data must be an expression of pointer or integer type; | |
204 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
205 | The result will have the same type as the original value. | |
206 | ||
207 | This operation is guaranteed to not leave the intermediate value | |
208 | available for attack before it is re-signed. | |
209 | ||
210 | Do not pass a null pointer to this function. A null pointer | |
211 | will not successfully authenticate. */ | |
212 | #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, __new_data) \ | |
213 | __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, __new_data) | |
214 | ||
215 | /* Authenticate a pointer using one scheme and resign it as a C | |
216 | function pointer. | |
217 | ||
218 | If the result is subsequently authenticated using the new scheme, that | |
219 | authentication is guaranteed to fail if and only if the initial | |
220 | authentication failed. | |
221 | ||
222 | The value must be an expression of function pointer type. | |
223 | The key must be a constant expression of type ptrauth_key. | |
224 | The extra data must be an expression of pointer or integer type; | |
225 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
226 | The result will have the same type as the original value. | |
227 | ||
228 | This operation is guaranteed to not leave the intermediate value | |
229 | available for attack before it is re-signed. Additionally, if this | |
230 | expression is used syntactically as the function expression in a | |
231 | call, only a single authentication will be performed. */ | |
232 | #define ptrauth_auth_function(__value, __old_key, __old_data) \ | |
233 | ptrauth_auth_and_resign(__value, __old_key, __old_data, ptrauth_key_function_pointer, 0) | |
234 | ||
235 | /* Authenticate a data pointer. | |
236 | ||
237 | The value must be an expression of non-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 | If the authentication fails, dereferencing the resulting pointer | |
244 | will fail. */ | |
245 | #define ptrauth_auth_data(__value, __old_key, __old_data) \ | |
246 | __builtin_ptrauth_auth(__value, __old_key, __old_data) | |
247 | ||
248 | /* Return an extra-discriminator value which can validly be used | |
249 | as the second argument to ptrauth_blend_discriminator or the | |
250 | third argument to the __ptrauth qualifier. | |
251 | ||
252 | The argument must be a string literal. | |
253 | A call to this function is an integer constant expression. */ | |
254 | #define ptrauth_string_discriminator(__string) \ | |
255 | __builtin_ptrauth_string_discriminator(__string) | |
256 | ||
257 | /* Compute a full pointer-width generic signature for the given | |
258 | value, using the given data as a salt. | |
259 | ||
260 | This generic signature is process-independent, but may not be | |
261 | consistent across reboots. | |
262 | ||
263 | This can be used to validate the integrity of arbitrary data | |
264 | by storing a signature for that data together with it. Because | |
265 | the signature is pointer-sized, if the stored signature matches | |
266 | the result of re-signing the current data, a match provides very | |
267 | strong evidence that the data has not been corrupted. | |
268 | ||
269 | The value must be an expression of pointer or integer type; if | |
270 | an integer, it will be coerced to uintptr_t. | |
271 | The extra data must be an expression of pointer or integer type; | |
272 | if an integer, it will be coerced to ptrauth_extra_data_t. | |
273 | The result will have type ptrauth_generic_signature_t. | |
274 | ||
275 | This operation will compute a meaningful signature even in processes | |
276 | which disable ABI pointer authentication. */ | |
277 | #define ptrauth_sign_generic_data(__value, __data) \ | |
278 | __builtin_ptrauth_sign_generic_data(__value, __data) | |
279 | ||
280 | ||
281 | /* Define some standard __ptrauth qualifiers used in the ABI. */ | |
282 | #define __ptrauth_function_pointer \ | |
283 | __ptrauth(ptrauth_key_function_pointer,0,0) | |
284 | #define __ptrauth_return_address \ | |
285 | __ptrauth(ptrauth_key_return_address,1,0) | |
286 | #define __ptrauth_block_invocation_pointer \ | |
287 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
288 | #define __ptrauth_block_copy_helper \ | |
289 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
290 | #define __ptrauth_block_destroy_helper \ | |
291 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
292 | #define __ptrauth_block_byref_copy_helper \ | |
293 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
294 | #define __ptrauth_block_byref_destroy_helper \ | |
295 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
296 | #define __ptrauth_objc_method_list_imp \ | |
297 | __ptrauth(ptrauth_key_function_pointer,1,0) | |
298 | #define __ptrauth_cxx_vtable_pointer \ | |
299 | __ptrauth(ptrauth_key_cxx_vtable_pointer,0,0) | |
300 | #define __ptrauth_cxx_vtt_vtable_pointer \ | |
301 | __ptrauth(ptrauth_key_cxx_vtable_pointer,0,0) | |
302 | #define __ptrauth_swift_heap_object_destructor \ | |
303 | __ptrauth(ptrauth_key_function_pointer,1,0xbbbf) | |
304 | ||
305 | /* Some situations in the C++ and Swift ABIs use declaration-specific | |
306 | or type-specific extra discriminators. */ | |
307 | #define __ptrauth_cxx_virtual_function_pointer(__declkey) \ | |
308 | __ptrauth(ptrauth_key_function_pointer,1,__declkey) | |
309 | #define __ptrauth_swift_function_pointer(__typekey) \ | |
310 | __ptrauth(ptrauth_key_function_pointer,0,__typekey) | |
311 | #define __ptrauth_swift_class_method_pointer(__declkey) \ | |
312 | __ptrauth(ptrauth_key_function_pointer,1,__declkey) | |
313 | #define __ptrauth_swift_protocol_witness_function_pointer(__declkey) \ | |
314 | __ptrauth(ptrauth_key_function_pointer,1,__declkey) | |
315 | #define __ptrauth_swift_value_witness_function_pointer(__key) \ | |
316 | __ptrauth(ptrauth_key_function_pointer,1,__key) | |
317 | ||
318 | #else | |
319 | ||
320 | #define ptrauth_strip(__value, __key) __value | |
321 | #define ptrauth_blend_discriminator(__pointer, __integer) ((uintptr_t)0) | |
cb323159 | 322 | #define ptrauth_type_discriminator(__type) ((uintptr_t)0) |
d9a64523 A |
323 | #define ptrauth_sign_constant(__value, __key, __data) __value |
324 | #define ptrauth_sign_unauthenticated(__value, __key, __data) __value | |
325 | #define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, __new_data) __value | |
326 | #define ptrauth_auth_function(__value, __old_key, __old_data) __value | |
327 | #define ptrauth_auth_data(__value, __old_key, __old_data) __value | |
328 | #define ptrauth_string_discriminator(__string) ((int)0) | |
329 | #define ptrauth_sign_generic_data(__value, __data) ((ptrauth_generic_signature_t)0) | |
330 | ||
331 | #define __ptrauth_function_pointer | |
332 | #define __ptrauth_return_address | |
333 | #define __ptrauth_block_invocation_pointer | |
334 | #define __ptrauth_block_copy_helper | |
335 | #define __ptrauth_block_destroy_helper | |
336 | #define __ptrauth_block_byref_copy_helper | |
337 | #define __ptrauth_block_byref_destroy_helper | |
338 | #define __ptrauth_objc_method_list_imp | |
339 | #define __ptrauth_cxx_vtable_pointer | |
340 | #define __ptrauth_cxx_vtt_vtable_pointer | |
341 | #define __ptrauth_swift_heap_object_destructor | |
342 | #define __ptrauth_cxx_virtual_function_pointer(__declkey) | |
343 | #define __ptrauth_swift_function_pointer(__typekey) | |
344 | #define __ptrauth_swift_class_method_pointer(__declkey) | |
345 | #define __ptrauth_swift_protocol_witness_function_pointer(__declkey) | |
346 | #define __ptrauth_swift_value_witness_function_pointer(__key) | |
347 | ||
348 | #endif /* __PTRAUTH_INTRINSICS__ */ | |
349 | ||
350 | #endif /* __PTRAUTH_H */ |