Changelog
All notable changes to this project are documented here.
The format is based on Keep a Changelog, and this project adheres to the version numbering of the PRoot release it re-implements (Termux PRoot 5.1.0).
Unreleased
Added
- Complete open-source documentation system:
README.mdwith feature overview, quick start, and badges- mdBook documentation site under
docs/(user guide, CLI reference, architecture, extensions, mixed-mode/QEMU, security model, development and testing guides) doc/proot.1manual pageCONTRIBUTING.md,CODE_OF_CONDUCT.md,SECURITY.md,CHANGELOG.md- GitHub issue templates and pull-request template
docsCI workflow:cargo docplus mdBook build and GitHub Pages deployment
Changed
- Expanded crate-level and module-level rustdoc coverage.
5.1.0 — clean-room Rust rewrite of PRoot 5.1.0
Added
-
Full clean-room Rust port of Termux PRoot 5.1.0:
- User-space
chroot(-r,-R,-S) - Virtual bind mounts (
-b,-m) with symlink-deref control - QEMU user-mode mixed execution (
-q) with/host-rootfs - ABI-aware syscall translation (x86-64, x32, i386, arm, arm64, sh4
tables in
data/) - ELF parsing, interpreter (
PT_INTERP) rewriting, loader stub, and shebang (#!) interpretation - Extensions:
-0/-ifake identity,--link2symlink,-Hhidden files,-kkernel-release kompat,-pport switch,-Lsymlink-size fix,--sysvipc(shm/sem/msg + helper daemon), mountinfo rewriting - Seccomp-accelerated syscall filtering
--kill-on-exit,-w,-vhandling identical to C
- User-space
-
src/sys.rsFFI boundary: every libc/syscall call is a thin audited wrapper; the rest of the codebase contains no direct FFI. -
Freestanding
loader/sub-crate (no_std, position-independent) injected into tracees forexecvecompletion, matching the C loader’s role. -
Modern Rust toolchain: edition 2024, MSRV 1.85, rustfmt/clippy enforcement,
unsafe_op_in_unsafe_fndenied, cargo-deny policy, GitHub Actions CI, Dependabot.
Fixed (relative to naive ports)
errnois cleared onprocess_vm_*fast paths, matching the C convention — stale errno previously poisonedgetresuid-style emulations and corrupted wait-status delivery.SIGTRAPdelivery semantics: only the first SIGTRAP is consumed for ptrace option setup; subsequent ones reach the guest handler.-qrunner resolution happens against the host filesystem (matching C’sreconf.tracee == NULLpath), so the QEMU binary is found via the hostPATHrather than the guest rootfs.- Kompat extension configuration is shared across tracees
(
Rc<RefCell<…>>), matching C’sINHERIT_PARENT → sharedmodel. - Misaligned
&mut *bytes.cast::<libc::stat>()uses replaced with typed reads — a genuine alignment-UB fix. - No
static mutanywhere: event flags are atomics, the pipe-shadow table isthread_local!, netlink probing uses an atomic cache.
Validation
- Upstream C integration suite: 113 checks pass, 0 failures
(8 environment skips, 9 expected failures — identical to the C
baseline; two QEMU-runner tests actually pass better than C because
the Rust binary has no
libtallocdependency). cargo fmt --check,cargo clippy --all-targets -D warnings,cargo test,cargo deny check, debug + release builds all clean.