bunpen: namespace: restore the working directory (if possible) after entering the mount namespace

This commit is contained in:
2024-08-27 18:06:47 +00:00
parent 469b9b9223
commit 99de056048

View File

@@ -40,6 +40,20 @@ export fn namespace_restrict(what: *resources) void = {
// mapped to non-ns ops by the same user, and vice-versa // mapped to non-ns ops by the same user, and vice-versa
write_uid_map(uid, gid); write_uid_map(uid, gid);
let pwd = strings::dup(os::getcwd()); // dup because API uses a static buffer
defer(free(pwd));
isolate_paths(what.paths);
// try to change to the old working directory;
// this can fail if it's not within the sandbox.
rtext::swallow_error("namespace: restore $PWD", os::chdir(pwd));
// TODO: CLONE_NEWPID (might not work without forking to also become reaper)
};
// reconfigures all the mounts so that after this call the only paths accessible
// are those reachable from the provided `paths`.
// N.B.: this function does NOT preserve the current working directory
fn isolate_paths(paths: []path::buffer) void = {
// allow new mounts to propagate from the parent namespace into the child // allow new mounts to propagate from the parent namespace into the child
// namespace, but not vice versa: // namespace, but not vice versa:
rtext::check_error("reconfigure / as MS_SLAVE", rtext::mount("/", "/", "", rtext::MS_SLAVE | rtext::MS_REC, null)); rtext::check_error("reconfigure / as MS_SLAVE", rtext::mount("/", "/", "", rtext::MS_SLAVE | rtext::MS_REC, null));
@@ -62,7 +76,6 @@ export fn namespace_restrict(what: *resources) void = {
rtext::check_error("mkdir new", rt::mkdir("new", 0o755)); rtext::check_error("mkdir new", rt::mkdir("new", 0o755));
rtext::check_error("mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", 0, null)); rtext::check_error("mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", 0, null));
{
// bind all the user-requested paths from `old/$p` into `new/$p`. // bind all the user-requested paths from `old/$p` into `new/$p`.
// use the `dirfd` abstraction so that paths meant for `old` can't crawl out // use the `dirfd` abstraction so that paths meant for `old` can't crawl out
// of that virtual fs. // of that virtual fs.
@@ -73,17 +86,12 @@ export fn namespace_restrict(what: *resources) void = {
let new_fs = os::dirfdopen(new_fd); let new_fs = os::dirfdopen(new_fd);
defer(free(new_fs)); defer(free(new_fs));
for (let path .. what.paths) { for (let path .. paths) {
bind_leaf(old_fs, new_fs, &path); bind_leaf(old_fs, new_fs, &path);
}; };
};
// pivot into the new rootfs // pivot into the new rootfs
pivot_into("new"); pivot_into("new");
// TODO: `chdir` back to the original dir we were executed from
// TODO: CLONE_NEWPID (might not work without forking to also become reaper)
}; };
// walk from root to `p`, creating any ancestors necessary and then binding the // walk from root to `p`, creating any ancestors necessary and then binding the