bunpen: barebones pasta integration
totally untested, except that it builds
This commit is contained in:
@@ -107,7 +107,7 @@ export fn namespace_restrict(what: *restrict::resources) void = {
|
||||
case restrict::net_none =>
|
||||
errors::ext::check("namespace: unshare net", rt::ext::unshare(rt::ext::clone_flag::NEWNET));
|
||||
case let subset: restrict::net_subset =>
|
||||
errors::ext::check("namespace: unshare net", rt::ext::unshare(rt::ext::clone_flag::NEWNET));
|
||||
setup_pasta(subset);
|
||||
case restrict::net_all =>
|
||||
log::println("[namespace] keeping net namespace");
|
||||
};
|
||||
@@ -164,19 +164,22 @@ type ns_ctx = struct {
|
||||
// - in the parent: wait for the child, then propagate its exit status
|
||||
fn fork_and_propagate() (void | os::exec::error) = {
|
||||
match (os::exec::fork()?) {
|
||||
case let child_pid: os::exec::process =>
|
||||
forward_signals(child_pid);
|
||||
log::println("[namespace/fork] signals configured");
|
||||
let status = wait_child(child_pid)?;
|
||||
let rc = rt::wexitstatus(status.status);
|
||||
// TODO: if the child exited due to a signal (e.g. SIGTERM), we (confusingly?) exit 0.
|
||||
// seems correct behavior may be to send the same termination signal to ourselves.
|
||||
log::printfln("[namespace/fork] child exited with {}; forwarding as {}", status.status, rc);
|
||||
os::exit(rc); // propagate exit code
|
||||
case let child_pid: os::exec::process => return wait_and_propagate(child_pid);
|
||||
case => log::println("[namespace/fork] continuing as child");
|
||||
};
|
||||
};
|
||||
|
||||
fn wait_and_propagate(child_pid: os::exec::process) (void | os::exec::error) = {
|
||||
forward_signals(child_pid);
|
||||
log::println("[namespace/fork] signals configured");
|
||||
let status = wait_child(child_pid)?;
|
||||
let rc = rt::wexitstatus(status.status);
|
||||
// TODO: if the child exited due to a signal (e.g. SIGTERM), we (confusingly?) exit 0.
|
||||
// seems correct behavior may be to send the same termination signal to ourselves.
|
||||
log::printfln("[namespace/fork] child exited with {}; forwarding as {}", status.status, rc);
|
||||
os::exit(rc); // propagate exit code
|
||||
};
|
||||
|
||||
fn wait_child(child_pid: os::exec::process) (os::exec::status | os::exec::error) = {
|
||||
for (true) {
|
||||
match (os::exec::wait(&child_pid)) {
|
||||
|
46
pkgs/additional/bunpen/restrict/ns/pasta.ha
Normal file
46
pkgs/additional/bunpen/restrict/ns/pasta.ha
Normal file
@@ -0,0 +1,46 @@
|
||||
// vim: set shiftwidth=2 :
|
||||
use errors;
|
||||
use errors::ext;
|
||||
use fmt;
|
||||
use os;
|
||||
use os::exec;
|
||||
use restrict;
|
||||
use rt;
|
||||
use rt::ext;
|
||||
|
||||
fn setup_pasta(net: restrict::net_subset) void = {
|
||||
// `pasta PID [options]`: creates a device in the netns of PID.
|
||||
// ordering:
|
||||
// 1. fork
|
||||
// 2. child: enter netns, signal parent.
|
||||
// 3. parent: fork and spawn `pasta --pid /proc/fd/$N`
|
||||
// then dumbly wait on child until completion
|
||||
// 4. child: wait for `pasta` to signal readiness on fd `$N`
|
||||
//
|
||||
// after that, we can continue on & exec into the user code
|
||||
//
|
||||
// TODO: this currently lacks the synchronization described above
|
||||
|
||||
match (os::exec::fork()) {
|
||||
case let child_pid: os::exec::process =>
|
||||
errors::ext::check("setup_pasta: attach", attach_pasta(child_pid));
|
||||
errors::ext::check("setup_pasta: wait", wait_and_propagate(child_pid));
|
||||
case void =>
|
||||
errors::ext::check("namespace: unshare net", rt::ext::unshare(rt::ext::clone_flag::NEWNET));
|
||||
case let e: os::exec::error =>
|
||||
errors::ext::check("setup_pasta: fork", e);
|
||||
};
|
||||
};
|
||||
|
||||
// spawn pasta as a separate process, and have it attach to the netns of the given pid.
|
||||
fn attach_pasta(child: os::exec::process) (void | os::exec::error | rt::errno) = {
|
||||
return match (os::exec::fork()?) {
|
||||
case let pasta_pid: os::exec::process => yield void;
|
||||
case void =>
|
||||
let pidstr = fmt::asprint(child: int);
|
||||
defer free(pidstr);
|
||||
let pasta_args = [ "pasta", pidstr ];
|
||||
// TODO: append dns, gateway arguments to `pasta`.
|
||||
yield rt::ext::execvpe("pasta", pasta_args, os::getenvs());
|
||||
};
|
||||
};
|
Reference in New Issue
Block a user