diff options
Diffstat (limited to 'crates/rebel-runner/src/ns.rs')
-rw-r--r-- | crates/rebel-runner/src/ns.rs | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/crates/rebel-runner/src/ns.rs b/crates/rebel-runner/src/ns.rs new file mode 100644 index 0000000..986aa80 --- /dev/null +++ b/crates/rebel-runner/src/ns.rs @@ -0,0 +1,84 @@ +use nix::{ + mount::{self, MntFlags, MsFlags}, + sched::CloneFlags, + unistd::{self, Gid, Pid, Uid}, +}; + +use rebel_common::error::*; + +use super::util::clone; + +pub fn mount_proc() { + mount::mount::<_, _, _, str>(Some("proc"), "/proc", Some("proc"), MsFlags::empty(), None) + .expect("Failed to mount /proc"); +} + +pub fn setup_userns(inner_uid: Uid, inner_gid: Gid, outer_uid: Uid, outer_gid: Gid) { + std::fs::write("/proc/self/setgroups", "deny").expect("Failed to write /proc/self/setgroups"); + std::fs::write( + "/proc/self/uid_map", + format!("{} {} 1", inner_uid, outer_uid), + ) + .expect("Failed to write /proc/self/uid_map"); + std::fs::write( + "/proc/self/gid_map", + format!("{} {} 1", inner_gid, outer_gid), + ) + .expect("Failed to write /proc/self/gid_map"); +} + +pub unsafe fn spawn<F>(flags: CloneFlags, f: F) -> nix::Result<Pid> +where + F: FnOnce(), +{ + assert!(flags.contains(CloneFlags::CLONE_NEWNS) || !flags.contains(CloneFlags::CLONE_NEWPID)); + + clone::spawn(Some(flags), || { + if flags.contains(CloneFlags::CLONE_NEWPID) { + mount_proc(); + } + f() + }) +} + +pub fn pivot_root(path: &str) { + (|| -> Result<()> { + unistd::chdir(path).context("chdir()")?; + mount::mount::<_, _, str, str>(Some("/proc"), "proc", None, MsFlags::MS_BIND, None) + .context("Failed to bind mount /proc")?; + unistd::pivot_root(".", ".").context("pivot_root()")?; + mount::umount2(".", MntFlags::MNT_DETACH).context("umount2()")?; + unistd::chdir("/").context("chdir(\"/\")")?; + Ok(()) + })() + .expect("Failed to pivot root"); +} + +pub fn container_mounts() -> Result<()> { + mount::mount( + Some("tmp"), + "/tmp", + Some("tmpfs"), + MsFlags::MS_NODEV | MsFlags::MS_NOSUID, + Some("mode=1777,size=1048576k"), + ) + .context("Failed to mount /tmp")?; + mount::mount( + Some("devpts"), + "/dev/pts", + Some("devpts"), + MsFlags::MS_NOSUID | MsFlags::MS_NOEXEC, + Some("newinstance,ptmxmode=0666,mode=0620"), + ) + .context("Failed to mount /dev/pts")?; + mount::mount( + Some("shm"), + "/dev/shm", + Some("tmpfs"), + MsFlags::MS_NOSUID | MsFlags::MS_NOEXEC | MsFlags::MS_NODEV, + Some("mode=1777,size=65536k"), + ) + .context("Failed to mount /dev/shm")?; + + Ok(()) +} |