aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Headers
diff options
context:
space:
mode:
authorAhmed Bougacha <ahmed@bougacha.org>2024-03-15 14:17:21 -0700
committerGitHub <noreply@github.com>2024-03-15 14:17:21 -0700
commit0481f049c37029d829dbc0c0cc5d1ee71c6d1c9a (patch)
tree56c4d328a8c36e0f3ddb97d0d926c40325a4d52d /clang/lib/Headers
parent60fa2b0670b874b702ddb9f81d098af692ea6875 (diff)
downloadllvm-0481f049c37029d829dbc0c0cc5d1ee71c6d1c9a.zip
llvm-0481f049c37029d829dbc0c0cc5d1ee71c6d1c9a.tar.gz
llvm-0481f049c37029d829dbc0c0cc5d1ee71c6d1c9a.tar.bz2
[AArch64][PAC] Support ptrauth builtins and -fptrauth-intrinsics. (#65996)
This defines the basic set of pointer authentication clang builtins (provided in a new header, ptrauth.h), with diagnostics and IRGen support. The availability of the builtins is gated on a new flag, `-fptrauth-intrinsics`. Note that this only includes the basic intrinsics, and notably excludes `ptrauth_sign_constant`, `ptrauth_type_discriminator`, and `ptrauth_string_discriminator`, which need extra logic to be fully supported. This also introduces clang/docs/PointerAuthentication.rst, which describes the ptrauth model in general, in addition to these builtins. Co-Authored-By: Akira Hatanaka <ahatanaka@apple.com> Co-Authored-By: John McCall <rjmccall@apple.com>
Diffstat (limited to 'clang/lib/Headers')
-rw-r--r--clang/lib/Headers/CMakeLists.txt1
-rw-r--r--clang/lib/Headers/module.modulemap5
-rw-r--r--clang/lib/Headers/ptrauth.h185
3 files changed, 191 insertions, 0 deletions
diff --git a/clang/lib/Headers/CMakeLists.txt b/clang/lib/Headers/CMakeLists.txt
index b9a966b..902e33b 100644
--- a/clang/lib/Headers/CMakeLists.txt
+++ b/clang/lib/Headers/CMakeLists.txt
@@ -214,6 +214,7 @@ set(x86_files
popcntintrin.h
prfchiintrin.h
prfchwintrin.h
+ ptrauth.h
ptwriteintrin.h
raointintrin.h
rdpruintrin.h
diff --git a/clang/lib/Headers/module.modulemap b/clang/lib/Headers/module.modulemap
index 56a13f6..8741968f 100644
--- a/clang/lib/Headers/module.modulemap
+++ b/clang/lib/Headers/module.modulemap
@@ -315,3 +315,8 @@ module opencl_c {
header "opencl-c.h"
header "opencl-c-base.h"
}
+
+module ptrauth {
+ header "ptrauth.h"
+ export *
+}
diff --git a/clang/lib/Headers/ptrauth.h b/clang/lib/Headers/ptrauth.h
new file mode 100644
index 0000000..56c3c36
--- /dev/null
+++ b/clang/lib/Headers/ptrauth.h
@@ -0,0 +1,185 @@
+/*===---- ptrauth.h - Pointer authentication -------------------------------===
+ *
+ * Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+ * See https://llvm.org/LICENSE.txt for license information.
+ * SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+ *
+ *===-----------------------------------------------------------------------===
+ */
+
+#ifndef __PTRAUTH_H
+#define __PTRAUTH_H
+
+typedef enum {
+ ptrauth_key_asia = 0,
+ ptrauth_key_asib = 1,
+ ptrauth_key_asda = 2,
+ ptrauth_key_asdb = 3,
+} ptrauth_key;
+
+/* An integer type of the appropriate size for a discriminator argument. */
+typedef __UINTPTR_TYPE__ ptrauth_extra_data_t;
+
+/* An integer type of the appropriate size for a generic signature. */
+typedef __UINTPTR_TYPE__ ptrauth_generic_signature_t;
+
+/* A signed pointer value embeds the original pointer together with
+ a signature that attests to the validity of that pointer. Because
+ this signature must use only "spare" bits of the pointer, a
+ signature's validity is probabilistic in practice: it is unlikely
+ but still plausible that an invalidly-derived signature will
+ somehow equal the correct signature and therefore successfully
+ authenticate. Nonetheless, this scheme provides a strong degree
+ of protection against certain kinds of attacks. */
+
+/* Authenticating a pointer that was not signed with the given key
+ and extra-data value will (likely) fail by trapping. */
+
+#if __has_feature(ptrauth_intrinsics)
+
+/* Strip the signature from a value without authenticating it.
+
+ If the value is a function pointer, the result will not be a
+ legal function pointer because of the missing signature, and
+ attempting to call it will result in an authentication failure.
+
+ The value must be an expression of pointer type.
+ The key must be a constant expression of type ptrauth_key.
+ The result will have the same type as the original value. */
+#define ptrauth_strip(__value, __key) __builtin_ptrauth_strip(__value, __key)
+
+/* Blend a constant discriminator into the given pointer-like value
+ to form a new discriminator. Not all bits of the inputs are
+ guaranteed to contribute to the result.
+
+ On arm64e, the integer must fall within the range of a uint16_t;
+ other bits may be ignored.
+
+ The first argument must be an expression of pointer type.
+ The second argument must be an expression of integer type.
+ The result will have type uintptr_t. */
+#define ptrauth_blend_discriminator(__pointer, __integer) \
+ __builtin_ptrauth_blend_discriminator(__pointer, __integer)
+
+/* Add a signature to the given pointer value using a specific key,
+ using the given extra data as a salt to the signing process.
+
+ This operation does not authenticate the original value and is
+ therefore potentially insecure if an attacker could possibly
+ control that value.
+
+ The value must be an expression of pointer type.
+ The key must be a constant expression of type ptrauth_key.
+ The extra data must be an expression of pointer or integer type;
+ if an integer, it will be coerced to ptrauth_extra_data_t.
+ The result will have the same type as the original value. */
+#define ptrauth_sign_unauthenticated(__value, __key, __data) \
+ __builtin_ptrauth_sign_unauthenticated(__value, __key, __data)
+
+/* Authenticate a pointer using one scheme and resign it using another.
+
+ If the result is subsequently authenticated using the new scheme, that
+ authentication is guaranteed to fail if and only if the initial
+ authentication failed.
+
+ The value must be an expression of pointer type.
+ The key must be a constant expression of type ptrauth_key.
+ The extra data must be an expression of pointer or integer type;
+ if an integer, it will be coerced to ptrauth_extra_data_t.
+ The result will have the same type as the original value.
+
+ This operation is guaranteed to not leave the intermediate value
+ available for attack before it is re-signed.
+
+ Do not pass a null pointer to this function. A null pointer
+ will not successfully authenticate.
+
+ This operation traps if the authentication fails. */
+#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
+ __new_data) \
+ __builtin_ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
+ __new_data)
+
+/* Authenticate a data pointer.
+
+ The value must be an expression of non-function pointer type.
+ The key must be a constant expression of type ptrauth_key.
+ The extra data must be an expression of pointer or integer type;
+ if an integer, it will be coerced to ptrauth_extra_data_t.
+ The result will have the same type as the original value.
+
+ This operation traps if the authentication fails. */
+#define ptrauth_auth_data(__value, __old_key, __old_data) \
+ __builtin_ptrauth_auth(__value, __old_key, __old_data)
+
+/* Compute a signature for the given pair of pointer-sized values.
+ The order of the arguments is significant.
+
+ Like a pointer signature, the resulting signature depends on
+ private key data and therefore should not be reliably reproducible
+ by attackers. That means that this can be used to validate the
+ integrity of arbitrary data by storing a signature for that data
+ alongside it, then checking that the signature is still valid later.
+ Data which exceeds two pointers in size can be signed by either
+ computing a tree of generic signatures or just signing an ordinary
+ cryptographic hash of the data.
+
+ The result has type ptrauth_generic_signature_t. However, it may
+ not have as many bits of entropy as that type's width would suggest;
+ some implementations are known to compute a compressed signature as
+ if the arguments were a pointer and a discriminator.
+
+ The arguments must be either pointers or integers; if integers, they
+ will be coerce to uintptr_t. */
+#define ptrauth_sign_generic_data(__value, __data) \
+ __builtin_ptrauth_sign_generic_data(__value, __data)
+
+#else
+
+#define ptrauth_strip(__value, __key) \
+ ({ \
+ (void)__key; \
+ __value; \
+ })
+
+#define ptrauth_blend_discriminator(__pointer, __integer) \
+ ({ \
+ (void)__pointer; \
+ (void)__integer; \
+ ((ptrauth_extra_data_t)0); \
+ })
+
+#define ptrauth_sign_unauthenticated(__value, __key, __data) \
+ ({ \
+ (void)__key; \
+ (void)__data; \
+ __value; \
+ })
+
+#define ptrauth_auth_and_resign(__value, __old_key, __old_data, __new_key, \
+ __new_data) \
+ ({ \
+ (void)__old_key; \
+ (void)__old_data; \
+ (void)__new_key; \
+ (void)__new_data; \
+ __value; \
+ })
+
+#define ptrauth_auth_data(__value, __old_key, __old_data) \
+ ({ \
+ (void)__old_key; \
+ (void)__old_data; \
+ __value; \
+ })
+
+#define ptrauth_sign_generic_data(__value, __data) \
+ ({ \
+ (void)__value; \
+ (void)__data; \
+ ((ptrauth_generic_signature_t)0); \
+ })
+
+#endif /* __has_feature(ptrauth_intrinsics) */
+
+#endif /* __PTRAUTH_H */