summaryrefslogtreecommitdiffstats
path: root/crates/rebel-runner/src/ns.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/rebel-runner/src/ns.rs')
-rw-r--r--crates/rebel-runner/src/ns.rs84
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(())
+}