bunpen: apply BUNPEN_DISABLE regex matching to BUNPEN_DROP_SHELL, too

This commit is contained in:
2025-06-06 03:44:21 +00:00
parent 1db734375a
commit 01438ff7bb
3 changed files with 50 additions and 18 deletions

View File

@@ -12,7 +12,7 @@ export type cli_opts = struct {
// `--bunpen-debug`
debug: uint,
disable: str,
drop_shell: bool,
drop_shell: str,
// [ "KEY=VALUE" ]
env: []str,
// `--bunpen-help`
@@ -99,6 +99,9 @@ export fn usage() void = {
fmt::println(" note that this doesn't enforce a complete match:")!;
fmt::println(" BUNPEN_DISABLE=host would disable sandboxing for 'host', 'hostname', and so on")!;
fmt::println(" consider BUNPEN_DISABLE='host$' to be more targeted")!;
fmt::println(" BUNPEN_DROP_SHELL=<specifier>")!;
fmt::println(" instead of running the program, drop into an interactive shell")!;
fmt::println(" uses the same specifier syntax as BUNPEN_DISABLE")!;
fmt::println(" BUNPEN_APPEND=--bunpen-flag1 --bunpen-flag2 ...")!;
fmt::println(" act as though the provided arg string appeared at the end of the CLI")!;
fmt::println("")!;
@@ -141,6 +144,10 @@ export fn parse_args(args: []str) (cli_opts | errors::invalid) = {
};
case void => void;
};
match (os::getenv("BUNPEN_DROP_SHELL")) {
case let d: str => parsed.drop_shell = d;
case void => void;
};
parse_args_into(&parsed, args)?;
@@ -183,7 +190,7 @@ fn parse_args_into(parsed: *cli_opts, args: []str) (void | errors::invalid) = {
case "--bunpen-debug=3" => parsed.debug = 3;
case "--bunpen-debug=4" => parsed.debug = 4;
case "--bunpen-dns" => idx += 1; parsed.dns = expect_arg("--bunpen-dns", next)?;
case "--bunpen-drop-shell" => parsed.drop_shell = true;
case "--bunpen-drop-shell" => parsed.drop_shell = "1";
case "--bunpen-env" => idx += 1; append(parsed.env, expect_arg("--bunpen-env", next)?);
case "--bunpen-help" => parsed.help = true;
case "--bunpen-keep-ipc" => parsed.keep_ipc = true;

View File

@@ -104,20 +104,8 @@ export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = {
req.exec_params = cli_opts_get_exec_params(opts, env);
//---- ingest `disable` ----//
if (opts.disable != "") {
if (opts.disable == "1" || opts.disable == "all" || opts.disable == "ALL" || opts.disable == "*")
if (does_option_apply_to_self(opts.disable, &req.exec_params))
return req.exec_params;
match (regex::compile(opts.disable)) {
case let re: regex::regex =>
defer regex::finish(&re);
if (regex::test(&re, req.exec_params.bin))
return req.exec_params;
if (len(req.exec_params.args) > 0 && regex::test(&re, req.exec_params.args[0]))
return req.exec_params;
case let e: regex::error =>
log::printfln("[config] failed to parse BUNPEN_DISABLE regex {}: {}", opts.disable, e);
};
};
//---- ingest `caps` ----//
req.resources.caps = resources::cap_array_to_caps(opts.keep_caps);
@@ -179,7 +167,7 @@ export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = {
};
//---- ingest `drop_shell` (must be done after autodetect) ----//
if (opts.drop_shell) {
if (does_option_apply_to_self(opts.drop_shell, &req.exec_params)) {
// ignore the original command, and overwrite it with an interactive shell.
// TODO: respect the user's `$SHELL`.
req.exec_params.bin = "/bin/sh";
@@ -190,6 +178,31 @@ export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = {
return req;
};
// consider a string like "", "0", "1", "all", "*", "sane-which", ...;
// return true if it either
// (1) looks truthy (1, all)
// (2) it looks to be referring to the current binary (*, sane-which)
fn does_option_apply_to_self(value: str, exec_params: *const exec_params) bool = {
if (value == "")
return false; // prevent over-eager regex match
if (value == "1" || value == "all" || value == "ALL" || value == "*")
return true;
match (regex::compile(value)) {
case let re: regex::regex =>
defer regex::finish(&re);
if (regex::test(&re, exec_params.bin))
return true;
if (len(exec_params.args) > 0 && regex::test(&re, exec_params.args[0]))
return true;
case let e: regex::error =>
log::printfln("[config] failed to parse option regex {}: {}", value, e);
};
return false;
};
// convert each item in `from` to a path, and append to `into`.
// non-absolute paths are interpreted as relative to `env.pwd`.
// a limited set of environment variables are expanded for each path; see `env_subst`.

View File

@@ -47,11 +47,23 @@ test_02_env_arg_01_disable() {
BUNPEN_DISABLE=1 bunpen true
}
test_02_env_arg_02_append() {
test_02_env_arg_02_disable_by_name_match() {
BUNPEN_DISABLE=env bunpen env true
}
test_02_env_arg_03_disable_by_name_no_match() {
BUNPEN_DISABLE=envv bunpen env true && return 1 || true
}
test_02_env_arg_04_disable_by_name_regex_match() {
BUNPEN_DISABLE=e.v? bunpen env true
}
test_02_env_arg_05_append() {
BUNPEN_APPEND="--bunpen-path /" bunpen ls /
}
test_02_env_arg_03_append_tolerates_whitespace() {
test_02_env_arg_06_append_tolerates_whitespace() {
BUNPEN_APPEND=" --bunpen-debug=4 --bunpen-keep-pid --bunpen-path / " bunpen ls /
}