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