Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
9385bce
glibc: Use Implies file to select IEEE-754 math over i386 FPU sysdeps
vidyalakshmir Feb 1, 2026
b36487c
Updated glibc build script to create static archives (.a) files for l…
vidyalakshmir Feb 1, 2026
46bcff1
Update the lind_compile script to link against libm by adding -lm option
vidyalakshmir Feb 1, 2026
bd0e43f
Enhance comments and structure in make_archive.sh
vidyalakshmir Feb 2, 2026
48c84db
Update glibc build script
vidyalakshmir Feb 2, 2026
99e2024
Updated SCRIPT_DIR to the beginning of the script
vidyalakshmir Feb 2, 2026
9dee7c1
Fix undefined symbol error for sched_setscheduler and sched_get_prior…
vidyalakshmir Feb 10, 2026
c0d54a2
Using default stub implementations of Floating point rounding and exc…
vidyalakshmir Feb 10, 2026
338149b
Add deterministic signal tests for various scenarios (#658)
ChinmayShringi Feb 1, 2026
10977d9
Update gitignore (#670)
Yaxuan-w Feb 2, 2026
651602e
refactor: replace LIND_ROOT namespace with chroot from RawPOSIX (#630)
rishabhBudhouliya Feb 3, 2026
bbada05
Remove flock.c from skip test cases (#678)
rennergade Feb 3, 2026
1f7d0b0
Update skip_test_cases.txt to remove specific tests (#679)
rennergade Feb 3, 2026
5726ab1
676 align compile target names (#677)
m-hemmings Feb 3, 2026
0ab4032
deps(gha)(deps): bump actions/cache in /.github/workflows (#683)
dependabot[bot] Feb 4, 2026
7e78057
vmmap: Expose range accessibility check (#546)
celinehoang177 Feb 4, 2026
b479267
fixed lind_debug_str (#686)
qianxichen233 Feb 4, 2026
a45fae9
lind_run: re-exec with sudo when not running as root (#688)
rishabhBudhouliya Feb 5, 2026
bc3ca81
Add 3i and grate documentation (#493)
Yaxuan-w Feb 5, 2026
5737e5a
Update gitignore (#702)
Yaxuan-w Feb 5, 2026
1a077f3
Remove non-deterministic tests from test runner (#706)
m-hemmings Feb 6, 2026
98c482a
Add support for flags to be passed to wasmtestreport.py and lind_comp…
m-hemmings Feb 7, 2026
b1095d5
fix: mmaptest.c test failure (#705)
rishabhBudhouliya Feb 8, 2026
6c7447c
fix: creat_access.c test failure (#704)
rishabhBudhouliya Feb 9, 2026
7abacde
Find and optimize all generated binaries (#713)
stupendoussuperpowers Feb 9, 2026
fb3ce47
fix for malloc_printerr (#708)
drapl0n Feb 10, 2026
c7e074e
Using default stub implementations within math/ folder of fegetround …
vidyalakshmir Feb 12, 2026
5cc888c
Fix undefined symbol error for sched_get_priority_min and sched_getsc…
vidyalakshmir Feb 12, 2026
1b9b635
Updated s_frexpl.c with latest glibc code that fixes the build error
vidyalakshmir Feb 17, 2026
8b62379
Added placeholder for libdl.a
vidyalakshmir Feb 19, 2026
88114fe
Added unwind_def object file for libc.a
vidyalakshmir Feb 19, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
with:
python-version: 3.x
- run: echo "cache_id=$(date --utc '+%V')" >> $GITHUB_ENV
- uses: actions/cache@8b402f58fbc84540c8b491a91e594a4576fec3d7 # v5.0.2
- uses: actions/cache@cdf6c1fa76f9f475f3d7449005a359c84ca0f306 # v5.0.3
with:
key: mkdocs-material-${{ env.cache_id }}
path: .cache
Expand Down
8 changes: 7 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,10 @@ clang+llvm-*

#Ignore Build artifacts
src/glibc/build/
src/tmp/
build/
lindfs/

#Ignore testing results
e2e_status
report.html
results.json
10 changes: 9 additions & 1 deletion Docker/Dockerfile.e2e
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,21 @@ COPY --parents src/glibc Makefile .
RUN make sysroot


# Build Docker image that includes the full lind-wasm toolchain
# NOTE: Lind-wasm source code is not included
# Build Docker image that includes the full lind-wasm toolchain
# NOTE: Lind-wasm source code is not included
FROM base AS release
COPY --from=build-wasmtime --parents src/wasmtime/target .

COPY --from=build-wasmtime --parents src/wasmtime/target .
COPY --from=build-wasmtime --parents build/wasmtime .
RUN chmod 0755 /build/wasmtime
COPY --from=build-glibc --parents src/glibc/sysroot .
COPY --from=build-glibc --parents build/sysroot .
COPY --parents scripts tests tools skip_test_cases.txt .

ENV LIND_WASM_ROOT=/

RUN install -D -m 0755 /scripts/lind_compile /usr/local/bin/lind_compile \
&& install -D -m 0755 /scripts/lind_run /usr/local/bin/lind_run \
&& ln -sf /usr/local/bin/lind_compile /usr/local/bin/lind-clang \
Expand All @@ -131,15 +136,18 @@ RUN install -D -m 0755 /scripts/lind_compile /usr/local/bin/lind_compile \
# Run all tests, print results, and exit with 1, if any test fails; 0 otherwise
FROM base AS test
COPY --parents scripts tests tools skip_test_cases.txt Makefile .
RUN chmod 0755 /scripts/wasmtestreport.py /scripts/lind_compile /scripts/lind_run
# Create symlink so hardcoded paths in wasmtime match Docker environment
RUN mkdir -p /home/lind && ln -sf / /home/lind/lind-wasm
# NOTE: Build artifacts from prior stages are only mounted, to save COPY time
# and cache layers. This means they are not preserved in the resulting image.
RUN --mount=from=build-wasmtime,source=src/wasmtime/target,destination=src/wasmtime/target \
--mount=from=build-wasmtime,source=build/wasmtime,destination=/build/wasmtime \
--mount=from=build-glibc,source=src/glibc/sysroot,destination=src/glibc/sysroot \
make test && \
OUT_DIR=/ REPORT_PATH=/report.html make md_generation


FROM scratch AS artifacts
COPY --from=test /report.html /wasm-e2e-report.html
COPY --from=test /e2e_comment.md /e2e_comment.md
Expand Down
6 changes: 1 addition & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ wasmtime: build-dir
cargo build --manifest-path src/wasmtime/Cargo.toml --release
cp src/wasmtime/target/release/wasmtime $(WASMTIME_BIN)

.PHONY: wasmtime-debug
wasmtime-debug: build-dir
cargo build --manifest-path src/wasmtime/Cargo.toml
cp src/wasmtime/target/debug/wasmtime $(WASMTIME_DEBUG_BIN)

.PHONY: lind-debug
lind-debug: build-dir
Expand All @@ -39,7 +35,7 @@ lind-debug: build-dir

# Build Wasmtime with the lind_debug feature enabled
cargo build --manifest-path src/wasmtime/Cargo.toml --features lind_debug
cp src/wasmtime/target/debug/wasmtime $(WASMTIME_DEBUG_BIN)
cp src/wasmtime/target/debug/wasmtime $(WASMTIME_BIN)
build_glibc:
# build sysroot passing -DLIND_DEBUG if LIND_DEBUG is set
if [ "$(LIND_DEBUG)" = "1" ]; then \
Expand Down
Binary file added docs/images/.DS_Store
Binary file not shown.
Binary file added docs/images/doc-images/grate-call-vmctx.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
72 changes: 43 additions & 29 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,60 +4,74 @@ id: Overview

# Lind-Wasm

Lind is a single-process sandbox that provides an option to safely execute programs. Lind executes applications using software fault isolation and a kernel microvisor to limit the potential of reaching bugs or security flaws in the application.
Lind is a sandbox that isolates different applications in the same address space. Thus, conceptually, it executes different applications (which traditionally would be different processes) in separate, non-overlapping parts of a single address space, under a single, non-privileged Linux process. To provide memory safety, control flow integrity, memory isolation, and similar properties, this version of Lind executes applications using [WebAssembly](webassembly.org) for software fault isolation. Lind also contains a custom kernel microvisor, written in Rust, which performs strict type checking and safe type conversion (e.g., between 32-bit and 64-bit representations), and enforces resource management and file-system isolation, thereby limiting the potential damage caused by bugs or security flaws in an application.

In Old Norse, Old High German and Old English a "lind" is a shield constructed with two layers of linden wood. Linden wood shields are lightweight, and do not split easily, an appropriate metaphor for a sandboxing system which employs two technologies.

## Core Concepts

- **Cage**: Lightweight isolation boundary within a process
- Can run legacy code (may need recompilation)
- Protects and isolates memory
- **Microvisor**: Small POSIX compliant kernel within a process
- Provides a POSIX interface
- Distinct isolation between cages
- **3i (three eye)**: Capability-based POSIX interfaces between cages
In Old Norse, Old High German and Old English a "lind" is a shield constructed with two layers of linden wood. Linden wood shields are lightweight, and do not split easily, an appropriate metaphor for a sandboxing system which is lightweight and which provides layered security.

## Technology Overview

### Cages
Memory and bookkeeping that encapsulates the idea of a typical OS process, encompassing applications as well as grates.
A cage runs a Linux application in an isolated part of the Lind process's namespace. The code must recompiled to run in Wasm and linked to our modified glibc so that it makes its system calls through 3i. However, the source code for applications only needs to be modified in rare cases (such as applications that directly make system calls).

### Grates
Can perform trusted operations on descendant cages without requiring code in the microvisor's TCB. Grates can run arbitrary code, with restrictions only placed by grates beneath them. The microvisor implements a grate with access to call into the Linux kernel.
A key advantage of 3i is the ability to support interposition. In other words, a cage can intercept the system calls from another cage. Because the use case of writing a cage to intercept system calls is very lightweight it is common in Lind. As such, we give these cages the special name "grate". This is meant to convey the mental picture of a caged application which calls down through a series of grates before (potentially) reaching the operating system.

Note that a grate is a cage and Lind makes no actual distinction between them. Any cage can make the system calls available to grates (unless a grate below it prevents it). It is just that most legacy applications do not need to regularly make such calls. This is analogous to strace and its use of the ptrace mechanism.

A major advantage is that this means that implementing something like an in-memory file system can now be done without changing the microvisor or other trusted code. A grate can intercept the file system calls and code written in C, Rust, etc. can be used to provide this functionality. Similarly, a network file system can be implemented in a grate by the grate making whatever network system calls are needed.

Another important feature of grates is that they are composable. A grate may itself have another grate beneath it which provides a separate service. The recommended grate creation philosophy of 3i is similar to the philosophy in Unix of having small, composable commands you combine with pipes and similar functionality. So, grates tend to be smaller, simpler utilities that can be combined. This is sensible since the overhead of having separate cages and calling between cages is very low.

Another similarity of Unix pipelines has to do with how grates interact. The overwhelmingly common use case for pipes in Unix is to chain commands together sequentially so that the stdout of one becomes the stdin of the next. However, the pipe functionality is itself general and supports many different use cases beyond this. The interposition mechanism in 3i is similar in that most grates are likely to be stacked and simply provide functionality to whatever is above them. However, since the system call table is per-cage and is truly programmable, a sufficiently privileged (ancestor) grate could rewire system calls for all of its descendents in any manner desired.

In addition to intercepting system calls, a grate can also perform system calls on behalf of a descendant cage. This is useful in situations where a cage should perform an operation like exiting or setting up a memory mapping or similar, where the goal is for the system to act as though the cage is making the call instead of the grate.

When performing system calls, it is often useful for a grate to be able to pass arguments that refer to buffers in other cages (e.g., the buffer used in a write call). Thus 3i system call arguments support a notion of which cage each argument comes from.

**Inheritance Properties**:

- A child inherits system calls from parent on fork
- If cage A was forked by cage B, cage A will have the same system call handlers as cage B
- If grate A was forkinterpose()'d by grate B, grate A inherits B's system call behavior changes
- A child inherits system call handlers from its parent on fork. Thus, if cage A was forked by cage B, cage A will have the same system call handlers as cage B
- An ancestor can change the system call table for its decendents and perform calls on their behalf.

### 3i System
The 3i system serves as:
## Core Concepts

- Central point for all communication between cages
- Table container for system call routing
- Security control mechanism for system call interception
- Privilege management system for blocking unnecessary calls
- **Cage**: This term describes the isolated memory namespace that an application executes in. It is analogous to a process in Linux.
- Can run legacy code compiled with Wasm as a target
- Protects and isolates memory, control flow, etc.
- **Microvisor**: RawPOSIX is a small kernel analogous to Linux running within the unprivileged Lind process. This is analogous to the Linux kernel. Note, however, that this and all of the rest of Lind runs as an unprivileged Linux process.
- Provides a POSIX-like interface (runs most Linux programs)
- Handles file descriptor separation, fork, exec, signals, threading, etc.
- **3i (pronounced "three-I")**: Capability-based POSIX interface to call between cages or into the microvisor. This is conceptually similar to a programmable system call table and IPC interface.
- Each cage has a separate system call table which can be independently changed to redirect into other cages or the microvisor
- Fast, isolated calling between cages
- Enables complex functionality (system call filtering, file systems, proxies, etc.) to be external to the microvisor

## Components

### Wasmtime
Wasmtime is a fast and secure runtime for WebAssembly designed by Bytecode Alliance. Lind-wasm uses wasmtime as a runtime with added support for multi-processing via Asyncify.
### Wasmtime (our caging technology)
[Wasmtime](https://wasmtime.dev) is a fast and secure runtime for WebAssembly designed by the [Bytecode Alliance](bytecodealliance.org). Lind-wasm uses wasmtime as a runtime with added support for multi-processing via Asyncify.

### lind-glibc

We’ve ported glibc so that it can be compiled to wasm bytecode and linked with any wasm binary. This includes minor changes like replacing assembly code, and add a mechansim to transfer system calls to the trusted runtime and microvisor.
We’ve ported glibc so that it can be compiled to wasm bytecode and linked with any wasm binary. This includes minor changes like replacing assembly code, and add a mechansim to transfer system calls to the trusted runtime and microvisor. Also, all system calls are converted to 64-bit system call types because all grates (and the underlying RawPOSIX implementation) support 64-bit system calls.

### RawPOSIX
### RawPOSIX (our microvisor technology)
Provides normal POSIX system calls including:

- Signals
- Fork/exec
- Fork
- Exec
- Threading
- File system
- Networking
- Separate handling of cages' fds and threads

### 3i Implementation
The iPC (intra-process call) interposable interface enables secure and efficient cage communication with function call-like speed. It provides POSIX interfaces between cages with interposition capabilities, enabling fine-grained security and access control while maintaining program behavior.
The intra-process interposable interface (3i) enables secure and efficient cage communication with speed similar to a function call. It provides POSIX interfaces between cages with interposition capabilities, enabling fine-grained security and access control by supporting the construction of grates.

## Frequent Q&A

### How hard is it to use Lind-Wasm?

Lind-Wasm aims to minimize application changes.
Most applications can run without source-level modifications and only need to be recompiled using `clang` with Lind-Wasm–related feature flags.
Loading