bunpen: clean up mount namespacing so that i could bind any directory -- including /tmp

This commit is contained in:
2024-08-25 13:27:31 +00:00
parent 7a902cabfe
commit 3010ff89d0

View File

@@ -43,31 +43,38 @@ export fn namespace_restrict(what: *resources) void = {
// namespace, but not vice versa:
rtext::check_error("reconfigure / as MS_SLAVE", rtext::mount("/", "/", "", rtext::MS_SLAVE | rtext::MS_REC, null));
// setup a new root in `/tmp`, mount the desired paths into it, and then pivot into it.
// in order to mount ANY directory from the old root into the new root,
// they have to be totally disparate. if we kept the old root at / and the new
// root at /tmp, then we couldn't bind `/tmp`.
//
// 1. pivoting _anywhere_ allows us to put the old root at `old`.
// i use `/tmp` here, just because that's how bubblewrap does it.
// 2. create a new rootfs at `new` and bind stuff into it.
// 3. then pivot a 2nd time, into `new` (and drop `old` altogether)
rtext::check_error("mount -t tmpfs tmpfs /tmp", rtext::mount("tmpfs", "/tmp", "tmpfs", 0, null));
// TODO: mount the paths the user asks for, but until then hardcode stuff:
rtext::check_error("mkdir /tmp/bin", rt::mkdir("/tmp/bin", 0o755));
rtext::check_error("mount /bin /tmp/bin", rtext::mount("/bin", "/tmp/bin", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/dev", rt::mkdir("/tmp/dev", 0o755));
// rtext::check_error("mount /dev /tmp/dev", rtext::mount("/dev", "/tmp/dev", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/etc", rt::mkdir("/tmp/etc", 0o755));
// rtext::check_error("mount /etc /tmp/etc", rtext::mount("/etc", "/tmp/etc", "", rtext::MS_BIND | rtext::MS_REC, null));
rtext::check_error("mkdir /tmp/nix", rt::mkdir("/tmp/nix", 0o755));
rtext::check_error("mount /nix /tmp/nix", rtext::mount("/nix", "/tmp/nix", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/proc", rt::mkdir("/tmp/proc", 0o755));
// rtext::check_error("mount /proc /tmp/proc", rtext::mount("/proc", "/tmp/proc", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/run", rt::mkdir("/tmp/run", 0o755));
// rtext::check_error("mount /run /tmp/run", rtext::mount("/run", "/tmp/run", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/sys", rt::mkdir("/tmp/sys", 0o755));
// rtext::check_error("mount /sys /tmp/sys", rtext::mount("/sys", "/tmp/sys", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/usr", rt::mkdir("/tmp/usr", 0o755));
// rtext::check_error("mount /usr /tmp/usr", rtext::mount("/usr", "/tmp/usr", "", rtext::MS_BIND | rtext::MS_REC, null));
// rtext::check_error("mkdir /tmp/var", rt::mkdir("/tmp/var", 0o755));
// rtext::check_error("mount /var /tmp/var", rtext::mount("/var", "/tmp/var", "", rtext::MS_BIND | rtext::MS_REC, null));
rtext::check_error("cd /tmp", os::chdir("/tmp"));
rtext::check_error("mkdir old", rt::mkdir("old", 0o755));
rtext::check_error("pivot_root . old", rtext::pivot_root(".", "old"));
rtext::check_error("cd /", os::chdir("/"));
// now we have `/`, empty except for the old rootfs available at `/old`
// prepare a new rootfs. it has to be its own mount (tmpfs), not just a dir.
rtext::check_error("mkdir new", rt::mkdir("new", 0o755));
rtext::check_error("mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", 0, null));
// bind old/$dir to new/$dir for every `dir` we want available in the sandbox:
// TODO: mount the paths the user asks for, but until then hardcode stuff.
rtext::check_error("mkdir new/bin", rt::mkdir("new/bin", 0o755));
rtext::check_error("mount old/bin new/bin", rtext::mount("old/bin", "new/bin", "", rtext::MS_BIND | rtext::MS_REC, null));
rtext::check_error("mkdir new/nix", rt::mkdir("new/nix", 0o755));
rtext::check_error("mount old/nix new/nix", rtext::mount("old/nix", "new/nix", "", rtext::MS_BIND | rtext::MS_REC, null));
// pivot into the new rootfs
rtext::check_error("cd new", os::chdir("new"));
rtext::check_error("pivot_root . .", rtext::pivot_root(".", "."));
// drop the old rootfs. weird idiom, but documented in `man 2 pivot_root`.
rtext::check_error("umount .", rt::umount2(".", rtext::MNT_DETACH));
rtext::check_error("cd /", os::chdir("/"));