[LLVMdev] [PATCH] Protection against stack-based memory corruption errors using SafeStack

Kostya Serebryany kcc at google.com
Fri Nov 14 14:15:25 PST 2014


On Wed, Nov 12, 2014 at 2:50 AM, Volodymyr Kuznetsov <vova.kuznetsov at epfl.ch
> wrote:

> Dear LLVM developers,
>
> We've applied the feedback we received on Phabricator on the SafeStack
> patches,
>

Did you investigate the possibility of moving the transformation from
codegen to the LLVM level, i.e. the same level where asan/msan/tsan/dfsan
work?
I understand that it's a lot of work, but it will pay off with greater
portability and maintainability later.

Also, did you reply to my comments about reusing compiler-rt code from
sanitizer_common?
I see lots of places in lib/safestack where you duplicate existing
functionality from lib/sanitizer_common

and added tests for all components of the SafeStack (thanks to our new
> developer Alexandre Bique at EPFL, who is working on the SafeStack
> starting this week). We would appreciate any suggestions on how we can
> further improve the SafeStack and help it's inclusion in LLVM.
>
> - Volodymyr Kuznetsov & the CPI team
>
> On Mon, Nov 3, 2014 at 5:05 PM, Volodymyr Kuznetsov <
> vova.kuznetsov at epfl.ch> wrote:
>
>> Dear LLVM developers,
>>
>> Our team has developed an LLVM-based protection mechanism that
>> (i) prevents control-flow hijack attacks enabled by memory
>> corruption errors and (ii) has very low performance overhead. We would like
>> to contribute the implementation to LLVM. We presented this work at
>> the OSDI 2014 conference, at several software companies, and several US
>> universities. We received positive feedback, and so we've open-sourced our
>> prototype available for download from our project website (
>> http://levee.epfl.ch).
>>
>> There are three components (safe stack, CPS, and CPI), and each can be
>> used individually. Our most stable part is the safe stack
>> instrumentation, which separates the program stack into a safe stack, which
>> stores return addresses, register spills, and local variables that are
>> statically verified to be accessed in a safe way, and the unsafe stack,
>> which stores everything else. Such separation makes it much harder for an
>> attacker to corrupt objects on the safe stack, including function pointers
>> stored in spilled registers and return addresses. A detailed description of
>> the individual components is available in our OSDI paper on code-pointer
>> integrity (http://dslab.epfl.ch/pubs/cpi.pdf).
>>
>> The overhead of our implementation of the safe stack is very close
>> to zero (0.01% on the Phoronix benchmarks and 0.03% on SPEC2006 CPU on
>> average). This is lower than the overhead of stack cookies, which
>> are supported by LLVM and are commonly used today, yet the
>> security guarantees of the safe stack are strictly stronger than stack
>> cookies. In some cases, the safe stack improves performance due to better
>> cache locality.
>>
>> Our current implementation of the safe stack is stable and robust,
>> we used it to recompile multiple projects on Linux including Chromium,
>> and we also recompiled the entire FreeBSD user-space system and more than
>> 100 packages. We ran unit tests on the FreeBSD system and many of the
>> packages and observed no errors caused by the safe stack. The safe stack is
>> also fully binary compatible with non-instrumented code and can be applied
>> to parts of a program selectively.
>>
>> We attach our implementation of the safe stack as three patches
>> against current SVN HEAD of LLVM (r221153), clang (r221154) and compiler-rt
>> (r220991). The same changes are also available on
>> https://github.com/cpi-llvm <http://github.com/cpi-llvm> in the
>> safestack-r221153 branches of corresponding repositories. The patches make
>> the following changes:
>>
>> -- Add the safestack function attribute, similar to the ssp,
>> sspstrong and sspreq attributes.
>> -- Add the SafeStack instrumentation pass that applies the safe stack to
>> all functions that have the safestack attribute. This pass moves all unsafe
>> local variables to the unsafe stack with a separate stack pointer, whereas
>> all safe variables remain on the regular stack that is managed by LLVM as
>> usual.
>> -- Invoke the pass as the last stage before code generation (at the same
>> time the existing cookie-based stack protector pass is invoked).
>> -- Add -fsafe-stack and -fno-safe-stack options to clang to control safe
>> stack usage (the safe stack is disabled by default).
>> -- Add __attribute__((no_safe_stack)) attribute to clang that can be used
>> to disable the safe stack for individual functions even when enabled
>> globally.
>> -- Add basic runtime support for the safe stack to compiler-rt.
>> The runtime manages unsafe stack allocation/deallocation for each thread.
>> -- Add unit tests for the safe stack.
>>
>> You can find more information about the safe stack, as well as
>> other parts of or control-flow hijack protection technique in our OSDI
>> paper. FYI here is the abstract of the paper:
>>
>> << Systems code is often written in low-level languages like C/C++,
>> which offer many benefits but also delegate memory management
>> to programmers. This invites memory safety bugs that attackers can exploit
>> to divert control flow and compromise the system. Deployed defense
>> mechanisms (e.g., ASLR, DEP) are incomplete, and stronger defense
>> mechanisms (e.g., CFI) often have high overhead and limited guarantees.
>>
>> We introduce code-pointer integrity (CPI), a new design point
>> that guarantees the integrity of all code pointers in a program
>> (e.g., function pointers, saved return addresses) and thereby prevents
>> all control-flow hijack attacks, including return-oriented programming.
>> We also introduce code-pointer separation (CPS), a relaxation of CPI
>> with better performance properties. CPI and CPS offer substantially
>> better security-to-overhead ratios than the state of the art, they
>> are practical (we protect a complete FreeBSD system and over 100
>> packages like apache and postgresql), effective (prevent all attacks in
>> the RIPE benchmark), and efficient: on SPEC CPU2006, CPS averages
>> 1.2% overhead for C and 1.9% for C/C++, while CPI’s overhead is 2.9% for
>> C and 8.4% for C/C++. >>
>>
>> (This is joint work with V. Kuznetsov, L. Szekeres, M. Payer, G. Candea,
>> R. Sekar, and D. Song)
>>
>> We look forward to your feedback and hope for a prompt merge into
>> LLVM, to make the software built with clang more secure.
>>
>> - Volodymyr Kuznetsov & the CPI team
>>
>
>
> _______________________________________________
> LLVM Developers mailing list
> LLVMdev at cs.uiuc.edu         http://llvm.cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvmdev
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-dev/attachments/20141114/92ba06cd/attachment.html>


More information about the llvm-dev mailing list