diff options
author | Peter Collingbourne <peter@pcc.me.uk> | 2018-04-04 21:55:44 +0000 |
---|---|---|
committer | Peter Collingbourne <peter@pcc.me.uk> | 2018-04-04 21:55:44 +0000 |
commit | f11eb3ebe77729426e562d7d4d7ebb1d5ff2e7c8 (patch) | |
tree | bb02cd6d80b6bbd8c47cc5b9490b26cb24a39d81 /clang/docs/ShadowCallStack.rst | |
parent | 4296ea72ffcef9fff5ce735dbbfeccd503200735 (diff) | |
download | bcm5719-llvm-f11eb3ebe77729426e562d7d4d7ebb1d5ff2e7c8.tar.gz bcm5719-llvm-f11eb3ebe77729426e562d7d4d7ebb1d5ff2e7c8.zip |
AArch64: Implement support for the shadowcallstack attribute.
The implementation of shadow call stack on aarch64 is quite different to
the implementation on x86_64. Instead of reserving a segment register for
the shadow call stack, we reserve the platform register, x18. Any function
that spills lr to sp also spills it to the shadow call stack, a pointer to
which is stored in x18.
Differential Revision: https://reviews.llvm.org/D45239
llvm-svn: 329236
Diffstat (limited to 'clang/docs/ShadowCallStack.rst')
-rw-r--r-- | clang/docs/ShadowCallStack.rst | 85 |
1 files changed, 64 insertions, 21 deletions
diff --git a/clang/docs/ShadowCallStack.rst b/clang/docs/ShadowCallStack.rst index 1436df274bd..b93eb0b7a70 100644 --- a/clang/docs/ShadowCallStack.rst +++ b/clang/docs/ShadowCallStack.rst @@ -9,11 +9,11 @@ Introduction ============ ShadowCallStack is an **experimental** instrumentation pass, currently only -implemented for x86_64, that protects programs against return address -overwrites (e.g. stack buffer overflows.) It works by saving a function's return -address to a separately allocated 'shadow call stack' in the function prolog and -checking the return address on the stack against the shadow call stack in the -function epilog. +implemented for x86_64 and aarch64, that protects programs against return +address overwrites (e.g. stack buffer overflows.) It works by saving a +function's return address to a separately allocated 'shadow call stack' +in the function prolog and checking the return address on the stack against +the shadow call stack in the function epilog. Comparison ---------- @@ -37,8 +37,16 @@ support. Compatibility ------------- -ShadowCallStack currently only supports x86_64. A runtime is not currently -provided in compiler-rt so one must be provided by the compiled application. +ShadowCallStack currently only supports x86_64 and aarch64. A runtime is not +currently provided in compiler-rt so one must be provided by the compiled +application. + +On aarch64, the instrumentation makes use of the platform register ``x18``. +On some platforms, ``x18`` is reserved, and on others, it is designated as +a scratch register. This generally means that any code that may run on the +same thread as code compiled with ShadowCallStack must either target one +of the platforms whose ABI reserves ``x18`` (currently Darwin, Fuchsia and +Windows) or be compiled with the flag ``-ffixed-x18``. Security ======== @@ -56,28 +64,37 @@ has been checked and before it has been returned to. Modifying the call-return semantics to fix this on x86_64 would incur an unacceptable performance overhead due to return branch prediction. -The instrumentation makes use of the ``gs`` segment register to reference the -shadow call stack meaning that references to the shadow call stack do not have -to be stored in memory. This makes it possible to implement a runtime that -avoids exposing the address of the shadow call stack to attackers that can read -arbitrary memory. However, attackers could still try to exploit side channels -exposed by the operating system `[1]`_ `[2]`_ or processor `[3]`_ to discover -the address of the shadow call stack. +The instrumentation makes use of the ``gs`` segment register on x86_64, +or the ``x18`` register on aarch64, to reference the shadow call stack +meaning that references to the shadow call stack do not have to be stored in +memory. This makes it possible to implement a runtime that avoids exposing +the address of the shadow call stack to attackers that can read arbitrary +memory. However, attackers could still try to exploit side channels exposed +by the operating system `[1]`_ `[2]`_ or processor `[3]`_ to discover the +address of the shadow call stack. .. _`[1]`: https://eyalitkin.wordpress.com/2017/09/01/cartography-lighting-up-the-shadows/ .. _`[2]`: https://www.blackhat.com/docs/eu-16/materials/eu-16-Goktas-Bypassing-Clangs-SafeStack.pdf .. _`[3]`: https://www.vusec.net/projects/anc/ -Leaf functions are optimized to store the return address in a free register -and avoid writing to the shadow call stack if a register is available. Very -short leaf functions are uninstrumented if their execution is judged to be -shorter than the race condition window intrinsic to the instrumentation. +On x86_64, leaf functions are optimized to store the return address in a +free register and avoid writing to the shadow call stack if a register is +available. Very short leaf functions are uninstrumented if their execution +is judged to be shorter than the race condition window intrinsic to the +instrumentation. + +On aarch64, the architecture's call and return instructions (``bl`` and +``ret``) operate on a register rather than the stack, which means that +leaf functions are generally protected from return address overwrites even +without ShadowCallStack. It also means that ShadowCallStack on aarch64 is not +vulnerable to the same types of time-of-check-to-time-of-use races as x86_64. Usage ===== -To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack`` flag -to both compile and link command lines. +To enable ShadowCallStack, just pass the ``-fsanitize=shadow-call-stack`` +flag to both compile and link command lines. On aarch64, you also need to pass +``-ffixed-x18`` unless your target already reserves ``x18``. Low-level API ------------- @@ -125,7 +142,20 @@ Generates the following x86_64 assembly when compiled with ``-O2``: pop %rcx retq -Adding ``-fsanitize=shadow-call-stack`` would output the following: +or the following aarch64 assembly: + +.. code-block:: none + + stp x29, x30, [sp, #-16]! + mov x29, sp + bl bar + add w0, w0, #1 + ldp x29, x30, [sp], #16 + ret + + +Adding ``-fsanitize=shadow-call-stack`` would output the following x86_64 +assembly: .. code-block:: gas @@ -148,3 +178,16 @@ Adding ``-fsanitize=shadow-call-stack`` would output the following: trap: ud2 + +or the following aarch64 assembly: + +.. code-block:: none + + str x30, [x18], #8 + stp x29, x30, [sp, #-16]! + mov x29, sp + bl bar + add w0, w0, #1 + ldp x29, x30, [sp], #16 + ldr x30, [x18, #-8]! + ret |