brintos

brintos / llvm-project-archived public Read only

0
0
Text · 18.7 KiB · ad28f06 Raw
408 lines · c
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-exception6 *7 *===-----------------------------------------------------------------------===8 */9 10#ifndef __PTRAUTH_H11#define __PTRAUTH_H12 13typedef enum {14  ptrauth_key_asia = 0,15  ptrauth_key_asib = 1,16  ptrauth_key_asda = 2,17  ptrauth_key_asdb = 3,18 19  /* A process-independent key which can be used to sign code pointers. */20  ptrauth_key_process_independent_code = ptrauth_key_asia,21 22  /* A process-specific key which can be used to sign code pointers. */23  ptrauth_key_process_dependent_code = ptrauth_key_asib,24 25  /* A process-independent key which can be used to sign data pointers. */26  ptrauth_key_process_independent_data = ptrauth_key_asda,27 28  /* A process-specific key which can be used to sign data pointers. */29  ptrauth_key_process_dependent_data = ptrauth_key_asdb,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 + 834     (or, in other words, the value of the stack pointer on function entry) */35  ptrauth_key_return_address = ptrauth_key_process_dependent_code,36 37  /* The key used to sign C function pointers.38     The extra data is always 0. */39  ptrauth_key_function_pointer = ptrauth_key_process_independent_code,40 41  /* The key used to sign C++ v-table pointers.42     The extra data is always 0. */43  ptrauth_key_cxx_vtable_pointer = ptrauth_key_process_independent_data,44 45  /* The key used to sign metadata pointers to Objective-C method-lists. */46  ptrauth_key_method_list_pointer = ptrauth_key_asda,47 48  /* The key used to sign Objective-C isa and super pointers. */49  ptrauth_key_objc_isa_pointer = ptrauth_key_process_independent_data,50  ptrauth_key_objc_super_pointer = ptrauth_key_process_independent_data,51 52  /* The key used to sign selector pointers */53  ptrauth_key_objc_sel_pointer = ptrauth_key_process_dependent_data,54 55  /* The key used to sign Objective-C class_ro_t pointers. */56  ptrauth_key_objc_class_ro_pointer = ptrauth_key_process_independent_data,57 58  /* The key used to sign pointers in ELF .init_array/.fini_array. */59  ptrauth_key_init_fini_pointer = ptrauth_key_process_independent_code,60 61  /* Other pointers signed under the ABI use private ABI rules. */62 63} ptrauth_key;64 65/* An integer type of the appropriate size for a discriminator argument. */66typedef __UINTPTR_TYPE__ ptrauth_extra_data_t;67 68/* An integer type of the appropriate size for a generic signature. */69typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;70 71/* A signed pointer value embeds the original pointer together with72   a signature that attests to the validity of that pointer.  Because73   this signature must use only "spare" bits of the pointer, a74   signature's validity is probabilistic in practice: it is unlikely75   but still plausible that an invalidly-derived signature will76   somehow equal the correct signature and therefore successfully77   authenticate.  Nonetheless, this scheme provides a strong degree78   of protection against certain kinds of attacks. */79 80/* Authenticating a pointer that was not signed with the given key81   and extra-data value will (likely) fail by trapping. */82 83/* The null function pointer is always the all-zero bit pattern.84   Signing an all-zero bit pattern will embed a (likely) non-zero85   signature in the result, and so the result will not seem to be86   a null function pointer.  Authenticating this value will yield87   a null function pointer back.  However, authenticating an88   all-zero bit pattern will probably fail, because the89   authentication will expect a (likely) non-zero signature to90   embedded in the value.91 92   Because of this, if a pointer may validly be null, you should93   check for null before attempting to authenticate it with one94   of these intrinsics.  This is not necessary when using the95   __ptrauth qualifier; the compiler will perform this check96   automatically. */97 98#if __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__)99 100/* Strip the signature from a value without authenticating it.101 102   If the value is a function pointer, the result will not be a103   legal function pointer because of the missing signature, and104   attempting to call it will result in an authentication failure.105 106   The value must be an expression of pointer type.107   The key must be a constant expression of type ptrauth_key.108   The result will have the same type as the original value. */109#define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key)110 111/* Blend a constant discriminator into the given pointer-like value112   to form a new discriminator.  Not all bits of the inputs are113   guaranteed to contribute to the result.114 115   On arm64e, the integer must fall within the range of a uint16_t;116   other bits may be ignored.117 118   For the purposes of ptrauth_sign_constant, the result of calling119   this function is considered a constant expression if the arguments120   are constant.  Some restrictions may be imposed on the pointer.121 122   The first argument must be an expression of pointer type.123   The second argument must be an expression of integer type.124   The result will have type uintptr_t. */125#define ptrauth_blend_discriminator(__pointer, __integer)                      \126  __builtin_ptrauth_blend_discriminator(__pointer, __integer)127 128/* Return a signed pointer for a constant address in a manner which guarantees129   a non-attackable sequence.130 131   The value must be a constant expression of pointer type which evaluates to132   a non-null pointer.133   The key must be a constant expression of type ptrauth_key.134   The extra data must be a constant expression of pointer or integer type;135   if an integer, it will be coerced to ptrauth_extra_data_t.136   The result will have the same type as the original value.137 138   This can be used in constant expressions.  */139#define ptrauth_sign_constant(__value, __key, __data)                          \140  __builtin_ptrauth_sign_constant(__value, __key, __data)141 142/* Add a signature to the given pointer value using a specific key,143   using the given extra data as a salt to the signing process.144 145   This operation does not authenticate the original value and is146   therefore potentially insecure if an attacker could possibly147   control that value.148 149   The value must be an expression of pointer type.150   The key must be a constant expression of type ptrauth_key.151   The extra data must be an expression of pointer or integer type;152   if an integer, it will be coerced to ptrauth_extra_data_t.153   The result will have the same type as the original value. */154#define ptrauth_sign_unauthenticated(__value, __key, __data)                   \155  __builtin_ptrauth_sign_unauthenticated(__value, __key, __data)156 157/* Authenticate a pointer using one scheme and resign it using another.158 159   If the result is subsequently authenticated using the new scheme, that160   authentication is guaranteed to fail if and only if the initial161   authentication failed.162 163   The value must be an expression of pointer type.164   The key must be a constant expression of type ptrauth_key.165   The extra data must be an expression of pointer or integer type;166   if an integer, it will be coerced to ptrauth_extra_data_t.167   The result will have the same type as the original value.168 169   This operation is guaranteed to not leave the intermediate value170   available for attack before it is re-signed.171 172   Do not pass a null pointer to this function. A null pointer173   will not successfully authenticate.174 175   This operation traps if the authentication fails. */176#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key,     \177                                __new_data)                                    \178  __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \179                                    __new_data)180 181/* Authenticate a pointer using one scheme and resign it as a C182   function pointer.183 184   If the result is subsequently authenticated using the new scheme, that185   authentication is guaranteed to fail if and only if the initial186   authentication failed.187 188   The value must be an expression of function pointer type.189   The key must be a constant expression of type ptrauth_key.190   The extra data must be an expression of pointer or integer type;191   if an integer, it will be coerced to ptrauth_extra_data_t.192   The result will have the same type as the original value.193 194   This operation is guaranteed to not leave the intermediate value195   available for attack before it is re-signed. Additionally, if this196   expression is used syntactically as the function expression in a197   call, only a single authentication will be performed. */198#define ptrauth_auth_function(__value, __old_key, __old_data)                  \199  ptrauth_auth_and_resign(__value, __old_key, __old_data,                      \200                          ptrauth_key_function_pointer, 0)201 202/* Authenticate a data pointer.203 204   The value must be an expression of non-function pointer type.205   The key must be a constant expression of type ptrauth_key.206   The extra data must be an expression of pointer or integer type;207   if an integer, it will be coerced to ptrauth_extra_data_t.208   The result will have the same type as the original value.209 210   This operation traps if the authentication fails. */211#define ptrauth_auth_data(__value, __old_key, __old_data)                      \212  __builtin_ptrauth_auth(__value, __old_key, __old_data)213 214/* Compute a constant discriminator from the given string.215 216   The argument must be a string literal of char character type.  The result217   has type ptrauth_extra_data_t.218 219   The result value is never zero and always within range for both the220   __ptrauth qualifier and ptrauth_blend_discriminator.221 222   This can be used in constant expressions.223*/224#define ptrauth_string_discriminator(__string)                                 \225  __builtin_ptrauth_string_discriminator(__string)226 227/* Compute a constant discriminator from the given type.228 229   The result can be used as the second argument to230   ptrauth_blend_discriminator or the third argument to the231   __ptrauth qualifier.  It has type size_t.232 233   If the type is a C++ member function pointer type, the result is234   the discriminator used to signed member function pointers of that235   type.  If the type is a function, function pointer, or function236   reference type, the result is the discriminator used to sign237   functions of that type.  It is ill-formed to use this macro with any238   other type.239 240   A call to this function is an integer constant expression. */241#define ptrauth_type_discriminator(__type)                                     \242  __builtin_ptrauth_type_discriminator(__type)243 244/* Compute the constant discriminator used by Clang to sign pointers with the245   given C function pointer type.246 247   A call to this function is an integer constant expression. */248#if __has_feature(ptrauth_function_pointer_type_discrimination)249#define ptrauth_function_pointer_type_discriminator(__type)                    \250  __builtin_ptrauth_type_discriminator(__type)251#else252#define ptrauth_function_pointer_type_discriminator(__type)                    \253  ((ptrauth_extra_data_t)0)254#endif255 256/* Compute a signature for the given pair of pointer-sized values.257   The order of the arguments is significant.258 259   Like a pointer signature, the resulting signature depends on260   private key data and therefore should not be reliably reproducible261   by attackers.  That means that this can be used to validate the262   integrity of arbitrary data by storing a signature for that data263   alongside it, then checking that the signature is still valid later.264   Data which exceeds two pointers in size can be signed by either265   computing a tree of generic signatures or just signing an ordinary266   cryptographic hash of the data.267 268   The result has type ptrauth_generic_signature_t.  However, it may269   not have as many bits of entropy as that type's width would suggest;270   some implementations are known to compute a compressed signature as271   if the arguments were a pointer and a discriminator.272 273   The arguments must be either pointers or integers; if integers, they274   will be coerce to uintptr_t. */275#define ptrauth_sign_generic_data(__value, __data)                             \276  __builtin_ptrauth_sign_generic_data(__value, __data)277 278/* C++ vtable pointer signing class attribute */279#define ptrauth_cxx_vtable_pointer(key, address_discrimination,                \280                                   extra_discrimination...)                    \281  [[clang::ptrauth_vtable_pointer(key, address_discrimination,                 \282                                  extra_discrimination)]]283 284/* The value is ptrauth_string_discriminator("init_fini") */285#define __ptrauth_init_fini_discriminator 0xd9d4286 287/* Objective-C pointer auth ABI qualifiers */288#define __ptrauth_objc_method_list_imp                                         \289  __ptrauth(ptrauth_key_function_pointer, 1, 0)290 291#if __has_feature(ptrauth_objc_method_list_pointer)292#define __ptrauth_objc_method_list_pointer                                     \293  __ptrauth(ptrauth_key_method_list_pointer, 1, 0xC310)294#else295#define __ptrauth_objc_method_list_pointer296#endif297 298#define __ptrauth_isa_discriminator 0x6AE1299#define __ptrauth_super_discriminator 0xB5AB300#define __ptrauth_objc_isa_pointer                                             \301  __ptrauth(ptrauth_key_objc_isa_pointer, 1, __ptrauth_isa_discriminator)302#if __has_feature(ptrauth_restricted_intptr_qualifier)303#define __ptrauth_objc_isa_uintptr                                             \304  __ptrauth_restricted_intptr(ptrauth_key_objc_isa_pointer, 1,                 \305                              __ptrauth_isa_discriminator)306#else307#define __ptrauth_objc_isa_uintptr                                             \308  __ptrauth(ptrauth_key_objc_isa_pointer, 1, __ptrauth_isa_discriminator)309#endif310 311#define __ptrauth_objc_super_pointer                                           \312  __ptrauth(ptrauth_key_objc_super_pointer, 1, __ptrauth_super_discriminator)313 314#define __ptrauth_objc_sel_discriminator 0x57c2315#if __has_feature(ptrauth_objc_interface_sel)316#define __ptrauth_objc_sel                                                     \317  __ptrauth(ptrauth_key_objc_sel_pointer, 1, __ptrauth_objc_sel_discriminator)318#else319#define __ptrauth_objc_sel320#endif321 322#define __ptrauth_objc_class_ro_discriminator 0x61f8323#define __ptrauth_objc_class_ro                                                \324  __ptrauth(ptrauth_key_objc_class_ro_pointer, 1,                              \325            __ptrauth_objc_class_ro_discriminator)326 327#else328 329#define ptrauth_strip(__value, __key)                                          \330  ({                                                                           \331    (void)__key;                                                               \332    __value;                                                                   \333  })334 335#define ptrauth_blend_discriminator(__pointer, __integer)                      \336  ({                                                                           \337    (void)__pointer;                                                           \338    (void)__integer;                                                           \339    ((ptrauth_extra_data_t)0);                                                 \340  })341 342#define ptrauth_sign_constant(__value, __key, __data)                          \343  ({                                                                           \344    (void)__key;                                                               \345    (void)__data;                                                              \346    __value;                                                                   \347  })348 349#define ptrauth_sign_unauthenticated(__value, __key, __data)                   \350  ({                                                                           \351    (void)__key;                                                               \352    (void)__data;                                                              \353    __value;                                                                   \354  })355 356#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key,     \357                                __new_data)                                    \358  ({                                                                           \359    (void)__old_key;                                                           \360    (void)__old_data;                                                          \361    (void)__new_key;                                                           \362    (void)__new_data;                                                          \363    __value;                                                                   \364  })365 366#define ptrauth_auth_function(__value, __old_key, __old_data)                  \367  ({                                                                           \368    (void)__old_key;                                                           \369    (void)__old_data;                                                          \370    __value;                                                                   \371  })372 373#define ptrauth_auth_data(__value, __old_key, __old_data)                      \374  ({                                                                           \375    (void)__old_key;                                                           \376    (void)__old_data;                                                          \377    __value;                                                                   \378  })379 380#define ptrauth_string_discriminator(__string)                                 \381  ({                                                                           \382    (void)__string;                                                            \383    ((ptrauth_extra_data_t)0);                                                 \384  })385 386#define ptrauth_type_discriminator(__type) ((ptrauth_extra_data_t)0)387#define ptrauth_function_pointer_type_discriminator(__type)                    \388  ((ptrauth_extra_data_t)0)389 390#define ptrauth_sign_generic_data(__value, __data)                             \391  ({                                                                           \392    (void)__value;                                                             \393    (void)__data;                                                              \394    ((ptrauth_generic_signature_t)0);                                          \395  })396 397 398#define ptrauth_cxx_vtable_pointer(key, address_discrimination,                \399                                   extra_discrimination...)400 401#define __ptrauth_objc_isa_pointer402#define __ptrauth_objc_isa_uintptr403#define __ptrauth_objc_super_pointer404 405#endif /* __has_feature(ptrauth_intrinsics) || defined(__PTRAUTH__) */406 407#endif /* __PTRAUTH_H */408