Index: docs/SafeStack.rst =================================================================== --- docs/SafeStack.rst +++ docs/SafeStack.rst @@ -15,7 +15,10 @@ 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 +`_. Performance ----------- @@ -34,37 +37,6 @@ 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 ` but not non-virtual indirect calls. - Compatibility ------------- @@ -83,21 +55,73 @@ 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 +`_, or a forward-edge control flow integrity +mechanism that enforces correct calling conventions at indirect call sites, +such as `IFCC `_ with arity +checks. Clang has control-flow integrity protection scheme for `C++ virtual +calls `, 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 `_ 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 @@ 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 @@ Design ====== -Please refer to -`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 `_ +project page for more information about the design of the SafeStack and its +related technologies. Publications ------------