diff --git a/pkgs/additional/bunpen/rtext/error.ha b/pkgs/additional/bunpen/errors/ext/check.ha similarity index 79% rename from pkgs/additional/bunpen/rtext/error.ha rename to pkgs/additional/bunpen/errors/ext/check.ha index 8689ebf5a..0564073c2 100644 --- a/pkgs/additional/bunpen/rtext/error.ha +++ b/pkgs/additional/bunpen/errors/ext/check.ha @@ -4,7 +4,7 @@ use log; use os::exec; use rt; -export fn check_error(context: str, what: (void | fs::error | os::exec::error | rt::errno)) void = { +export fn check(context: str, what: (void | fs::error | os::exec::error | rt::errno)) void = { match (what) { case let e: fs::error => log::fatalf("{}: {}", context, fs::strerror(e)); case let e: os::exec::error => log::fatalf("{}: {}", context, os::exec::strerror(e)); @@ -13,7 +13,7 @@ export fn check_error(context: str, what: (void | fs::error | os::exec::error | }; }; -export fn swallow_error(context: str, what: (void | fs::error | os::exec::error | rt::errno)) void = { +export fn swallow(context: str, what: (void | fs::error | os::exec::error | rt::errno)) void = { match (what) { // N.B.: use `println(...)` over `printfln("{}: {}")` so that my treelogger // can extract the context. diff --git a/pkgs/additional/bunpen/main.ha b/pkgs/additional/bunpen/main.ha index ff5804d9f..fe4015a06 100644 --- a/pkgs/additional/bunpen/main.ha +++ b/pkgs/additional/bunpen/main.ha @@ -1,5 +1,6 @@ // vim: set shiftwidth=2 : use config; +use errors::ext; use log; use log::tree; use restrict; @@ -17,7 +18,7 @@ fn do_exec(path: str, args: []str) (os::exec::error | void) = { log::printfln("exec ({}): {}", path, joined); }; - rtext::check_error("exec", rtext::execve(path, args, os::getenvs())); + errors::ext::check("exec", rtext::execve(path, args, os::getenvs())); // XXX: os::exec::exec offers no way to preserve argv0, but it does // work if you don't care about that: @@ -50,5 +51,5 @@ export fn main() void = { // XXX: landlock prevents other sandboxers like `bwrap` from executing, // because it forbids all future `mount` syscalls. so don't landlock. // restrict::landlock_restrict(&req.resources); - rtext::check_error("exec ", do_exec(req.exec_bin, req.exec_args)); + errors::ext::check("exec ", do_exec(req.exec_bin, req.exec_args)); }; diff --git a/pkgs/additional/bunpen/restrict/landlock.ha b/pkgs/additional/bunpen/restrict/landlock.ha index 9c7d2fb5b..353717c8c 100644 --- a/pkgs/additional/bunpen/restrict/landlock.ha +++ b/pkgs/additional/bunpen/restrict/landlock.ha @@ -1,4 +1,5 @@ // vim: set shiftwidth=2 : +use errors::ext; use fs; use log; use os; @@ -89,7 +90,7 @@ export fn landlock_restrict(what: *resources) void = { for (let pathbuf .. what.paths) { let pathstr = path::string(&pathbuf); log::printfln("[landlock] permit path: {}", pathstr); - rtext::swallow_error("[landlock/path] omitting from sandbox: failed to add path", allow_path(ruleset_fd, pathstr)); + errors::ext::swallow("[landlock/path] omitting from sandbox: failed to add path", allow_path(ruleset_fd, pathstr)); }; rtext::landlock_restrict_self(ruleset_fd)!; diff --git a/pkgs/additional/bunpen/restrict/namespace.ha b/pkgs/additional/bunpen/restrict/namespace.ha index 394debfd9..0dd0bbdac 100644 --- a/pkgs/additional/bunpen/restrict/namespace.ha +++ b/pkgs/additional/bunpen/restrict/namespace.ha @@ -1,4 +1,5 @@ // vim: set shiftwidth=2 : +use errors::ext; use fmt; use fs; use io; @@ -60,8 +61,8 @@ export fn namespace_restrict(what: *resources) void = { // (and the wrapper only exits once *all* orphaned children die). // i don't need children to outlive the main process, so i fork once and let // the sandboxed program be reaper for all its children. - rtext::check_error("[namespace/fork] forking new PID 1", fork_and_propagate()); - // rtext::check_error("[namespace/fork] forking second time", fork_and_propagate()); + errors::ext::check("[namespace/fork] forking new PID 1", fork_and_propagate()); + // errors::ext::check("[namespace/fork] forking second time", fork_and_propagate()); }; let pwd = strings::dup(os::getcwd()); // dup because API uses a static buffer @@ -69,7 +70,7 @@ export fn namespace_restrict(what: *resources) void = { 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)); + errors::ext::swallow("namespace: restore $PWD", os::chdir(pwd)); }; // fork and: @@ -91,7 +92,7 @@ fn fork_and_propagate() (void | os::exec::error) = { fn isolate_paths(paths: []path::buffer) void = { // allow new mounts to propagate from the parent namespace into the child // namespace, but not vice versa: - rtext::check_error("[namespace] reconfigure / as MS_SLAVE", rtext::mount("/", "/", "", rtext::mount_flag::SLAVE | rtext::mount_flag::REC, null)); + errors::ext::check("[namespace] reconfigure / as MS_SLAVE", rtext::mount("/", "/", "", rtext::mount_flag::SLAVE | rtext::mount_flag::REC, null)); // 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 @@ -102,16 +103,16 @@ fn isolate_paths(paths: []path::buffer) void = { // 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("[namespace] mount -t tmpfs tmpfs /tmp", rtext::mount("tmpfs", "/tmp", "tmpfs", rtext::mount_flag::NODEV | rtext::mount_flag::NOSUID, null)); + errors::ext::check("[namespace] mount -t tmpfs tmpfs /tmp", rtext::mount("tmpfs", "/tmp", "tmpfs", rtext::mount_flag::NODEV | rtext::mount_flag::NOSUID, null)); pivot_into("/tmp", "old"); // 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("[namespace] mkdir new", rt::mkdir("new", 0o755)); - rtext::check_error("[namespace] mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", 0, null)); - // rtext::check_error("[namespace] mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", rtext::mount_flag::NODEV | rtext::mount_flag::NOSUID, null)); - // rtext::check_error("[namespace] mount -o rbind new new", rtext::mount("new", "new", "", rtext::mount_flag::BIND | rtext::mount_flag::REC, null)); + errors::ext::check("[namespace] mkdir new", rt::mkdir("new", 0o755)); + errors::ext::check("[namespace] mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", 0, null)); + // errors::ext::check("[namespace] mount -t tmpfs tmpfs new", rtext::mount("tmpfs", "new", "tmpfs", rtext::mount_flag::NODEV | rtext::mount_flag::NOSUID, null)); + // errors::ext::check("[namespace] mount -o rbind new new", rtext::mount("new", "new", "", rtext::mount_flag::BIND | rtext::mount_flag::REC, null)); // try to mount a new /proc. // - this is "safe" because we're not doing anything @@ -125,15 +126,15 @@ fn isolate_paths(paths: []path::buffer) void = { // - bind-mounting /proc is _in theory_ safe (it's a namespace-aware fs), // but in practice there are namespacing bugs at least as recently as 2021: // - rtext::swallow_error("[namespace] mkdir new/proc", rt::mkdir("new/proc", 0o755)); - rtext::swallow_error("[namespace] mount /new/proc", rtext::mount( + errors::ext::swallow("[namespace] mkdir new/proc", rt::mkdir("new/proc", 0o755)); + errors::ext::swallow("[namespace] mount /new/proc", rtext::mount( "proc", "new/proc", "proc", rtext::mount_flag::NOSUID | rtext::mount_flag::NOEXEC | rtext::mount_flag::NODEV, null )); // provide a new `/tmp` too. - rtext::swallow_error("[namespace] mkdir new/tmp", rt::mkdir("new/tmp", 0o777)); - rtext::swallow_error("[namespace] mount -t tmpfs tmpfs new/tmp", rtext::mount("tmpfs", "new/tmp", "tmpfs", 0, null)); + errors::ext::swallow("[namespace] mkdir new/tmp", rt::mkdir("new/tmp", 0o777)); + errors::ext::swallow("[namespace] mount -t tmpfs tmpfs new/tmp", rtext::mount("tmpfs", "new/tmp", "tmpfs", 0, null)); // 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 @@ -231,7 +232,7 @@ fn bind_leaf(old_fs: *fs::fs, new_fs: *fs::fs, user_path: *path::buffer) void = }; log::printfln("[namespace/bind] mount {} {}", path::string(&old_pathbuf), path::string(&new_pathbuf)); - rtext::swallow_error("[namespace/bind] bind_leaf: mount", rtext::mount( + errors::ext::swallow("[namespace/bind] bind_leaf: mount", rtext::mount( path::string(&old_pathbuf), path::string(&new_pathbuf), "", rtext::mount_flag::BIND | rtext::mount_flag::REC, null )); }; @@ -281,17 +282,17 @@ fn bind_component(old_fs: *fs::fs, new_fs: *fs::fs, strpath: str, remaining: str // at some directory (to be created) underneath it. fn pivot_into(new_root: str, stash_old_root: (str|void) = void) void = { log::printfln("[namespace] pivot_root {}", new_root); - rtext::check_error("[namespace] cd ", os::chdir(new_root)); + errors::ext::check("[namespace] cd ", os::chdir(new_root)); match (stash_old_root) { case let old: str => - rtext::check_error("[namespace] mkdir ", rt::mkdir(old, 0o755)); - rtext::check_error("[namespace] pivot_root . ", rtext::pivot_root(".", old)); + errors::ext::check("[namespace] mkdir ", rt::mkdir(old, 0o755)); + errors::ext::check("[namespace] pivot_root . ", rtext::pivot_root(".", old)); case void => - rtext::check_error("[namespace] pivot_root . .", rtext::pivot_root(".", ".")); + errors::ext::check("[namespace] pivot_root . .", rtext::pivot_root(".", ".")); // drop the old rootfs. weird idiom, but documented in `man 2 pivot_root`. - rtext::check_error("[namespace] umount .", rt::umount2(".", rtext::umount_flag::MNT_DETACH)); + errors::ext::check("[namespace] umount .", rt::umount2(".", rtext::umount_flag::MNT_DETACH)); }; - rtext::check_error("[namespace] cd /", os::chdir("/")); + errors::ext::check("[namespace] cd /", os::chdir("/")); }; fn write_uid_map(uid: unix::uid, gid: unix::gid) void = {