Repository navigation
Conversation
A nested grant's symlink check ran before bwrap re-resolved the grant's path, so a program with write access to the parent could swap in a link between them. Where bwrap lists --bind-fd and the kernel has openat2, each grant is now opened once as an O_PATH descriptor, a nested one beneath its parent with RESOLVE_NO_SYMLINKS | RESOLVE_BENEATH, and bound with --bind-fd. Descriptors are mapped only in the child after fork (command-fds), never inheritable in the host. Elsewhere grants stay bound by path, as before, and BubblewrapBackend::binds_by_descriptor reports which is in effect.
The bubblewrap backend installed no seccomp filter, so keyctl, bpf, perf, io_uring, mount, setns, file handles and similar calls stayed reachable from a jail. A deny list compiled with seccompiler now goes to bwrap as two --add-seccomp-fd filters on pipes mapped into the child: EPERM for the deny list, ENOSYS for clone3 so the C library falls back to a clone whose flags the filter can check. ptrace stays allowed on Linux 4.8 and later; unshare and clone are denied only with a CLONE_NEW* flag. A bwrap without --add-seccomp-fd, or an architecture other than x86_64 and aarch64, leaves the backend unavailable rather than starting jails unfiltered.
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars.
|
Tiny Sweeper reviewReviewed head: Verdict: Ready for maintainer review · Priority: none Diagnostics and supporting detailsFull summaryPull request purpose (title): Start every bwrap jail under a seccomp deny list. Tiny Sweeper completed its review; deterministic results follow. Unreviewed paths
Review snapshot
Completeness: Complete What changedThe jail now compiles two seccomp filters (an EPERM deny list with x32 twins and a clone3-to-ENOSYS filter) for x86_64 and aarch64 from kernel release and process architecture; a bwrap without --add-seccomp-fd or a filter for the architecture makes the backend unavailable. Spawn prep appends --add-seccomp-fd arguments for filters numbered after grants and maps all descriptors via command_fds in the child only. The launcher script takes a keep-count and spares fds 10 and up while closing every other inherited descriptor above 2. Grants may be bound from O_PATH descriptors (nested with RESOLVE_NO_SYMLINKS|RESOLVE_BENEATH) instead of by path, with binds_by_descriptor reporting which is in effect; module docs gain a Seccomp section and the gap is narrowed accordingly. New Linux dependencies are added: command-fds, nix (fs), seccompiler (default features off) and libc. Features
Tests
FindingsNo active actionable findings. Before mergeNone. Agent review detailscritique
security
tests
commits
description
Evidence and run details
|
# Conflicts: # crates/tinybox-jail/src/bwrap/launcher_tests.rs
…p8-bwrap-pasta-net
Summary
The bubblewrap jail backend installed no seccomp filter, so
keyctl(the user's kernel keyrings),bpf,perf_event_open,io_uring,mount,setns,open_by_handle_atand similar calls stayed reachable from inside a jail. This was the first item of the backend's known gaps.Every jail now starts under a deny list compiled with
seccompilerforx86_64oraarch64. bwrap installs it on the child after its own setup, through two--add-seccomp-fdpipes mapped into the child only, the same way #160 maps the grant descriptors.EPERM.clone3fails withENOSYS, so the C library falls back toclone, whose flags the filter can read.x86_64. The x32-ABI twins of the denied calls are denied too.keyctl,add_key,request_keyprocess_vm_readv/writevbpf,perf_event_open,userfaultfd,io_uring_*pivot_root,setnsclone/unsharewith anyCLONE_NEW*flag--disable-usernsopen_by_handle_at,name_to_handle_atkexec,reboot, swap,acct, host clock,syslog,quotactl,vhangupioctl(TIOCSTI/TIOCLINUX)iopl,ioperm,modify_ldt,uselib,_sysctl(x86_64)Left allowed on purpose:
ptraceon Linux 4.8 and later, where seccomp is re-checked after a tracer edits a call and the pid namespace confines it to the jail's own processes. On older kernels it is denied.unshare/clonewithout namespace flags.personality.A
bwrapwithout--add-seccomp-fd, or another architecture, leaves the backend unavailable, with the reason in the debug log. A jail is refused rather than started unfiltered.Stacked on #160; review only the last commit.
Related issue
Part of #104 (item 2, seccomp), with the follow-up to #27.
API or behavior changes
BubblewrapBackend::installs_seccomp().tinybox-jail:seccompiler0.5 (default features off; Apache-2.0 OR BSD-3-Clause; depends only on libc) and a directlibc(already in the lockfile).EPERMfor the calls above. Debuggers still work on Linux 4.8+.--add-seccomp-fd(bubblewrap older than 0.5) no longer get the bwrap backend.tinybox-linux) is not filtered yet; it follows once its descriptor passing lands.Validation
On our Linux CI runner (kernel 7.0.0, bubblewrap 0.9.0, python3 3.12). The gates and the full runs are at a2b222b524; the head differs only by applying
cargo fmt's one-hunk patch. The module run and the first three red controls are from an earlier build of this commit (c4f3bcc5bb) that had the same filter and wiring, before the fake-bwrapfixtures learned--help:cargo build --locked --all-targets --all-features: ok. The new lockfile entries are exactly what cargo resolves.cargo deny --locked check:seccompilerandlibcadd no findings.cargo clippy --all-targets --all-features -- -D warnings: 0 errors, same as main.RUSTDOCFLAGS="-D warnings" cargo doc: ok.TINYBOX_REQUIRE_BWRAP=1 cargo test --locked --all-features --no-fail-fast -p tinybox-jail: 278 passed, 0 failed. That includes all 24 livebwrap_isolationtests under the filter.cargo test -p tinybox-modulenative shell and stdio: 48 passed. The jailed tests ran under the filter.cargo test --workspace --no-fail-fast: 1592 passed, 0 failed, with no failures unique to this branch.keyctl: the live test seeskeyctl -1 EKEYREVOKED, so not denied, and fails;ptraceeverywhere: the trace test seesptrace -1 EPERMand fails;Tests
ptracedenied only before 4.8;bwrapfixtures, which now answer--help):bwrapwhose--helplacks--add-seccomp-fdis not used, even though it passes the isolation probe;bwrap_isolation, raw syscalls throughpython3inside the jail):keyctlreturns-1 EPERMwhilegetpidworks;ptraceits own child.keyctlfrom the list fails the EPERM test;ptraceeverywhere fails the trace test;--add-seccomp-fdfails the refusal test, so the refusal really keys on that flag.Documentation
tinybox-jail/src/bwrap/mod.rs: the isolation text, a new Seccomp section, and the known gap removed. Module docs inbwrap/seccomp.rs.Checklist
#[allow(...)],#[ignore], or relaxed lints.envcontents in the diff or the description