r240472 - SafeStack documentation improvements

Peter Collingbourne peter at pcc.me.uk
Tue Jun 23 15:24:45 PDT 2015


Author: pcc
Date: Tue Jun 23 17:24:45 2015
New Revision: 240472

URL: http://llvm.org/viewvc/llvm-project?rev=240472&view=rev
Log:
SafeStack documentation improvements

This patch makes the following improvements to the SafeStack documentation:

Explicitly states the security guarantees of the SafeStack
Clarifies which of the security guarantees are probabilistic
Re-orders security limitations to put the most severe ones first
Explains how `__attribute__((no_sanitize("safe-stack")))` works and how to use it safely
Explains that SafeStack should be combined with a forward-edge protection mechanism, such as CPI, IFCC or others
Multiple readability and stylistic improvements

Patch by Volodymyr Kuznetsov!

Differential Revision: http://reviews.llvm.org/D10598

Modified:
    cfe/trunk/docs/SafeStack.rst

Modified: cfe/trunk/docs/SafeStack.rst
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/docs/SafeStack.rst?rev=240472&r1=240471&r2=240472&view=diff
==============================================================================
--- cfe/trunk/docs/SafeStack.rst (original)
+++ cfe/trunk/docs/SafeStack.rst Tue Jun 23 17:24:45 2015
@@ -15,7 +15,10 @@ the safe stack and the unsafe stack. The
 register spills, and local variables that are always accessed in a safe way,
 while the unsafe stack stores everything else. This separation ensures that
 buffer overflows on the unsafe stack cannot be used to overwrite anything
-on the safe stack, which includes return addresses.
+on the safe stack.
+
+SafeStack is a part of the `Code-Pointer Integrity (CPI) Project
+<http://dslab.epfl.ch/proj/cpi/>`_.
 
 Performance
 -----------
@@ -34,37 +37,6 @@ used through multiple stack frames. Movi
 stack increases the locality of frequently accessed values on the stack, such
 as register spills, return addresses, and small local variables.
 
-Limitations
------------
-
-SafeStack has not been subjected to a comprehensive security review, and there
-exist known weaknesses, including but not limited to the following.
-
-In its current state, the separation of local variables provides protection
-against stack buffer overflows, but the safe stack itself is not protected
-from being corrupted through a pointer dereference. The Code-Pointer
-Integrity paper describes two ways in which we may protect the safe stack:
-hardware segmentation on the 32-bit x86 architecture or information hiding
-on other architectures.
-
-Even with information hiding, the safe stack would merely be hidden
-from attackers by being somewhere in the address space. Depending on the
-application, the address could be predictable even on 64-bit address spaces
-because not all the bits are addressable, multiple threads each have their
-stack, the application could leak the safe stack address to memory via
-``__builtin_frame_address``, bugs in the low-level runtime support etc.
-Safe stack leaks could be mitigated by writing and deploying a static binary
-analysis or a dynamic binary instrumentation based tool to find leaks.
-
-This approach doesn't prevent an attacker from "imbalancing" the safe
-stack by say having just one call, and doing two rets (thereby returning
-to an address that wasn't meant as a return address). This can be at least
-partially mitigated by deploying SafeStack alongside a forward control-flow
-integrity mechanism to ensure that calls are made using the correct calling
-convention. Clang does not currently implement a comprehensive forward
-control-flow integrity protection scheme; there exists one that protects
-:doc:`virtual calls <ControlFlowIntegrity>` but not non-virtual indirect calls.
-
 Compatibility
 -------------
 
@@ -83,21 +55,73 @@ work with SafeStack. One example is mark
 implementations for C/C++ (e.g., Oilpan in chromium/blink), which must be
 changed to look for the live pointers on both safe and unsafe stacks.
 
-SafeStack supports linking together modules that are compiled with and without
-SafeStack, both statically and dynamically. One corner case that is not
-supported is using ``dlopen()`` to load a dynamic library that uses SafeStack into
-a program that is not compiled with SafeStack but uses threads.
+SafeStack supports linking statically modules that are compiled with and
+without SafeStack. An executable compiled with SafeStack can load dynamic
+libraries that are not compiled with SafeStack. At the moment, compiling
+dynamic libraries with SafeStack is not supported.
 
 Signal handlers that use ``sigaltstack()`` must not use the unsafe stack (see
 ``__attribute__((no_sanitize("safe-stack")))`` below).
 
 Programs that use APIs from ``ucontext.h`` are not supported yet.
 
+Security
+--------
+
+SafeStack protects return addresses, spilled registers and local variables that
+are always accessed in a safe way by separating them in a dedicated safe stack
+region. The safe stack is automatically protected against stack-based buffer
+overflows, since it is disjoint from the unsafe stack in memory, and it itself
+is always accessed in a safe way. In the current implementation, the safe stack
+is protected against arbitrary memory write vulnerabilities though
+randomization and information hiding: the safe stack is allocated at a random
+address and the instrumentation ensures that no pointers to the safe stack are
+ever stored outside of the safe stack itself (see limitations below).
+
+Known security limitations
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+A complete protection against control-flow hijack attacks requires combining
+SafeStack with another mechanism that enforces the integrity of code pointers
+that are stored on the heap or the unsafe stack, such as `CPI
+<http://dslab.epfl.ch/proj/cpi/>`_, or a forward-edge control flow integrity
+mechanism that enforces correct calling conventions at indirect call sites,
+such as `IFCC <http://research.google.com/pubs/archive/42808.pdf>`_ with arity
+checks. Clang has control-flow integrity protection scheme for `C++ virtual
+calls <ControlFlowIntegrity>`, but not non-virtual indirect calls. With
+SafeStack alone, an attacker can overwrite a function pointer on the heap or
+the unsafe stack and cause a program to call arbitrary location, which in turn
+might enable stack pivoting and return-oriented programming.
+
+In its current implementation, SafeStack provides precise protection against
+stack-based buffer overflows, but protection against arbitrary memory write
+vulnerabilities is probabilistic and relies on randomization and information
+hiding. The randomization is currently based on system-enforced ASLR and shares
+its known security limitations. The safe stack pointer hiding is not perfect
+yet either: system library functions such as ``swapcontext``, exception
+handling mechanisms, intrinsics such as ``__builtin_frame_address``, or
+low-level bugs in runtime support could leak the safe stack pointer. In the
+future, such leaks could be detected by static or dynamic analysis tools and
+prevented by adjusting such functions to either encrypt the stack pointer when
+storing it in the heap (as already done e.g., by ``setjmp``/``longjmp``
+implementation in glibc), or store it in a safe region instead.
+
+The `CPI paper <http://dslab.epfl.ch/pubs/cpi.pdf>`_ describes two alternative,
+stronger safe stack protection mechanisms, that rely on software fault
+isolation, or hardware segmentation (as available on x86-32 and some x86-64
+CPUs).
+
+At the moment, SafeStack assumes that the compiler's implementation is correct.
+This has not been verified except through manual code inspection, and could
+always regress in the future. It's therefore desirable to have a separate
+static or dynamic binary verification tool that would check the correctness of
+the SafeStack instrumentation in final binaries.
+
 Usage
 =====
 
-To enable SafeStack, just pass ``-fsanitize=safe-stack`` flag to both compile and link
-command lines.
+To enable SafeStack, just pass ``-fsanitize=safe-stack`` flag to both compile
+and link command lines.
 
 Supported Platforms
 -------------------
@@ -129,10 +153,11 @@ function, even if enabled globally (see
 attribute may be required for functions that make assumptions about the
 exact layout of their stack frames.
 
-Care should be taken when using this attribute. The return address is not
-protected against stack buffer overflows, and it is easier to leak the
-address of the safe stack to memory by taking the address of a local variable.
-
+All local variables in functions with this attribute will be stored on the safe
+stack. The safe stack remains unprotected against memory errors when accessing
+these variables, so extra care must be taken to manually ensure that all such
+accesses are safe. Furthermore, the addresses of such local variables should
+never be stored on the heap, as it would leak the location of the SafeStack.
 
 ``__builtin___get_unsafe_stack_ptr()``
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -149,10 +174,9 @@ current thread.
 Design
 ======
 
-Please refer to
-`http://dslab.epfl.ch/proj/cpi/ <http://dslab.epfl.ch/proj/cpi/>`_ for more
-information about the design of the SafeStack and its related technologies.
-
+Please refer to the `Code-Pointer Integrity <http://dslab.epfl.ch/proj/cpi/>`_
+project page for more information about the design of the SafeStack and its
+related technologies.
 
 Publications
 ------------





More information about the cfe-commits mailing list