bunpen: proof-of-concept mount namespacing

This commit is contained in:
2024-08-24 20:01:27 +00:00
parent 9ab6d101f6
commit f0efa0c255
2 changed files with 88 additions and 2 deletions

View File

@@ -1,13 +1,21 @@
// vim: set shiftwidth=2 :
use fs;
use io;
use log;
use os;
use rt;
use rtext;
use unix;
export fn namespace_restrict(what: *resources) void = {
let proc_fd = rt::open("/proc", rt::O_PATH | rt::O_CLOEXEC, 0)!;
let proc_fs = os::dirfdopen(proc_fd);
// unshare as much as possible, by default:
let what_to_unshare =
rtext::CLONE_NEWCGROUP |
rtext::CLONE_NEWIPC |
rtext::CLONE_NEWNET |
rtext::CLONE_NEWNS |
rtext::CLONE_NEWUSER |
rtext::CLONE_NEWUTS
;
@@ -15,8 +23,58 @@ export fn namespace_restrict(what: *resources) void = {
log::println("namespace: permit net");
what_to_unshare &= ~rtext::CLONE_NEWNET;
};
log::printfln("namespace: unshare {}", what_to_unshare);
rtext::unshare(what_to_unshare)!;
// TODO: LONE_NEWNS (mount namespace)
// CLONE_NEWPID (might not work without forking to also become reaper)
// before mounting anything, set up the uids and gids in this namespace.
// without this, everything shows up as 65534 a.k.a. 'nobody' a.k.a. 'overflow',
// and `mkdir` will return EOVERFLOW.
// all this does is make it so that namespace operations under uid 1000 are
// mapped to non-ns ops by the same user, and vice-versa
write_uid_map(proc_fs);
rt::mount("tmpfs", "/tmp", &['t': u8, 'm', 'p', 'f', 's', 0]: *const u8, rtext::MS_NODEV | rtext::MS_NOSUID, null)!;
// chroot to `/tmp`, with the old root being placed at `/tmp/oldroot` (i.e. /oldroot)
check_error("cd /tmp", os::chdir("/tmp"));
check_error("mkdir /tmp/oldroot", rt::mkdir(&['o': u8, 'l', 'd', 'r', 'o', 'o', 't', 0]: *const u8, 0o755));
rtext::pivot_root("/tmp", "oldroot")!;
check_error("cd /", os::chdir("/"));
// chroot back into `/oldroot`.
// TODO: we should rather chroot into `/newroot`, after mounting everything
// there. this is just a proof-of-concept
check_error("cd /oldroot", os::chdir("/oldroot"));
rtext::pivot_root("/oldroot", ".")!;
check_error("cd /", os::chdir("/"));
// TODO: CLONE_NEWPID (might not work without forking to also become reaper)
};
fn check_error(op: str, c: (void | fs::error | rt::errno)) void = {
match (c) {
case void => void;
case let e: rt::errno => log::fatalf("{}: {}: {}", op, rt::errname(e), rt::strerror(e));
case let e: fs::error => log::fatalf("{}: {}", op, fs::strerror(e));
};
};
// fn write_uid_map(proc_fd: int) void = {
// // let uid_fd = rt::open("/proc/self/uid_map", rt::O_RDWR | rt::O_CLOEXEC, 0)!;
// let uid_fd = rt::openat2(proc_fd, "self/uid_map", rt::open_how {
// flags: rt::O_RDWR | rt::O_CLOEXEC, ...
// })!;
// io::write(uid_fd, &['1': u8, '0', '0', '0', ' ', '0', ' ', '1', 0])!;
// };
fn write_uid_map(proc_fs: *fs::fs) void = {
let uid_fd = fs::open(proc_fs, "self/uid_map", fs::flag::RDWR)!;
io::write(uid_fd, &['1': u8, '0', '0', '0', ' ', '1', '0', '0', '0', ' ', '1', '\n', 0])!;
let setgroups_fd = fs::open(proc_fs, "self/setgroups", fs::flag::RDWR)!;
io::write(setgroups_fd, &['d': u8, 'e', 'n', 'y', '\n', 0])!;
let gid_fd = fs::open(proc_fs, "self/gid_map", fs::flag::RDWR)!;
io::write(gid_fd, &['1': u8, '0', '0', ' ', '1', '0', '0', ' ', '1', '\n', 0])!;
};

View File

@@ -0,0 +1,28 @@
// vim: set shiftwidth=2 :
export const MS_RDONLY: u64 = 1;
export const MS_NOSUID: u64 = 2;
export const MS_NODEV: u64 = 4;
export const MS_NOEXEC: u64 = 8;
export const MS_SYNCHRONOUS: u64 = 16;
export const MS_REMOUNT: u64 = 32;
export const MS_MANDLOCK: u64 = 64;
export const MS_DIRSYNC: u64 = 128;
export const MS_NOSYMFOLLOW: u64 = 256;
export const MS_NOATIME: u64 = 1024;
export const MS_NODIRATIME: u64 = 2048;
export const MS_BIND: u64 = 4096;
export const MS_MOVE: u64 = 8192;
export const MS_REC: u64 = 16384;
export const MS_VERBOSE: u64 = 32768;
export const MS_SILENT: u64 = 32768;
export const MS_POSIXACL: u64 =(1<<16);
export const MS_UNBINDABLE: u64 =(1<<17);
export const MS_PRIVATE: u64 =(1<<18);
export const MS_SLAVE: u64 =(1<<19);
export const MS_SHARED: u64 =(1<<20);
export const MS_RELATIME: u64 =(1<<21);
export const MS_KERNMOUNT: u64 =(1<<22);
export const MS_I_VERSION: u64 =(1<<23);
export const MS_STRICTATIME: u64 =(1<<24);
export const MS_LAZYTIME: u64 =(1<<25);