================ @@ -500,12 +711,916 @@ type. Implementations are not required to make all bits of the result equally significant; in particular, some implementations are known to not leave meaningful data in the low bits. +Standard ``__ptrauth`` qualifiers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``<ptrauth.h>`` additionally provides several macros which expand to +``__ptrauth`` qualifiers for common ABI situations. + +For convenience, these macros expand to nothing when pointer authentication is +disabled. + +These macros can be found in the header; some details of these macros may be +unstable or implementation-specific. + + +Theory of operation +------------------- + +The threat model of pointer authentication is as follows: + +- The attacker has the ability to read and write to a certain range of + addresses, possibly the entire address space. However, they are constrained + by the normal rules of the process: for example, they cannot write to memory + that is mapped read-only, and if they access unmapped memory it will trigger + a trap. + +- The attacker has no ability to add arbitrary executable code to the program. + For example, the program does not include malicious code to begin with, and + the attacker cannot alter existing instructions, load a malicious shared + library, or remap writable pages as executable. If the attacker wants to get + the process to perform a specific sequence of actions, they must somehow + subvert the normal control flow of the process. + +In both of the above paragraphs, it is merely assumed that the attacker's +*current* capabilities are restricted; that is, their current exploit does not +directly give them the power to do these things. The attacker's immediate goal +may well be to leverage their exploit to gain these capabilities, e.g. to load +a malicious dynamic library into the process, even though the process does not +directly contain code to do so. + +Note that any bug that fits the above threat model can be immediately exploited +as a denial-of-service attack by simply performing an illegal access and +crashing the program. Pointer authentication cannot protect against this. +While denial-of-service attacks are unfortunate, they are also unquestionably +the best possible result of a bug this severe. Therefore, pointer authentication +enthusiastically embraces the idea of halting the program on a pointer +authentication failure rather than continuing in a possibly-compromised state. + +Pointer authentication is a form of control-flow integrity (CFI) enforcement. +The basic security hypothesis behind CFI enforcement is that many bugs can only +be usefully exploited (other than as a denial-of-service) by leveraging them to +subvert the control flow of the program. If this is true, then by inhibiting or +limiting that subversion, it may be possible to largely mitigate the security +consequences of those bugs by rendering them impractical (or, ideally, +impossible) to exploit. + +Every indirect branch in a program has a purpose. Using human intelligence, a +programmer can describe where a particular branch *should* go according to this +purpose: a ``return`` in ``printf`` should return to the call site, a particular +call in ``qsort`` should call the comparator that was passed in as an argument, +and so on. But for CFI to enforce that every branch in a program goes where it +*should* in this sense would require CFI to perfectly enforce every semantic +rule of the program's abstract machine; that is, it would require making the +programming environment perfectly sound. That is out of scope. Instead, the +goal of CFI is merely to catch attempts to make a branch go somewhere that its +obviously *shouldn't* for its purpose: for example, to stop a call from +branching into the middle of a function rather than its beginning. As the +information available to CFI gets better about the purpose of the branch, CFI +can enforce tighter and tighter restrictions on where the branch is permitted to +go. Still, ultimately CFI cannot make the program sound. This may help explain +why pointer authentication makes some of the choices it does: for example, to +sign and authenticate mostly code pointers rather than every pointer in the +program. Preventing attackers from redirecting branches is both particularly +important and particularly approachable as a goal. Detecting corruption more +broadly is infeasible with these techniques, and the attempt would have far +higher cost. + +Attacks on pointer authentication +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pointer authentication works as follows. Every indirect branch in a program has +a purpose. For every purpose, the implementation chooses a +:ref:`signing schema<Signing schemas>`. At some place where a pointer is known +to be correct for its purpose, it is signed according to the purpose's schema. +At every place where the pointer is needed for its purpose, it is authenticated +according to the purpose's schema. If that authentication fails, the program is +halted. + +There are a variety of ways to attack this. + +Attacks of interest to programmers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These attacks arise from weaknesses in the default protections offered by +pointer authentication. They can be addressed by using attributes or intrinsics +to opt in to stronger protection. + +Substitution attacks +++++++++++++++++++++ + +An attacker can simply overwrite a pointer intended for one purpose with a +pointer intended for another purpose if both purposes use the same signing +schema and that schema does not use address diversity. + +The most common source of this weakness is when code relies on using the default +language rules for C function pointers. The current implementation uses the +exact same signing schema for all C function pointers, even for functions of +substantially different type. While efforts are ongoing to improve constant +diversity for C function pointers of different type, there are necessary limits +to this. The C standard requires function pointers to be copyable with +``memcpy``, which means that function pointers can never use address diversity. +Furthermore, even if a function pointer can only be replaced with another +function of the exact same type, that can still be useful to an attacker, as in +the following example of a hand-rolled "v-table": + +.. code-block:: c + + struct ObjectOperations { + void (*retain)(Object *); + void (*release)(Object *); + void (*deallocate)(Object *); + void (*logStatus)(Object *); + }; + +The weakness in this design is that by lacking any context specific +discriminator, means an attacker can substiture any of these fields with any ---------------- kbeyls wrote:
s/substiture/substitute/? also maybe s/, means/, it means/? Otherwise looks good, thanks! 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