bunpen: pasta: share /proc/self/ns/net with pasta in a way that will be friendlier to sandboxing

This commit is contained in:
2024-12-30 16:58:26 +00:00
parent 2d989327f7
commit 0a9e5b9f68

View File

@@ -32,6 +32,11 @@ fn pasta_restrict(net: resources::net_subset) void = {
// TODO: stronger isolation (mount namespace).
// errors::ext::check("[namespace/pasta] unshare PID", rt::ext::unshare(rt::ext::clone_flag::NEWPID));
// grab a handle to the namespaces of the primary process.
// then we can fork, unshare net (in parent) and refer to that unshared netns
// in the child (pasta) via ${ns_fd}/net.
let ns_fd = errors::ext::check_int("setup_pasta: open /proc/self/ns", rt::open("/proc/self/ns", rt::O_RDONLY, 0o400));
let (pipe_parent_rd, pipe_child_wr) = unix::pipe()!;
let (pipe_child_rd, pipe_parent_wr) = unix::pipe()!;
log::printfln("[namespace/pasta]: forking: child will launch pasta while parent will exec user code");
@@ -44,22 +49,12 @@ fn pasta_restrict(net: resources::net_subset) void = {
errors::ext::check("namespace: unshare net", rt::ext::unshare(rt::ext::clone_flag::NEWNET));
errors::ext::check("setup_pasta: config routing", config_routing_in_ns(net));
// open the net ns and share that with our child, who can then share it
// with pasta
let netns_fd = errors::ext::check_int("setup_pasta: open /proc/self/ns/net", rt::open("/proc/self/ns/net", rt::O_RDONLY, 0o400));
// drop enough caps so that pasta has permissions to enter our new netns.
// TODO: just set the desired caps here, and then don't try to do it again.
capability_restrict(rt::ext::CAPS_NONE);
// let the other thread know we're ready for pasta to attach to us
let netns_fd_bytes = [
netns_fd: u8,
(netns_fd >> 8): u8,
(netns_fd >> 16): u8,
(netns_fd >> 24): u8,
];
io::write(pipe_parent_wr, netns_fd_bytes)!;
io::write(pipe_parent_wr, [1u8])!;
// wait for the other thread to attach pasta.
// pasta signals readiness by writing its pid (followed by \n) to a file.
@@ -75,28 +70,15 @@ fn pasta_restrict(net: resources::net_subset) void = {
io::close(pipe_parent_wr)!;
io::close(pipe_parent_rd)!;
let parent_pid = rt::getppid();
let parent_pidfd = errors::ext::check_int(
"setup_pasta: pidfd_open(parent_pid)",
rt::ext::pidfd_open(parent_pid),
);
// wait for the parent to signal that it's ready for us to attach pasta.
let netns_child_fd_bytes: [4]u8 = [0...];
io::readall(pipe_child_rd, &netns_child_fd_bytes)!;
let netns_child_fd: int = (
(netns_child_fd_bytes[0]: int) |
(netns_child_fd_bytes[1]: int << 8) |
(netns_child_fd_bytes[1]: int << 16) |
(netns_child_fd_bytes[1]: int << 24)
);
let netns = errors::ext::check_int(
"setup_pasta: pidfd_getfd(parent_pidfd, netns_u8)",
rt::ext::pidfd_getfd(parent_pidfd, netns_child_fd),
);
io::readall(pipe_child_rd, &[0u8])!;
// exec into pasta.
errors::ext::check("setup_pasta: attach", attach_pasta(net, netns, pipe_child_wr));
let netns_fd = errors::ext::check_int(
"setup_pasta: open('/proc/self/ns/net')",
rt::openat2(ns_fd, "net", &rt::open_how { ... }, size(rt::open_how)),
);
errors::ext::check("setup_pasta: attach", attach_pasta(net, netns_fd, pipe_child_wr));
// XXX: this code below never actually gets run
// cleanup: we're done with the pipes