Thanks for your interest in contributing! BoxKernel is a clean-room Rust re-implementation of Termux PRoot 5.1.0 whose overriding constraint is behavioral parity with the C reference. Every contribution is judged against that constraint first, idiomaticity second.
Requirements:
- Linux (the tool instruments
ptrace,seccomp,process_vm_*) - Rust 1.85 or newer — pinned via
rust-toolchain.toml(rustfmtandclippycomponents are pulled automatically) - No other dependencies;
libcis the only crate dependency
$ git clone https://github.com/BoxOSLab/BoxKernel.git
$ cd BoxKernel
$ cargo build # debug build: target/debug/proot
$ cargo build --release # release build
$ cargo test # unit testssrc/ files carry comments naming the C function each one ports
(e.g. // port of translate_sysenter_end()). When fixing a bug:
- Reproduce first — write a shell/C reproducer, or better, run the relevant test from the upstream suite (see below).
- Check the C reference for the intended semantics — the comment above each function names its C counterpart.
- Keep C-identical error paths: return
-errnofrom the innermost failing operation, preserveerrnoconventions (sys::clear_errnobefore calls whose success is measured througherrno == 0), and keep C's verdicts for edge cases even when they look odd — they are usually load-bearing. - Fix the Rust code; re-run the reproducer and the suite.
The C implementation's integration suite is the behavioral contract. To run it against the Rust binary:
$ cd ../proot/tests # the C reference checkout
$ make -C . test PROOT=/path/to/BoxKernel/target/release/prootExpected result: 113 ok, 0 failed, 8 skipped, 9 xfail (environment dependent). A change is not done until this suite is green.
CI runs all of these; run them locally before pushing:
$ cargo fmt --all -- --check
$ cargo clippy --all-targets --locked -- -D warnings
$ cargo test --locked
$ cargo deny check # license + advisory audit
$ cargo build --release --locked- Edition 2024, MSRV 1.85 — do not use APIs stabilized after 1.85.
unsafe_op_in_unsafe_fn = "deny"is set crate-wide.
unsafe is confined to the FFI boundary and to a few documented
islands:
| Location | Rule |
|---|---|
src/sys.rs |
The only place raw libc calls may appear. Every wrapper is a small safe function with a // SAFETY: comment. Callers keep C-style status/errno semantics. |
src/execve/elf.rs |
Union accessors (as32/as64/as32_mut/as64_mut) — ELF-class-validated, all-POD structs. |
src/tracee/event.rs |
Kernel-provided siginfo_t/utsname reads. |
loader/ |
Freestanding no_std naked functions and asm! — inherently unsafe, kept minimal. |
Rules for new code:
- No
static mut. Use atomics orthread_local!. - No
transmute/transmute_copy. Serialize POD structs throughsys::as_bytes/sys::as_bytes_mut; cross-field reads viaoffset_of!. - No raw pointers in safe function signatures. Machine words
(
usize) represent addresses/data insys::ptraceand friends. - Every remaining
unsafeblock needs a// SAFETY:comment stating the invariant it relies on. - If a safe
stdAPI exists with identical semantics, use it (e.g.std::os::unix::fs::MetadataExtinstead of re-readingstatfields) — but keep C-visible error semantics throughsys::wrappers when errno identity matters.
- Small, focused commits — one logical change each, following the
existing history (
Isolate unsafe…,Fix SIGTRAP re-delivery…). - Commit message: imperative subject line, why in the body when it is not obvious.
- Do not commit build artifacts or secrets;
target/is gitignored.
- Bugs: use the bug report template
and include
proot -v 9 …output where relevant. - Features: open a feature request describing the C-PRoot behavior or the new capability; parity-affecting changes need a corresponding C-test-suite story.
Participation is governed by the Contributor Covenant.