1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
//! 🅱️🧦 bandsocks //! ================ //! //! it's a lightweight sandbox for Linux, written in pure Rust! //! //! it runs docker images! //! //! it can run nested inside unprivileged containers! //! //! it's a library with minimal external dependencies! //! //! it's highly experimental! //! //! ```text //! 🎶 🎹🧦 🎸🧦 🎸🧦 🎷🧦 🎺🧦 🥁🧦 🎶 //! ``` //! //! Scope //! ===== //! //! Let's make it easy to run somewhat-untrusted computational workloads //! like media codecs from inside an existing async rust app. There is //! no networking or traditional storage support inside containers. The //! container uses a virtual filesystem backed by read-only image contents and //! mounted I/O channels. //! //! Getting Started //! =============== //! //! The easiest way to start is via [Container::pull], which sets up a registry //! client with default options, downloads an image to cache as necessary, and //! provides a [ContainerBuilder] for further customization. //! //! ``` //! #[tokio::main] //! async fn main() { //! let s = "busybox@sha256:cddb0e8f24f292e9b7baaba4d5f546db08f0a4b900be2048c6bd704bd90c13df"; //! bandsocks::Container::pull(&s.parse().unwrap()) //! .await.unwrap() //! .arg("busybox").arg("--help") //! .interact().await.unwrap(); //! } //! ``` //! //! Architecture //! ============ //! //! The isolation in bandsocks comes primarily from a seccomp system call //! filter. A small set of system calls are allowed to pass through to the host //! kernel, while many system calls are disallowed entirely and others are //! emulated by our runtime. //! //! There is a 1:1 relationship between virtualized processes and host //! processes, but virtual processes have their own ID namespace. File //! descriptors are also mapped 1:1, so that read() and write() syscalls can be //! a pass-through after files are opened via a slower emulated open() call. //! //! The emulated paths look a bit like User Mode Linux or gvisor. A ptrace-based //! runtime we call `sand` is responsible for emulating operations like //! open() and exec() using only allowed syscalls. For filesystem access, `sand` //! uses an inter-process communication channel to request live file descriptors //! from the virtual filesystem. //! //! The `sand` runtime is also written in Rust, but it uses a lower-level style //! that bypasses the Rust and C standard libraries in order to have tight //! control over its system call usage. It is a single process per container, //! using asynchronous rust to respond to events from all processes/threads //! within that particular container. #[cfg(not(any(target_os = "linux", target_os = "android")))] compile_error!("bandsocks only works on linux or android"); #[macro_use] extern crate lazy_static; #[macro_use] extern crate serde; #[macro_use] extern crate hash32_derive; mod container; mod errors; mod filesystem; mod image; mod ipcserver; mod manifest; mod process; mod registry; mod sand; mod taskcall; pub use crate::{ container::*, errors::*, filesystem::{mount::*, socket::*}, image::*, registry::*, };