bunpen: implement --bunpen-try-keep-users to try to keep the user namespace, but create a new one if keeping the existing one would require less sandboxing elsewhere
This commit is contained in:
@@ -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 <path>")!;
|
||||
fmt::println(" allow access to the host <path> 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);
|
||||
};
|
||||
};
|
||||
|
||||
|
@@ -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 =>
|
||||
|
@@ -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',
|
||||
|
@@ -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,
|
||||
};
|
||||
|
Reference in New Issue
Block a user