Skip to content
/ lfi Public
forked from zyedidia/lfi

Lightweight Fault Isolation: Practical, Efficient, and Secure Software Sandboxing

License

Notifications You must be signed in to change notification settings

brandonlou/lfi

 
 

Repository files navigation

Lightweight Fault Isolation

Lightweight Fault Isolation (LFI) is a performant and secure software sandboxing system targeting the ARM64 architecture. LFI allows you to run up to 64K sandboxes in a single address space while guaranteeing that the sandboxes are completely isolated from each other. Each sandbox may be given up to 4GiB of memory.

The LFI sandboxer only accepts ELF binaries that pass a verification step to ensure they are safe to run. These binaries may be generated by any LFI-compatible compiler toolchain.

We provide a compiler pass that reads arbitrary GNU assembly files (.s), and produces assembly files that will pass verification. Currently, we also provide wrapper tools to transparently use the assembly rewriter with any version of Clang, as well as prebuilt LFI-compatible libraries for an LLVM-based C/C++ toolchain (compiler-rt, musl-libc, libc++, libc++abi, libunwind). Support for GCC is currently experimental but we have a working prototype that we hope to provide soon.

LFI-compatible programs are performant: on the SPEC 2017 benchmark suite, we observe a runtime overhead of 7% and a code size overhead of 14%. This compares well with LLVM-based ahead-of-time WebAssembly compilers, which incur upwards of 20% runtime overhead (measured on an M1 Mac and a GCP T2A instance). LFI is also secure: the compiler toolchain used to produce LFI-compatible programs is not a part of the trusted code base, and speculative sandbox breakout attacks are mitigated by default (the sandbox does not rely on any branching bounds checks or strong CFI).

LFI supports all source-level language features and targets the ARMv8.0-A ISA (including SIMD), but does not support dynamic code generation. We are also planning to add support for ARMv8.1+ extensions.

LFI is currently in development. For now, please only use it for experimentation. In particular, so far the runtime has been primarily used for collecting measurements, and may not provide a fully sandboxed environment. We are currently working on ensuring it is fully secure.

Please see the following paper for more details: https://zyedidia.github.io/papers/lfi_asplos24.pdf.

Tools

The LFI project provides the following tools:

  • lfi-gen: reads a .s file, and produces an LFI-compatible .s file.
  • lfi-verify: verifies ELF binaries for LFI-compatibility.
  • lfi-run: runs an LFI-compatible binary.
  • lfi-compile: when invoked with a recognized compiler, this program will automatically interpose on the compilation process and invoke lfi-gen on the intermediate .s file. Currently only supports clang/clang++/gcc/g++.
  • compiler: a collection of wrapper scripts that invoke lfi-compile with a desired compiler and set of compiler flags.

Installation

First, install your system's version of Clang, LLVM, and LLD. We typically test with LLVM 15, but any relatively modern version should work.

Prebuilt toolchain

A prebuilt toolchain is provided in the GitHub releases: https://github.com/zyedidia/lfi/releases/tag/prerelease. It is built for Linux AArch64.

The tarball provides the LFI binaries in the bin directory, and a compiler sysroot in toolchain.

Building from source

Note: for artifact evaluation (reproducing paper results), please first check out the tag ae-initial.

To build the LFI binaries from source, run the following:

go install ./lfi-gen
go install ./lfi-compile

cd lfi-verify
cargo install --path /path/to/bin
cd ..

cd lfi-run
knit
mv lfi-run /path/to/bin
cd ..

Next you must build the runtime libraries including the C and C++ standard libraries, and compiler-rt.

We recommend LLVM version 15.0.7. This can be installed on Ubuntu 22.04 with sudo apt install clang-15 llvm-15 lld-15. To make it the default clang on your system, run the script ./toolchain/update-alternatives.sh 15 200.

Then you can install the LLVM toolchain:

cd toolchain
./install-toolchain /tmp/lfi/toolchain
sudo mv /tmp/lfi /opt
# put /opt/lfi/toolchain/bin on your PATH

Example

Once you have installed all the tools, you can build simple programs.

#include <stdio.h>
int main() {
    printf("Hello from LFI\n");
    return 0;
}
$ lfi-clang hello.c -O2 -o hello
$ lfi-verify hello # check if it verifies
verifying test
verification passed (3.2 MB/s)
$ lfi-run hello
Hello from LFI

Roadmap

The LFI project is currently under development. We are currently focused on the following features:

  • New capabilities and full security for the runtime.
  • Support for additional ARM extensions.
  • Support for GCC (in-progress).
  • Optimized integration with WebAssembly (efficiently run WebAssembly inside LFI).
  • Instrumentation of static binaries, so you don't need to recompile your program.
  • Support for cool new features that are not yet announced.
  • Support for ARM software context IDs for mitigating Spectre attacks (requires modifications to Linux, which Arm will hopefully implement soon).

We are currently exploring support for x86-64 and hope to have a prototype available the coming months.

About

Lightweight Fault Isolation: Practical, Efficient, and Secure Software Sandboxing

Resources

License

Stars

Watchers

Forks

Languages

  • C 51.6%
  • D 18.6%
  • Go 10.9%
  • C++ 6.3%
  • Rust 5.2%
  • Assembly 3.8%
  • Other 3.6%