================ @@ -255,33 +260,160 @@ signing schema breaks down even more simply: It is important that the signing schema be independently derived at all signing and authentication sites. Preferably, the schema should be hard-coded everywhere it is needed, but at the very least, it must not be derived by -inspecting information stored along with the pointer. +inspecting information stored along with the pointer. See the section on +`Attacks on pointer authentication`_ for more information. + -Language Features +Language features ----------------- -There is currently one main pointer authentication language feature: +There are three levels of the pointer authentication language feature: + +- The language implementation automatically signs and authenticates function + pointers (and certain data pointers) across a variety of standard situations, + including return addresses, function pointers, and C++ virtual functions. The + intent is for all pointers to code in program memory to be signed in some way + and for all branches to code in program text to authenticate those + signatures. + +- The language also provides extensions to override the default rules used by + the language implementation. For example, the ``__ptrauth`` type qualifier + can be used to change how pointers are signed when they are stored in + a particular variable or field; this provides much stronger protection than + is guaranteed by the default rules for C function and data pointers. -- The language provides the ``<ptrauth.h>`` intrinsic interface for manually - signing and authenticating pointers in code. These can be used in +- Finally, the language provides the ``<ptrauth.h>`` intrinsic interface for + manually signing and authenticating pointers in code. These can be used in circumstances where very specific behavior is required. +Language implementation +~~~~~~~~~~~~~~~~~~~~~~~ + +For the most part, pointer authentication is an unobserved detail of the +implementation of the programming language. Any element of the language +implementation that would perform an indirect branch to a pointer is implicitly +altered so that the pointer is signed when first constructed and authenticated +when the branch is performed. This includes: + +- indirect-call features in the programming language, such as C function + pointers, C++ virtual functions, C++ member function pointers, the "blocks" + C extension, and so on; + +- returning from a function, no matter how it is called; and + +- indirect calls introduced by the implementation, such as branches through the + global offset table (GOT) used to implement direct calls to functions defined + outside of the current shared object. + +For more information about this, see the `Language ABI`_ section. + +However, some aspects of the implementation are observable by the programmer or +otherwise require special notice. + +C data pointers +^^^^^^^^^^^^^^^ + +The current implementation in Clang does not sign pointers to ordinary data by +default. For a partial explanation of the reasoning behind this, see the +`Theory of Operation`_ section. + +A specific data pointer which is more security-sensitive than most can be +signed using the `__ptrauth qualifier`_ or using the ``<ptrauth.h>`` +intrinsics. + +C function pointers +^^^^^^^^^^^^^^^^^^^ -Language Extensions +The C standard imposes restrictions on the representation and semantics of +function pointer types which make it difficult to achieve satisfactory +signature diversity in the default language rules. See `Attacks on pointer +authentication`_ for more information about signature diversity. Programmers +should strongly consider using the ``__ptrauth`` qualifier to improve the +protections for important function pointers, such as the components of of +a hand-rolled "v-table"; see the section on the `__ptrauth qualifier`_ for +details. + +The value of a pointer to a C function includes a signature, even when the +value is cast to a non-function-pointer type like ``void*`` or ``intptr_t``. On +implementations that use high bits to store the signature, this means that +relational comparisons and hashes will vary according to the exact signature +value, which is likely to change between executions of a program. In some +implementations, it may also vary based on the exact function pointer type. + +Null pointers +^^^^^^^^^^^^^ + +In principle, an implementation could derive the signed null pointer value +simply by applying the standard signing algorithm to the raw null pointer +value. However, for likely signing algorithms, this would mean that the signed +null pointer value would no longer be statically known, which would have many +negative consequences. For one, it would become substantially more expensive +to emit null pointer values or to perform null-pointer checks. For another, +the pervasive (even if technically unportable) assumption that null pointers +are bitwise zero would be invalidated, making it substantially more difficult +to adopt pointer authentication, as well as weakening common optimizations for +zero-initialized memory such as the use of ``.bzz`` sections. Therefore it is +beneficial to treat null pointers specially by giving them their usual +representation. On AArch64, this requires additional code when working with +possibly-null pointers, such as when copying a pointer field that has been +signed with address diversity. + +While this representation of nulls is the safest option for the general case, +there are some situations in which a null pointer may have important semantic +or security impact. For that purpose clang has the concept of a pointer ---------------- ojhunt wrote:
definitely pushed now https://github.com/llvm/llvm-project/pull/152596 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits