A clean-room Rust rewrite of PRoot 5.1.0:
a user-space implementation of chroot, mount --bind, and
binfmt_misc — no privileges or setup required.
BoxKernel traces child processes with ptrace(2) (plus seccomp
filtering where the kernel supports it) and rewrites their system calls.
Use it to run programs against an arbitrary guest root filesystem,
relocate files into a different place in the hierarchy, execute binaries
built for another CPU architecture transparently through QEMU user-mode,
or instrument Linux processes through its extension mechanism.
- User-space
chroot— confine programs to an arbitrary directory (-r,-R,-S) without root privileges. - Virtual bind mounts — make any host file or directory visible
anywhere in the guest namespace (
-b/-m), with symlink-aware overlay semantics. binfmt_misc-style execution — transparent QEMU user-mode execution for foreign-architecture binaries (-q), including mixed mode: host and guest programs interoperating in one filesystem namespace via/host-rootfs.- Full syscall translation — path canonicalization,
openat-style resolution through/proc/<pid>/fd, ABI-aware 32/64-bit syscall handling, ELF parsing with interpreter/loader manipulation and shebang interpretation. - Compatibility extensions — fake root identity (
-0,-i), hard-link emulation (--link2symlink), helper-file hiding (-H), kernel-release spoofing (-k), protected-port remapping (-p), symlink-size fixups (-L), System V IPC emulation (--sysvipc), and a mountinfo rewriter. - Seccomp acceleration — kernel-side syscall filtering reduces ptrace round-trips where supported.
- ptrace instrumentation engine — extensions subscribe to typed events (path translation, syscall enter/exit, inheritance, signals) through a single modular dispatcher.
The C reference implementation is battle-tested but carries decades of manual memory management, global state, and unchecked pointers. This rewrite keeps behavioral parity (validated against the C test suite — 113 checks green) while gaining Rust's guarantees:
- All
libc/kernel-boundaryunsafeis isolated in one auditable module (src/sys.rs); nostatic mut, notransmute, no scattered FFI calls. - Modular design — path translation, syscall dispatch, extensions, ELF loading, and tracee memory access are independent modules behind typed interfaces.
- Modern toolchain — edition 2024, rustfmt + clippy + cargo-deny
enforced in CI,
unsafe_op_in_unsafe_fndenied crate-wide.
$ cargo build --release # produces target/release/proot
$ ./target/release/proot --version
BoxKernel 5.1.0
# Run a command inside a guest rootfs
$ ./target/release/proot -r ~/alpine-rootfs /bin/sh
# Bind a host file into the guest view
$ ./target/release/proot -b /etc/hostname /bin/cat /etc/hostname
# Fake root for package managers
$ ./target/release/proot -0 -r ~/alpine-rootfs /sbin/apk add gcc
# Foreign architecture via QEMU user-mode
$ ./target/release/proot -R ~/armhf-rootfs -q qemu-arm /bin/bashThe installed binary is named proot for drop-in compatibility with
existing scripts (e.g. proot-distro).
| Document | Contents |
|---|---|
| User guide | Recipes: chroot, binds, -R/-S, fake root |
| Command-line reference | Every option, argument, and side effect |
| Architecture | How the ptrace engine, translation pipeline, and modules fit together |
| Extensions | What each built-in extension does and how to write one |
| Mixed mode & QEMU | Foreign-architecture and host/guest mixed execution |
| Security model | What BoxKernel does not protect you from |
| Development | Toolchain, lint/test commands, unsafe policy, parity rules |
| Testing | Unit tests and the C-reference integration suite |
man proot (doc/proot.1) |
The manual page |
The rendered book is published to GitHub Pages by the docs workflow.
Requirements: Linux, Rust 1.85+ (pinned by
rust-toolchain.toml), and a C toolchain is
not needed — the only crate dependency is libc.
$ cargo build --release
$ cargo test # unit tests
$ cargo fmt --check && cargo clippy --all-targets -- -D warnings
$ cargo deny check # license/advisory auditSee Development for the full workflow, including running the upstream C integration suite against the Rust binary.
- Not a security boundary. PRoot confuses programs; it does not confine them. A guest program can modify or delete every host file the invoking user could. Never use it to isolate untrusted code — see SECURITY.md.
- Syscall tracing has a performance cost — small for I/O-bound loads, noticeable for syscall-heavy ones (mitigated by seccomp).
- Programs relying on real
chroot(2), setuid, or unemulatable kernel facilities will misbehave.
GPL-2.0-or-later, matching the upstream PRoot license. See LICENSE.
PRoot was written by Cédric Vincent at STMicroelectronics and is maintained by the Termux contributors. BoxKernel is a clean-room Rust re-implementation maintained by BoxOSLab.