# How LiteBox Achieves Linux-on-Windows Userland Execution Without a VM

> Discover how LiteBox enables native Linux userland execution on Windows without a VM. Explore its innovative approach to Linux kernel ABI re-implementation and system call translation.

- Repository: [Microsoft/litebox](https://github.com/microsoft/litebox)
- Tags: internals
- Published: 2026-02-16

---

**LiteBox runs native Linux binaries on Windows by re-implementing the Linux kernel ABI in user-mode and providing a Windows-specific platform layer that translates system calls to Windows APIs, eliminating the need for a hypervisor or virtual machine.**

LiteBox is an open-source project from Microsoft that enables **Linux-on-Windows userland execution without a VM** by acting as a user-mode compatibility layer. Instead of virtualizing hardware or running a full Linux kernel, LiteBox intercepts Linux system calls at the binary level and redirects them to native Windows implementations. This architecture allows unmodified Linux ELF binaries to run as standard Windows processes.

## Platform Multiplexing Architecture

### Compile-Time Platform Selection

The core LiteBox runtime is platform-agnostic. The concrete platform implementation is selected at compile time via the `litebox_platform_multiplex` crate. In [`litebox_platform_multiplex/src/lib.rs`](https://github.com/microsoft/litebox/blob/main/litebox_platform_multiplex/src/lib.rs), the `Platform` type is aliased to the Windows-specific implementation when the `platform_windows_userland` feature is enabled:

```rust
// litebox_platform_multiplex/src/lib.rs
pub type Platform = litebox_platform_windows_userland::WindowsUserland;

```

This design allows the same Linux shim code to run on different platforms by swapping the underlying implementation.

## Windows Userland Platform Implementation

The `litebox_platform_windows_userland` crate provides the concrete Windows implementations for all platform primitives required by the Linux ABI.

### Memory Management via Windows APIs

Memory operations are mapped directly to Windows virtual memory APIs. The implementation in [`litebox_platform_windows_userland/src/lib.rs`](https://github.com/microsoft/litebox/blob/main/litebox_platform_windows_userland/src/lib.rs) provides `allocate_pages` using `VirtualAlloc2` and `protect_pages` using `VirtualProtect`. Page queries use `VirtualQuery` to inspect memory regions.

### Threading and Exception Handling

Thread creation uses Windows thread primitives via `std::thread::Builder`. A custom vectored exception handler (`vectored_exception_handler`) intercepts Windows page-fault exceptions and converts them into Linux-style signals. This handler also restores the guest's FS base register when the Windows scheduler clears it.

### FS-Base Emulation for Linux ABI Compatibility

The x86-64 Linux ABI requires the `fsbase` register for thread-local storage. LiteBox emulates this by storing `THREAD_FS_BASE` per-thread in Windows TLS. The `set_thread_fs_base` and `get_thread_fs_base` functions manage this state, invoked via the `PunchthroughToken` mechanism to ensure correct context switching between Linux guest code and Windows host code.

## Linux Shim Layer

The `litebox_shim_linux` crate implements the Linux system-call ABI on top of the abstract platform interface. It translates high-level Linux semantics into the generic platform primitives.

For example, Unix-domain sockets are implemented in [`litebox_shim_linux/src/syscalls/unix.rs`](https://github.com/microsoft/litebox/blob/main/litebox_shim_linux/src/syscalls/unix.rs), using LiteBox's event and channel primitives that ultimately resolve to Windows synchronization objects like `WaitOnAddress` when running on the Windows platform.

## Syscall Rewriting and ELF Loading

Unmodified Linux binaries contain the `syscall` instruction that would normally trap into the Linux kernel. Since LiteBox runs in user-mode without a kernel, it must rewrite the binary before execution.

The `litebox_syscall_rewriter` crate handles this transformation. In [`litebox_syscall_rewriter/src/main.rs`](https://github.com/microsoft/litebox/blob/main/litebox_syscall_rewriter/src/main.rs), the `hook_syscalls_in_elf` function parses the input ELF, locates every `syscall` instruction, and replaces it with a small trampoline that jumps into the shim's `enter_syscall` entry point. The rewritten binary is written out (e.g., `program.hooked`) for execution.

## The Runner Orchestration

`litebox_runner_linux_on_windows_userland` is the executable that wires everything together. Located in [`litebox_runner_linux_on_windows_userland/src/main.rs`](https://github.com/microsoft/litebox/blob/main/litebox_runner_linux_on_windows_userland/src/main.rs), it performs the following steps:

1. Creates the `WindowsUserland` platform instance via `WindowsUserland::new()`.
2. Sets the global platform using `litebox_platform_multiplex::set_platform`.
3. Reads the target ELF and rewrites syscalls via `litebox_syscall_rewriter::hook_syscalls_in_elf`.
4. Creates a `Task` with default Linux-style credentials (`init_task`).
5. Spawns a Windows thread via `ThreadProvider::spawn_thread` that runs the shim entry point (`run_thread`) with the guest context (`PtRegs`).
6. Handles syscalls in the shim, which invoke the platform's concrete implementations, effectively translating Linux calls to Windows.

```rust
// litebox_runner_linux_on_windows_userland/src/main.rs (excerpt)
let platform = litebox_platform_windows_userland::WindowsUserland::new();
litebox_platform_multiplex::set_platform(platform);
let elf = std::fs::read(&args.input)?;
let hooked = litebox_syscall_rewriter::hook_syscalls_in_elf(&elf, None)?;
let shim = litebox_shim_linux::Shim::new(...);
let ctx = shim.prepare_initial_context(&hooked)?;
litebox::platform::ThreadProvider::spawn_thread(&platform, &ctx, shim)?;

```

## Why No VM Is Required

LiteBox achieves **Linux-on-Windows userland execution without a VM** through several architectural decisions that keep all execution within a standard Windows process:

* **All state lives in user-mode:** Memory is allocated with Windows virtual-memory APIs; page faults are caught by the vectored exception handler and turned into LiteBox "exceptions".

* **Emulated kernel state:** The Linux shim maintains process state (credentials, file descriptors, signal handlers) as ordinary Rust data structures within the process heap. There is no ring-0 transition or kernel context switch.

* **Binary translation:** The `syscall` instruction is rewritten to a trampoline before execution, converting what would be a kernel trap into a function call to the shim's `enter_syscall`. This eliminates the need for hardware virtualization extensions.

* **No kernel-mode code:** Everything runs in a normal process, making the approach lightweight, sandboxable, and easy to integrate with existing Windows tooling.

## Practical Examples

### Running a Linux Binary on Windows

To execute a Linux ELF on Windows using LiteBox, build the runner and invoke it with the target binary:

```bash

# Build the Windows-userland runner (requires a Windows host)

cargo build -p litebox_runner_linux_on_windows_userland --release

# Run a Linux ELF (e.g., hello_world) – the runner rewrites syscalls on-the-fly

target\release\litebox_runner_linux_on_windows_userland.exe ./test_bins/hello_world

```

Under the hood, the runner creates a `WindowsUserland` platform, rewrites the ELF via `hook_syscalls_in_elf`, and spawns a guest thread that translates Linux syscalls to Windows APIs.

### Manual Syscall Rewriting

You can programmatically rewrite Linux binaries to replace `syscall` instructions with LiteBox trampolines:

```rust
use litebox_syscall_rewriter::hook_syscalls_in_elf;
use std::fs;

fn rewrite(path: &str) -> std::io::Result<()> {
    let data = fs::read(path)?;
    let hooked = hook_syscalls_in_elf(&data, None)?;
    fs::write(format!("{}.hooked", path), hooked)?;
    Ok(())
}

fn main() {
    rewrite("hello_world").expect("rewrite failed");
}

```

The resulting `hello_world.hooked` can be executed by the Windows runner without further modification.

### Accessing Platform Primitives

User code can access the underlying Windows platform implementations through the multiplex layer:

```rust
use litebox_platform_multiplex::platform;

fn current_time() {
    let now = platform().now(); // uses WindowsUserland::now()
    println!("Instant: {} ns", now.0);
}

```

Because `platform()` returns a reference to the global `WindowsUserland` instance, any code that links against LiteBox can directly use Windows-specific primitives like `WaitOnAddress` for synchronization or `QueryUnbiasedInterruptTimePrecise` for timing.

## Key Source Files

| File | Role | Link |
|------|------|------|
| [`litebox_platform_multiplex/src/lib.rs`](https://github.com/microsoft/litebox/blob/main/litebox_platform_multiplex/src/lib.rs) | Selects the concrete platform (`WindowsUserland`) at compile time | [view](https://github.com/microsoft/litebox/blob/main/litebox_platform_multiplex/src/lib.rs) |
| [`litebox_platform_windows_userland/src/lib.rs`](https://github.com/microsoft/litebox/blob/main/litebox_platform_windows_userland/src/lib.rs) | Implements memory, threading, exception handling, FS-base, and syscall translation on Windows | [view](https://github.com/microsoft/litebox/blob/main/litebox_platform_windows_userland/src/lib.rs) |
| [`litebox_shim_linux/src/syscalls/unix.rs`](https://github.com/microsoft/litebox/blob/main/litebox_shim_linux/src/syscalls/unix.rs) | Provides Linux-compatible Unix-socket and other syscall implementations that call into the platform layer | [view](https://github.com/microsoft/litebox/blob/main/litebox_shim_linux/src/syscalls/unix.rs) |
| [`litebox_syscall_rewriter/src/main.rs`](https://github.com/microsoft/litebox/blob/main/litebox_syscall_rewriter/src/main.rs) | Parses ELF binaries and replaces `syscall` instructions with trampolines into the shim | [view](https://github.com/microsoft/litebox/blob/main/litebox_syscall_rewriter/src/main.rs) |
| [`litebox_runner_linux_on_windows_userland/src/main.rs`](https://github.com/microsoft/litebox/blob/main/litebox_runner_linux_on_windows_userland/src/main.rs) | Orchestrates platform initialization, ELF rewriting, thread creation, and start-up of the guest | [view](https://github.com/microsoft/litebox/blob/main/litebox_runner_linux_on_windows_userland/src/main.rs) |
| [`litebox/src/lib.rs`](https://github.com/microsoft/litebox/blob/main/litebox/src/lib.rs) (core) | Defines the abstract `Platform` trait, `shim` interface, and common runtime utilities | [view](https://github.com/microsoft/litebox/blob/main/litebox/src/lib.rs) |

These files together illustrate the complete pathway from a raw Linux ELF to a running process inside a Windows user-mode environment, all without launching a virtual machine.

## Summary

- LiteBox achieves **Linux-on-Windows userland execution without a VM** by re-implementing the Linux kernel ABI entirely in user-mode Rust code.
- The architecture uses **platform multiplexing** to select Windows-specific implementations at compile time via `litebox_platform_multiplex`.
- **Binary rewriting** replaces `syscall` instructions with trampolines that jump into the LiteBox shim, eliminating the need for kernel traps or hardware virtualization.
- The **Windows userland platform** provides memory management via `VirtualAlloc2`, threading via Windows APIs, and exception handling through vectored exception handlers that emulate Linux signals.
- **FS-base emulation** maintains Linux thread-local storage compatibility by storing the `fsbase` register in Windows TLS and restoring it during context switches.

## Frequently Asked Questions

### How does LiteBox differ from WSL2?

WSL2 uses a lightweight utility virtual machine running a full Linux kernel to provide compatibility. LiteBox does not use any virtualization technology; it runs native Linux binaries directly inside a Windows process by rewriting system calls and emulating kernel semantics in user-mode. This makes LiteBox lighter and more integrated with the host Windows environment than WSL2's VM-based approach.

### Can LiteBox run any Linux binary, or only specific ones?

LiteBox can run unmodified Linux ELF binaries that use the system calls implemented by the `litebox_shim_linux` layer. The syscall rewriter in [`litebox_syscall_rewriter/src/main.rs`](https://github.com/microsoft/litebox/blob/main/litebox_syscall_rewriter/src/main.rs) processes the binary to replace `syscall` instructions with trampolines. As long as the binary's system calls are supported by the shim, it will execute on Windows without modification.

### What happens when a Linux program tries to access the filesystem?

When a Linux program invokes a filesystem syscall (e.g., `open`, `read`, `write`), the Linux shim translates this into the abstract platform interface. The `WindowsUserland` implementation then maps these operations to Windows file APIs like `CreateFileW` or `ReadFile`. Paths are translated between Linux and Windows conventions, allowing the Linux binary to interact with the host Windows filesystem.

### How does LiteBox handle Linux signals like SIGSEGV?

LiteBox installs a vectored exception handler (`vectored_exception_handler` in [`litebox_platform_windows_userland/src/lib.rs`](https://github.com/microsoft/litebox/blob/main/litebox_platform_windows_userland/src/lib.rs)) that catches Windows structured exceptions (like access violations). The handler converts these Windows exceptions into Linux-style signals and delivers them to the guest's signal handlers. The handler also manages the FS-base register state, ensuring thread-local storage remains consistent after Windows interrupts the thread.