use nix::{ mount::{self, MntFlags, MsFlags}, sched::CloneFlags, unistd::{self, Gid, Pid, Uid}, }; use 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(flags: CloneFlags, f: F) -> nix::Result 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(()) }