diff --git a/pkgs/additional/bunpen/config/cli.ha b/pkgs/additional/bunpen/config/cli.ha index f33785b26..607d6c3ff 100644 --- a/pkgs/additional/bunpen/config/cli.ha +++ b/pkgs/additional/bunpen/config/cli.ha @@ -21,6 +21,7 @@ export type cli_opts = struct { keep_pid: bool, paths: []str, run_paths: []str, + try_keep_users: bool, }; export fn usage() void = { @@ -46,6 +47,8 @@ export fn usage() void = { fmt::println(" allow unrestricted access to the network")!; fmt::println(" --bunpen-keep-pid")!; fmt::println(" allow this process to see other processes running on the machine")!; + fmt::println(" --bunpen-try-keep-users")!; + fmt::println(" if we have permissions to perform all other operations without creating a new user namespace, then don't create a user namespace")!; fmt::println(" --bunpen-path ")!; fmt::println(" allow access to the host within the sandbox")!; fmt::println(" path is interpreted relative to the working directory if not absolute")!; @@ -99,22 +102,23 @@ export fn parse_args(args: []str) (cli_opts | errors::invalid) = { next = &args[idx+1]; }; switch (arg) { - case "--bunpen-autodetect" => idx += 1; parsed.autodetect = autodetect_fromstr(expect_arg("--bunpen-autodetect", next)?)?; - case "--bunpen-cap" => idx += 1; parse_caparg(&parsed, expect_arg("--bunpen-cap", next)?)?; - case "--bunpen-debug" => parsed.debug = 2; - case "--bunpen-debug=0" => parsed.debug = 0; - case "--bunpen-debug=1" => parsed.debug = 1; - case "--bunpen-debug=2" => parsed.debug = 2; - case "--bunpen-debug=3" => parsed.debug = 3; - case "--bunpen-debug=4" => parsed.debug = 4; - case "--bunpen-drop-shell" => parsed.drop_shell = true; - case "--bunpen-help" => parsed.help = true; - case "--bunpen-home-path" => idx += 1; append(parsed.home_paths, expect_arg("--bunpen-home-path", next)?); - case "--bunpen-keep-net" => parsed.keep_net = true; - case "--bunpen-keep-pid" => parsed.keep_pid = true; - case "--bunpen-path" => idx += 1; append(parsed.paths, expect_arg("--bunpen-path", next)?); - case "--bunpen-run-path" => idx += 1; append(parsed.run_paths, expect_arg("--bunpen-run-path", next)?); - case => append(parsed.cmd, arg); + case "--bunpen-autodetect" => idx += 1; parsed.autodetect = autodetect_fromstr(expect_arg("--bunpen-autodetect", next)?)?; + case "--bunpen-cap" => idx += 1; parse_caparg(&parsed, expect_arg("--bunpen-cap", next)?)?; + case "--bunpen-debug" => parsed.debug = 2; + case "--bunpen-debug=0" => parsed.debug = 0; + case "--bunpen-debug=1" => parsed.debug = 1; + case "--bunpen-debug=2" => parsed.debug = 2; + case "--bunpen-debug=3" => parsed.debug = 3; + case "--bunpen-debug=4" => parsed.debug = 4; + case "--bunpen-drop-shell" => parsed.drop_shell = true; + case "--bunpen-help" => parsed.help = true; + case "--bunpen-home-path" => idx += 1; append(parsed.home_paths, expect_arg("--bunpen-home-path", next)?); + case "--bunpen-keep-net" => parsed.keep_net = true; + case "--bunpen-keep-pid" => parsed.keep_pid = true; + case "--bunpen-path" => idx += 1; append(parsed.paths, expect_arg("--bunpen-path", next)?); + case "--bunpen-run-path" => idx += 1; append(parsed.run_paths, expect_arg("--bunpen-run-path", next)?); + case "--bunpen-try-keep-users" => parsed.try_keep_users = true; + case => append(parsed.cmd, arg); }; }; diff --git a/pkgs/additional/bunpen/config/translate_opts.ha b/pkgs/additional/bunpen/config/translate_opts.ha index 4bec93c33..1f3134b08 100644 --- a/pkgs/additional/bunpen/config/translate_opts.ha +++ b/pkgs/additional/bunpen/config/translate_opts.ha @@ -109,6 +109,9 @@ export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = { //---- ingest `run_paths` ----// ingest_paths(&req.resources.paths, opts.run_paths, os::getenv("XDG_RUNTIME_DIR")); + //---- ingest `try_keep_users` ----// + req.resources.try_users = opts.try_keep_users; + //---- ingest `autodetect` (must be done after exec_params) ----// match (opts.autodetect) { case let method: autodetect => diff --git a/pkgs/additional/bunpen/restrict/namespace.ha b/pkgs/additional/bunpen/restrict/namespace.ha index 200e3d0f6..939040823 100644 --- a/pkgs/additional/bunpen/restrict/namespace.ha +++ b/pkgs/additional/bunpen/restrict/namespace.ha @@ -36,9 +36,22 @@ export fn namespace_restrict(what: *resources) void = { log::println("[namespace] keeping pid namespace"); what_to_unshare &= ~rt::ext::clone_flag::NEWPID; }; + if (what.try_users) { + log::println("[namespace] keeping user namespace *if possible*"); + let unshare_keep_users = what_to_unshare & ~rt::ext::clone_flag::NEWUSER; + match (rt::ext::unshare(unshare_keep_users)) { + case void => + log::println("[namespace] unshared user namespace successfully"); + what_to_unshare = 0; + case let e: rt::errno => + errors::ext::swallow("[namespace] unshare user namespace", e); + }; + }; - log::printfln("[namespace] unshare {}", what_to_unshare: u64); - errors::ext::check("namespace: unshare", rt::ext::unshare(what_to_unshare)); + if (what_to_unshare != 0) { + log::printfln("[namespace] unshare {}", what_to_unshare: u64); + errors::ext::check("namespace: unshare", rt::ext::unshare(what_to_unshare)); + }; // 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', diff --git a/pkgs/additional/bunpen/restrict/resources.ha b/pkgs/additional/bunpen/restrict/resources.ha index 33311fe16..e052a25af 100644 --- a/pkgs/additional/bunpen/restrict/resources.ha +++ b/pkgs/additional/bunpen/restrict/resources.ha @@ -13,4 +13,7 @@ export type resources = struct { // true to allow operations on other processes (e.g. viewing their cmdline, // killing them, etc). pid: bool, + // try to keep access to the current user namespace, but let it go if holding + // onto it would prevent us from sandboxing further + try_users: bool, };