summaryrefslogtreecommitdiffstats
path: root/crates/runner/src/ns.rs
blob: 4a8e3e71f2dfa38ea3f167b5ba391bf5f818e4e3 (plain)
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
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<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(())
}