bunpen: plumb pasta CLI options up through main

This commit is contained in:
2024-09-19 23:52:07 +00:00
parent bf53ab1cb1
commit 2a4043523d
5 changed files with 49 additions and 18 deletions

View File

@@ -25,9 +25,9 @@ export type cli_opts = struct {
run_paths: []str, run_paths: []str,
try_keep_users: bool, try_keep_users: bool,
net_dev: (void | str), net_dev: str,
net_gateway: (void | str), net_gateway: str,
dns: (void | str), dns: str,
}; };
export fn usage() void = { export fn usage() void = {
@@ -99,7 +99,7 @@ export fn usage() void = {
}; };
export fn parse_args(args: []str) (cli_opts | errors::invalid) = { export fn parse_args(args: []str) (cli_opts | errors::invalid) = {
let parsed = cli_opts { autodetect = void, net_dev = void, net_gateway = void, dns = void, ... }; let parsed = cli_opts { autodetect = void, ... };
match (os::getenv("BUNPEN_DISABLE")) { match (os::getenv("BUNPEN_DISABLE")) {
case let d: str => parsed.disable = d; case let d: str => parsed.disable = d;

View File

@@ -61,7 +61,10 @@ fn cli_opts_get_exec_params(opts: cli_opts) exec_params = {
}; };
export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = { export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = {
let req = cli_request { ... }; let req = cli_request {
resources = restrict::resources { net = restrict::net_none, ... },
...
};
//---- ingest `help` ----// //---- ingest `help` ----//
if (opts.help) { if (opts.help) {
@@ -90,7 +93,6 @@ export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = {
//---- ingest `caps` ----// //---- ingest `caps` ----//
req.resources.caps = restrict::cap_array_to_caps(opts.keep_caps); req.resources.caps = restrict::cap_array_to_caps(opts.keep_caps);
//---- ingest `home_paths` ----// //---- ingest `home_paths` ----//
ingest_paths(&req.resources.paths, opts.home_paths, os::getenv("HOME")); ingest_paths(&req.resources.paths, opts.home_paths, os::getenv("HOME"));
//---- ingest `keep_all_caps` ----// //---- ingest `keep_all_caps` ----//
@@ -100,8 +102,19 @@ export fn ingest_cli_opts(opts: cli_opts) (cli_request | exec_params | help) = {
//---- ingest `keep_ipc` ----// //---- ingest `keep_ipc` ----//
req.resources.ipc = opts.keep_ipc; req.resources.ipc = opts.keep_ipc;
//---- ingest `net_dev`, `net_gateway`, `dns` ----//
let net_subset = restrict::net_subset {
dev = opts.net_dev,
dns = opts.dns,
gateway = opts.net_gateway,
};
if (net_subset.dev != "" && net_subset.dns != "" && net_subset.gateway != "")
req.resources.net = net_subset;
//---- ingest `keep_net` ----// //---- ingest `keep_net` ----//
req.resources.net = opts.keep_net; if (opts.keep_net)
req.resources.net = restrict::net_all;
//---- ingest `keep_pid` ----// //---- ingest `keep_pid` ----//
req.resources.pid = opts.keep_pid; req.resources.pid = opts.keep_pid;

View File

@@ -82,11 +82,15 @@ export fn landlock_restrict(what: *resources) void = {
ruleset_attr.handled_access_fs &= ~rt::ext::landlock_access_fs::IOCTL_DEV; ruleset_attr.handled_access_fs &= ~rt::ext::landlock_access_fs::IOCTL_DEV;
}; };
if (what.net) { // XXX: `what.net` only affects TCP. UDP, and ICMP remain possible always
// un-restrict net access match (what.net) {
log::println("[landlock] permit net"); case net_none => void;
ruleset_attr.handled_access_net = 0; case let subset: net_subset =>
}; // XXX: `what.net` only affects TCP. UDP, and ICMP remain possible always log::println("[landlock] unable to retain just a subset of net resources");
case net_all =>
log::println("[landlock] permit net");
ruleset_attr.handled_access_net = 0;
};
let ruleset_fd = errors::ext::check_u64( let ruleset_fd = errors::ext::check_u64(
"landlock_create_ruleset", "landlock_create_ruleset",

View File

@@ -34,9 +34,13 @@ export fn namespace_restrict(what: *resources) void = {
log::println("[namespace] keeping ipc namespace"); log::println("[namespace] keeping ipc namespace");
what_to_unshare &= ~rt::ext::clone_flag::NEWIPC; what_to_unshare &= ~rt::ext::clone_flag::NEWIPC;
}; };
if (what.net) { match (what.net) {
log::println("[namespace] keeping net namespace"); case net_none => void;
what_to_unshare &= ~rt::ext::clone_flag::NEWNET; case let subset: net_subset =>
log::println("[namespace] TODO: not keeping subset of net namespace");
case net_all =>
log::println("[namespace] keeping net namespace");
what_to_unshare &= ~rt::ext::clone_flag::NEWNET;
}; };
if (what.pid) { if (what.pid) {
log::println("[namespace] keeping pid namespace"); log::println("[namespace] keeping pid namespace");

View File

@@ -9,9 +9,7 @@ export type resources = struct {
caps: rt::ext::caps, caps: rt::ext::caps,
// true to allow speaking to other processes in the same IPC namespace // true to allow speaking to other processes in the same IPC namespace
ipc: bool, ipc: bool,
// true to allow unrestricted net access. net: net_resources,
// false to maximally disable net access.
net: bool,
// true to allow operations on other processes (e.g. viewing their cmdline, // true to allow operations on other processes (e.g. viewing their cmdline,
// killing them, etc). // killing them, etc).
pid: bool, pid: bool,
@@ -19,3 +17,15 @@ export type resources = struct {
// onto it would prevent us from sandboxing further // onto it would prevent us from sandboxing further
try_users: bool, try_users: bool,
}; };
export type net_subset = struct {
// name of the network device through which traffic should be routed
dev: str,
// IP address of a DNS server reachable through these other settings
dns: str,
// IP address of the gateway, by which traffic will be routed
gateway: str,
};
export type net_none = void;
export type net_all = void;
export type net_resources = (net_none | net_subset | net_all);