Skip to content

Commit 2b79c5f

Browse files
committed
Reorganize into landing page for lfi-project
1 parent e3f05dd commit 2b79c5f

417 files changed

Lines changed: 99 additions & 143708 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

LICENSE

Lines changed: 0 additions & 378 deletions
This file was deleted.

README.md

Lines changed: 74 additions & 186 deletions
Original file line numberDiff line numberDiff line change
@@ -1,221 +1,109 @@
1-
<h1>LFI <img src="assets/lfi-logo.svg" alt="logo" width="30px"/></h1>
1+
# Lightweight Fault Isolation
22

3-
![Test Workflow](https://github.com/zyedidia/lfi/actions/workflows/test.yaml/badge.svg)
4-
[![MPL License](https://img.shields.io/badge/license-MPL%202.0-blue)](https://github.com/zyedidia/lfi/blob/master/LICENSE)
3+
Welcome to the home of the Lightweight Fault Isolation (LFI) project. The
4+
project is hosted on GitHub in the https://github.com/lfi-project organization.
5+
This repository contains information and tutorials about how to use LFI.
56

6-
LFI (Lightweight Fault Isolation) is a performant and secure software
7-
sandboxing system targeting the ARM64 and x86-64 architectures. LFI allows you
8-
to run ~64K (ARM64) or ~3K (x86-64) sandboxes in a single address space while
9-
guaranteeing that the sandboxes cannot read or write each other's memory. Each
10-
sandbox may be given up to 4GiB of memory. These sandboxes are very efficient:
11-
on ARM64 they run with roughly 7% overhead compared to native code when
12-
sandboxing reads and writes, and 1.5% overhead when only sandboxing writes
13-
(x86-64 has slightly higher overheads). Since all sandboxes exist in the same
14-
address space, context switches do not require changing the CPU's privilege
15-
level (i.e., transitioning to kernel mode).
16-
17-
The code for LFI is currently being reorganized as part of a transition to a
18-
production-ready project. Please see https://github.com/lfi-project and stay
19-
tuned for more details.
20-
21-
# Tools
7+
The GitHub organization has several repositories for the different components of LFI:
228

23-
The LFI project provides the following tools:
9+
* [`lfi-runtime`](https://github.com/lfi-project/lfi-runtime): the runtime responsible for loading LFI programs, handling host calls, and running verification.
10+
* [`lfi-verifier`](https://github.com/lfi-project/lfi-verifier): the LFI verifier.
11+
* [`lfi-rewriter`](https://github.com/lfi-project/lfi-rewriter): the LFI rewriter for GNU assembly, and a post-linker tool for performing binary transformations after linking (only necessary on x86-64).
12+
* [`lfi-bind`](https://github.com/lfi-project/lfi-bind): a tool for generating trampolines and initialization routines for running libraries inside of LFI sandboxes.
13+
* [`lfi-llvm-toolchain`](https://github.com/lfi-project/lfi-llvm-toolchain): scripts for building an LLVM-based LFI compiler toolchain, along with a sysroot including compiler-rt, musl, libc++, and mimalloc.
14+
* [`llvm-project`](https://github.com/lfi-project/llvm-project): our development fork of the LLVM project.
15+
* [`lfi-specification`](https://github.com/lfi-project/lfi-specification): the LaTeX sources for the LFI specification document.
2416

25-
* `lfi-leg`: reads a `.s` file, and produces an LFI-compatible `.s` file.
26-
* `lfi-verify`: verifies ELF binaries for LFI-compatibility.
27-
* `lfi-postlink`: patches binaries after linking (required for certain x86-64 optimizations).
28-
* `lfi-run`: runs an LFI-compatible binary.
17+
As a research project, LFI implementation initially existed in the
18+
https://github.com/zyedidia/lfi repository. See the `lfi-research` branch of
19+
this repository for that version.
2920

30-
# Installation
21+
# What is LFI?
3122

32-
There are two components to LFI: a compiler toolchain that can build
33-
LFI-compatible binaries, and a runtime library for creating, verifying, and
34-
managing sandboxes. For either of these components, you can either use prebuilt
35-
versions provided with releases, or build from source.
36-
37-
## Prebuilt distribution
38-
39-
Prebuilt toolchains are provided in the GitHub releases:
40-
https://github.com/zyedidia/lfi/releases/. The prebuilt toolchain includes a
41-
full Clang compiler based on LLVM 19.
42-
43-
When you download a prebuilt toolchain, you will see the following directories:
23+
LFI (Lightweight Fault Isolation) is a performant and secure software
24+
sandboxing system targeting the Arm64 and x86-64 architectures. LFI allows you
25+
to run ~64K (Arm64) or ~3K (x86-64) sandboxes in a single address space while
26+
guaranteeing that the sandboxes cannot read or write each other's memory. Each
27+
sandbox may be given up to 4GiB of memory. These sandboxes are very efficient:
28+
they run with roughly 7% (Arm64)/8% (x86-64) overhead compared to native code
29+
when sandboxing reads and writes, and 1.5% (Arm64)/6% (x86-64) overhead when
30+
only sandboxing writes, measured on SPEC 2017. Since all sandboxes exist in the
31+
same address space, context switches do not require changing the CPU's
32+
privilege level (i.e., transitioning to kernel mode).
4433

45-
* `lfi-bin/`: contains the LFI rewriter, verifier, and runtime. Put this on
46-
your `PATH`.
47-
* `bin/`: contains the LLVM compiler binaries.
48-
* `sysroot/`: contains the LFI sysroot, including libc, libc++, a dynamic
49-
linker, and additional runtime support libraries.
34+
# Getting Started
5035

51-
## Building from source
36+
To get started with LFI, you'll need an LFI compiler. You can get one from
37+
https://github.com/lfi-project/lfi-llvm-toolchain. Prebuilt compilers aarch64
38+
and x86-64 compilers are hosted in the releases:
39+
https://github.com/lfi-project/lfi-llvm-toolchain/releases/tag/v0.9.
5240

53-
To build and install the LFI tools, run the following commands:
41+
After opening the archive, you should see a directory structure like this:
5442

5543
```
56-
meson setup build --prefix=$PWD/install
57-
cd build
58-
ninja install
44+
├── bin
45+
│   ├── LLVM tools (clang, lld, ...)
46+
├── include
47+
├── lfi-bin
48+
│   ├── lfi-postlink
49+
│   ├── lfi-rewrite
50+
│   ├── lfi-run
51+
│   ├── lfi-verify
52+
│   ├── ARCH-lfi-linux-musl-clang -> ../bin/clang
53+
│   └── ARCH-lfi-linux-musl-clang++ -> ../bin/clang++
54+
├── lfi-clang
55+
│   ├── ARCH-lfi-linux-musl-clang -> ../bin/clang
56+
│   └── ARCH-lfi-linux-musl-clang++ -> ../bin/clang++
57+
├── lib
58+
├── libexec
59+
├── share
60+
└── sysroot
5961
```
6062

61-
You will find the generated binaries, libraries, and headers in `$PWD/install`
62-
(or in your prefix of choice). Before building a compiler toolchain, you should
63-
make sure the installed `bin` directory is on your `PATH`.
64-
65-
Next, you might want to build a compiler toolchain based on LLVM or GCC. For
66-
instructions and scripts, see [lfi-gcc](https://github.com/zyedidia/lfi-gcc)
67-
and [lfi-llvm](https://github.com/zyedidia/lfi-llvm-toolchain).
63+
You'll want to add the `lfi-bin` directory to your `PATH`. If you already have
64+
the LFI tools installed via a separate installation, consider only adding
65+
`lfi-clang` to your `PATH` instead.
6866

69-
# Example
67+
Once you have a compiler, you should be able to build a simple C or C++ program:
7068

71-
Once you have installed all the tools, you can build simple programs.
72-
73-
```
69+
```c
7470
#include <stdio.h>
7571
int main() {
7672
printf("Hello from LFI\n");
7773
return 0;
7874
}
7975
```
8076

81-
With Clang:
77+
Compile and run using `lfi-run`:
8278

8379
```
8480
$ aarch64-lfi-linux-musl-clang hello.c -O2 -o hello -static-pie
85-
$ lfi-verify hello # check if it verifies (also performed by lfi-run)
86-
verifying test
87-
verification passed (3.2 MB/s)
88-
$ lfi-run hello
81+
$ lfi-run -v ./hello
8982
Hello from LFI
9083
```
9184

92-
And with GCC:
85+
You can use the prebuilt `lfi-run` tool from the prebuilt archive. You can also
86+
easily build the LFI runtime from source:
9387

9488
```
95-
$ aarch64-lfi-linux-musl-gcc hello.c -O2 -o hello -static-pie
96-
$ lfi-run hello
97-
Hello from LFI
89+
git clone https://github.com/lfi-project/lfi-runtime
90+
cd lfi-runtime
91+
meson setup build
92+
cd build
93+
ninja
94+
./tools/lfi-run/lfi-run ...
9895
```
9996

100-
# Advanced Usage
97+
The `lfi-run` tool is primarily meant for benchmarking and testing. It does not
98+
run verification by default (pass `-v` to enable), and it allows full
99+
filesystem access by default. See the usage (`lfi-run --help`) for more
100+
information.
101101

102-
The `lfi-leg` rewriter tool supports options for configuring the sandboxing approach.
102+
# Next Steps
103103

104-
```
105-
Usage: lfi-leg [OPTION...] INPUT
106-
lfi-gen: rewrite assembly files to be compatible with LFI
107-
108-
-a, --arch=ARCH Set the target architecture (arm64,amd64)
109-
--cfi=TYPE Select CFI mechanism (bundle16,bundle32)
110-
--no-guard-elim Do not run redundant guard elimination
111-
--no-segue Do not use segment register to store the sandbox
112-
base
113-
-o, --output=FILE Output to FILE instead of standard output
114-
--poc Produce position-oblivious code (implies
115-
--sys-external)
116-
--single-thread Specify single-threaded target
117-
--sys-external Store runtime call table outside sandbox
118-
-s, --sandbox=TYPE Select sandbox type
119-
(full,stores,bundle-jumps,none)
120-
-?, --help Give this help list
121-
--usage Give a short usage message
122-
```
104+
After building and running your first LFI program, you may want to pursue
105+
several further directions. See the following guides for some suggestions:
123106

124-
Some notes:
125-
126-
* By default, LFI on x86-64 uses 16-byte bundles. We have measured better
127-
performance with 32-byte bundles on Intel machines, and better performance
128-
with 16-byte bundles on AMD machines. LFI does not use bundles on Arm64.
129-
* The `--sandbox` option can be used to configure isolation granularity. With
130-
`stores`, only stores and control-flow is sandboxed. Programs are allowed to
131-
read outside of their memory. With `bundle-jumps`, LFI only enforces that
132-
bundles are the targets of jumps, but does not enforce that jumps are
133-
constrained to the sandbox, and does not enforce memory isolation.
134-
* The `--single-thread` option in combination with `--sandbox=bundle-jumps`
135-
allows for more efficient return sequences, but is only applicable when
136-
sandboxed programs are single-threaded.
137-
138-
# Technical Summary
139-
140-
The LFI sandboxer only accepts ELF binaries that pass a verification step to
141-
ensure they are safe to run. This verifier works by analyzing binary machine
142-
code to ensure that the program will not access memory outside of its 4GiB
143-
region or execute any system calls or other "unsafe" instructions. The verifier
144-
is extremely simple, and is implemented in only a few hundred lines of code,
145-
located in `lfi-verify/arm64/verify.c`. Thanks to the verifier, the compiler
146-
used to generate the code is untrusted, so bugs in LLVM or GCC cannot cause
147-
security vulnerabilities. This approach is both more secure and more performant
148-
than current approaches that rely on a trusted compiler like Cranelift. The
149-
verifier is also efficient, and can process machine code at a throughput of
150-
100+ MiB/s on a Macbook Air.
151-
152-
In addition, LFI binaries may be generated by any LFI-compatible compiler
153-
toolchain. LFI-compatible Clang and GCC toolchains are provided.
154-
155-
The core of the LFI toolchain is an assembly rewriter that reads arbitrary GNU
156-
assembly files (`.s`) and produces assembly files that will pass verification
157-
when compiled and linked. This rewriter is implemented as a set of PEG parsers
158-
that are compiled to C using Leg, and consists of roughly 2,000 lines of code
159-
total (ARM64 and x86-64). It is located in `lfi-leg/`.
160-
161-
LFI-compatible programs are performant: on the SPEC 2017 benchmark suite, we
162-
measured a runtime overhead of 7% and a code size overhead of 14% for full
163-
isolation. This compares well with LLVM-based ahead-of-time WebAssembly
164-
compilers, which incur upwards of 20% runtime overhead. Additionally, LFI can
165-
be used for pure fault isolation, where sandboxes may read, but not write,
166-
each other's memory. In this case, we measured a runtime overhead of around
167-
1.5%. LFI also compares well with Native Client (NaCl), the most widely-known
168-
prior SFI system, which incurred around 16% overhead for full isolation and 7%
169-
overhead for just stores on x86-64 SPEC benchmarks. NaCl never received Arm64
170-
support before being deprecated.
171-
172-
LFI is also secure: the compiler toolchain used to
173-
produce LFI-compatible programs is not a part of the trusted code base, and LFI
174-
is significantly more Spectre-resistant compared to WebAssembly.
175-
176-
LFI supports all source-level language features and targets the ARMv8.0-A ISA
177-
(including SIMD) plus the ARMv8.1 LSE extension.
178-
179-
The last component of an LFI system is the runtime, which loads programs and
180-
handles runtime calls (e.g., syscalls) on their behalf. To create your own
181-
runtime, you can use `liblfi`, which provides utility functions for creating and
182-
running sandboxes, and handling runtime calls (it is up to you what runtime
183-
calls are available and what they do).
184-
185-
The `lfi-run` program is an example LFI runtime that behaves like a subset of
186-
Linux, and can be used to run many programs compiled for Linux with an LFI
187-
toolchain. This runtime is useful for running benchmarks such as SPEC 2017.
188-
189-
LFI is currently in development and is a research project.
190-
191-
# Library Sandboxing
192-
193-
By default, the LFI compiler produces executables that you can run in a
194-
sandboxed environment. To adapt this model to library sandboxing, a tool called
195-
[lfi-bind](https://github.com/zyedidia/lfi-bind) can be used to generate bindings for
196-
a library compiled with LFI so that functions within the sandbox can be invoked
197-
by a host. Since the LFI sandbox runs within a single process, invoking a
198-
sandboxed function is very cheap -- roughly 20-40 cycles.
199-
200-
## Specification
201-
202-
LFI's current sandboxing schemes for Arm64 and x86-64 are documented in the
203-
[LFI specification](https://www.scs.stanford.edu/~zyedidia/docs/lfi/lfi-spec.pdf).
204-
205-
# Publication
206-
207-
Zachary Yedidia. "Lightweight Fault Isolation: Practical, Efficient, and Secure Software Sandboxing." ASPLOS 2024. [Link](https://zyedidia.github.io/papers/lfi_asplos24.pdf).
208-
209-
# Roadmap
210-
211-
The LFI project is currently under development. Here are some directions we are
212-
interested in (some of which are being actively developed):
213-
214-
* Integration with library sandboxing tools.
215-
* New capabilities and full security for the runtime.
216-
* Optimized integration with WebAssembly (efficiently run WebAssembly inside LFI).
217-
* Support for dynamic recompilation to other architectures.
218-
* Native support for RISC-V.
219-
* Instrumentation of static binaries, so you don't need to recompile your program.
220-
* Support for Arm software context IDs for mitigating Spectre attacks (requires
221-
modifications to Linux, which Arm will hopefully implement soon).
107+
* Setting up benchmarking with `lfi-bench` and SPEC 2017: [guide](docs/BENCHMARKING.md).
108+
* Using LFI to sandbox libraries: [guide](docs/LIBRARIES.md).
109+
* Learning more about how LFI works: [guide](docs/DETAILS.md).

assets/lfi-logo.svg

Lines changed: 0 additions & 104 deletions
This file was deleted.

docs/BENCHMARKING.md

Lines changed: 0 additions & 69 deletions
This file was deleted.

docs/DETAILS.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# Technical Summary
2+
3+
LFI works primarily via three components: the compiler, the verifier, and the runtime. When targeting LFI you must compile your program for the LFI target,
4+
which applies a set of simple rewrites on the generated assembly to ensure that the generated assembly is secure. The LFI compiler can compile a wide variety
5+
of unmodified input programs, including those that make extensive use hand-written assembly. The LFI compiler is currently implemented as a modification to LLVM
6+
that invokes a text-based GNU assembly rewriting tool at the assembler stage.
7+
8+
Compiling a program for the LFI target produces an ELF file. Once you have done so it can be loaded and run by the LFI runtime. Since the program is untrusted and
9+
potentially malicious, the runtime applies the LFI verifier to the program before loading it into executable memory. The verifier is a trusted program and ensures
10+
that all security invariants of the sandbox are maintained by the untrusted program. These invariants include things like: not loading/storing any memory more than 4GiB
11+
beyond the base of the sandbox, not modifying certain reserved registers, not branching to any system call instructions or other unsafe instructions, etc...
12+
13+
Once verification passes, the runtime begins executing the program and is responsible for handling any host calls (calls into the runtime) that it makes. By default, the runtime
14+
performs Linux emulation, with support for a subset of Linux system calls, allowing you to run Linux programs within an LFI sandbox.
15+
16+
For more detailed two-page description of LFI for Arm64 and x86-64, please see this [short paper](https://www.scs.stanford.edu/~zyedidia/docs/papers/lfi-short.pdf).
17+
18+
LFI's current sandboxing schemes for Arm64 and x86-64 are documented in the [LFI specification](https://www.scs.stanford.edu/~zyedidia/docs/lfi/lfi-spec.pdf).
19+
20+
# Publications
21+
22+
The following papers describe the LFI scheme in more detail. The first describes the Arm64 scheme, and the second describes an optimization for x86-64 that we use. For more details about the x86-64 mechanism see the [short paper](https://www.scs.stanford.edu/~zyedidia/docs/papers/lfi-short.pdf) as well as prior work on [Google Native Client](https://www.scs.stanford.edu/~zyedidia/docs/papers/nacl2.pdf).
23+
24+
* Zachary Yedidia. "Lightweight Fault Isolation: Practical, Efficient, and Secure Software Sandboxing." ASPLOS 2024. [Link](https://zyedidia.github.io/papers/lfi_asplos24.pdf).
25+
* Shravan Narayan, Tal Garfinkel, Evan Johnson, Zachary Yedidia, Yingchen Wang, Andrew Brown, Anjo Vahldiek-Oberwagner, Michael LeMay, Wenyong Huang, Xin Wang, Mingqiu Sun, Dean Tullsen, Deian Stefan. "Segue & ColorGuard: Optimizing SFI Performance and Scalability on Modern Architectures." ASPLOS 2025. [Link](https://zyedidia.github.io/papers/seguecg.pdf).

docs/PODMAN.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)